[DebianGIS-dev] r916 - in packages: . openev openev/branches openev/branches/upstream openev/branches/upstream/current openev/branches/upstream/current/CVS openev/branches/upstream/current/contrib openev/branches/upstream/current/contrib/S52 openev/branches/upstream/current/contrib/S52/doc openev/branches/upstream/current/delivery openev/branches/upstream/current/delivery/CVS openev/branches/upstream/current/doc openev/branches/upstream/current/doc/CVS openev/branches/upstream/current/html openev/branches/upstream/current/html/CVS openev/branches/upstream/current/html/developer_info openev/branches/upstream/current/html/developer_info/CVS openev/branches/upstream/current/pics openev/branches/upstream/current/pics/CVS openev/branches/upstream/current/pymod openev/branches/upstream/current/pymod/CVS openev/branches/upstream/current/ramps openev/branches/upstream/current/ramps/CVS openev/branches/upstream/current/symbols openev/branches/upstream/current/symbols/CVS openev/branches/upstream/current/tools openev/branches/upstream/current/tools/CVS openev/branches/upstream/current/xmlconfig openev/branches/upstream/current/xmlconfig/CVS
frankie at alioth.debian.org
frankie at alioth.debian.org
Sat Jun 23 22:26:31 UTC 2007
Author: frankie
Date: 2007-06-23 22:26:29 +0000 (Sat, 23 Jun 2007)
New Revision: 916
Added:
packages/openev/
packages/openev/branches/
packages/openev/branches/upstream/
packages/openev/branches/upstream/current/
packages/openev/branches/upstream/current/.cvsignore
packages/openev/branches/upstream/current/COPYING
packages/openev/branches/upstream/current/CVS/
packages/openev/branches/upstream/current/CVS/Entries
packages/openev/branches/upstream/current/CVS/Entries.Log
packages/openev/branches/upstream/current/CVS/Repository
packages/openev/branches/upstream/current/CVS/Root
packages/openev/branches/upstream/current/ChangeLog
packages/openev/branches/upstream/current/Makefile
packages/openev/branches/upstream/current/Makefile.in
packages/openev/branches/upstream/current/TODO
packages/openev/branches/upstream/current/aclocal.m4
packages/openev/branches/upstream/current/appcurlayer.c
packages/openev/branches/upstream/current/appcurlayer.h
packages/openev/branches/upstream/current/configure
packages/openev/branches/upstream/current/configure.in
packages/openev/branches/upstream/current/contrib/
packages/openev/branches/upstream/current/contrib/S52/
packages/openev/branches/upstream/current/contrib/S52/COPYING
packages/openev/branches/upstream/current/contrib/S52/ChangeLog
packages/openev/branches/upstream/current/contrib/S52/Makefile
packages/openev/branches/upstream/current/contrib/S52/README
packages/openev/branches/upstream/current/contrib/S52/S52.c
packages/openev/branches/upstream/current/contrib/S52/S52.h
packages/openev/branches/upstream/current/contrib/S52/S52CS.c
packages/openev/branches/upstream/current/contrib/S52/S52CS.h
packages/openev/branches/upstream/current/contrib/S52/S52GL.c
packages/openev/branches/upstream/current/contrib/S52/S52GL.h
packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp
packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp.h
packages/openev/branches/upstream/current/contrib/S52/S52OSG.h
packages/openev/branches/upstream/current/contrib/S52/S52PL.c
packages/openev/branches/upstream/current/contrib/S52/S52PL.h
packages/openev/branches/upstream/current/contrib/S52/S52glxsimple.c
packages/openev/branches/upstream/current/contrib/S52/S52raz-3.2.rle
packages/openev/branches/upstream/current/contrib/S52/S52raz.s
packages/openev/branches/upstream/current/contrib/S52/S52type.h
packages/openev/branches/upstream/current/contrib/S52/S52utils.c
packages/openev/branches/upstream/current/contrib/S52/S52utils.h
packages/openev/branches/upstream/current/contrib/S52/S57data.c
packages/openev/branches/upstream/current/contrib/S52/S57data.h
packages/openev/branches/upstream/current/contrib/S52/S57gv.c
packages/openev/branches/upstream/current/contrib/S52/S57gv.h
packages/openev/branches/upstream/current/contrib/S52/S57ogr.c
packages/openev/branches/upstream/current/contrib/S52/S57ogr.h
packages/openev/branches/upstream/current/contrib/S52/TODO
packages/openev/branches/upstream/current/contrib/S52/doc/
packages/openev/branches/upstream/current/contrib/S52/doc/C1.lup_collision.txt
packages/openev/branches/upstream/current/contrib/S52/doc/att.txt
packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.dia
packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.png
packages/openev/branches/upstream/current/contrib/S52/doc/libS52-layout.dia
packages/openev/branches/upstream/current/contrib/S52/doc/obj.txt
packages/openev/branches/upstream/current/contrib/S52/ex0_xwin.c
packages/openev/branches/upstream/current/contrib/S52/gvS57layer.c
packages/openev/branches/upstream/current/contrib/S52/gvS57layer.h
packages/openev/branches/upstream/current/contrib/S52/ogrS57layers.c
packages/openev/branches/upstream/current/contrib/S52/s52test.c
packages/openev/branches/upstream/current/contrib/S52/s52test.conf
packages/openev/branches/upstream/current/crs.c
packages/openev/branches/upstream/current/crs.h
packages/openev/branches/upstream/current/dbfopen.c
packages/openev/branches/upstream/current/delivery/
packages/openev/branches/upstream/current/delivery/CVS/
packages/openev/branches/upstream/current/delivery/CVS/Entries
packages/openev/branches/upstream/current/delivery/CVS/Repository
packages/openev/branches/upstream/current/delivery/CVS/Root
packages/openev/branches/upstream/current/delivery/INSTALL.TXT
packages/openev/branches/upstream/current/delivery/install
packages/openev/branches/upstream/current/delivery/license.txt
packages/openev/branches/upstream/current/delivery/mkdist
packages/openev/branches/upstream/current/delivery/mksrcdist.sh
packages/openev/branches/upstream/current/delivery/package
packages/openev/branches/upstream/current/delivery/setup_openev
packages/openev/branches/upstream/current/doc/
packages/openev/branches/upstream/current/doc/CVS/
packages/openev/branches/upstream/current/doc/CVS/Entries
packages/openev/branches/upstream/current/doc/CVS/Repository
packages/openev/branches/upstream/current/doc/CVS/Root
packages/openev/branches/upstream/current/doc/Makefile
packages/openev/branches/upstream/current/doc/asilogo.eps
packages/openev/branches/upstream/current/doc/future.tex
packages/openev/branches/upstream/current/doc/gvclass.fig
packages/openev/branches/upstream/current/doc/gvdata.fig
packages/openev/branches/upstream/current/doc/l2h-init.perl
packages/openev/branches/upstream/current/doc/layerdlg.eps
packages/openev/branches/upstream/current/doc/lodgen.fig
packages/openev/branches/upstream/current/doc/openev.tex
packages/openev/branches/upstream/current/doc/openev_bigpicture.fig
packages/openev/branches/upstream/current/doc/openevlogo.eps
packages/openev/branches/upstream/current/doc/openevreport.cls
packages/openev/branches/upstream/current/doc/openevreport.perl
packages/openev/branches/upstream/current/doc/phaseclip.fig
packages/openev/branches/upstream/current/doc/toolbar.eps
packages/openev/branches/upstream/current/gextra.c
packages/openev/branches/upstream/current/gextra.h
packages/openev/branches/upstream/current/gtkcolorwell.c
packages/openev/branches/upstream/current/gtkcolorwell.h
packages/openev/branches/upstream/current/gv_config.h.in
packages/openev/branches/upstream/current/gv_config.h_win32
packages/openev/branches/upstream/current/gvarealayer.c
packages/openev/branches/upstream/current/gvarealayer.h
packages/openev/branches/upstream/current/gvareas.c
packages/openev/branches/upstream/current/gvareas.h
packages/openev/branches/upstream/current/gvareatool.c
packages/openev/branches/upstream/current/gvareatool.h
packages/openev/branches/upstream/current/gvautopan.c
packages/openev/branches/upstream/current/gvautopan.h
packages/openev/branches/upstream/current/gvdata.c
packages/openev/branches/upstream/current/gvdata.h
packages/openev/branches/upstream/current/gview.h
packages/openev/branches/upstream/current/gvlayer.c
packages/openev/branches/upstream/current/gvlayer.h
packages/openev/branches/upstream/current/gvlinelayer.c
packages/openev/branches/upstream/current/gvlinelayer.h
packages/openev/branches/upstream/current/gvlinetool.c
packages/openev/branches/upstream/current/gvlinetool.h
packages/openev/branches/upstream/current/gvmanager.c
packages/openev/branches/upstream/current/gvmanager.h
packages/openev/branches/upstream/current/gvmesh.c
packages/openev/branches/upstream/current/gvmesh.h
packages/openev/branches/upstream/current/gvnodetool.c
packages/openev/branches/upstream/current/gvnodetool.h
packages/openev/branches/upstream/current/gvogr.c
packages/openev/branches/upstream/current/gvpointlayer.c
packages/openev/branches/upstream/current/gvpointlayer.h
packages/openev/branches/upstream/current/gvpoints.c
packages/openev/branches/upstream/current/gvpoints.h
packages/openev/branches/upstream/current/gvpointtool.c
packages/openev/branches/upstream/current/gvpointtool.h
packages/openev/branches/upstream/current/gvpoitool.c
packages/openev/branches/upstream/current/gvpoitool.h
packages/openev/branches/upstream/current/gvpolylines.c
packages/openev/branches/upstream/current/gvpolylines.h
packages/openev/branches/upstream/current/gvpquerylayer.c
packages/openev/branches/upstream/current/gvpquerylayer.h
packages/openev/branches/upstream/current/gvprint.c
packages/openev/branches/upstream/current/gvproperties.c
packages/openev/branches/upstream/current/gvproperties.h
packages/openev/branches/upstream/current/gvraster.c
packages/openev/branches/upstream/current/gvraster.h
packages/openev/branches/upstream/current/gvrasteraverage.c
packages/openev/branches/upstream/current/gvrasteraverage.h
packages/openev/branches/upstream/current/gvrastercache.c
packages/openev/branches/upstream/current/gvrastercache.h
packages/openev/branches/upstream/current/gvrasterconvert.c
packages/openev/branches/upstream/current/gvrasterize.c
packages/openev/branches/upstream/current/gvrasterize.h
packages/openev/branches/upstream/current/gvrasterlayer.c
packages/openev/branches/upstream/current/gvrasterlayer.h
packages/openev/branches/upstream/current/gvrasterlut.c
packages/openev/branches/upstream/current/gvrasterlut.h
packages/openev/branches/upstream/current/gvrastersource.c
packages/openev/branches/upstream/current/gvrastertypes.h
packages/openev/branches/upstream/current/gvrecords.c
packages/openev/branches/upstream/current/gvrecords.h
packages/openev/branches/upstream/current/gvrecttool.c
packages/openev/branches/upstream/current/gvrecttool.h
packages/openev/branches/upstream/current/gvrenderinfo.c
packages/openev/branches/upstream/current/gvrenderinfo.h
packages/openev/branches/upstream/current/gvroitool.c
packages/openev/branches/upstream/current/gvroitool.h
packages/openev/branches/upstream/current/gvrotatetool.c
packages/openev/branches/upstream/current/gvrotatetool.h
packages/openev/branches/upstream/current/gvselecttool.c
packages/openev/branches/upstream/current/gvselecttool.h
packages/openev/branches/upstream/current/gvshape.c
packages/openev/branches/upstream/current/gvshapefile.c
packages/openev/branches/upstream/current/gvshapelayer.c
packages/openev/branches/upstream/current/gvshapelayer.h
packages/openev/branches/upstream/current/gvshapes.c
packages/openev/branches/upstream/current/gvshapes.h
packages/openev/branches/upstream/current/gvshapeslayer.c
packages/openev/branches/upstream/current/gvshapeslayer.h
packages/openev/branches/upstream/current/gvskirt.c
packages/openev/branches/upstream/current/gvsymbolmanager.c
packages/openev/branches/upstream/current/gvsymbolmanager.h
packages/openev/branches/upstream/current/gvtess.c
packages/openev/branches/upstream/current/gvtess.h
packages/openev/branches/upstream/current/gvtessshape.c
packages/openev/branches/upstream/current/gvtexturecache.c
packages/openev/branches/upstream/current/gvtool.c
packages/openev/branches/upstream/current/gvtool.h
packages/openev/branches/upstream/current/gvtoolbox.c
packages/openev/branches/upstream/current/gvtoolbox.h
packages/openev/branches/upstream/current/gvtracktool.c
packages/openev/branches/upstream/current/gvtracktool.h
packages/openev/branches/upstream/current/gvtypes.h
packages/openev/branches/upstream/current/gvundo.c
packages/openev/branches/upstream/current/gvundo.h
packages/openev/branches/upstream/current/gvutils.c
packages/openev/branches/upstream/current/gvutils.h
packages/openev/branches/upstream/current/gvviewarea.c
packages/openev/branches/upstream/current/gvviewarea.h
packages/openev/branches/upstream/current/gvviewlink.c
packages/openev/branches/upstream/current/gvviewlink.h
packages/openev/branches/upstream/current/gvwinprint.c
packages/openev/branches/upstream/current/gvzoompantool.c
packages/openev/branches/upstream/current/gvzoompantool.h
packages/openev/branches/upstream/current/html/
packages/openev/branches/upstream/current/html/CVS/
packages/openev/branches/upstream/current/html/CVS/Entries
packages/openev/branches/upstream/current/html/CVS/Entries.Log
packages/openev/branches/upstream/current/html/CVS/Repository
packages/openev/branches/upstream/current/html/CVS/Root
packages/openev/branches/upstream/current/html/Tool_Export.html
packages/openev/branches/upstream/current/html/busy.gif
packages/openev/branches/upstream/current/html/classify.gif
packages/openev/branches/upstream/current/html/customization.html
packages/openev/branches/upstream/current/html/developer_info/
packages/openev/branches/upstream/current/html/developer_info/COURSE1_big_picture.png
packages/openev/branches/upstream/current/html/developer_info/COURSE1_gdal_datamodel.html
packages/openev/branches/upstream/current/html/developer_info/COURSE1_lib_inherit.gif
packages/openev/branches/upstream/current/html/developer_info/COURSE1_numpy.html
packages/openev/branches/upstream/current/html/developer_info/COURSE1_oev_talk.html
packages/openev/branches/upstream/current/html/developer_info/COURSE1_openev.html
packages/openev/branches/upstream/current/html/developer_info/COURSE1_python.html
packages/openev/branches/upstream/current/html/developer_info/COURSE1_test.png
packages/openev/branches/upstream/current/html/developer_info/CVS/
packages/openev/branches/upstream/current/html/developer_info/CVS/Entries
packages/openev/branches/upstream/current/html/developer_info/CVS/Repository
packages/openev/branches/upstream/current/html/developer_info/CVS/Root
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_building_maintenance.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_classify_example.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.tif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_components.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_gdal.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_greyscale_raster.tif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss2.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss3.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss4.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss5.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_mini_raster.tif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss2.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss3.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_openev_files.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.dbf
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shp
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shx
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_print_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_example.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss2.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss3.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss4.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss5.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_python_bindings.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss2.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss3.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss4.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_scripts.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.dbf
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shp
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shx
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shapefile_ss1.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_subpixel_interpolation.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tools_commands.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial1.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial2.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial3.html
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.dbf
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shp
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shx
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classify.gif
packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_layerstyles.gif
packages/openev/branches/upstream/current/html/developer_info/pyshell_example.gif
packages/openev/branches/upstream/current/html/developer_info/pyshell_full.gif
packages/openev/branches/upstream/current/html/developer_info/pyshell_help.gif
packages/openev/branches/upstream/current/html/edittools.gif
packages/openev/branches/upstream/current/html/edittools.html
packages/openev/branches/upstream/current/html/equalize.gif
packages/openev/branches/upstream/current/html/exporttool_advgui.gif
packages/openev/branches/upstream/current/html/exporttool_basicgui.gif
packages/openev/branches/upstream/current/html/files.html
packages/openev/branches/upstream/current/html/gvogrdlg.gif
packages/openev/branches/upstream/current/html/gvpquerypropdlg.html
packages/openev/branches/upstream/current/html/gvpquerypropdlg_drawstyle.gif
packages/openev/branches/upstream/current/html/gvpquerypropdlg_general.gif
packages/openev/branches/upstream/current/html/gvprint.gif
packages/openev/branches/upstream/current/html/gvprint.html
packages/openev/branches/upstream/current/html/gvrasterpropdlg.html
packages/openev/branches/upstream/current/html/gvrasterpropdlg_drawstyle.gif
packages/openev/branches/upstream/current/html/gvrasterpropdlg_general.gif
packages/openev/branches/upstream/current/html/gvrasterpropdlg_imageinfo.gif
packages/openev/branches/upstream/current/html/gvrasterpropdlg_lut.jpg
packages/openev/branches/upstream/current/html/gvrasterpropdlg_source.gif
packages/openev/branches/upstream/current/html/gvvectorpropdlg.html
packages/openev/branches/upstream/current/html/gvvectorpropdlg_drawstyle.gif
packages/openev/branches/upstream/current/html/gvvectorpropdlg_general.gif
packages/openev/branches/upstream/current/html/help.gif
packages/openev/branches/upstream/current/html/idle.gif
packages/openev/branches/upstream/current/html/layerdlg.gif
packages/openev/branches/upstream/current/html/layerdlg.html
packages/openev/branches/upstream/current/html/layerdlg_delete.gif
packages/openev/branches/upstream/current/html/layerdlg_lower.gif
packages/openev/branches/upstream/current/html/layerdlg_new.gif
packages/openev/branches/upstream/current/html/layerdlg_raise.gif
packages/openev/branches/upstream/current/html/legend.gif
packages/openev/branches/upstream/current/html/linear.gif
packages/openev/branches/upstream/current/html/log.gif
packages/openev/branches/upstream/current/html/logo.jpg
packages/openev/branches/upstream/current/html/mainwindow.gif
packages/openev/branches/upstream/current/html/mainwindow.html
packages/openev/branches/upstream/current/html/nonelut.gif
packages/openev/branches/upstream/current/html/onetoone.gif
packages/openev/branches/upstream/current/html/open3d.gif
packages/openev/branches/upstream/current/html/open3d.html
packages/openev/branches/upstream/current/html/openevmain.html
packages/openev/branches/upstream/current/html/openfile.gif
packages/openev/branches/upstream/current/html/performance.html
packages/openev/branches/upstream/current/html/pref_cache.gif
packages/openev/branches/upstream/current/html/pref_help.gif
packages/openev/branches/upstream/current/html/pref_raster.gif
packages/openev/branches/upstream/current/html/pref_tracking.gif
packages/openev/branches/upstream/current/html/preferences.html
packages/openev/branches/upstream/current/html/print.gif
packages/openev/branches/upstream/current/html/pyshell.html
packages/openev/branches/upstream/current/html/pyshell_default.gif
packages/openev/branches/upstream/current/html/refresh.gif
packages/openev/branches/upstream/current/html/rotatetool.gif
packages/openev/branches/upstream/current/html/seeall.gif
packages/openev/branches/upstream/current/html/tool_hist.gif
packages/openev/branches/upstream/current/html/tool_roigeneral.gif
packages/openev/branches/upstream/current/html/tools_openev.gif
packages/openev/branches/upstream/current/html/veclayerselect.html
packages/openev/branches/upstream/current/html/viewarea_keys.html
packages/openev/branches/upstream/current/html/windowed.gif
packages/openev/branches/upstream/current/html/worldg.gif
packages/openev/branches/upstream/current/html/worldrgb.gif
packages/openev/branches/upstream/current/html/zoom_control.gif
packages/openev/branches/upstream/current/html/zoomin.gif
packages/openev/branches/upstream/current/html/zoomout.gif
packages/openev/branches/upstream/current/install-sh
packages/openev/branches/upstream/current/invdistance.c
packages/openev/branches/upstream/current/invdistance.h
packages/openev/branches/upstream/current/ipgcplayer.c
packages/openev/branches/upstream/current/ipgcplayer.h
packages/openev/branches/upstream/current/llrasterize.c
packages/openev/branches/upstream/current/makefile.vc
packages/openev/branches/upstream/current/nmake.opt
packages/openev/branches/upstream/current/pics/
packages/openev/branches/upstream/current/pics/CVS/
packages/openev/branches/upstream/current/pics/CVS/Entries
packages/openev/branches/upstream/current/pics/CVS/Repository
packages/openev/branches/upstream/current/pics/CVS/Root
packages/openev/branches/upstream/current/pics/atlantis_logo.xpm
packages/openev/branches/upstream/current/pics/busy.xpm
packages/openev/branches/upstream/current/pics/ck_off_l.xpm
packages/openev/branches/upstream/current/pics/ck_on_l.xpm
packages/openev/branches/upstream/current/pics/classify.xpm
packages/openev/branches/upstream/current/pics/delete.xpm
packages/openev/branches/upstream/current/pics/equalize.xpm
packages/openev/branches/upstream/current/pics/eye.xpm
packages/openev/branches/upstream/current/pics/geo_innovation.xpm
packages/openev/branches/upstream/current/pics/help.xpm
packages/openev/branches/upstream/current/pics/idle.xpm
packages/openev/branches/upstream/current/pics/legend.xpm
packages/openev/branches/upstream/current/pics/linear.xpm
packages/openev/branches/upstream/current/pics/log.xpm
packages/openev/branches/upstream/current/pics/lower.xpm
packages/openev/branches/upstream/current/pics/new.xpm
packages/openev/branches/upstream/current/pics/node_cursor.xbm
packages/openev/branches/upstream/current/pics/node_cursor_mask.xbm
packages/openev/branches/upstream/current/pics/nonelut.xpm
packages/openev/branches/upstream/current/pics/onetoone.xpm
packages/openev/branches/upstream/current/pics/openev.xpm
packages/openev/branches/upstream/current/pics/openfile.xpm
packages/openev/branches/upstream/current/pics/pan_left.xpm
packages/openev/branches/upstream/current/pics/pan_rght.xpm
packages/openev/branches/upstream/current/pics/print.xpm
packages/openev/branches/upstream/current/pics/raise.xpm
packages/openev/branches/upstream/current/pics/recenter.xpm
packages/openev/branches/upstream/current/pics/refresh.xpm
packages/openev/branches/upstream/current/pics/root.xpm
packages/openev/branches/upstream/current/pics/save.xpm
packages/openev/branches/upstream/current/pics/seeall.xpm
packages/openev/branches/upstream/current/pics/sym_circle.xpm
packages/openev/branches/upstream/current/pics/sym_cross.xpm
packages/openev/branches/upstream/current/pics/sym_filled_circle.xpm
packages/openev/branches/upstream/current/pics/sym_filled_square.xpm
packages/openev/branches/upstream/current/pics/sym_filled_star.xpm
packages/openev/branches/upstream/current/pics/sym_filled_triangle.xpm
packages/openev/branches/upstream/current/pics/sym_square.xpm
packages/openev/branches/upstream/current/pics/sym_star.xpm
packages/openev/branches/upstream/current/pics/sym_triangle.xpm
packages/openev/branches/upstream/current/pics/sym_vertical.xpm
packages/openev/branches/upstream/current/pics/sym_x.xpm
packages/openev/branches/upstream/current/pics/vexcel_logo.xpm
packages/openev/branches/upstream/current/pics/warning.xpm
packages/openev/branches/upstream/current/pics/windowed.xpm
packages/openev/branches/upstream/current/pics/worldg.xpm
packages/openev/branches/upstream/current/pics/worldrgb.xpm
packages/openev/branches/upstream/current/pics/zoomin.xpm
packages/openev/branches/upstream/current/pics/zoomout.xpm
packages/openev/branches/upstream/current/pics/zoomrect.xpm
packages/openev/branches/upstream/current/pymod/
packages/openev/branches/upstream/current/pymod/.cvsignore
packages/openev/branches/upstream/current/pymod/CVS/
packages/openev/branches/upstream/current/pymod/CVS/Entries
packages/openev/branches/upstream/current/pymod/CVS/Repository
packages/openev/branches/upstream/current/pymod/CVS/Root
packages/openev/branches/upstream/current/pymod/Makefile.in
packages/openev/branches/upstream/current/pymod/_gtkmissing.def
packages/openev/branches/upstream/current/pymod/_gview.def
packages/openev/branches/upstream/current/pymod/filedlg.py
packages/openev/branches/upstream/current/pymod/generate.py
packages/openev/branches/upstream/current/pymod/gtkmissing.c
packages/openev/branches/upstream/current/pymod/gtkmissing.py
packages/openev/branches/upstream/current/pymod/gv.defs
packages/openev/branches/upstream/current/pymod/gv_ciet.c
packages/openev/branches/upstream/current/pymod/gvalg.py
packages/openev/branches/upstream/current/pymod/gvbitlayerlut.py
packages/openev/branches/upstream/current/pymod/gvclassification.py
packages/openev/branches/upstream/current/pymod/gvclassifydlg.py
packages/openev/branches/upstream/current/pymod/gvcommand.py
packages/openev/branches/upstream/current/pymod/gvconst.py
packages/openev/branches/upstream/current/pymod/gvcorecmds.py
packages/openev/branches/upstream/current/pymod/gvhtml.py
packages/openev/branches/upstream/current/pymod/gview.py
packages/openev/branches/upstream/current/pymod/gviewapp.py
packages/openev/branches/upstream/current/pymod/gvlabeledit.py
packages/openev/branches/upstream/current/pymod/gvlegenddlg.py
packages/openev/branches/upstream/current/pymod/gvmaptools.py
packages/openev/branches/upstream/current/pymod/gvmodule.c
packages/openev/branches/upstream/current/pymod/gvmodule_defs.c
packages/openev/branches/upstream/current/pymod/gvmodule_impl.c
packages/openev/branches/upstream/current/pymod/gvogrdlg.py
packages/openev/branches/upstream/current/pymod/gvogrfs.py
packages/openev/branches/upstream/current/pymod/gvogrfsgui.py
packages/openev/branches/upstream/current/pymod/gvplot.py
packages/openev/branches/upstream/current/pymod/gvpquerypropdlg.py
packages/openev/branches/upstream/current/pymod/gvprint.py
packages/openev/branches/upstream/current/pymod/gvrasterpropdlg.py
packages/openev/branches/upstream/current/pymod/gvsdsdlg.py
packages/openev/branches/upstream/current/pymod/gvselbrowser.py
packages/openev/branches/upstream/current/pymod/gvshell.py
packages/openev/branches/upstream/current/pymod/gvsignaler.py
packages/openev/branches/upstream/current/pymod/gvutils.py
packages/openev/branches/upstream/current/pymod/gvvectorpropdlg.py
packages/openev/branches/upstream/current/pymod/gvviewwindow.py
packages/openev/branches/upstream/current/pymod/ibrowse.py
packages/openev/branches/upstream/current/pymod/layerdlg.py
packages/openev/branches/upstream/current/pymod/makefile.vc
packages/openev/branches/upstream/current/pymod/mkgv.py
packages/openev/branches/upstream/current/pymod/nls.py
packages/openev/branches/upstream/current/pymod/oe_about.py
packages/openev/branches/upstream/current/pymod/oeattedit.py
packages/openev/branches/upstream/current/pymod/openev.py
packages/openev/branches/upstream/current/pymod/pathutils.py
packages/openev/branches/upstream/current/pymod/pgu.py
packages/openev/branches/upstream/current/pymod/pgucolor.py
packages/openev/branches/upstream/current/pymod/pgucolorsel.py
packages/openev/branches/upstream/current/pymod/pgucolourswatch.py
packages/openev/branches/upstream/current/pymod/pgucombo.py
packages/openev/branches/upstream/current/pymod/pguentry.py
packages/openev/branches/upstream/current/pymod/pgufilesel.py
packages/openev/branches/upstream/current/pymod/pgufont.py
packages/openev/branches/upstream/current/pymod/pgugrid.py
packages/openev/branches/upstream/current/pymod/pgumenu.py
packages/openev/branches/upstream/current/pymod/pguprogress.py
packages/openev/branches/upstream/current/pymod/pgushapesgrid.py
packages/openev/branches/upstream/current/pymod/pgutextarea.py
packages/openev/branches/upstream/current/pymod/pgutogglebutton.py
packages/openev/branches/upstream/current/pymod/pyshell.py
packages/openev/branches/upstream/current/pymod/scmexpr.py
packages/openev/branches/upstream/current/pymod/testmain.py
packages/openev/branches/upstream/current/pymod/toolexample.py
packages/openev/branches/upstream/current/pymod/toolfile_example.txt
packages/openev/branches/upstream/current/pymod/vecplot.py
packages/openev/branches/upstream/current/pymod/vrtutils.py
packages/openev/branches/upstream/current/ramps/
packages/openev/branches/upstream/current/ramps/CVS/
packages/openev/branches/upstream/current/ramps/CVS/Entries
packages/openev/branches/upstream/current/ramps/CVS/Repository
packages/openev/branches/upstream/current/ramps/CVS/Root
packages/openev/branches/upstream/current/ramps/blue_green_ramp.txt
packages/openev/branches/upstream/current/ramps/blue_ramp.txt
packages/openev/branches/upstream/current/ramps/blue_white_red_ramp.txt
packages/openev/branches/upstream/current/ramps/brown_ramp.txt
packages/openev/branches/upstream/current/ramps/cyan_ramp.txt
packages/openev/branches/upstream/current/ramps/discrete_1.txt
packages/openev/branches/upstream/current/ramps/discrete_2.txt
packages/openev/branches/upstream/current/ramps/gray_ramp.txt
packages/openev/branches/upstream/current/ramps/green_ramp.txt
packages/openev/branches/upstream/current/ramps/green_yellow_red_ramp.txt
packages/openev/branches/upstream/current/ramps/lavender_ramp.txt
packages/openev/branches/upstream/current/ramps/orange_brown_ramp.txt
packages/openev/branches/upstream/current/ramps/orange_ramp.txt
packages/openev/branches/upstream/current/ramps/pink_red_ramp.txt
packages/openev/branches/upstream/current/ramps/purple_ramp.txt
packages/openev/branches/upstream/current/ramps/real_blue_ramp.txt
packages/openev/branches/upstream/current/ramps/real_red_ramp.txt
packages/openev/branches/upstream/current/ramps/red_blue_ramp.txt
packages/openev/branches/upstream/current/ramps/red_green_ramp.txt
packages/openev/branches/upstream/current/ramps/red_ramp.txt
packages/openev/branches/upstream/current/ramps/rose_red_ramp.txt
packages/openev/branches/upstream/current/ramps/yellow_ramp.txt
packages/openev/branches/upstream/current/shapefil.h
packages/openev/branches/upstream/current/shpopen.c
packages/openev/branches/upstream/current/symbols/
packages/openev/branches/upstream/current/symbols/CVS/
packages/openev/branches/upstream/current/symbols/CVS/Entries
packages/openev/branches/upstream/current/symbols/CVS/Repository
packages/openev/branches/upstream/current/symbols/CVS/Root
packages/openev/branches/upstream/current/symbols/circle.xml
packages/openev/branches/upstream/current/symbols/circle_filled.xml
packages/openev/branches/upstream/current/symbols/cross.xml
packages/openev/branches/upstream/current/symbols/dash.xml
packages/openev/branches/upstream/current/symbols/square.xml
packages/openev/branches/upstream/current/symbols/square_filled.xml
packages/openev/branches/upstream/current/symbols/triangle.xml
packages/openev/branches/upstream/current/symbols/triangle_filled.xml
packages/openev/branches/upstream/current/symbols/x.xml
packages/openev/branches/upstream/current/testmain.c
packages/openev/branches/upstream/current/tools/
packages/openev/branches/upstream/current/tools/.cvsignore
packages/openev/branches/upstream/current/tools/CVS/
packages/openev/branches/upstream/current/tools/CVS/Entries
packages/openev/branches/upstream/current/tools/CVS/Repository
packages/openev/branches/upstream/current/tools/CVS/Root
packages/openev/branches/upstream/current/tools/Tool_DriverList.py
packages/openev/branches/upstream/current/tools/Tool_Export.py
packages/openev/branches/upstream/current/tools/Tool_ShapesGrid.py
packages/openev/branches/upstream/current/tools/Tool_autopan.py
packages/openev/branches/upstream/current/tools/calculator.py
packages/openev/branches/upstream/current/tools/compose.py
packages/openev/branches/upstream/current/tools/fft.py
packages/openev/branches/upstream/current/tools/gvrastertools.py
packages/openev/branches/upstream/current/tools/imgproctemplate.py
packages/openev/branches/upstream/current/tools/isodata.py
packages/openev/branches/upstream/current/tools/mil_symbols.py
packages/openev/branches/upstream/current/tools/open_raw.py
packages/openev/branches/upstream/current/tools/open_subarea.py
packages/openev/branches/upstream/current/tools/rendertest.py
packages/openev/branches/upstream/current/xmlconfig/
packages/openev/branches/upstream/current/xmlconfig/CVS/
packages/openev/branches/upstream/current/xmlconfig/CVS/Entries
packages/openev/branches/upstream/current/xmlconfig/CVS/Repository
packages/openev/branches/upstream/current/xmlconfig/CVS/Root
packages/openev/branches/upstream/current/xmlconfig/DefaultIconFile.xml
packages/openev/branches/upstream/current/xmlconfig/DefaultMenuFile.xml
packages/openev/branches/upstream/current/xmlconfig/DefaultPyshellFile.xml
packages/openev/tags/
Log:
[svn-inject] Installing original source of openev
Added: packages/openev/branches/upstream/current/.cvsignore
===================================================================
--- packages/openev/branches/upstream/current/.cvsignore (rev 0)
+++ packages/openev/branches/upstream/current/.cvsignore 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,9 @@
+*.lib
+*.pdb
+*.exe
+*.ilk
+gv_config.h
+config.status
+config.log
+config.cache
+gvtest
Added: packages/openev/branches/upstream/current/COPYING
===================================================================
--- packages/openev/branches/upstream/current/COPYING (rev 0)
+++ packages/openev/branches/upstream/current/COPYING 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,438 @@
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
Added: packages/openev/branches/upstream/current/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,131 @@
+/.cvsignore/1.4/Tue Jul 25 14:22:32 2000//
+/COPYING/1.2/Sat Sep 16 14:03:43 2000//
+/ChangeLog/1.249/Fri Jan 14 15:46:09 2005//
+/Makefile/1.19/Mon Apr 5 05:09:49 2004//
+/Makefile.in/1.41/Thu Aug 18 03:28:36 2005//
+/TODO/1.18/Sun Jun 27 20:18:13 2004//
+/aclocal.m4/1.6/Tue Jan 20 16:05:55 2004//
+/appcurlayer.c/1.4/Thu Feb 27 03:59:21 2003//
+/appcurlayer.h/1.1/Fri Aug 25 20:02:22 2000//
+/configure/1.16/Thu Jun 24 21:09:58 2004//
+/configure.in/1.16/Thu Jun 24 21:09:58 2004//
+/crs.c/1.2/Fri Oct 26 13:14:24 2001//
+/crs.h/1.2/Fri Oct 26 13:14:24 2001//
+/dbfopen.c/1.4/Thu Sep 30 17:06:33 2004/-ko/
+/gextra.c/1.4/Tue Jun 20 13:26:54 2000//
+/gextra.h/1.4/Tue Jun 20 13:27:08 2000//
+/gtkcolorwell.c/1.7/Thu Sep 27 00:39:14 2001//
+/gtkcolorwell.h/1.3/Wed Sep 26 20:29:35 2001//
+/gv_config.h.in/1.3/Wed Jun 28 13:10:42 2000//
+/gv_config.h_win32/1.1/Sun Apr 16 21:59:14 2000//
+/gvarealayer.c/1.18/Mon Nov 4 21:42:06 2002//
+/gvarealayer.h/1.4/Tue Jun 20 13:27:08 2000//
+/gvareas.c/1.15/Mon Nov 4 21:42:06 2002//
+/gvareas.h/1.11/Mon Nov 4 21:42:06 2002//
+/gvareatool.c/1.25/Thu Oct 28 21:59:52 2004//
+/gvareatool.h/1.7/Thu Aug 10 15:56:53 2000//
+/gvautopan.c/1.3/Mon Sep 12 15:33:10 2005//
+/gvautopan.h/1.3/Mon Sep 12 15:33:10 2005//
+/gvdata.c/1.15/Fri Feb 7 20:06:49 2003//
+/gvdata.h/1.13/Fri Feb 7 20:06:49 2003//
+/gview.h/1.16/Tue Feb 22 13:22:36 2005//
+/gvlayer.c/1.13/Fri Oct 12 17:44:18 2001//
+/gvlayer.h/1.13/Fri Oct 12 17:44:18 2001//
+/gvlinelayer.c/1.12/Tue Nov 5 18:56:24 2002//
+/gvlinelayer.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvlinetool.c/1.19/Mon Nov 4 21:42:06 2002//
+/gvlinetool.h/1.6/Tue Jun 20 13:27:08 2000//
+/gvmanager.c/1.14/Tue Feb 10 15:38:30 2004//
+/gvmanager.h/1.6/Tue Feb 10 15:38:31 2004//
+/gvmesh.c/1.37/Tue Aug 30 12:31:32 2005//
+/gvmesh.h/1.19/Fri Apr 12 14:40:36 2002//
+/gvnodetool.c/1.13/Mon Nov 4 21:42:06 2002//
+/gvnodetool.h/1.4/Mon Sep 30 20:09:27 2002//
+/gvogr.c/1.5/Tue Jan 20 16:05:02 2004//
+/gvpointlayer.c/1.6/Tue Nov 5 18:56:24 2002//
+/gvpointlayer.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvpoints.c/1.7/Mon Nov 4 21:42:06 2002//
+/gvpoints.h/1.4/Mon Nov 4 21:42:06 2002//
+/gvpointtool.c/1.11/Mon Apr 9 18:15:20 2001//
+/gvpointtool.h/1.4/Tue Jun 20 13:27:08 2000//
+/gvpoitool.c/1.3/Tue Jan 14 16:16:24 2003//
+/gvpoitool.h/1.1/Thu Feb 28 18:52:22 2002//
+/gvpolylines.c/1.10/Tue Nov 5 18:56:21 2002//
+/gvpolylines.h/1.7/Mon Nov 4 21:42:06 2002//
+/gvpquerylayer.c/1.11/Fri Aug 20 13:53:47 2004//
+/gvpquerylayer.h/1.5/Fri Aug 20 13:53:48 2004//
+/gvprint.c/1.8/Thu Feb 15 16:36:51 2001//
+/gvproperties.c/1.5/Mon Sep 9 16:22:45 2002//
+/gvproperties.h/1.6/Mon Nov 4 21:42:06 2002//
+/gvraster.c/1.75/Mon Sep 20 13:15:35 2004//
+/gvraster.h/1.28/Thu Jan 22 19:57:11 2004//
+/gvrasteraverage.c/1.18/Wed Feb 18 16:07:27 2004//
+/gvrasteraverage.h/1.8/Tue Jul 24 02:21:54 2001//
+/gvrastercache.c/1.12/Tue Jun 20 13:26:55 2000//
+/gvrastercache.h/1.10/Tue Jun 20 13:27:08 2000//
+/gvrasterconvert.c/1.20/Wed Jun 23 14:35:03 2004//
+/gvrasterize.c/1.5/Fri Nov 19 23:59:37 2004//
+/gvrasterize.h/1.3/Fri Nov 19 23:59:37 2004//
+/gvrasterlayer.c/1.87/Tue Aug 30 12:44:11 2005//
+/gvrasterlayer.h/1.32/Wed Jun 23 14:35:05 2004//
+/gvrasterlut.c/1.31/Tue Aug 30 12:58:56 2005//
+/gvrasterlut.h/1.15/Tue Aug 30 12:58:56 2005//
+/gvrastersource.c/1.16/Wed Jun 23 14:35:05 2004//
+/gvrastertypes.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvrecords.c/1.5/Wed Aug 6 22:26:03 2003//
+/gvrecords.h/1.5/Wed Aug 6 22:26:03 2003//
+/gvrecttool.c/1.7/Mon Nov 4 21:42:06 2002//
+/gvrecttool.h/1.3/Thu Jul 27 20:06:23 2000//
+/gvrenderinfo.c/1.23/Wed Jun 25 16:42:18 2003//
+/gvrenderinfo.h/1.15/Wed Jun 25 16:42:18 2003//
+/gvroitool.c/1.11/Mon Nov 4 21:42:06 2002//
+/gvroitool.h/1.8/Thu Jul 27 20:06:23 2000//
+/gvrotatetool.c/1.2/Wed Jun 25 17:07:22 2003//
+/gvrotatetool.h/1.1/Wed Jun 25 16:40:44 2003//
+/gvselecttool.c/1.17/Tue Sep 16 15:43:11 2003//
+/gvselecttool.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvshape.c/1.21/Tue Jan 4 18:50:29 2005//
+/gvshapefile.c/1.21/Tue May 27 21:32:40 2003//
+/gvshapelayer.c/1.26/Fri May 16 18:26:33 2003//
+/gvshapelayer.h/1.11/Thu Feb 27 04:00:19 2003//
+/gvshapes.c/1.20/Fri Jan 14 16:51:51 2005//
+/gvshapes.h/1.26/Fri Jan 14 16:51:51 2005//
+/gvshapeslayer.c/1.73/Thu Apr 8 18:03:18 2004//
+/gvshapeslayer.h/1.18/Fri Sep 12 17:35:43 2003//
+/gvskirt.c/1.6/Mon Oct 7 06:08:07 2002//
+/gvsymbolmanager.c/1.12/Mon Feb 16 17:08:12 2004//
+/gvsymbolmanager.h/1.5/Tue Sep 2 17:25:08 2003//
+/gvtess.c/1.12/Tue Dec 10 02:57:33 2002//
+/gvtess.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvtessshape.c/1.11/Tue Feb 25 19:41:23 2003//
+/gvtexturecache.c/1.4/Thu Dec 13 03:29:17 2001//
+/gvtool.c/1.11/Mon Jan 17 18:37:43 2005//
+/gvtool.h/1.8/Mon Jan 17 18:37:43 2005//
+/gvtoolbox.c/1.8/Thu Aug 3 18:39:49 2000//
+/gvtoolbox.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvtracktool.c/1.8/Mon Nov 4 21:42:07 2002//
+/gvtracktool.h/1.2/Tue Jun 20 13:27:08 2000//
+/gvtypes.h/1.15/Fri Mar 5 23:40:12 2004//
+/gvundo.c/1.6/Mon Sep 30 20:50:32 2002//
+/gvundo.h/1.3/Tue Jun 20 13:27:08 2000//
+/gvutils.c/1.22/Wed Jun 23 14:35:05 2004//
+/gvutils.h/1.5/Sun Apr 22 17:32:25 2001//
+/gvviewarea.c/1.125/Fri Jan 14 15:27:26 2005//
+/gvviewarea.h/1.60/Fri Jan 14 15:27:28 2005//
+/gvviewlink.c/1.12/Tue Jan 18 19:55:42 2005//
+/gvviewlink.h/1.5/Fri Feb 21 22:35:31 2003//
+/gvwinprint.c/1.4/Tue May 1 19:21:51 2001//
+/gvzoompantool.c/1.7/Mon Jul 10 13:37:05 2000//
+/gvzoompantool.h/1.2/Tue Jun 20 13:27:08 2000//
+/install-sh/1.1/Mon Apr 5 02:18:04 2004//
+/invdistance.c/1.3/Sun Apr 22 17:33:24 2001//
+/invdistance.h/1.2/Sun Apr 22 17:33:24 2001//
+/ipgcplayer.c/1.15/Mon Feb 23 20:16:36 2004//
+/ipgcplayer.h/1.1/Fri Jul 14 18:24:57 2000//
+/llrasterize.c/1.9/Tue Nov 23 06:14:55 2004//
+/makefile.vc/1.31/Tue Feb 22 13:22:36 2005//
+/nmake.opt/1.3/Tue Feb 22 13:22:37 2005//
+/shapefil.h/1.4/Thu Sep 12 15:17:21 2002/-ko/
+/shpopen.c/1.3/Thu Sep 12 15:17:21 2002/-ko/
+/testmain.c/1.33/Wed Jun 25 17:52:08 2003//
+D
Added: packages/openev/branches/upstream/current/CVS/Entries.Log
===================================================================
--- packages/openev/branches/upstream/current/CVS/Entries.Log (rev 0)
+++ packages/openev/branches/upstream/current/CVS/Entries.Log 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,9 @@
+A D/delivery////
+A D/doc////
+A D/html////
+A D/pics////
+A D/pymod////
+A D/ramps////
+A D/symbols////
+A D/tools////
+A D/xmlconfig////
Added: packages/openev/branches/upstream/current/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev
Added: packages/openev/branches/upstream/current/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/ChangeLog
===================================================================
--- packages/openev/branches/upstream/current/ChangeLog (rev 0)
+++ packages/openev/branches/upstream/current/ChangeLog 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1254 @@
+2005-01-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gviewarea/gview: Added accessors on GvViewArea for flip flags,
+ and modified so they are saved/restored in project file.
+
+2004-10-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvviewwindow.py: added case for opening raster files
+ with 2 bands where the second is an alpha band. It creates it as
+ an RGBA layer.
+
+2004-09-30 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * dbfopen.c: updated DBFIsAttributeNULL with code from
+ equivalent file from gdal so that empty integer values will
+ be interpreted as NULLs (instead of 0).
+
+2004-09-20 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * gvraster.c: added patch for isnan support on win32
+
+2004-08-27 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * pymod/gvclassifydlg.py: changed use of repr to str to prevent
+ floating point numbers from having excessive decimal places. Also
+ modified the logic in the reclassify dialog to build the list of
+ choices in correct order (previously it came from dictionary keys)
+
+2004-08-20 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvpquerylayer.{c,h}, pymod/gv.defs, pymod/gview.py:
+ GvPqueryLayer() constructor accepts passed in GvShapes.
+ GvPqueryLayer now serializes and deserializes correctly.
+
+2004-08-17 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * pymod/gv_ciet.c, pymod/gvmodule.c: added function to return arbitrary
+ columns of a gvrecords object as a python dictionary
+
+2004-08-16 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * pymod/filedlg.py: modified handling of filters to repect order in which
+ they are specified when populating the dropdown list
+
+2004-07-24 Andrey Kiselev <dron at remotesensing.org>
+
+ * tools/fft.py: Added new 'Fast Fourier Transform' tool.
+
+ * pymod/gvprint.py: Added possibility to explicitly specify printed image
+ size; several GUI tweaks.
+
+2004-07-23 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * pymod/gvclassifydlg.py: restructured signals for OK and apply
+ to prevent a problem where listeners to the ok signal or classifcation
+ -changed signal could be called before the classification had actually
+ been applied to the layer
+
+2004-07-20 Paul Spencer <pspencer at dmsolutions.ca>
+
+ * pymod/filedly.py: added patch from Zak (zjames at dmsolutions.ca)
+ to handle manual input in a more reliable way
+
+ * pymod/pgufont.py: added ability to load a font and report statistics
+ on the font such as text width and height
+
+2004-07-02 Julien Demaria <dem at acri-st.fr>
+
+ * pymod/{gview.py, gviewapp.py, gvutils.py, gvviewwindow.py,
+ pathutils.py}: Enhance project files portability : now filesystem
+ filenames can be retrieved relatively to the project file if the
+ absolute path doesn't exist. Implement also path separator portability.
+ Use internally a PortablePath object (in pymod/pathutils.py).
+ Backward compatibility with old project files.
+ Tested between Linux, Solaris and Win32 systems.
+
+ * pymod/gview.py: last_strech restored in projects reloading
+
+ * pymod/gvutils: Change to don't crash OpenEV when a deserialization
+ of a layer fails in projects reloading.
+ Popup a gvutils.warning instead.
+
+ * pymod/gviewapp.py, xmlconfig/DefaultMenuFile.xml: add a
+ "File/Save Project as..." menu.
+
+ * pymod/gviewapp.py: Fixed a little bug in project filename saving :
+ .opf extension wasn't well added.
+
+2004-05-18 Andrey Kiselev <dron at remotesensing.org>
+
+ * tools/open_subarea.py: New 'Open Subarea' tool added.
+
+2004-05-12 Andrey Kiselev <dron at remotesensing.org>
+
+ * pymod/gvrasterpropdlg.py: Preliminary support for changing
+ projection on the fly.
+
+2004-05-12 Julien Demaria <dem at acri-st.fr>
+
+ * pymod/gvmodule.c: Fix a bug in _wrap_gv_raster_layer_get_mesh_lod :
+ this wrapper created a python double from a C int and then the
+ mesh_lod was wrong (example 223.454).
+ The wrapper now returns an int.
+ This bug crashed OpenEV when for example we save a project,
+ then reload it : if the wrong mesh is big on a lot of images of the
+ project, this uses a lot of memory and done an allocation error.
+ Note that all projects saved until this fix have wrong mesh_lods...
+
+2004-04-21 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvutils.c: Fix comparisons with NODATA value.
+
+ * pymod/gview.py: Fixed problem with reading NODATA value from
+ the project file.
+
+ * pymod/{gviewapp.py, gvviewwindow.py}: New option added: save
+ last visited directory in the config file.
+
+ * gvrastersource.c, pymod/gview.py: Fixed erroneous setting of the
+ minimum and maximum levels in greyscale lock mode as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=270
+
+2004-04-04 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Makefile.in: added various stuff related to installing into an
+ OpenEV style tree.
+
+2004-02-18 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvrastersource.c, pymod/gview.py: Fixed erroneous setting of the
+ minimum and maximum levels in greyscale lock mode as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=270
+
+ * gvmesh.c, gvrasteraverage.c: Use gv_raster_get_nodata() instead of
+ GDALGetRasterNoDataValue().
+
+2004-02-10 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvmanager.c, gvmanager.h, pymod/{gvmodule.c, gview.py,
+ gvviewwindow.py, gviewapp.py}: Added method open_gdal_dataset() to
+ load GDAL dataset without referencing by filename.
+
+2004-01-23 Andrey Kiselev <dron at remotesensing.org>
+
+ * pymod/gvrasterpropdlg.py: New control to display and change NODATA
+ value for viewed RasterSource.
+
+2004-01-22 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvraster.c, gvraster.h: Use gv_raster_get_nodata() function to fetch
+ the NODATA value from the image using GDALGetRasterNoDataValue().
+
+ * gvrastersource.c, gvrasterlayer.h: Added methods
+ gv_raster_layer_nodata_set() and gv_raster_layer_nodata_get() to work
+ with nodata_* layer properties and method gv_raster_layer_type_get()
+ to query raster data type.
+
+ * gvutils.c: gv_format_point_query() returns "[NODATA]" label if value
+ marked as NODATA.
+
+ * pymod/gviewapp.py: New switch to control displaying "[NODATA]" marks
+ in the tracker tool. Tweaks in 'Preferences' dialog.
+
+ * pymod/gview.py: New methods in GvRasterLayer class: nodata_get(),
+ nodata_set(), type_get(). get_nodata() method now deprecated (though,
+ it does the same as nodata_get).
+
+ * pymod/{gv.defs, gvmodule.c}: Added wrappers for
+ gv_raster_layer_nodata_set(), gv_raster_layer_nodata_get() and
+ gv_raster_layer_type_get().
+
+2003-06-25 Paul Spencer <pgs at magma.ca>
+
+ * gvshapes.c: added define of M_PI if not already defined.
+
+2003-05-27 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrenderinfo.c: Fixed support for getting ogr-pen-* pen names
+ from the "id" attribute as well as from the "p" pattern attribute.
+
+ * gvrecords.c: Added new support for efficient fixed schema/fixed
+ field length records. Not yet complete.
+
+ * gvshapefile.c: Added support for reading multi-part arcs as
+ a COLLECTION of lines.
+
+2003-05-22 Diana Esch-Mosher <desch-mosher at lanl.gov>
+
+ * pymod/gvutils.py: return from parse_accelerator
+ incorrectly shifted
+
+2003-05-08 Paul Spencer <pgs at magma.ca>
+
+ * gvviewarea.c: modified logic controlling adjustments
+ to use a step size of 1/4 the page size
+
+ * pymod/gvogrfs.py: fixed a bug when params had attributes
+ with no values.
+
+2003-04-09 Paul Spencer <pgs at magma.ca>
+
+ * gvrenderinfo.h,gvrenderinfo.c: added shadow, halo and
+ background color attributes to label tool
+
+ * gvshapelayer.c: added initialization of shadow, halo
+ and background color attributes to label tool
+
+ * gvshapeslayer.c: added rendering of halo and shadow
+ effects for label tool
+
+2003-04-08 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvsymbolmanager.c: Added gv_symbol_manager_save_vector_symbol()
+ function to save vector symbols with new names.
+
+2003-04-07 Andrey Kiselev <dron at remotesensing.org>
+
+ * gvsymbolmanager.c: gv_symbol_manager_get_symbol() now able
+ to load and inject vector symbols.
+
+2003-04-07 Paul Spencer <pgs at magma.ca>
+
+ * gvrenderinfo.h,gvrenderinfo.c: added pattern attribute to
+ pen objects
+
+ * gvshapelayer.c: added initialization of pattern attribute
+ on new pen objects
+
+ * gvshapeslayer.c: added rendering of patterns in pen objects
+
+2003-04-02 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvmodule.c, pymod/gview.py: added wrapper for
+ gv_format_point_query to gvmodule.c and added method to
+ GvViewArea to call it.
+
+2003-02-14 Paul Spencer <pgs at magma.ca>
+
+ * pymod/filedlg.py: added ability to allow users to select mulitple
+ files
+
+ * pymodpgutextarea.py: added page_up/page_down functions.
+
+ * gvrenderinfo.c, gvrenderinfo.h, gvshapelayer.c, gvshapeslayer.c added
+ support for line widths in PENs and _area_edge_width and _line_width
+
+ * pymod/gvvectorpropdlg.py: added support for _area_edge_width,
+ _line_width, and _gl_antialias
+
+2003-01-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvogr.c, pymod/gvviewwindow.py, pymod/gvogrdlg.py: added new dialog
+ to allow selection from amoung OGR layers, and loading using an
+ user SQL query.
+
+2002-11-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrenderinfo/gvshapeslayer.c: added support for LABEL anchor
+ (justification) attribute.
+
+2002-11-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvsymbolmanager.c: Incorporated Pauls GvSymbolManager object, and
+ support for raster symbols. Some work still outstanding.
+
+2002-10-30 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvraster.c: modified to fill partial tiles with data extended out
+ from the valid data. This fixes some esoteric "streaking" problems.
+
+2002-10-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvraster.c: Modified gv_raster_build_poly_transform() to
+ back off using the highest possible order polynomial if the
+ CRS_compute_georef_equations() call fails. This ensures that
+ underdetermined sets of GCPs (ie. those with linear dependencies)
+ can still produce useful polynomials, even if they are only 1st order.
+
+2002-09-30 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvnodetool.c, gvareatoolc, gvshapesfile.c: try to maintain closed
+ ring integrity while editing areas, and enforce it when saving to
+ shapefiles.
+
+ * gvshapeslayer.c: Fixed some quirks with display list support.
+ Ensure that selected shapes are drawn (get rid of hit_selected).
+ Also ensure that the display list is wiped in case of selection or
+ display change events.
+
+2002-09-27 Paul Spencer <pgs at magma.ca>
+
+ * gvshapeslayer.c, gvshapeslayer.h: added display lists to
+ speed up rendering of shapes layers and added antialiasing
+ support for line layers
+ * gvskirt.c: changed how skirts polygons are built and removed
+ the white lines.
+
+2002-09-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: Ensure depth buffer is cleared before doing
+ a render_to_func. This fixes problems printing 3D views at 1:1.
+
+2002-09-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * oeattedit.py: Gillian added the ability to create new fields.
+
+2002-09-11 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gview.py, etc: modifications so that 3D views can be saved to
+ project files, and restored properly.
+
+ * gvviewarea.c: ensure GL_NORMALIZE and GL_DEPTH_TEST are
+ disabled in 2D mode (gl_view_area_expose()).
+
+2002-09-10 Frank Warmerdam <warmerdam at pobox.com>
+
+ * added get_height_scale() method on GvViewArea.
+
+2002-08-09 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pgucombo.py: fixed a problem in set_popdown_strings
+
+ * pymod/pgucolor.py: added discrete color ramp support
+
+ * pymod/gvclassification.py and gvclassifydlg.py: finished vector
+ classification support started by Frank.
+
+2002-07-24 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Reimplemented the GvProperties using symbol tables and integer
+ quark ids. Must faster performance with many properties in one list.
+ Memory for strings never recovered, but only one copy of any given
+ string in the string table.
+
+2002-07-23 Paul Spencer <pgs at magma.ca>
+
+ * added pgutextarea.py, a simple scrollable text widget (read-only)
+
+2002-07-18 Paul Spencer <pgs at magma.ca>
+
+ * gvshapefile.c, gvshapes.h: added gv_shapes_to_dbf to allow a
+ GvShapes container's attributes to be saved directly to a DBF
+ file without needing to save the whole shape file.
+
+ * gvmodule.c: added wrapper for gv_shapes_to_dbf
+
+ * gview.py: added GvShapes.save_to_dbf()
+
+2002-07-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gviewapp.py, gvviewwindow.py: Added load/save project support.
+
+ * gvviewarea.c/h: Added properties to the GvViewArea.
+
+2002-05-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshape.c/gvshapes.c/gvshape.h/gvshapeslayer.c: Added partial
+ support for the new GVSHAPE_COLLECTION primitive type.
+
+2002-03-21 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrenderinfo/gvvectorpropdlg: Added concept of _gv_ogrfs_point,
+ _gv_ogrfs_line and _gv_ogrfs_area properties on GvShapesLayers to
+ indicate the styling for particular geometry types (as opposed to
+ the _gv_ogrfs which would apply to all). Use this for symbols and
+ labels in gvvectorpropdlg.py. This responds to 528432 on SourceForge.
+
+2002-03-20 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea/gvrasterlayer: added the render_exact flag to GvViewArea
+ indicating the proper resolution textures should be loaded and
+ used immediately rather than deferring their load till after the
+ current render. This is used by the printing engine to ensure
+ appropriate output.
+
+2002-03-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshape.c: added preliminary gv_shape_clip_to_rect() implementation.
+
+2002-03-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvmesh.c/gvshapes.c: added default_height argument to add_height()
+ functions. This is used when no value can be found for a mesh or
+ shape vertex.
+
+2002-02-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrenderinfo/gvshapelayer/gvshapeslayer: Added support for PEN and
+ BRUSH tools. Currently just gets color ... other styling is ignored.
+
+2002-01-30 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewlink.c: Implement more sophisticated state copying that is
+ aware of raw/geo, and projections. It also preserves viewstate shape.
+
+ * gvviewarea: added set_state() and get_primary_raster() methods.
+
+2002-01-18 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gview.py: added the GvShapes.get_extents() method.
+
+2002-01-17 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvselecttool.c: Fixed bug that was preventing shift-leftclick from
+ working to add/subtract a feature to/from the selection.
+
+2001-12-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvtexturecache.c/gvviewarea.c: avoid purging textures used within this
+ render operation. Avoid texture thrashing hell in at least some
+ situations.
+
+ * gvviewarea.c: fixed fit_all_layers to fetch/compute the volume
+ for the 3d view setting. Was uninitialized in some cases before.
+
+ * pymod/gvviewwindow.py: fixed invocation of 3d positioning dialog.
+
+ * html/*: updated mainwindow dialog and associated materials.
+
+2001-11-29 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvraster.c, gvrasterlayer.c: Add use of autoscale_samples to
+ determine the number of samples requested from a raster for scaling.
+ Currently there is no gui element to set this preference.
+
+2001-11-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterlayer.c: added mesh_is_dirty flag, and code to update mesh
+ on redraw if it is dirty. Flag is set on geotransform-changed signal
+ from prototype GvRaster.
+
+ * gvraster.c: added set_gcps(), get_gcps() and geotransform-changed
+ signal.
+
+2001-11-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/pyshell.py: fixed overwrite problem on windows using
+ freeze()/thaw() on text widget.
+
+2001-11-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gviewapp.py: moved GvViewApp and related code here from
+ openev.py.
+
+ * pymod/gvshell.py: moved shell instrinsics like display() and roi()
+ here from openev.py.
+
+ * pymod/pyshell.py: added locals pseudo-command to dump local vars.
+
+2001-11-09 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvogr.cpp: copy over style string as _gv_ogrfs if available.
+
+2001-11-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvmodule.c: fixed serious memory leak in
+ gv_shapes_get_properties.
+
+2001-10-25 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterlayer.c, pymod/openev.py: added support for a global
+ interp_mode preference to control the default subpixel interpolation
+ mode of raster layers on creation.
+
+2001-10-22 Paul Spencer <pgs at magma.ca>
+
+ * gvselecttool.c: in gv_selection_tool_deactivate(), moved call to
+ base class deactivate to after the tool specific deactivation to
+ ensure that the tool properly deregisters callbacks.
+
+2001-10-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: Call gv_view_area_state_changed() in
+ gv_view_area_add_layer() to ensure a refresh.
+ Bug 527 in DMSG Bugzilla.
+
+2001-10-17 Frank Warmerdam <warmerdam at pobox.com>
+
+ * added support for composing 2D complex PCT with 1D enhancement LUT.
+ GUI image enhancements now apply to complex layers as well.
+
+2001-10-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvviewwindow.py: added new enhancement options.
+
+ * pymod/gview.py: added various enhancement related stuff.
+
+ * gvrasterlayer.c: added autoscale and histogram functions on the
+ view.
+
+ * gvraster.c: autoscale() can now be passed a sample set.
+
+2001-10-12 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvrasterpropdlg.py: improved logic for setting the initial
+ min and max of the scaling controls.
+
+ * gviewarea.c/gvrasterlayer.c:
+
+ GvLayer's now maintain a pending_idle flag indicating if they have
+ pending idle work that will lead to a refined redraw.
+
+ GvViewArea's now establish a timer after a redraw to keep track of
+ the elapsed time since the last redraw. This can be used via
+ the gv_view_area_redraw_timeout() function for layer idle work handlers
+ to find out if it is time for an intermediate redraw.
+
+ The gv_view_area_pending_idle_work() function may be used to check
+ if there are layers with pending idle work for a view.
+
+ The GvRasterLayer idle work function now utilizes the above to ensure
+ that a redraw occurs only onces all idle work is finished or the
+ view wide timeout has occured. This prevents extra redraws from
+ occuring when many raster layers are displayed.
+
+2001-10-11 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: modified to avoid doing re-render on WIN32 if
+ the view hasn't really changed. This avoids slow rerenders with Mesa
+ on windows in response to window expose events generated by covering
+ dialogs.
+
+2001-09-26 Paul Spencer <pgs at magma.ca>
+
+ * gtkcolorwell.c: fixed drawing code in _set_ functions to eliminate
+ gtkcritical when changing color of a color well and fixed 'new' to
+ not try to resize the preview widget.
+
+ * gtkcolorwell.h: removed da member of gtkcolorwell class as it was
+ not referenced (related to above)
+
+2001-09-25 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterlayer.c: Ensure idle tasks are cleaned up in finalize.
+ Was causing occasional crashes.
+
+2001-09-17 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvogrfsgui.py: updated to work with ColorButton changes
+
+ * pymod/pgucolor.py: moved a couple of lines from ColorButton to
+ gtkmissing.py
+
+ * pymod/gtkmissing.py: added get_color and set_color to GtkColorWell
+
+ * pymod/gvmodule.c: removed extraneous initialization in gtk_color_well_get_d
+
+2001-09-16 Paul Spencer <pgs at magma.ca>
+
+ * gtkcolorwell.c: modified render to honour use_alpha setting and
+ modified gtk_color_well_set_* to only call render/draw if widget
+ is realized.
+
+ * pymod/gvmodule.c: removed extra declaration in gtk_color_well_get_d
+
+ * pymod/gtkmissing.py: added get_d to GtkColorWell
+
+ * pymod/pgucolor.py: removed GtkColorWell (in gtkmissing) and added
+ __init__ and get_color to ColorButton
+
+2001-09-15 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvmodule.c: added python bindings for gtk_color_well_get_d
+ function.
+
+ * pymod/pgucolor.py: added python wrapper class GtkColorWell and
+ modified ColorButton to extend GtkColorWell
+
+ * gtkcolorwell.c: modified render code to honour transparency
+ Note that this is not quite complete as it currently always
+ renders using transparency.
+
+2001-09-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gv.defs,gtkmissing.py: implement python bindings for
+ the GtkColorWell class.
+
+2001-08-23 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlabeledit.py: added default_ogrfs = None to __init__ to allow
+ caller to override the default ogr feature spec
+
+2001-08-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gv_raster_layer_lut_put(): If any of the palette values have a
+ non-255 alpha, enable alpha blending.
+
+ * gvmesh.c: Implement gv_mesh_reset_to_identity(). Use this
+ in gv_raster_layer_new() instead of reversing the geo to pixel
+ transform for cases where it isn't cleanly invertible.
+
+2001-08-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterconvert.c: fixed leakage of nodata_mask in convert
+ functions.
+
+2001-08-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * added standard deviation scaling support.
+
+2001-08-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshapefile.c: call SHPDestroyShape() on shapes after done converting
+ them into GvShapes.
+
+ * gvshape.c, etc: modified GvShape objects to be reference counted.
+ Python GvShape maintains a reference to the C GvShape while the
+ python object is alive. Resolves some serious memory leaks.
+
+ * gvmesh.c: fixed serious bug with edge tiles that are not of a
+ reduced size being collapsed to zero space. Affects images that
+ 508 wide for instance.
+
+ * gvrasterize.c: fixed leak of polyInts array.
+
+2001-08-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvdata.c: implemented gv_data_registry_dump() for debugging
+ creation and destruction of all GvData derived objects.
+
+ * gvmesh.c: implement finalize, remove normals support.
+
+ * pymod/gview.py: GvTool.get_view() now returns None if the view isn't
+ set yet.
+
+2001-08-07 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlabeledit.py: added code to pick out default colors for labels
+ and added a missing signal in the close() method
+
+2001-07-25 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvviewarea.py: fixed zoom ratio display so it is correct
+ when a layer is first loaded.
+
+2001-07-24 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterlut.c: added EV style 2D colormap for complex images.
+ Applied it in gvrasterpropdlg.py, gview.py, gvrasterlayer.c, etc.
+
+2001-07-23 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasteraverage.c: added 8bit averaging scheme that works for
+ scaled phase.
+
+2001-07-17 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: fixed bug with flip_y introduced in mesh_is_raw
+ changing support.
+
+2001-07-13 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvskirt.c: new - build 3D skirt for raster layer.
+
+ * gvmesh.c: added gv_mesh_get_height().
+
+2001-07-03 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c/gvrasterlayer.c: Added gv_*_{set,get}_raw() support.
+
+2001-06-30 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvogrfsgui.py - hacked around an artefact of GtkSpinBox to
+ make the x and y offset widgets editable by hand.
+
+ * pymod/gvclassificationdlg.py - modified the Ramp Menu to ensure
+ first item is visible (sometimes it was not rendering correctly).
+
+ * pymod/gvlegenddlg.py - modified window resize logic to layout the
+ legend more accurately when the window is resized.
+
+2001-06-27 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/openev.py, pymod/gvviewwindow.py, pymod/gvsdsdlg.py:
+
+ Add GDAL subdataset selection dialog, mostly for OGDI.
+
+2001-06-25 Gillian Walters <gwalter at atlsci.com>
+
+ * I've updated mkdist, install, and package in the openev/delivery
+ directory. The changes I've made are:
+
+ 1) updated the python1.5 copies/compiles to python2.1
+ 2) added the ramps directory
+ 3) changed the old copy paths to the ones appropriate for where I am
+ building things
+ 4) Removed the -z option in package's tar command (gsar3 and octane
+ don't like it).
+
+2001-06-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/layerdlg.py: Modified remove_view() to avoid calling
+ self.viewmenu.get_active() when there may be no active menu item
+ left as this triggers a crash.
+
+2001-06-20 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvdata.c: Fixed gv_data_set_name() to avoid emitting a metadata
+ changed event if the object is in the destroyed state.
+
+2001-06-14 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: Added GDK_GLX_RED/GREEN/BLUE_SIZE attributes when
+ choosing visual to ensure we get the most capable, not least capable
+ x visual (especially when using raw X Mesa support)
+
+2001-06-11 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pguentry.py: new file - added to simplify managing unsightly
+ gtk'isms on text boxes.
+
+ * pymod/gvclassifydlg.py: modified to use pguentry.
+
+2001-05-25 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvclassifydlg.py: close reclassify dlg if required when the
+ classify dialog is closing.
+
+2001-05-24 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvclassifydlg.py: removed ramps from reclassify dialog and
+ enabled the first ramp in the config file to be the default ramp.
+
+ * pymod/gvlegenddlg.py: added resizing code to grow window to accomodate
+ more classes
+
+2001-05-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/pyshell.py: Cntl-D behaviour fix from Jeffrey D. Collins.
+
+2001-05-15 Paul Spencer <pgs at magma.ca>
+
+ * gvdata.c: added meta-changed signal for signaling changes to meta-data not related
+ to drawing (such as layer name changes) and modified set_name to send this signal.
+
+ * gvdata.h: added meta-changed signal support
+
+ * pymod/gvutils.py: modified is_shapefile to use lower instead of
+ tolower
+
+2001-05-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewwindow.py: modified to allow selection of shapefiles based
+ on .shp, .shx or .dbf.
+
+2001-05-14 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlegenddlg.py: modified to handle multi-line titles and
+ improved the handling of spacing with large fonts selected.
+
+2001-05-12 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlegenddlg.py: modified to allow user defineable color sample
+ sizes through two preferences - 'legend-sample-x-size' and
+ 'legend-sample-y-size'. If not available, the default size is 20 in
+ both directions.
+
+2001-05-08 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlegenddlg.py: fixed problems with font handling that caused
+ a crash when opening the legend dialog.
+
+ * pics/sym-*.xpm: icons added for each built in symbol for use with
+ the GvSymbolStyle widget in gvogrfsgui.py
+
+ * pymod/pgucolor.py: fixed bug that allowed multiple color choosers
+ for a single color button at the same time.
+
+2001-05-07 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c, gvshapeslayer.c, gvselecttool.c: Modifications to
+ ensure that text can be drawn if the origin is off the view port, and
+ to ensure that offsets for text being dragged is properly handled.
+
+ * pymod/gvclassifydlg.py: enable rescaling.
+
+ * pymod/gvclassification.py: fixed problems with rescaling.
+
+2001-05-05 Paul Spencer <pgs at magma.ca>
+
+ * pymod/gvlabeledit.py: added interactive mode where text changes are
+ reported on character basis, turned off by default.
+
+ * pymod/gvogrfsgui.py: added interactive text update plus changed direction
+ of dy offset
+
+2001-05-04 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/pgufilesel.py: implement support for remembering the
+ last directory accessed whe file dialog reopened (Robert Rowe).
+
+ * pymod/gvviewwindow.py: Allow opening multiples files based on
+ wildcards (Robert Rowe).
+
+2001-05-04 Paul Spencer <pgs at magma.ca>
+
+ * pymod/ogrfsgui.py: bug fixes plus optional label offsets for
+ GvLabelStyle.
+
+ * pymod/gvlabeledit.py: bug fixes plus added new method for starting
+ a new label.
+
+2001-05-02 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pgumenu.py: added pgumenu to provide a MenuFactory that supports
+ images in the menu.
+
+2001-05-01 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvtessshape.c, gvtess.c: Fixed the Mesa 3.3 compatibility fixes. :-)
+
+ * gvwinprint.c: reimplemented to use StretchDIBits(), and to avoid
+ using negative heights to represent upsidedown coordinate systems.
+
+ * gvrenderinfo.c: modified to create an "X" sized box for empty
+ strings.
+
+2001-04-29 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pgufont.py: added to provide new font handling for labels.
+
+ * pymod/pgucombo.py: added to provide a convenient way of making
+ combo boxes that can't be edited.
+
+ * pymod/ogrfs.py: added has_part() to OGRFeatureStyle
+
+2001-04-26 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: call glFinish() before swapbuffer to fix lots of
+ problems under Mesa on Windows. Note that Mesa bug report 419222
+ provides the correct fix in Mesa, but we workaround the problem.
+
+2001-04-25 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrenderinfo.c, gvshapeslayer.c: added proper support for descenders.
+
+2001-04-24 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvtess.c, gvtessshape.c: hopefully fixed compatibility issue with
+ Mesa 3.3 (see bug report 418325).
+
+2001-04-23 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added set_properties(), and __delattr__ support for the GvShape
+ from python.
+
+ * pymod/gvselbrowser.py: added callback on oid text field.
+
+2001-04-22 Paul Spencer <pgs at magma.ca>
+ * invdistance.c: added optional parameter for exponent to d in
+ IDW algorithm
+
+ * invdistance.h: changed header for above change
+
+ * gvutils.c: added gv_short_path_name for determining the 8.3 name
+ of a path/file in win32 (defaults to full path in linux)
+
+ * pymod/gvmodule.c: added _wrap_gv_short_path_name and changed
+ _wrap_WIDInterpolate
+
+2001-04-19 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvmesh.h: don't include gvmesh.h!
+
+ * pymod/*.py: avoid use of += for compatibility with python 1.5.x.
+
+2001-04-16 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvvecpropdlg.py: Paul added symbol support.
+
+ * gvshapeslayer.c: Paul added filled start support.
+
+ * pymod/gvogrfs.py: Paul added OGRFeatureStyle class.
+
+2001-04-14 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pgucolor.py: added color_string_to_tuple() utility method
+
+2001-04-11 Paul Spencer <pgs at magma.ca>
+
+ * pymod/pgucolor.py: modified to support opacity correctly
+
+2001-04-09 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gview.py: expose new entry points (ie subselection).
+
+ * gvogrfs.py: improved color handling.
+
+ * pymod/gvviewwindow.py: Use oeattedit.launch().
+
+ * pymod/openev.py: Instantiate GvSelectionManager.
+
+ * pymod/oeattedit.py: Upgraded to support subselection and use of
+ GvSelectionManager.
+
+ * pymod/gvselbrowser.py: New control for subselection browsing,
+ and GvSelectionManager.
+
+ * pics/pan_{right,left}.xpm: New, for gvselbrowser right/left arrows.
+
+ * gvrenderinfo.c/h: New, code for parsing rendering information.
+
+ * gvshapeslayer.c/h: overhauled ogrfs drawing to use renderinfo,
+ added selection box for text.
+
+ * gvshapelayer.c: added renderinfo, and subselection support.
+
+ * gvviewarea.c,h: added ability to query available fonts.
+
+ * gvselecttool.c: Don't allow deletes or moves in read-only layers.
+
+ * gvlayer.{c,h}: Added explicit view to GvLayer.
+
+2001-04-02 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvraster/vecpropdlg.py: fixed some geometry quirks.
+
+ * gvraster.c/gv.defs/gview.py: Expose gv_raster_autoscale() to
+ python.
+
+2001-03-29 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshapefile.c: Look for first non-NULL shape instead of the very
+ first shape when getting a template shape for setting output type.
+
+ * llrasterize.c/gvrasterize.c: Modified to support "fill_short" flag
+ indicating if slivers should be burned in or ignored.
+
+2001-03-28 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshapes.c: Modified to "look around a couple of pixels" when
+ hitting no data values in add_height().
+
+ * gvmesh.c: Changed to try and fill in nodata values on mesh with
+ average of adjacent mesh points if possible.
+
+ * gvlayer.c/h: added explicit pointer to GvViewArea.
+
+ * gvviewarea.c: don't reset view transform in render_to_func at 1:1.
+
+2001-03-26 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: restructure bmfont handling to preserve GdkFont handle
+
+2001-03-22 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvviewarea.c: fixed bug in gv_view_load_bmfont() with reporting
+ the error when a load fails.
+
+2001-03-21 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gvvectorpropdlg.py: add support for labels in the drawing
+ style section.
+
+ * pymod/gvogrfs.py: new - parse OGR Feature Style strings.
+
+ * gvshapeslayer.c: allow setting _gv_ogrfs on layer, and add support
+ for text from fields.
+
+ * Added legend and classification dialog into OpenEV itself.
+
+2001-03-20 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gview.py: added __str__ method on GvShape.
+
+ * gvshapefile.c: fixed to use binary flag for dbf file.
+
+ * pymod/gview.py, gvmodule.c: Fixed handling of fetching out-of-range
+ shapes from a GvShapes to return an IndexError exception instead of
+ crashing.
+
+2001-03-13 Frank Warmerdam <warmerdam at pobox.com>
+
+ * pymod/gview.py: added GvShapes.add_field() and GvShapes.get_schema()
+ methods.
+
+2001-02-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvprint.c: Fixed problem with print_handler not being de-initialized
+ after a file is complete.
+
+2001-02-06 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Build in OGR support on Windows.
+
+2001-02-03 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added gv_view_area_get_mode().
+
+2001-01-31 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added rough attempt to find and include libproj.so in
+ delivery/mkdist.sh.
+
+ * delivery/setup_openev: modified to pass arguments other than -h on
+ to openev.py.
+
+2001-01-30 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvaverage.c: added logic to try and preserve the standard deviation
+ in the complex averaging code.
+
+ * gvmodule.c: Added access to GvManager.queue_task() from python.
+
+ * gvrasterlayer.c: No longer purges textures on a display-change.
+ Added gv_raster_layer_purge_all_textures(), to clear textures on in
+ cases where this is necessary. Now can change alpha with
+ texture_mode_set() without throwing away textures.
+
+ * gvmanager.c: added gv_manager_dump()
+
+2001-01-26 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvshapeslayer.c: Draw points and symbols with z taken into account.
+
+ * gvshapes.c: Fixed add_height() code. Was corrupting (transforming)
+ x and y coordinates.
+
+ * gvviewarea.c: ensure fit_all_layers(), Home, and fit_extents all
+ produce compatible results. Route all view setting through
+ gv_viewarea_set_3d_view(). Fix up default view. Remove view setting
+ in get_volume() function.
+
+2001-01-23 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added GIF print support to gvprint.py.
+
+2001-01-19 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Improved 3D near range calculation a bit - better for stuff with
+ small numbers like images georeferenced in lat/long.
+
+2001-01-18 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added gv_shapes_add_height() and python wrappers.
+
+2001-01-15 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Added support for the view_background_color preference in
+ gvviewwindow.py.
+
+2001-01-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * fixed additional window edge conditions in gv_raster_tile_get_gdal.
+
+2000-12-08 Frank Warmerdam <warmerdam at pobox.com>
+
+ * Fixed configure/configure.in to use $GL_LIBS as per the bug
+ from Bernhard.
+
+2000-12-03 Frank Warmerdam <warmerdam at pobox.com>
+
+ * gvrasterize.c: fixed bug with allocation of nParts.
+
+2000-11-27 Frank Warmerdam <warmerdam at pobox.com>
+
+ * fixed edge handling bugs with rasters smaller than one tile
+ in gvraster.c::gv_raster_tile_get_gdal().
+
+2000-11-13 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Fixed memory leak in gvogr.cpp with geometryless features.
+
+2000-10-31 Frank Warmerdam <warmerda at cs46980-c>
+
+ * gvraster.c: Fixed serious bug with memory corruption
+ that is mostly likely to occur with large images. See
+ Bug 120968 on SourceForge.
+
+2000-10-30 Frank Warmerdam <warmerda at cs46980-c>
+
+ * pymod/gvviewwindow.py: Use new gdal.GetLastErrorMsg() call to
+ report a more detailed error message to the user if an open fails.
+
+2000-10-29 Frank Warmerdam <warmerda at cs46980-c>
+
+ * gvshapefile.c: Modified to add one attribute if there are none,
+ to avoid problem reported by Alan R. of J2-Geomatics with saving
+ shapefiles and there not being useable in ArcView.
+
+2000-10-25 <srawlin at srawlin.atlsci.com>
+
+ * Release 1.0.0 Also created a branch in CVS (asi-rel-1-0-patches)
+ for Atlantis to maintain and patch.
+
+2000-10-24 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Modified gvogr.cpp to discard input features without any geometry.
+ Don't apply unset attributes as properties. Modified gvviewwindow.py
+ ogr load code to not add empty layers to the view.
+
+
+2000-10-18 Frank Warmerdam <warmerda at cs46980-c>
+
+ * gvhtml.py: Fixed to avoid launching two browsers on NT. Report
+ error if no browser found on unix.
+
+2000-10-06 Frank Warmerdam <warmerda at cs46980-c>
+
+ * Added concept of background color to the GvViewArea.
+
+ * Set nodata value on GvRasterLayer (in gv_raster_layer_new()) if
+ one is present on the prototype GDALRasterBand.
+
+2000-09-29 Frank Warmerdam <warmerda at home.com>
+
+ * Changed PrefDialog to allocate 900K+25% of file cache to GDAL
+ and remainder to GvRaster caching. The old amount of 900K+10%
+ was too little in many cases.
+
+ * Changed the import to temporarily up GDAL cache to at least
+ 20MB.
+
+2000-09-29 Steve Rawlinson <srawlin at atlsci.com>
+
+ * Added Edit/GoTo function. Involved adding new dialog to
+ gvviewwindow.py and gv_view_area_map_location function.
+ Also fixed focus problem with new Zoom Ratio menu item,
+ and changed position of boxes in Track Tool preference
+ tab to be more intuitive.
+
+2000-09-29 Frank Warmerdam <warmerda at home.com>
+
+ * Fixed bugs in nodata handling in gvmodule, and gvrastersource.c.
+
+2000-09-28 Frank Warmerdam <warmerda at home.com>
+
+ * Ensure that GvShapes.__getitem__() returns None for missing
+ GvShape's instead of a python GvShape with a "NULL" _o field.
+
+2000-09-27 Frank Warmerdam <warmerda at home.com>
+
+ * The GvRaster will down let GDAL down the decimation when the
+ sample type is GvSMSample instead of GvSMAverage. This gives a
+ major performance boost for large images.
+
+ * Added "_sample()" functions for float, and complex data, and
+ use in gv_raster_new()
+
+ * Added "default_raster_sample" preference. It is used by
+ GvManager to default GvRaster sampling method, and is set by
+ the preferences dialog. Updated help as well.
+
+ * Added gvclassifydlg.py, though it isn't hooked into the UI of
+ regular OpenEV yet.
+
+ * GvLegendDialog now locks down view, and auto-regenerates when
+ the legend properties information changes.
+
+2000-09-20 Frank Warmerdam <warmerda at home.com>
+
+ * Added preliminary implementation of GvClassification and
+ GvLegendDialog.
+
+ * Modified GvViewArea to allow any GDK support font name, not
+ just those in a predefined list.
+
+ * Added support for text labels on GvPointShapes via the
+ _gv_ogrfs property based on the OGR label specification, and
+ bitmap fonts.
+
+ * Added GvData.set_properties() method.
+
+2000-09-15 Frank Warmerdam <warmerda at home.com>
+
+ * Added GvShape.destroy() method.
+
+2000-09-14 Frank Warmerdam <warmerda at home.com>
+
+ * Added gvrasterize.c/h, and invdistance.c, algorithms for
+ rasterizing polygons and for interpolating rasters from point
+ data.
+
+2000-08-25 Frank Warmerdam <warmerda at home.com>
+
+ * gvraster*: added preliminary support for nodata values in raster
+ layers. Currently not automatically initialized.
+
+ * gvrasterlut.c: Changed phase colour mapping to match what EV does.
+
+ * gvutils.c: added reporting of phase and magnitude in
+ tracktool, and point query layer ... should be optional!
+
+ * gvviewwindow.c: fixed some serious bugs with sliders.
+
+ * gvraster.c: HasArbitraryOverviews() support added.
+
+ * ATP CDROM Finalized, and CVS tagged (Steve really)
+
+2000-08-23 Frank Warmerdam <warmerda at home.com>
+
+ * gvraster/gvutils: PIXEL now a special projection name.
+
+ * Open3D: Wrote help topic (open3d.html).
+
+ * gvmesh.c: Fixed problems with detail > 8.
+
+ * gvmesh.c: Use nodata value if available, and avoid off-by-one
+ errors when setting mesh elevations from file.
+
+2000-08-18 Frank Warmerdam <warmerda at home.com>
+
+ * gvrasterlayer.c: hack to work around loss of syncronization with
+ Xi Graphics X servers when loading too many textures in a row.
+
+2000-08-17 Frank Warmerdam <warmerda at home.com>
+
+ * added scrollbar support to GvViewArea, and added a GtkScrolledWindow
+ around the view area in gvviewwindow.py.
+
+2000-07-27 Frank Warmerdam <warmerda at home.com>
+
+ * Added boundary constraints for all editing modes (but not dragging
+ of selections).
+
+ * added editing of existing rectangles.
+
+2000-07-26 Frank Warmerdam <warmerda at home.com>
+
+ * Added Paul Spencer's color swatch support.
+
+ * Added rectangle editing mode.
+
+2000-07-24 Frank Warmerdam <warmerda at home.com>
+
+ * Created a 0.8.2 binary release on windows.
+
+2000-07-25 Frank Warmerdam <warmerda at rommel.atlsci.com>
+
+ * gvmanager/gvrasterlayer: added support for dequeuing old task
+ on the same raster layer.
+
+2000-07-18 Frank Warmerdam <warmerda at home.com>
+
+ * gvrasterlayer.c: modified rules in idle handler to improve texture
+ cache utilization.
+
+2000-07-17 Frank Warmerdam <warmerda at home.com>
+
+ * gvareatool.c: <delete> now deletes last vertex of ring. Ring
+ deleted when vertex count drops to zero.
+
+ * Added code to maintain last_draw_time in GvViewArea, and to
+ scale wait time by it in gvrasterlayer.c.
+
+ * gvpointtool.c/gvlinetool.c/gvnodetool.c: <delete> key will
+ now delete a node, and the whole ring or shape if their node
+ count drops to zero.
+
+2000-07-13 Frank Warmerdam
+
+ * Issued 0.8.0 binary release on Windows.
+
+
Added: packages/openev/branches/upstream/current/Makefile
===================================================================
--- packages/openev/branches/upstream/current/Makefile (rev 0)
+++ packages/openev/branches/upstream/current/Makefile 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2 @@
+default:
+ configure
Added: packages/openev/branches/upstream/current/Makefile.in
===================================================================
--- packages/openev/branches/upstream/current/Makefile.in (rev 0)
+++ packages/openev/branches/upstream/current/Makefile.in 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,88 @@
+
+INST_PREFIX = @prefix@
+
+SRC = gvviewarea.c gvdata.c gvlayer.c gvutils.c gvrecords.c \
+ gvpolylines.c gvlinelayer.c gvtool.c gvlinetool.c \
+ gvtoolbox.c gvshapelayer.c gvselecttool.c gextra.c \
+ gvareas.c gvarealayer.c gvareatool.c gvtess.c gvtessshape.c \
+ gvnodetool.c gvundo.c gvpoints.c gvpointlayer.c gvpointtool.c \
+ gvpquerylayer.c gvviewlink.c gvroitool.c gvmesh.c gvrasterlayer.c \
+ gvraster.c gvrasterlut.c gvrasteraverage.c gvrasterconvert.c \
+ gvrastercache.c gvtracktool.c gtkcolorwell.c crs.c gvprint.c \
+ gvproperties.c gvshape.c gvshapes.c gvshapeslayer.c gvzoompantool.c \
+ gvmanager.c gvrastersource.c gvtexturecache.c ipgcplayer.c \
+ gvrecttool.c appcurlayer.c gvrenderinfo.c gvskirt.c gvogr.c \
+ invdistance.c gvrasterize.c llrasterize.c gvpoitool.c gvsymbolmanager.c \
+ gvrotatetool.c gvautopan.c \
+ \
+ gvshapefile.c shpopen.c dbfopen.c
+
+CXXSRC =
+
+OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o)
+
+CC = @CC@
+CXX = @CXX@
+
+OPTFLAGS = @OPTFLAGS@
+
+CFLAGS = $(OPTFLAGS) @C_WFLAGS@ @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+
+LIBS = $(LDFLAGS) @LIBS@
+
+INSTALL = ./install-sh -c
+INSTALL_LIB = ./install-sh -c
+INSTALL_DIR = ./install-sh -d
+
+default: configure libgv.a gvtest
+ (cd pymod; $(MAKE))
+
+all: default
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $<
+
+libgv.a: $(OBJ)
+ rm -f $@
+ ar cq $@ $(OBJ)
+ @RANLIB@ $@
+
+gvtest: testmain.o libgv.a
+ $(CXX) -g -o $@ testmain.o libgv.a $(LIBS)
+
+clean:
+ rm -f gvtest *.o *.so *.a
+ (cd pymod; $(MAKE) clean)
+
+distclean: dist-clean
+
+dist-clean: clean
+ rm Makefile config.log config.cache config.status
+
+configure: configure.in
+ -autoconf
+
+install:
+ $(INSTALL_DIR) $(INST_PREFIX)/bin
+ $(INSTALL_DIR) $(INST_PREFIX)/ramps
+ $(INSTALL_DIR) $(INST_PREFIX)/tools
+ $(INSTALL_DIR) $(INST_PREFIX)/pymod
+ $(INSTALL_DIR) $(INST_PREFIX)/html
+ $(INSTALL_DIR) $(INST_PREFIX)/pics
+ $(INSTALL_DIR) $(INST_PREFIX)/symbols
+ $(INSTALL_DIR) $(INST_PREFIX)/xmlconfig
+ $(INSTALL) gvtest $(INST_PREFIX)/bin
+ $(INSTALL_LIB) pymod/_gvmodule.so $(INST_PREFIX)/pymod
+ $(INSTALL_LIB) pymod/_gtkmissing.so $(INST_PREFIX)/pymod
+ cp pymod/*.py $(INST_PREFIX)/pymod
+ cp pymod/*.so $(INST_PREFIX)/pymod
+ chmod a+x $(INST_PREFIX)/pymod/openev.py
+ chmod a+x $(INST_PREFIX)/pymod/ibrowse.py
+ chmod a+x $(INST_PREFIX)/pymod/gvplot.py
+ cp tools/*.* $(INST_PREFIX)/tools
+ cp ramps/*.* $(INST_PREFIX)/ramps
+ cp html/*.* $(INST_PREFIX)/html
+ cp symbols/*.* $(INST_PREFIX)/symbols
+ cp xmlconfig/*.* $(INST_PREFIX)/xmlconfig
Added: packages/openev/branches/upstream/current/TODO
===================================================================
--- packages/openev/branches/upstream/current/TODO (rev 0)
+++ packages/openev/branches/upstream/current/TODO 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,90 @@
+
+Thinking about (Gillian):
+
+* Update Open Raw to use VRT (optionally?) instead of Paux so that binary
+ files with more data types can be opened. This would possibly require
+ updates to the VRT format.
+
+* Line of interest (LOI) tool and possibly a general polygon Area of
+ interest (AOI) tool similar to existing POI/ROI tools.
+ LOI: Should have "changing" (new node added to incomplete line) and
+ "changed" signals (line has been completed by right clicking, or an
+ already complete line has been modified). Should allow one line. Once
+ a line is complete, should behave like node edit tool (allow moving nodes
+ or adding new nodes) except that left clicking that doesn't fall on the
+ line should start a new loi and delete the old one. Tool should not
+ require a shape layer.
+
+* Add linestyles with points at nodes only to methods of drawing lines
+ (follow ogr spec).
+
+* Graphical tool for combining files into a single dataset, splitting a
+ dataset into several files, importing ground control points into a
+ dataset, adding a colourtable or metadata, reprojecting existing
+ geocoding information (not resampling- just reprojecting gcp's).
+ Basically, a tool for manipulating VRT's without the user having to
+ know so much about them.
+
+Would like to have (Frank):
+
+* The Tabular Shapes Attribute Grid Demo should have the ability to
+ edit the attributes added, and it should move into the Edit menu to
+ replace the existing crappy Vector Layer Attributes dialog. It should
+ also likely report the layer it is displaying somewhere on the dialog.
+
+Short-term (Andrey)
+
+* Tool for manual image enchancements (both for the whole image and
+ in the ROI area)
+
+* GUI to edit geocoding information
+
+* `Open Sub-area' dialog.
+
+Long-term (Andrey)
+
+* Vector layer reprojection.
+
+* Image calibration.
+
+* GUI frontend for GDAL warping interface.
+
+* GUI for image registration.
+
+* Filter tool.
+
+* Spectral plots, profile plots.
+
+* Angle measurement.
+
+* Image classification, pixel editor, pseudocolor table editor.
+
+Old to-do list (Sept. 2000)
+
+-*-mode: text; mode: auto-fill-*-
+
+* ROI mode shouldn't stop showing roi when user clicks in a
+ different window.
+
+* Select mode should be able to select from any layer ... perhaps
+ based on a setup option.
+
+* Line tool: continue existing line if the first click is over
+an end vertex.
+
+* toolbox: preserve selection state across certain tools
+
+* Select tool: it's easy to accidentally translate a line when you
+just want to select it. Possibly add some kind of sensitivity
+measure, e.g. no translation if only one motion event recieved.
+
+* Tools: should use the view draw signal to invoke a draw instead of
+connecting to the layer draw method? Or make the base tool class
+handle this somehow?
+
+* View area: change cursor when panning/rotating/scaling.
+
+* Undo: add redo capablility.
+
+* Node tool: Add and drag a new node is entered as two operations to
+undo. This might be more intuative as one compound operation.
Added: packages/openev/branches/upstream/current/aclocal.m4
===================================================================
--- packages/openev/branches/upstream/current/aclocal.m4 (rev 0)
+++ packages/openev/branches/upstream/current/aclocal.m4 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,507 @@
+
+dnl
+dnl Major portions of this file taken from the pygtk aclocal.m4 file.
+dnl Other parts derived from libgeotiff, and GDAL.
+dnl
+
+AC_DEFUN(AC_COMPILER_WFLAGS,
+[
+ # Remove -g from compile flags, we will add via CFG variable if
+ # we need it.
+ CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"`
+ CFLAGS=`echo "$CFLAGS " | sed "s/-g //"`
+
+ # check for GNU compiler, and use -Wall
+ if test "$GCC" = "yes"; then
+ C_WFLAGS="-Wall"
+ AC_DEFINE(USE_GNUCC)
+ fi
+ if test "$GXX" = "yes"; then
+ CXX_WFLAGS="-Wall"
+ AC_DEFINE(USE_GNUCC)
+ fi
+ AC_SUBST(CXX_WFLAGS,$CXX_WFLAGS)
+ AC_SUBST(C_WFLAGS,$C_WFLAGS)
+])
+
+AC_DEFUN(AC_COMPILER_PIC,
+[
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fPIC -c conftest.c 2>&1`"; then
+ C_PIC=-fPIC
+ else
+ C_PIC=
+ fi
+ if test -z "`${CXX-g++} -fPIC -c conftest.c 2>&1`"; then
+ CXX_PIC=-fPIC
+ else
+ CXX_PIC=
+ fi
+ rm -f conftest*
+
+ AC_SUBST(CXX_PIC,$CXX_PIC)
+ AC_SUBST(C_PIC,$C_PIC)
+])
+
+AC_DEFUN(AC_LD_SHARED,
+[
+ echo 'int main(){ g(); return 0; }' > conftest1.c
+
+ echo 'void g(){}' > conftest2.c
+ ${CC} ${C_PIC} -c conftest2.c
+
+ LD_SHARED="/bin/true"
+ if test -z "`ld -shared conftest2.o -o libconftest.so 2>&1`" ; then
+ if test -z "`${CC} conftest1.c libconftest.so -o conftest1 2>&1`"; then
+ LD_LIBRARY_PATH_OLD="$LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="`pwd`"
+ export LD_LIBRARY_PATH
+ if test -z "`./conftest1 2>&1`" ; then
+ echo "checking for ld -shared ... yes"
+ LD_SHARED="ld -shared"
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH_OLD"
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ rm -f conftest* libconftest*
+
+ AC_SUBST(LD_SHARED,$LD_SHARED)
+])
+
+AC_DEFUN(AM_PATH_PYTHON,
+ [AC_CHECK_PROGS(PYTHON, python python2.2 python2.1 python2.0 python1.5,no)
+ if test "$PYTHON" != no; then
+ AC_MSG_CHECKING([where .py files should go])
+changequote(, )dnl
+ pythondir=`$PYTHON -c '
+import sys
+print "%s/lib/python%s/site-packages" % (sys.prefix, sys.version[:3])'`
+changequote([, ])dnl
+ AC_MSG_RESULT($pythondir)
+ AC_MSG_CHECKING([where python extensions should go])
+changequote(, )dnl
+ pyexecdir=`$PYTHON -c '
+import sys
+if sys.version[0] > "1" or sys.version[2] > "4":
+ print "%s/lib/python%s/site-packages" % (sys.exec_prefix, sys.version[:3])
+else:
+ print "%s/lib/python%s/sharedmodules" % (sys.exec_prefix, sys.version[:3])'`
+changequote([, ])dnl
+ AC_MSG_RESULT($pyexecdir)
+ else
+ # these defaults are version independent ...
+ AC_MSG_CHECKING([where .py files should go])
+ pythondir='$(prefix)/lib/site-python'
+ AC_MSG_RESULT($pythondir)
+ AC_MSG_CHECKING([where python extensions should go])
+ pyexecdir='$(exec_prefix)/lib/site-python'
+ AC_MSG_RESULT($pyexecdir)
+ fi
+ AC_SUBST(pythondir)
+ AC_SUBST(pyexecdir)])
+
+
+dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
+dnl Check if a module containing a given symbol is visible to python.
+AC_DEFUN(AM_CHECK_PYMOD,
+[AC_REQUIRE([AM_PATH_PYTHON])
+py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
+AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
+ifelse([$2],[], [prog="
+import sys
+try:
+ import $1
+except ImportError:
+ sys.exit(1)
+except:
+ sys.exit(0)
+sys.exit(0)"], [prog="
+import $1
+$1.$2"])
+if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
+ then
+ eval "py_cv_mod_$py_mod_var=yes"
+ else
+ eval "py_cv_mod_$py_mod_var=no"
+ fi
+])
+py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
+if test "x$py_val" != xno; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], [],, [$3
+])dnl
+else
+ AC_MSG_RESULT(no)
+ ifelse([$4], [],, [$4
+])dnl
+fi
+])
+
+# AM_PATH_GTKGL([ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]])
+AC_DEFUN(AM_PATH_GTKGL,
+[
+AC_REQUIRE([AM_PATH_GTK])
+AC_PROVIDE([AM_PATH_GTKGL])
+
+AC_ARG_WITH(gl-prefix, [ --with-gl-prefix=PFX Prefix where OpenGL or Mesa is installed],
+ gl_prefix="$withval",
+ gl_prefix="")
+
+AC_ARG_WITH(gtkgl-prefix, [ --with-gtkgl-prefix=PFX Prefix where GtkGLArea is installed],
+ gtkgl_prefix="$withval",
+ gtkgl_prefix="")
+
+
+
+if test x$gl_prefix != x ; then
+ GL_CFLAGS="-I$gl_prefix/include"
+ GL_LDOPTS="-L$gl_prefix/lib"
+else
+ GL_CFLAGS=""
+ GL_LDOPTS=""
+fi
+
+saved_LIBS="$LIBS"
+saved_CFLAGS="$CFLAGS"
+
+# test for plain OpenGL
+AC_MSG_CHECKING([GL])
+LIBS="$GTK_LIBS $GL_LDOPTS -lGLU -lGL $saved_LIBS"
+AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_GL=yes, have_GL=no)
+AC_MSG_RESULT($have_GL)
+
+if test x$have_GL = xyes; then
+
+ GL_LIBS="-lGLU -lGL"
+
+else
+
+ # test for Mesa
+ AC_MSG_CHECKING([Mesa])
+ LIBS="$saved_LIBS $GTK_LIBS $GL_LDOPTS -lMesaGLU -lMesaGL"
+ AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_Mesa=yes, have_Mesa=no)
+ AC_MSG_RESULT($have_Mesa)
+
+ if test x$have_Mesa = xyes; then
+
+ GL_LIBS="-lMesaGLU -lMesaGL"
+
+ else
+
+ # test for Mesa with threads
+ AC_MSG_CHECKING([Mesa with pthreads])
+ LIBS="$GTK_LIBS $GL_LDOPTS -lMesaGL -lMesaGLU -lpthread $saved_LIBS"
+ AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_Mesa_pthread=yes, have_Mesa_pthread=no)
+ AC_MSG_RESULT($have_Mesa_pthread)
+
+ if test x$have_Mesa_pthread = xyes; then
+
+ GL_LIBS="-lMesaGLU -lMesaGL -lpthread"
+
+ else
+
+ #all failed
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_LIBS=""
+ GTKGL_CFLAGS=""
+ ifelse([$2], , :, [$2])
+
+ fi
+ fi
+fi
+
+
+if test x$gtkgl_prefix != x; then
+ GTKGL_CFLAGS="-I$gtkgl_prefix/include"
+ GTKGL_LDOPTS="-L$gtkgl_prefix/lib"
+else
+ GTKGL_CFLAGS=""
+ GTKGL_LDOPTS=""
+fi
+
+AC_MSG_CHECKING([GtkGLArea])
+LIBS="$GTK_LIBS $GL_LDOPTS -lgtkgl $GL_LIBS $GTKGL_LDOPTS $saved_LIBS"
+AC_TRY_LINK( ,[ char gtk_gl_area_new(); gtk_gl_area_new(); ], have_gtkgl=yes, have_gtkgl=no)
+AC_MSG_RESULT($have_gtkgl)
+
+if test x$have_gtkgl = xyes; then
+
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_CFLAGS="$GTKGL_CFLAGS $GL_CFLAGS"
+ GTKGL_LIBS="$GTKGL_LDOPTS -lgtkgl $GL_LDOPTS $GL_LIBS"
+ ifelse([$1], , :, [$1])
+
+else
+
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_LIBS=""
+ GTKGL_CFLAGS=""
+ ifelse([$2], , :, [$2])
+
+fi
+
+AC_SUBST(GTKGL_CFLAGS)
+AC_SUBST(GTKGL_LIBS)
+
+])
+
+# Configure paths for GTK+
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)],
+ gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+ gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program],
+ , enable_gtktest=yes)
+
+ for module in . $4
+ do
+ case "$module" in
+ gthread)
+ gtk_config_args="$gtk_config_args gthread"
+ ;;
+ esac
+ done
+
+ if test x$gtk_config_exec_prefix != x ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ fi
+ if test x$gtk_config_prefix != x ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ fi
+
+ AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+ min_gtk_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+ no_gtk=""
+ if test "$GTK_CONFIG" = "no" ; then
+ no_gtk=yes
+ else
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_gtktest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$GTK_LIBS $LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+ rm -f conf.gtktest
+ AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.gtktest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_gtk_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+ if ((gtk_major_version != $gtk_config_major_version) ||
+ (gtk_minor_version != $gtk_config_minor_version) ||
+ (gtk_micro_version != $gtk_config_micro_version))
+ {
+ printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+ $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf ("*** was found! If gtk-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+ printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+ else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+ (gtk_minor_version != GTK_MINOR_VERSION) ||
+ (gtk_micro_version != GTK_MICRO_VERSION))
+ {
+ printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+ else
+ {
+ if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+ printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_gtk" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GTK_CONFIG" = "no" ; then
+ echo "*** The gtk-config script installed by GTK could not be found"
+ echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GTK_CONFIG environment variable to the"
+ echo "*** full path to gtk-config."
+ else
+ if test -f conf.gtktest ; then
+ :
+ else
+ echo "*** Could not run GTK test program, checking why..."
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+ AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GTK or finding the wrong"
+ echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+ echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+ echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GTK_CFLAGS)
+ AC_SUBST(GTK_LIBS)
+ rm -f conf.gtktest
+])
+
+
+# serial 1
+
+dnl finds information needed for compilation of shared library style python
+dnl extensions. AM_PATH_PYTHON should be called before hand.
+dnl NFW: Modified from original to avoid overridding CC, SO and OPT
+AC_DEFUN(AM_INIT_PYEXEC_MOD,
+ [AC_REQUIRE([AM_PATH_PYTHON])
+ AC_MSG_CHECKING([for python headers])
+ AC_CACHE_VAL(am_cv_python_includes,
+ [changequote(,)dnl
+ am_cv_python_includes="`$PYTHON -c '
+import sys
+includepy = \"%s/include/python%s\" % (sys.prefix, sys.version[:3])
+if sys.version[0] > \"1\" or sys.version[2] > \"4\":
+ libpl = \"%s/include/python%s\" % (sys.exec_prefix, sys.version[:3])
+else:
+ libpl = \"%s/lib/python%s/config\" % (sys.exec_prefix, sys.version[:3])
+print \"-I%s -I%s\" % (includepy, libpl)'`"
+ changequote([, ])])
+ PYTHON_INCLUDES="$am_cv_python_includes"
+ AC_MSG_RESULT(found)
+ AC_SUBST(PYTHON_INCLUDES)
+
+ AC_MSG_CHECKING([definitions from Python makefile])
+changequote(, )dnl
+ py_makefile="`$PYTHON -c '
+import sys
+print \"%s/lib/python%s/config/Makefile\"%(sys.exec_prefix, sys.version[:3])'`"
+changequote([, ])dnl
+
+ if test ! -f "$py_makefile"; then
+ AC_MSG_ERROR([*** Couldnt find the python config makefile. Maybe you are
+*** missing the development portion of the python installation])
+ fi
+ eval `sed -n \
+-e "s/^CC=[ ]*\(.*\)/am_cv_python_CC='\1'/p" \
+-e "s/^OPT=[ ]*\(.*\)/am_cv_python_OPT='\1'/p" \
+-e "s/^CCSHARED=[ ]*\(.*\)/am_cv_python_CCSHARED='\1'/p" \
+-e "s/^LDSHARED=[ ]*\(.*\)/am_cv_python_LDSHARED='\1'/p" \
+-e "s/^SO=[ ]*\(.*\)/am_cv_python_SO='\1'/p" \
+ $py_makefile`
+
+ AC_MSG_RESULT(done)
+ PYTHON_CC="$am_cv_python_CC"
+ PYTHON_OPT="$am_cv_python_OPT"
+ PYTHON_SO="$am_cv_python_SO"
+ PYTHON_CFLAGS="$am_cv_python_CCSHARED \$(OPT)"
+ PYTHON_LINK="$am_cv_python_LDSHARED -o \[$]@"
+
+ AC_SUBST(PYTHON_CC)dnl
+ AC_SUBST(PYTHON_OPT)dnl
+ AC_SUBST(PYTHON_SO)dnl
+ AC_SUBST(PYTHON_CFLAGS)dnl
+ AC_SUBST(PYTHON_LINK)])
Added: packages/openev/branches/upstream/current/appcurlayer.c
===================================================================
--- packages/openev/branches/upstream/current/appcurlayer.c (rev 0)
+++ packages/openev/branches/upstream/current/appcurlayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,269 @@
+/******************************************************************************
+ * $Id: appcurlayer.c,v 1.4 2003/02/27 03:59:21 warmerda Exp $
+ *
+ * Project: APP/Currents
+ * Purpose: Implementation of current layer.
+ *
+ * This layer is intended specifically for use in APP, and
+ * should only be changed on behalf of Atlantis, though it can
+ * serve as an example of custom layer drawing for others.
+ *
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: appcurlayer.c,v $
+ * Revision 1.4 2003/02/27 03:59:21 warmerda
+ * added view to gv_shapes_layer_get_draw_info
+ *
+ * Revision 1.3 2002/11/05 04:05:31 warmerda
+ * geocoord update
+ *
+ * Revision 1.2 2001/08/08 17:44:12 warmerda
+ * use gv_shape_type() macro
+ *
+ * Revision 1.1 2000/08/25 20:02:22 warmerda
+ * New
+ *
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include "appcurlayer.h"
+#include "gvutils.h"
+#include <GL/gl.h>
+
+static void app_cur_layer_class_init(AppCurLayerClass *klass);
+static void app_cur_layer_init(AppCurLayer *layer);
+static void app_cur_layer_setup(GvLayer *layer, GvViewArea *view);
+static void app_cur_layer_draw(GvLayer *layer, GvViewArea *view);
+static void app_cur_layer_draw_selected(GvShapeLayer *layer,
+ GvViewArea *view);
+
+#ifndef PI
+#define PI 3.1415927
+#endif
+
+GtkType
+app_cur_layer_get_type(void)
+{
+ static GtkType cur_layer_type = 0;
+
+ if (!cur_layer_type)
+ {
+ static const GtkTypeInfo cur_layer_info =
+ {
+ "AppCurLayer",
+ sizeof(AppCurLayer),
+ sizeof(AppCurLayerClass),
+ (GtkClassInitFunc) app_cur_layer_class_init,
+ (GtkObjectInitFunc) app_cur_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ cur_layer_type = gtk_type_unique(gv_shapes_layer_get_type(),
+ &cur_layer_info);
+ }
+ return cur_layer_type;
+}
+
+static void
+app_cur_layer_class_init(AppCurLayerClass *klass)
+{
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ layer_class->setup = app_cur_layer_setup;
+ layer_class->draw = app_cur_layer_draw;
+ shape_layer_class->draw_selected = app_cur_layer_draw_selected;
+}
+
+static void
+app_cur_layer_init(AppCurLayer *layer)
+{
+}
+
+GtkObject *
+app_cur_layer_new(GvShapes *data)
+{
+ AppCurLayer *layer = APP_CUR_LAYER(gtk_type_new(
+ app_cur_layer_get_type()));
+
+ if( data == NULL )
+ {
+ data = GV_SHAPES(gv_shapes_new());
+ gv_data_set_name( GV_DATA(data), "Currents" );
+ }
+
+ gv_shapes_layer_set_data( GV_SHAPES_LAYER(layer), data );
+ gv_data_set_name( GV_DATA(layer), gv_data_get_name(GV_DATA(data)) );
+
+ return GTK_OBJECT(layer);
+}
+
+/*******************************************************/
+
+static void
+app_cur_layer_setup(GvLayer *rlayer, GvViewArea *view)
+{
+}
+
+static void
+app_cur_draw_arrow( gfloat base_x, gfloat base_y,
+ gfloat head_x, gfloat head_y )
+
+{
+ gfloat vx1, vy1, rl1, vx2, vy2, angle2;
+
+ glBegin( GL_LINES );
+
+ glVertex2f( head_x, head_y );
+ glVertex2f( base_x, base_y );
+
+ vx1 = base_x - head_x;
+ vy1 = base_y - head_y;
+ rl1 = sqrt(vx1*vx1+vy1*vy1);
+
+ angle2 = atan2(vy1,vx1) + PI/4;
+ vy2 = (rl1/3.0) * sin(angle2);
+ vx2 = (rl1/3.0) * cos(angle2);
+
+ glVertex2f( head_x, head_y );
+ glVertex2f( head_x + vx2, head_y + vy2 );
+
+ angle2 = atan2(vy1,vx1) - PI/4;
+ vy2 = (rl1/3.0) * sin(angle2);
+ vx2 = (rl1/3.0) * cos(angle2);
+
+ glVertex2f( head_x, head_y );
+ glVertex2f( head_x + vx2, head_y + vy2 );
+
+ glEnd();
+}
+
+static void
+app_cur_layer_draw_arrow( GvViewArea *view, AppCurLayer *layer,
+ GvShape *shape, int selected )
+
+{
+ gfloat x, y, x_head, y_head;
+ GLgeocoord dx, dy;
+ GvColor color;
+ GvShapeDrawInfo drawinfo;
+
+ /* get and set color */
+ gv_shapes_layer_get_draw_info( view, GV_SHAPES_LAYER(layer), &drawinfo );
+ gv_color_copy( color, drawinfo.point_color );
+
+ gv_shapes_layer_override_color( shape, color, "_gv_color" );
+
+ glColor4fv( color );
+
+ /* Compute main drawing location */
+ x = gv_shape_get_x(shape, 0, 0 );
+ y = gv_shape_get_y(shape, 0, 0 );
+
+ /* Compute head location */
+
+ x_head = x - 30;
+ y_head = y + 20;
+
+ app_cur_draw_arrow( x, y, x_head, y_head );
+
+ /* compute selected box size */
+ dx = 5.0;
+ dy = 5.0;
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ /* Draw selection box around base point, if selected */
+ if( selected )
+ {
+ glBegin(GL_LINE_LOOP);
+ glVertex2f( x-dx, y-dy );
+ glVertex2f( x+dy, y-dx );
+ glVertex2f( x+dx, y+dy );
+ glVertex2f( x-dy, y+dx );
+ glVertex2f( x-dx, y-dy );
+ glEnd();
+ }
+}
+
+static void
+app_cur_layer_draw(GvLayer *rlayer, GvViewArea *view)
+{
+ AppCurLayer *layer = APP_CUR_LAYER(rlayer);
+ gint i, points;
+ gint *selected, presentation;
+ gint hit_selected = FALSE;
+ GvShape *shape;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ for (i=0; i < points; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_POINT )
+ app_cur_layer_draw_arrow( view, layer, shape, FALSE );
+ }
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ app_cur_layer_draw_selected(GV_SHAPE_LAYER(layer), view);
+ }
+}
+
+static void
+app_cur_layer_draw_selected(GvShapeLayer *rlayer, GvViewArea *view)
+{
+ AppCurLayer *layer = APP_CUR_LAYER(rlayer);
+ gint i, points;
+ gint *selected;
+ GvShape *shape;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ for (i=0; i < points; ++i)
+ {
+ if ( !selected[i] )
+ continue;
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_POINT )
+ app_cur_layer_draw_arrow( view, layer, shape, TRUE );
+ }
+}
+
+
Added: packages/openev/branches/upstream/current/appcurlayer.h
===================================================================
--- packages/openev/branches/upstream/current/appcurlayer.h (rev 0)
+++ packages/openev/branches/upstream/current/appcurlayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * $Id: appcurlayer.h,v 1.1 2000/08/25 20:02:22 warmerda Exp $
+ *
+ * Project: APP/Currents
+ * Purpose: APP Currents Layer declarations.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: appcurlayer.h,v $
+ * Revision 1.1 2000/08/25 20:02:22 warmerda
+ * New
+ *
+ */
+
+#ifndef __APPCURLAYER_H__
+#define __APPCURLAYER_H__
+
+#include "gvshapeslayer.h"
+
+#define APP_TYPE_CUR_LAYER (app_cur_layer_get_type ())
+#define APP_CUR_LAYER(obj) (GTK_CHECK_CAST ((obj), APP_TYPE_CUR_LAYER, AppCurLayer))
+#define APP_CUR_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), APP_TYPE_CUR_LAYER, AppCurLayerClass))
+#define APP_IS_CUR_LAYER(obj) (GTK_CHECK_TYPE ((obj),APP_TYPE_CUR_LAYER))
+#define APP_IS_CUR_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
+ APP_TYPE_CUR_LAYER))
+
+typedef struct _AppCurLayer AppCurLayer;
+typedef struct _AppCurLayerClass AppCurLayerClass;
+
+struct _AppCurLayer
+{
+ GvShapesLayer layer;
+};
+
+struct _AppCurLayerClass
+{
+ GvShapesLayerClass parent_class;
+};
+
+GtkType app_cur_layer_get_type(void);
+GtkObject* app_cur_layer_new(GvShapes *);
+
+#endif /* __APPCURLAYER_H__ */
+
Added: packages/openev/branches/upstream/current/configure
===================================================================
--- packages/openev/branches/upstream/current/configure (rev 0)
+++ packages/openev/branches/upstream/current/configure 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,6408 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="Makefile.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX RANLIB ac_ct_RANLIB CPP EGREP CXX_WFLAGS C_WFLAGS CXX_PIC C_PIC LD_SHARED PYTHON pythondir pyexecdir PYTHON_INCLUDES PYTHON_CC PYTHON_OPT PYTHON_SO PYTHON_CFLAGS PYTHON_LINK GTK_CONFIG GTK_CFLAGS GTK_LIBS GTKGL_CFLAGS GTKGL_LIBS GDAL_INC OGR_SOURCE OPTFLAGS LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-gtktest Do not try to compile and run a test GTK program
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)
+ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)
+ --with-gl-prefix=PFX Prefix where OpenGL or Mesa is installed
+ --with-gtkgl-prefix=PFX Prefix where GtkGLArea is installed
+ --with-gdal=ARG Path to GDAL installation tree
+ --with-ogr Enable OGR Linkage
+ --with-double-geocoord Use double precision GL coordinates
+ --with-render-plugin Enable plugin (rendering)
+ --with-debug Build debug (else optimized)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_headers="$ac_config_headers gv_config.h"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+ CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+LIBS="$LIBS -L/usr/local/lib"
+CFLAGS="$CFLAGS -I/usr/local/include"
+CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+
+
+
+echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+ LIBS="-ldl $LIBS"
+
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h unistd.h dbmalloc.h dlfcn.h string.h strings.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int
+main ()
+{
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func__doprnt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+ # Remove -g from compile flags, we will add via CFG variable if
+ # we need it.
+ CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"`
+ CFLAGS=`echo "$CFLAGS " | sed "s/-g //"`
+
+ # check for GNU compiler, and use -Wall
+ if test "$GCC" = "yes"; then
+ C_WFLAGS="-Wall"
+ cat >>confdefs.h <<\_ACEOF
+#define USE_GNUCC 1
+_ACEOF
+
+ fi
+ if test "$GXX" = "yes"; then
+ CXX_WFLAGS="-Wall"
+ cat >>confdefs.h <<\_ACEOF
+#define USE_GNUCC 1
+_ACEOF
+
+ fi
+ CXX_WFLAGS=$CXX_WFLAGS
+
+ C_WFLAGS=$C_WFLAGS
+
+
+
+ echo 'void f(){}' > conftest.c
+ if test -z "`${CC-cc} -fPIC -c conftest.c 2>&1`"; then
+ C_PIC=-fPIC
+ else
+ C_PIC=
+ fi
+ if test -z "`${CXX-g++} -fPIC -c conftest.c 2>&1`"; then
+ CXX_PIC=-fPIC
+ else
+ CXX_PIC=
+ fi
+ rm -f conftest*
+
+ CXX_PIC=$CXX_PIC
+
+ C_PIC=$C_PIC
+
+
+
+ echo 'int main(){ g(); return 0; }' > conftest1.c
+
+ echo 'void g(){}' > conftest2.c
+ ${CC} ${C_PIC} -c conftest2.c
+
+ LD_SHARED="/bin/true"
+ if test -z "`ld -shared conftest2.o -o libconftest.so 2>&1`" ; then
+ if test -z "`${CC} conftest1.c libconftest.so -o conftest1 2>&1`"; then
+ LD_LIBRARY_PATH_OLD="$LD_LIBRARY_PATH"
+ LD_LIBRARY_PATH="`pwd`"
+ export LD_LIBRARY_PATH
+ if test -z "`./conftest1 2>&1`" ; then
+ echo "checking for ld -shared ... yes"
+ LD_SHARED="ld -shared"
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH_OLD"
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ else
+ echo "checking for ld -shared ... no"
+ fi
+ rm -f conftest* libconftest*
+
+ LD_SHARED=$LD_SHARED
+
+
+
+for ac_prog in python python2.2 python2.1 python2.0 python1.5
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_PYTHON+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$PYTHON"; then
+ ac_cv_prog_PYTHON="$PYTHON" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PYTHON="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+PYTHON=$ac_cv_prog_PYTHON
+if test -n "$PYTHON"; then
+ echo "$as_me:$LINENO: result: $PYTHON" >&5
+echo "${ECHO_T}$PYTHON" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$PYTHON" && break
+done
+test -n "$PYTHON" || PYTHON="no"
+
+ if test "$PYTHON" != no; then
+ echo "$as_me:$LINENO: checking where .py files should go" >&5
+echo $ECHO_N "checking where .py files should go... $ECHO_C" >&6
+ pythondir=`$PYTHON -c '
+import sys
+print "%s/lib/python%s/site-packages" % (sys.prefix, sys.version[:3])'`
+ echo "$as_me:$LINENO: result: $pythondir" >&5
+echo "${ECHO_T}$pythondir" >&6
+ echo "$as_me:$LINENO: checking where python extensions should go" >&5
+echo $ECHO_N "checking where python extensions should go... $ECHO_C" >&6
+ pyexecdir=`$PYTHON -c '
+import sys
+if sys.version[0] > "1" or sys.version[2] > "4":
+ print "%s/lib/python%s/site-packages" % (sys.exec_prefix, sys.version[:3])
+else:
+ print "%s/lib/python%s/sharedmodules" % (sys.exec_prefix, sys.version[:3])'`
+ echo "$as_me:$LINENO: result: $pyexecdir" >&5
+echo "${ECHO_T}$pyexecdir" >&6
+ else
+ # these defaults are version independent ...
+ echo "$as_me:$LINENO: checking where .py files should go" >&5
+echo $ECHO_N "checking where .py files should go... $ECHO_C" >&6
+ pythondir='$(prefix)/lib/site-python'
+ echo "$as_me:$LINENO: result: $pythondir" >&5
+echo "${ECHO_T}$pythondir" >&6
+ echo "$as_me:$LINENO: checking where python extensions should go" >&5
+echo $ECHO_N "checking where python extensions should go... $ECHO_C" >&6
+ pyexecdir='$(exec_prefix)/lib/site-python'
+ echo "$as_me:$LINENO: result: $pyexecdir" >&5
+echo "${ECHO_T}$pyexecdir" >&6
+ fi
+
+
+
+
+ echo "$as_me:$LINENO: checking for python headers" >&5
+echo $ECHO_N "checking for python headers... $ECHO_C" >&6
+ if test "${am_cv_python_includes+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ am_cv_python_includes="`$PYTHON -c '
+import sys
+includepy = \"%s/include/python%s\" % (sys.prefix, sys.version[:3])
+if sys.version[0] > \"1\" or sys.version[2] > \"4\":
+ libpl = \"%s/include/python%s\" % (sys.exec_prefix, sys.version[:3])
+else:
+ libpl = \"%s/lib/python%s/config\" % (sys.exec_prefix, sys.version[:3])
+print \"-I%s -I%s\" % (includepy, libpl)'`"
+
+fi
+
+ PYTHON_INCLUDES="$am_cv_python_includes"
+ echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6
+
+
+ echo "$as_me:$LINENO: checking definitions from Python makefile" >&5
+echo $ECHO_N "checking definitions from Python makefile... $ECHO_C" >&6
+ py_makefile="`$PYTHON -c '
+import sys
+print \"%s/lib/python%s/config/Makefile\"%(sys.exec_prefix, sys.version[:3])'`"
+
+ if test ! -f "$py_makefile"; then
+ { { echo "$as_me:$LINENO: error: *** Couldnt find the python config makefile. Maybe you are
+*** missing the development portion of the python installation" >&5
+echo "$as_me: error: *** Couldnt find the python config makefile. Maybe you are
+*** missing the development portion of the python installation" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ eval `sed -n \
+-e "s/^CC= *\(.*\)/am_cv_python_CC='\1'/p" \
+-e "s/^OPT= *\(.*\)/am_cv_python_OPT='\1'/p" \
+-e "s/^CCSHARED= *\(.*\)/am_cv_python_CCSHARED='\1'/p" \
+-e "s/^LDSHARED= *\(.*\)/am_cv_python_LDSHARED='\1'/p" \
+-e "s/^SO= *\(.*\)/am_cv_python_SO='\1'/p" \
+ $py_makefile`
+
+ echo "$as_me:$LINENO: result: done" >&5
+echo "${ECHO_T}done" >&6
+ PYTHON_CC="$am_cv_python_CC"
+ PYTHON_OPT="$am_cv_python_OPT"
+ PYTHON_SO="$am_cv_python_SO"
+ PYTHON_CFLAGS="$am_cv_python_CCSHARED \$(OPT)"
+ PYTHON_LINK="$am_cv_python_LDSHARED -o \$@"
+
+
+
+
+py_mod_var=`echo thread'_' | sed 'y%./+-%__p_%'`
+echo "$as_me:$LINENO: checking for python module thread" >&5
+echo $ECHO_N "checking for python module thread... $ECHO_C" >&6
+if eval "test \"\${py_cv_mod_$py_mod_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+prog="
+import sys
+try:
+ import thread
+except ImportError:
+ sys.exit(1)
+except:
+ sys.exit(0)
+sys.exit(0)"
+if $PYTHON -c "$prog" 1>&5 2>&5
+ then
+ eval "py_cv_mod_$py_mod_var=yes"
+ else
+ eval "py_cv_mod_$py_mod_var=no"
+ fi
+
+fi
+
+py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
+if test "x$py_val" != xno; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ extra_mods=gthread
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ extra_mods=
+fi
+
+
+
+# Check whether --with-gtk-prefix or --without-gtk-prefix was given.
+if test "${with_gtk_prefix+set}" = set; then
+ withval="$with_gtk_prefix"
+ gtk_config_prefix="$withval"
+else
+ gtk_config_prefix=""
+fi;
+
+# Check whether --with-gtk-exec-prefix or --without-gtk-exec-prefix was given.
+if test "${with_gtk_exec_prefix+set}" = set; then
+ withval="$with_gtk_exec_prefix"
+ gtk_config_exec_prefix="$withval"
+else
+ gtk_config_exec_prefix=""
+fi;
+# Check whether --enable-gtktest or --disable-gtktest was given.
+if test "${enable_gtktest+set}" = set; then
+ enableval="$enable_gtktest"
+
+else
+ enable_gtktest=yes
+fi;
+
+ for module in . $extra_mods
+ do
+ case "$module" in
+ gthread)
+ gtk_config_args="$gtk_config_args gthread"
+ ;;
+ esac
+ done
+
+ if test x$gtk_config_exec_prefix != x ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ fi
+ if test x$gtk_config_prefix != x ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ fi
+
+ # Extract the first word of "gtk-config", so it can be a program name with args.
+set dummy gtk-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_GTK_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $GTK_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_GTK_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_path_GTK_CONFIG" && ac_cv_path_GTK_CONFIG="no"
+ ;;
+esac
+fi
+GTK_CONFIG=$ac_cv_path_GTK_CONFIG
+
+if test -n "$GTK_CONFIG"; then
+ echo "$as_me:$LINENO: result: $GTK_CONFIG" >&5
+echo "${ECHO_T}$GTK_CONFIG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ min_gtk_version=1.2.1
+ echo "$as_me:$LINENO: checking for GTK - version >= $min_gtk_version" >&5
+echo $ECHO_N "checking for GTK - version >= $min_gtk_version... $ECHO_C" >&6
+ no_gtk=""
+ if test "$GTK_CONFIG" = "no" ; then
+ no_gtk=yes
+ else
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+ gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+ gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+ if test "x$enable_gtktest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$GTK_LIBS $LIBS"
+ rm -f conf.gtktest
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.gtktest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_gtk_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+ if ((gtk_major_version != $gtk_config_major_version) ||
+ (gtk_minor_version != $gtk_config_minor_version) ||
+ (gtk_micro_version != $gtk_config_micro_version))
+ {
+ printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+ $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf ("*** was found! If gtk-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+ printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+ else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+ (gtk_minor_version != GTK_MINOR_VERSION) ||
+ (gtk_micro_version != GTK_MICRO_VERSION))
+ {
+ printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+ else
+ {
+ if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+ printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+no_gtk=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_gtk" = x ; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ :
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ if test "$GTK_CONFIG" = "no" ; then
+ echo "*** The gtk-config script installed by GTK could not be found"
+ echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GTK_CONFIG environment variable to the"
+ echo "*** full path to gtk-config."
+ else
+ if test -f conf.gtktest ; then
+ :
+ else
+ echo "*** Could not run GTK test program, checking why..."
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version));
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GTK or finding the wrong"
+ echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+ echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+ echo "*** may want to edit the gtk-config script: $GTK_CONFIG"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ fi
+
+
+ rm -f conf.gtktest
+
+
+
+
+
+
+
+# Check whether --with-gl-prefix or --without-gl-prefix was given.
+if test "${with_gl_prefix+set}" = set; then
+ withval="$with_gl_prefix"
+ gl_prefix="$withval"
+else
+ gl_prefix=""
+fi;
+
+
+# Check whether --with-gtkgl-prefix or --without-gtkgl-prefix was given.
+if test "${with_gtkgl_prefix+set}" = set; then
+ withval="$with_gtkgl_prefix"
+ gtkgl_prefix="$withval"
+else
+ gtkgl_prefix=""
+fi;
+
+
+
+if test x$gl_prefix != x ; then
+ GL_CFLAGS="-I$gl_prefix/include"
+ GL_LDOPTS="-L$gl_prefix/lib"
+else
+ GL_CFLAGS=""
+ GL_LDOPTS=""
+fi
+
+saved_LIBS="$LIBS"
+saved_CFLAGS="$CFLAGS"
+
+# test for plain OpenGL
+echo "$as_me:$LINENO: checking GL" >&5
+echo $ECHO_N "checking GL... $ECHO_C" >&6
+LIBS="$GTK_LIBS $GL_LDOPTS -lGLU -lGL $saved_LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+ char glBegin(); glBegin();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ have_GL=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+have_GL=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $have_GL" >&5
+echo "${ECHO_T}$have_GL" >&6
+
+if test x$have_GL = xyes; then
+
+ GL_LIBS="-lGLU -lGL"
+
+else
+
+ # test for Mesa
+ echo "$as_me:$LINENO: checking Mesa" >&5
+echo $ECHO_N "checking Mesa... $ECHO_C" >&6
+ LIBS="$saved_LIBS $GTK_LIBS $GL_LDOPTS -lMesaGLU -lMesaGL"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+ char glBegin(); glBegin();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ have_Mesa=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+have_Mesa=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $have_Mesa" >&5
+echo "${ECHO_T}$have_Mesa" >&6
+
+ if test x$have_Mesa = xyes; then
+
+ GL_LIBS="-lMesaGLU -lMesaGL"
+
+ else
+
+ # test for Mesa with threads
+ echo "$as_me:$LINENO: checking Mesa with pthreads" >&5
+echo $ECHO_N "checking Mesa with pthreads... $ECHO_C" >&6
+ LIBS="$GTK_LIBS $GL_LDOPTS -lMesaGL -lMesaGLU -lpthread $saved_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+ char glBegin(); glBegin();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ have_Mesa_pthread=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+have_Mesa_pthread=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $have_Mesa_pthread" >&5
+echo "${ECHO_T}$have_Mesa_pthread" >&6
+
+ if test x$have_Mesa_pthread = xyes; then
+
+ GL_LIBS="-lMesaGLU -lMesaGL -lpthread"
+
+ else
+
+ #all failed
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_LIBS=""
+ GTKGL_CFLAGS=""
+ build_gtkgl=false
+
+ fi
+ fi
+fi
+
+
+if test x$gtkgl_prefix != x; then
+ GTKGL_CFLAGS="-I$gtkgl_prefix/include"
+ GTKGL_LDOPTS="-L$gtkgl_prefix/lib"
+else
+ GTKGL_CFLAGS=""
+ GTKGL_LDOPTS=""
+fi
+
+echo "$as_me:$LINENO: checking GtkGLArea" >&5
+echo $ECHO_N "checking GtkGLArea... $ECHO_C" >&6
+LIBS="$GTK_LIBS $GL_LDOPTS -lgtkgl $GL_LIBS $GTKGL_LDOPTS $saved_LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+ char gtk_gl_area_new(); gtk_gl_area_new();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ have_gtkgl=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+have_gtkgl=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $have_gtkgl" >&5
+echo "${ECHO_T}$have_gtkgl" >&6
+
+if test x$have_gtkgl = xyes; then
+
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_CFLAGS="$GTKGL_CFLAGS $GL_CFLAGS"
+ GTKGL_LIBS="$GTKGL_LDOPTS -lgtkgl $GL_LDOPTS $GL_LIBS"
+ build_gtkgl=true
+
+else
+
+ LIBS="$saved_LIBS"
+ CFLAGS="$saved_CFLAGS"
+ GTKGL_LIBS=""
+ GTKGL_CFLAGS=""
+ build_gtkgl=false
+
+fi
+
+
+
+
+
+
+if test "$build_gtkgl" != "true" ; then
+ echo "=============================================================="
+ echo "GView will not work without GtkGLArea widget, please install."
+ echo "See http://www.student.oulu.fi/~jlof/gtkglarea/"
+ echo "=============================================================="
+fi
+
+LIBS="$GTKGL_LDOPTS -lgtkgl $GL_LDOPTS $GL_LIBS $GTK_LIBS $LIBS"
+CFLAGS="$GTKGL_CFLAGS $GTK_CFLAGS $CFLAGS"
+
+
+
+
+# Check whether --with-gdal or --without-gdal was given.
+if test "${with_gdal+set}" = set; then
+ withval="$with_gdal"
+
+fi;
+
+if test "x$with_gdal" != "x" ; then
+ GDAL_HOME=$with_gdal
+ { echo "$as_me:$LINENO: Using requested GDAL_HOME of $GDAL_HOME" >&5
+echo "$as_me: Using requested GDAL_HOME of $GDAL_HOME" >&6;}
+elif test "x$GDAL_HOME" != "x" ; then
+ { echo "$as_me:$LINENO: Using predefined GDAL_HOME=$GDAL_HOME" >&5
+echo "$as_me: Using predefined GDAL_HOME=$GDAL_HOME" >&6;}
+elif test -f ../gdal/GDALmake.opt.in -o -f ../gdal/include/gdal.h ; then
+ GDAL_HOME=`pwd`/../gdal
+ { echo "$as_me:$LINENO: Found local GDAL_HOME=$GDAL_HOME" >&5
+echo "$as_me: Found local GDAL_HOME=$GDAL_HOME" >&6;}
+fi
+
+GDAL_LIB="-lgdal"
+
+ORIG_LIBS="$LIBS"
+LIBS="$GDAL_LIB -L$GDAL_HOME/lib $ORIG_LIBS"
+echo "$as_me:$LINENO: checking for GDALOpen in -lgdal" >&5
+echo $ECHO_N "checking for GDALOpen in -lgdal... $ECHO_C" >&6
+if test "${ac_cv_lib_gdal_GDALOpen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdal $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char GDALOpen ();
+int
+main ()
+{
+GDALOpen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_gdal_GDALOpen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_gdal_GDALOpen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_gdal_GDALOpen" >&5
+echo "${ECHO_T}$ac_cv_lib_gdal_GDALOpen" >&6
+if test $ac_cv_lib_gdal_GDALOpen = yes; then
+ gdal_found=1
+else
+ gdal_found=0
+fi
+
+
+if test "$gdal_found" != "1" ; then
+ LIBS="$GDAL_LIB -L$GDAL_HOME $ORIG_LIBS"
+ echo "$as_me:$LINENO: checking for GDALOpen in -lgdal" >&5
+echo $ECHO_N "checking for GDALOpen in -lgdal... $ECHO_C" >&6
+if test "${ac_cv_lib_gdal_GDALOpen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdal $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char GDALOpen ();
+int
+main ()
+{
+GDALOpen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_gdal_GDALOpen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_gdal_GDALOpen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_gdal_GDALOpen" >&5
+echo "${ECHO_T}$ac_cv_lib_gdal_GDALOpen" >&6
+if test $ac_cv_lib_gdal_GDALOpen = yes; then
+ gdal_found=1
+else
+ gdal_found=0
+fi
+
+fi
+
+if test "$gdal_found" != "1" ; then
+ LIBS="$ORIG_LIBS"
+ echo "$as_me:$LINENO: checking for GDALOpen in -lgdal" >&5
+echo $ECHO_N "checking for GDALOpen in -lgdal... $ECHO_C" >&6
+if test "${ac_cv_lib_gdal_GDALOpen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdal $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char GDALOpen ();
+int
+main ()
+{
+GDALOpen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_gdal_GDALOpen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_gdal_GDALOpen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_gdal_GDALOpen" >&5
+echo "${ECHO_T}$ac_cv_lib_gdal_GDALOpen" >&6
+if test $ac_cv_lib_gdal_GDALOpen = yes; then
+ gdal_found=1
+else
+ gdal_found=0
+fi
+
+fi
+
+gdal_missing_msg='
+OpenEV requires GDAL library, but it was not found. Please download
+and install it. See http://www.remotesensing.org/gdal
+'
+if test "$gdal_found" != "1" ; then
+ { { echo "$as_me:$LINENO: error: $gdal_missing_msg" >&5
+echo "$as_me: error: $gdal_missing_msg" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+gdal_h_missing_msg='
+OpenEV requires GDAL, but gdal.h was not found. Please ensure GDAL,
+and the development include files are installed, or that you run configure
+with --with-gdal=/path/to/gdal/installation.
+See http://www.remotesensing.org/gdal
+'
+
+GDAL_INC=""
+
+if test "x$GDAL_HOME" != "x" ; then
+
+ if test -f "$GDAL_HOME/include/gdal.h" ; then
+ GDAL_INC="-I$GDAL_HOME/include"
+ elif test -f "$GDAL_HOME/port/cpl_port.h" \
+ -a -f "$GDAL_HOME/gcore/gdal.h" \
+ -a -f "$GDAL_HOME/ogr/ogr_api.h" ; then
+ GDAL_INC="-I$GDAL_HOME/port -I$GDAL_HOME/gcore -I$GDAL_HOME/ogr"
+ else
+ { { echo "$as_me:$LINENO: error: $gdal_h_missing_msg" >&5
+echo "$as_me: error: $gdal_h_missing_msg" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+fi
+
+CPPFLAGS="$GDAL_INC $CPPFLAGS"
+
+
+for ac_header in gdal.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+if test "x$ac_cv_header_gdal_h" != "xyes" ; then
+ { { echo "$as_me:$LINENO: error: $gdal_h_missing_msg" >&5
+echo "$as_me: error: $gdal_h_missing_msg" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+GDAL_INC=$GDAL_INC
+
+cat >>confdefs.h <<_ACEOF
+#define USE_GDAL 1
+_ACEOF
+
+
+
+
+# Check whether --with-ogr or --without-ogr was given.
+if test "${with_ogr+set}" = set; then
+ withval="$with_ogr"
+
+fi;
+
+if test "$with_ogr" != no ; then
+ echo "checking for OGR ... enabled"
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OGR 1
+_ACEOF
+
+ CFLAGS="-I$GDAL_HOME/ogr/ogrsf_frmts $CFLAGS"
+ OGR_SOURCE=gvogr.cpp
+else
+ echo "checking for OGR ... disabled by user"
+ OGR_SOURCE=
+fi
+
+OGR_SOURCE=$OGR_SOURCE
+
+
+
+
+# Check whether --with-double-geocoord or --without-double-geocoord was given.
+if test "${with_double_geocoord+set}" = set; then
+ withval="$with_double_geocoord"
+
+fi;
+
+echo "$as_me:$LINENO: checking geoocord type" >&5
+echo $ECHO_N "checking geoocord type... $ECHO_C" >&6
+if test "$with_double_geocoord" == "yes" ; then
+ CFLAGS="$CFLAGS -DGV_USE_DOUBLE_PRECISION_COORD"
+ echo "$as_me:$LINENO: result: double" >&5
+echo "${ECHO_T}double" >&6
+else
+ echo "$as_me:$LINENO: result: float" >&5
+echo "${ECHO_T}float" >&6
+fi
+
+
+
+# Check whether --with-render-plugin or --without-render-plugin was given.
+if test "${with_render_plugin+set}" = set; then
+ withval="$with_render_plugin"
+
+fi;
+
+echo "$as_me:$LINENO: checking for plugin enabled" >&5
+echo $ECHO_N "checking for plugin enabled... $ECHO_C" >&6
+if test "$with_render_plugin" == "yes" ; then
+ # Will enable g_module_* code.
+ CFLAGS="$CFLAGS -malign-double -fPIC -DGV_USE_RENDER_PLUGIN"
+ # This is needed to access stuff inside libgv.a from the plugin.
+ LDFLAGS="$LDFLAGS -rdynamic"
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+
+# Check whether --with-debug or --without-debug was given.
+if test "${with_debug+set}" = set; then
+ withval="$with_debug"
+
+fi;
+
+echo "$as_me:$LINENO: checking debug/opt compile options" >&5
+echo $ECHO_N "checking debug/opt compile options... $ECHO_C" >&6
+
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-g //"`
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"`
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-O //"`
+
+if test "$with_debug" == "yes" ; then
+
+ OPTFLAGS=-g
+ echo "$as_me:$LINENO: result: adding -g" >&5
+echo "${ECHO_T}adding -g" >&6
+
+elif test "$with_debug" == "no" ; then
+
+ OPTFLAGS=-O2
+ echo "$as_me:$LINENO: result: adding -O2" >&5
+echo "${ECHO_T}adding -O2" >&6
+
+elif test "$with_debug" != "" ; then
+
+ OPTFLAGS=$with_debug
+ echo "$as_me:$LINENO: result: adding $with_debug" >&5
+echo "${ECHO_T}adding $with_debug" >&6
+
+else
+ OPTFLAGS="-O2 -g"
+ echo "$as_me:$LINENO: result: adding -O2 -g" >&5
+echo "${ECHO_T}adding -O2 -g" >&6
+fi
+
+
+CFLAGS=$CFLAGS
+
+OPTFLAGS=$OPTFLAGS
+
+ ac_config_files="$ac_config_files Makefile pymod/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf at gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "pymod/Makefile" ) CONFIG_FILES="$CONFIG_FILES pymod/Makefile" ;;
+ "gv_config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS gv_config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s, at SHELL@,$SHELL,;t t
+s, at PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s, at PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s, at PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s, at PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s, at PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s, at PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s, at exec_prefix@,$exec_prefix,;t t
+s, at prefix@,$prefix,;t t
+s, at program_transform_name@,$program_transform_name,;t t
+s, at bindir@,$bindir,;t t
+s, at sbindir@,$sbindir,;t t
+s, at libexecdir@,$libexecdir,;t t
+s, at datadir@,$datadir,;t t
+s, at sysconfdir@,$sysconfdir,;t t
+s, at sharedstatedir@,$sharedstatedir,;t t
+s, at localstatedir@,$localstatedir,;t t
+s, at libdir@,$libdir,;t t
+s, at includedir@,$includedir,;t t
+s, at oldincludedir@,$oldincludedir,;t t
+s, at infodir@,$infodir,;t t
+s, at mandir@,$mandir,;t t
+s, at build_alias@,$build_alias,;t t
+s, at host_alias@,$host_alias,;t t
+s, at target_alias@,$target_alias,;t t
+s, at DEFS@,$DEFS,;t t
+s, at ECHO_C@,$ECHO_C,;t t
+s, at ECHO_N@,$ECHO_N,;t t
+s, at ECHO_T@,$ECHO_T,;t t
+s, at LIBS@,$LIBS,;t t
+s, at CC@,$CC,;t t
+s, at CFLAGS@,$CFLAGS,;t t
+s, at LDFLAGS@,$LDFLAGS,;t t
+s, at CPPFLAGS@,$CPPFLAGS,;t t
+s, at ac_ct_CC@,$ac_ct_CC,;t t
+s, at EXEEXT@,$EXEEXT,;t t
+s, at OBJEXT@,$OBJEXT,;t t
+s, at CXX@,$CXX,;t t
+s, at CXXFLAGS@,$CXXFLAGS,;t t
+s, at ac_ct_CXX@,$ac_ct_CXX,;t t
+s, at RANLIB@,$RANLIB,;t t
+s, at ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s, at CPP@,$CPP,;t t
+s, at EGREP@,$EGREP,;t t
+s, at CXX_WFLAGS@,$CXX_WFLAGS,;t t
+s, at C_WFLAGS@,$C_WFLAGS,;t t
+s, at CXX_PIC@,$CXX_PIC,;t t
+s, at C_PIC@,$C_PIC,;t t
+s, at LD_SHARED@,$LD_SHARED,;t t
+s, at PYTHON@,$PYTHON,;t t
+s, at pythondir@,$pythondir,;t t
+s, at pyexecdir@,$pyexecdir,;t t
+s, at PYTHON_INCLUDES@,$PYTHON_INCLUDES,;t t
+s, at PYTHON_CC@,$PYTHON_CC,;t t
+s, at PYTHON_OPT@,$PYTHON_OPT,;t t
+s, at PYTHON_SO@,$PYTHON_SO,;t t
+s, at PYTHON_CFLAGS@,$PYTHON_CFLAGS,;t t
+s, at PYTHON_LINK@,$PYTHON_LINK,;t t
+s, at GTK_CONFIG@,$GTK_CONFIG,;t t
+s, at GTK_CFLAGS@,$GTK_CFLAGS,;t t
+s, at GTK_LIBS@,$GTK_LIBS,;t t
+s, at GTKGL_CFLAGS@,$GTKGL_CFLAGS,;t t
+s, at GTKGL_LIBS@,$GTKGL_LIBS,;t t
+s, at GDAL_INC@,$GDAL_INC,;t t
+s, at OGR_SOURCE@,$OGR_SOURCE,;t t
+s, at OPTFLAGS@,$OPTFLAGS,;t t
+s, at LIBOBJS@,$LIBOBJS,;t t
+s, at LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s, at configure_input@,$configure_input,;t t
+s, at srcdir@,$ac_srcdir,;t t
+s, at abs_srcdir@,$ac_abs_srcdir,;t t
+s, at top_srcdir@,$ac_top_srcdir,;t t
+s, at abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s, at builddir@,$ac_builddir,;t t
+s, at abs_builddir@,$ac_abs_builddir,;t t
+s, at top_builddir@,$ac_top_builddir,;t t
+s, at abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
Property changes on: packages/openev/branches/upstream/current/configure
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/configure.in
===================================================================
--- packages/openev/branches/upstream/current/configure.in (rev 0)
+++ packages/openev/branches/upstream/current/configure.in 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,212 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(Makefile.in)
+AC_CONFIG_HEADER(gv_config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+
+AC_PROG_RANLIB
+
+dnl We always want to check /usr/local for stuff.
+LIBS="$LIBS -L/usr/local/lib"
+CFLAGS="$CFLAGS -I/usr/local/include"
+CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+
+dnl Checks for libraries.
+AC_CHECK_LIB(dl,dlopen,,,)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h unistd.h dbmalloc.h dlfcn.h string.h strings.h)
+
+dnl Checks for library functions.
+AC_C_BIGENDIAN
+AC_FUNC_VPRINTF
+
+AC_COMPILER_WFLAGS
+AC_COMPILER_PIC
+AC_LD_SHARED
+
+dnl
+dnl Python related checks.
+dnl
+AM_PATH_PYTHON
+
+AM_INIT_PYEXEC_MOD
+
+AM_CHECK_PYMOD(thread,,extra_mods=gthread,extra_mods=)
+
+AM_PATH_GTK(1.2.1,,,$extra_mods)
+
+AM_PATH_GTKGL(build_gtkgl=true, build_gtkgl=false)
+
+if test "$build_gtkgl" != "true" ; then
+ echo "=============================================================="
+ echo "GView will not work without GtkGLArea widget, please install."
+ echo "See http://www.student.oulu.fi/~jlof/gtkglarea/"
+ echo "=============================================================="
+fi
+
+LIBS="$GTKGL_LDOPTS -lgtkgl $GL_LDOPTS $GL_LIBS $GTK_LIBS $LIBS"
+CFLAGS="$GTKGL_CFLAGS $GTK_CFLAGS $CFLAGS"
+
+dnl ---------------------------------------------------------------------------
+
+dnl
+dnl Find the required GDAL libraries, and include files.
+dnl
+
+AC_ARG_WITH(gdal,[ --with-gdal[=ARG] Path to GDAL installation tree],,)
+
+if test "x$with_gdal" != "x" ; then
+ GDAL_HOME=$with_gdal
+ AC_MSG_NOTICE([Using requested GDAL_HOME of $GDAL_HOME])
+elif test "x$GDAL_HOME" != "x" ; then
+ AC_MSG_NOTICE([Using predefined GDAL_HOME=$GDAL_HOME])
+elif test -f ../gdal/GDALmake.opt.in -o -f ../gdal/include/gdal.h ; then
+ GDAL_HOME=`pwd`/../gdal
+ AC_MSG_NOTICE([Found local GDAL_HOME=$GDAL_HOME])
+fi
+
+GDAL_LIB="-lgdal"
+
+dnl Check $GDAL_HOME/lib for library binary first.
+ORIG_LIBS="$LIBS"
+LIBS="$GDAL_LIB -L$GDAL_HOME/lib $ORIG_LIBS"
+AC_CHECK_LIB(gdal,GDALOpen,gdal_found=1,gdal_found=0)
+
+dnl Not found? Now check $GDAL_HOME.
+if test "$gdal_found" != "1" ; then
+ LIBS="$GDAL_LIB -L$GDAL_HOME $ORIG_LIBS"
+ AC_CHECK_LIB(gdal,GDALOpen,gdal_found=1,gdal_found=0)
+fi
+
+dnl Still not found? Check for system wide installation.
+if test "$gdal_found" != "1" ; then
+ LIBS="$ORIG_LIBS"
+ AC_CHECK_LIB(gdal,GDALOpen,gdal_found=1,gdal_found=0)
+fi
+
+gdal_missing_msg='
+OpenEV requires GDAL library, but it was not found. Please download
+and install it. See http://www.remotesensing.org/gdal
+'
+if test "$gdal_found" != "1" ; then
+ AC_MSG_ERROR([$gdal_missing_msg])
+fi
+
+gdal_h_missing_msg='
+OpenEV requires GDAL, but gdal.h was not found. Please ensure GDAL,
+and the development include files are installed, or that you run configure
+with --with-gdal=/path/to/gdal/installation.
+See http://www.remotesensing.org/gdal
+'
+
+GDAL_INC=""
+
+if test "x$GDAL_HOME" != "x" ; then
+
+ if test -f "$GDAL_HOME/include/gdal.h" ; then
+ GDAL_INC="-I$GDAL_HOME/include"
+ elif test -f "$GDAL_HOME/port/cpl_port.h" \
+ -a -f "$GDAL_HOME/gcore/gdal.h" \
+ -a -f "$GDAL_HOME/ogr/ogr_api.h" ; then
+ GDAL_INC="-I$GDAL_HOME/port -I$GDAL_HOME/gcore -I$GDAL_HOME/ogr"
+ else
+ AC_MSG_ERROR([$gdal_h_missing_msg])
+ fi
+
+fi
+
+CPPFLAGS="$GDAL_INC $CPPFLAGS"
+
+AC_CHECK_HEADERS(gdal.h)
+if test "x$ac_cv_header_gdal_h" != "xyes" ; then
+ AC_MSG_ERROR([$gdal_h_missing_msg])
+fi
+
+AC_SUBST(GDAL_INC,$GDAL_INC)
+AC_DEFINE_UNQUOTED(USE_GDAL)
+
+dnl --------------------------------------------------------------------------
+
+AC_ARG_WITH(ogr,[ --with-ogr Enable OGR Linkage],,)
+
+if test "$with_ogr" != no ; then
+ echo "checking for OGR ... enabled"
+ AC_DEFINE_UNQUOTED(HAVE_OGR)
+ CFLAGS="-I$GDAL_HOME/ogr/ogrsf_frmts $CFLAGS"
+ OGR_SOURCE=gvogr.cpp
+else
+ echo "checking for OGR ... disabled by user"
+ OGR_SOURCE=
+fi
+
+AC_SUBST(OGR_SOURCE,$OGR_SOURCE)
+
+dnl --------------------------------------------------------------------------
+
+AC_ARG_WITH(double-geocoord,[ --with-double-geocoord Use double precision GL coordinates],,)
+
+AC_MSG_CHECKING([geoocord type])
+if test "$with_double_geocoord" == "yes" ; then
+ CFLAGS="$CFLAGS -DGV_USE_DOUBLE_PRECISION_COORD"
+ AC_MSG_RESULT([double])
+else
+ AC_MSG_RESULT([float])
+fi
+
+dnl --------------------------------------------------------------------------
+
+AC_ARG_WITH(render-plugin,[ --with-render-plugin Enable plugin (rendering)],,)
+
+AC_MSG_CHECKING([for plugin enabled])
+if test "$with_render_plugin" == "yes" ; then
+ # Will enable g_module_* code.
+ CFLAGS="$CFLAGS -malign-double -fPIC -DGV_USE_RENDER_PLUGIN"
+ # This is needed to access stuff inside libgv.a from the plugin.
+ LDFLAGS="$LDFLAGS -rdynamic"
+
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
+dnl --------------------------------------------------------------------------
+
+AC_ARG_WITH(debug,[ --with-debug Build debug (else optimized)],,)
+
+AC_MSG_CHECKING([debug/opt compile options])
+
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-g //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-g //"`
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"`
+CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O //"`
+CFLAGS=`echo "$CFLAGS " | sed "s/-O //"`
+
+if test "$with_debug" == "yes" ; then
+
+ OPTFLAGS=-g
+ AC_MSG_RESULT([adding -g])
+
+elif test "$with_debug" == "no" ; then
+
+ OPTFLAGS=-O2
+ AC_MSG_RESULT([adding -O2])
+
+elif test "$with_debug" != "" ; then
+
+ OPTFLAGS=$with_debug
+ AC_MSG_RESULT([adding $with_debug])
+
+else
+ OPTFLAGS="-O2 -g"
+ AC_MSG_RESULT([adding -O2 -g])
+fi
+
+
+AC_SUBST(CFLAGS,$CFLAGS)
+AC_SUBST(OPTFLAGS,$OPTFLAGS)
+AC_OUTPUT(Makefile pymod/Makefile)
Added: packages/openev/branches/upstream/current/contrib/S52/COPYING
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/COPYING (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/COPYING 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Added: packages/openev/branches/upstream/current/contrib/S52/ChangeLog
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/ChangeLog (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/ChangeLog 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,160 @@
+05OCT2004
+ -update new code to CVS
+
+04OCT2004
+ -rtag freeze_V-1_0
+
+22AUG2004
+ -add S52_obj handle
+ -refactor code to work with S52_obj
+ -change ex0 traget and code to S52glxsimple
+ -add target s52osg
+ -add code to create an .osg file for osgviewer
+ -reorganize Makefile
+
+21JUL2004
+ -add color palette switch 'on-the-fly'
+
+12JUL2004
+ -code clean up
+ -add better text handling (GL)
+ -add light translation into text (CS)
+ -various bug fix
+
+01JUL2004
+ -removed S52rgb
+ -add display supression of object (PL)
+ -add palette selection (utils)
+ -add font creation in gvS57layer
+ -code cleanup
+
+27JUN2004
+ -fix pattern/projection
+ -code cleanup
+ -fix unlink object after pick
+ -set correct extend by loading M_COVR first
+ -optimize tess to strip/fan
+
+26JUN2004
+ -add a bounch of update from Christian Tveen
+ -indexed color
+ -pick return list of S57 object
+ -parse attribute list for official att
+ -some work on priority handling
+ -fix leak
+ -add solaris switch
+ -clean up some projection code
+ -clean up code formatting
+
+21JUN2004
+ -move PROJ stuff in S57data
+
+20JUN2004
+ -generalise S57 loading (GV/OGR)
+ -mod initGL to S52_GL_initGL
+ -fix pattern
+
+22MAI2004
+ -move Christian code in main branch
+ -update README
+ -mod Makefile
+
+19MAI2004
+ -add Christian code to split GV/OGR dependency
+ --add ex0_xwin.c, ogrS57layers.c, S57data.[ch], S57ogr.[ch]
+
+07MAI2004
+ -mod LUP table name for indexing (PL)
+ -add mariner selection for are/line (conf)
+ -mod for futur object layer switching code (GL)
+ -bunch of code cleanup
+ -add S52_MAR_SYMPLIFIED_PNT (utils)
+
+03MAI2004
+ -started cursor pick
+
+27APR2004
+ -add glcontext switching
+ -removed dependency to openev STENCIL glcontext
+ -start color handling (CIE->RGB)
+
+26APR2004
+ -extend size feedback buffer (GL)
+ -add Z clip plane for line removal (GL)
+
+25APR2004
+ -add GL selection for OBSTRN04 (CS)
+ -add GL selection for WRECKS02 (CS)
+
+20APR2004
+ -add GL selection for DEPCNT02 (CS)
+
+12APR2004
+ -add line mask for line object and area object
+
+09APR2004
+ -merge obj attributs with obj geo
+
+07APR2004
+ -move vector parser into PL module (GL/PL)
+ -code clean up
+
+02APR2004
+ -mariner parameter handling
+ -attribute handling
+ -start coding LIGHTS05
+
+18MAR2004
+ -fix area pattern upside down (GL)
+ -add layer override logic
+
+16MAR2004
+ -add antialiase
+ -fix line orientation for area object
+
+12MAR2004
+ -fix upside down complex line style (GL)
+
+10MAR2004
+ -fix typo: FSHRES51, ACHRES51, DIAMOND1 (CS)
+
+08MAR2004
+ -add symbol orientation
+
+07MAR2004
+ -add default color (PL)
+ -add nature of seabed abbreviation (PL)
+ -fix symbol creation (GL)
+ -fix symbol tansparency
+
+26FEB2004
+ -fix symbol drawn with point (SPRING)
+
+25FEB2004
+ -fix area obstruction in AA5C1JKL.000 (CS)
+
+20FEB2004
+ -fix list number (dec to octal in CS)
+ -check data type correctness w/ g++ (CS)
+
+16FEB2004
+ -fix depth symbols (CS)
+
+15FRB2004
+ -exclude stuff outside view window (GL)
+
+10FEB2004
+ -fix tess problem in Chart No 1
+
+20JAN2004
+ -patch removed since Frank commited it to OpenEV
+
+04JAN2004
+ -opaque pointer for global PLib struct
+ -opaque pointer for global geo data struct
+
+23DEC2003
+ -add code for plugin,
+ -add projection (mercator)
+ -code clean up
+
Added: packages/openev/branches/upstream/current/contrib/S52/Makefile
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/Makefile (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/Makefile 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,182 @@
+# Makefile: build libS52.so for openev plugin
+#
+# SD AUG2004
+
+### TARGET SELECTION SECTION ###
+#all: default # normal (openev plugin) --using GV & GTK
+#all: test # debug (static) --using GV & GTK
+#all: osg # debug (static) --using GV, GTK & OSG
+all: glx # debug (static) --using only GLX & OGR
+
+
+### VARIABLES SECTION ###
+#CC = tcc
+#CC = gcc
+#CC = gcc-2.95
+CC = gcc-3.4
+
+#CXX = g++-2.95 -O0
+#CXX = g++ -O0
+#CXX = g++-3.4 -O0 -fpermissive
+CXX = g++-3.4
+
+TAGS = ctags
+
+OPENEV_HOME = ../../openev
+
+CFLAGS = -malign-double -fPIC `gtk-config --cflags` \
+ -I. -I$(OPENEV_HOME) \
+ -I/usr/X11R6/include -DGV_USE_DOUBLE_PRECISION_COORD\
+ -I/usr/local/include
+
+LDFLAGS = -rdynamic
+
+OGL_LIBS = -lGL -lGLU
+OSG_LIBS = -losg -losgProducer
+GTK_LIBS = -lgtkgl -lgtk -lgdk
+GV__LIBS = $(OPENEV_HOME)/libgv.a
+
+LIBS = -L/usr/lib -L/usr/local/lib \
+ -lgmodule -lgthread -lglib -lgdal -lproj \
+ $(OGL_LIBS)
+
+OBJS = S52.o S52raz-3.2.rle.o S57data.o S52GL.o S52PL.o S52CS.o S52utils.o
+
+
+### TARGETS' VARIABLES ###
+# this is the normal build (openev plugin)
+default: CC += -O2
+default: CFLAGS += -DS52_USE_GV
+default: objs = $(OBJS) gvS57layer.o S57gvgeo.o
+default: libs = $(LIBS) $(GTK_LIBS) $(GV__LIBS) ./libS52.so
+default: gvS57layer.o S57gvgeo.o libS52.so s52plugin
+
+# this wil build a 'stand-alone' for debuging (see bellow)
+test: CC += -O0 -g -Wall
+test: CFLAGS += -DS52_USE_GV
+test: objs = $(OBJS) gvS57layer.o S57gvgeo.o
+test: libs = $(LIBS) $(GTK_LIBS) $(GV__LIBS) ./libS52.a
+test: gvS57layer.o S57gv.o libS52.a s52test
+
+# this will build a 'stand alone' that use OSG
+osg: CC += -O0 -g -Wall
+osg: CFLAGS += -DS52_USE_GV -DS52_USE_OSG
+osg: objs = $(OBJS) gvS57layer.o S57gvgeo.o S52OSG.o
+osg: libs = $(LIBS) $(GTK_LIBS) ./libS52.a $(GV__LIBS) -losg -losgProducer
+osg: gvS57layer.o S57gv.o S52OSG.o libS52.a s52osg
+
+# this will build a 'stand alone' for GLX and OGR only
+# (ie will not depend on GTK or GV)
+glx: CC += -O0 -g -Wall
+glx: objs = $(OBJS) S57ogr.o
+glx: libs = $(LIBS) ./libS52.a
+glx: S57ogr.o libS52.a s52glxsimple
+
+### COMPILE SECTION ###
+#S57gvgeo.o: S57gvgeo.c S57src.h
+#S57gvgeo.o:S57gvgeo.c
+# $(CC) $(CFLAGS) -c S57gvgeo.c
+
+#S57ogr.o: S57ogr.c S57src.h
+# $(CC) $(CFLAGS) -c S57ogr.c
+
+#s52test.o: s52test.c
+# $(CC) $(CFLAGS) -c s52test.c
+
+#%.o : %.c
+%.o : %.c %.h
+ -rm libS52.a
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.cpp S52OSG.cpp.h %.h
+ $(CXX) $(CFLAGS) -c $<
+
+# precompile header
+S52OSG.cpp.h:
+ $(CXX) $(CFLAGS) -c $@
+
+S52OSG.h:
+ $(CXX) $(CFLAGS) -c $@
+
+# assembler
+#S52raz-3.2.rle.o: S52raz-3.2.rle
+# -rm -f data2obj.s
+# sed -e 's/VAR_NAME/S52raz/' \
+# -e 's/VAR_LEN/S52razLen/' \
+# -e 's/DATAFILE/S52raz-3.2.rle/' \
+# data2obj.tmpl > data2obj.s
+# gcc -c data2obj.s -o $@
+
+#S52raz-3.2.rle.o: S52raz-3.2.rle S52raz.s
+S52raz-3.2.rle.o:
+ gcc -c S52raz.s -o $@
+
+
+### LINK SECTION ###
+# dynamic --libgv.a will load libS52.so plug-in
+# Note: S52utils is needed before libS52.so is up
+s52plugin: s52test.o libS52.so $(GV__LIBS)
+# @echo LIBS: $(LIBS)
+ $(CC) $(LDFLAGS) s52test.o S52utils.o $(libs) -o $@
+
+libS52.so: $(OBJS)
+ $(CC) -shared -o libS52.so $(objs)
+
+### DEBUG SECTION ###
+#
+# For this next target (s52test & s52osg) to link staticaly
+# replace the code in gv_shapes_layer_set_data() inside the
+# #define GV_USE_RENDER_PLUGIN with:
+#
+# extern void gv_S57_layer_init(GvShapesLayer *layer);
+# gv_S57_layer_init(layer);
+#
+# Then run 'make libgv.a' from openev before building s52test.
+# (Note that this break the gvtest build because the symbol
+# gv_S57_layer_init is unknown to GV. But will allow to build
+# s52test staticaly.)
+#
+# static --debug, libgv.a is linked to libS52.a
+
+# debug --libS52.a
+s52test: s52test.o libS52.a $(GV__LIBS)
+ $(CC) s52test.o $(libs) -o $@
+
+# debug --same + OSG
+s52osg: s52test.o libS52.a $(GV__LIBS)
+ $(CC) s52test.o $(libs) -o $@
+
+# debug --this target depend on only on GLX & OGR (not GV, GTK)
+# --no need to edit code in OpenEV
+s52glxsimple: S52glxsimple.o libS52.a
+ $(CC) S52glxsimple.o $(libs) -o $@
+
+# debug (static)
+libS52.a: $(OBJS)
+# @echo "OBJS: $(objs)"
+ rm -f $@
+ ar cq $@ $(objs)
+ ranlib $@
+
+
+
+### UTILS SECTION ###
+clean:
+ rm -f s52plugin s52test s52osg s52glxsimple *.o *.s *.gch \
+ libS52.a libS52.so tags try openc.*
+
+install:
+ install libS52.so `gdal-config --prefix`/lib
+
+uninstall:
+ rm -f `gdal-config --prefix`/lib/libS52.so
+
+backup: clean
+ tar cvf openc.tar *
+ bzip2 openc.tar
+
+tags:
+ $(TAGS) *.c *.h
+
+run:
+ ./s52test
Added: packages/openev/branches/upstream/current/contrib/S52/README
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/README (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/README 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,184 @@
+README: OpENCview project, libS52.so installation notes and disclaimer
+
+Spetember 2004
+
+
+INTRODUCTION:
+=============
+
+OpENCview is a project to build an Open Source viewer of
+Electronic Navigational Chart (ENC).
+
+This release implement basic rendering of IHO' S-52
+(IHO, ECDIS PRESENTATION LIBRARY, USERS' MANUAL, Edition / revision 3.2,
+March 2000, Special Publication No. 52 ANNEX A of APPENDIX 2,
+published by the International Hydrographic Bureau, MONACO)
+via the plugin libS52.so for OpenEV. Note that the current Edition of
+the S-52 specification is 4.2 and is not available for free download as
+was Ed. 3.2 (pslb03_2.pdf) from IHO web site.
+
+This software is not intended for general public but to
+interested party in the GIS/marine field.
+
+
+DISCLAIMER:
+===========
+
+OpENCview is not indented for navigational use. It cannot
+be used as a paper chart replacement.
+
+
+SPECIFICATION:
+==============
+
+All specification used to code libS52.so are available
+for free from the Internet:
+
+organization specs specs URL / Implementation URL
+------------ ----- ----------------------------
+
+IHO S-52 IHO S-52 USERS' MANUAL, Ed. 3.2
+ www.iho.shom.fr/general/ecdis/pslb03_2.pdf
+ Implementor: Sylvain Duclos
+ cvs.sourceforge.net:/cvsxroot/openev/contrib/S52
+
+IHO S-57 IHO S-57 Appendix B.1
+ www.iho.shom.fr/general/ecdis/20SOC.pdf
+ Implementor: Frank Warmerdam
+ gdal.velocet.ca/projects/s57/
+
+OpenGIS OpenGIS OpenGIS Abstract Specification
+ www.opengis.org/techno/specs.htm
+ Implementor: Frank Warmerdam
+ gdal.velocet.ca/projects/opengis/
+
+SGI OpenGL OpenGL Specification
+ www.opengl.org/developers/documentation/index.html
+ Implementor: Brian Paul
+ www.mesa3d.org
+
+X.Org X Window Sys. X Window System
+ www.x.org
+ Implementor: The XFree86 Project Inc.
+ www.xfree86.org
+
+
+
+INSTALLATION:
+=============
+
+Linux/Unix:
+-----------
+
+1- generate configure for openev:
+ $cd ../../openev
+ $autoconf
+
+2- configure openev:
+ $./configure --with-gdal=<your_full_path_to>/gdal \
+ --with-ogr --with-double-geocoord --with-render-plugin
+
+3- compile openev:
+ $make clean
+ $make
+
+4- compile libS52:
+ $cd openev/contrib/S52
+ $make
+
+5- install libS52.so in /usr/local/lib (as root):
+ #make install
+
+6- set environnement variable:
+ $export S57_CSV=<path_to_gdal_data_directory>
+ $export OGR_S57_OPTIONS=LNAM_REFS:ON,UPDATES:ON,\
+ SPLIT_MULTIPOINT:ON,PRESERVE_EMPTY_NUMBERS:ON,\
+ RETURN_LINKAGES:ON
+
+7- test:
+ $openev/openev/gvtest -ogr=<ENC>
+ -OR-
+ $openev/contrib/S52/s52testdyn (s52test.conf will need ENC path ajusted)
+
+Windows:
+--------
+
+1- FIXME!
+
+
+FILE LIST:
+==========
+
+In openev/contrib/S52 are the following files:
+
+ ChangeLog -log of code change,
+ COYING -GPL license,
+ Makefile -make instruction to build libS52.so,
+ README -this file,
+ S52CS.c -S52 Conditional Symbology (CS) instruction
+ S52CS.h -interface to CS,
+ S52GL.c -OpenGL S52 renderer (GL),
+ S52GL.h -interface to GL,
+ S52PL.c -S52 Presentation Library parser (PL),
+ S52PL.h -interface to PL,
+ S52raz-3.2.rle -data: alternate rasterization rules,
+ S52type.h -header for S52 primitive type,
+ S52utils.c -utilitys,
+ S52utils.h -interface to utilitys,
+ S57gvgeo.c -connect to OpenEV (gv) geo data (S57),
+ S57ogr.c -connect to OGR data,
+ S57src.h -interface to S57gvgeo & S57ogr,
+ S57data.c -handle S57 data,
+ S57data.h -interface to S57 data,
+ TODO -jot pad for missing stuff,
+ data2obj.tmpl -template to create ELF object from data files (above)
+ doc/ -directory olding various notes
+ doc/C1.lup_collision.txt -list of objects that can switch layers (IHO)
+ doc/S57.note -note on S57 DB structure,
+ doc/obj.txt -S57 objects
+ doc/att.txt. -S57 attibutes
+ doc/boylat24.dia -BOYLAT24 object construct seen from S52 (Dia)
+ doc/boylat24.png -boylat24.dia converted to PNG
+ gvS57layer.c -plugin entree point / interface to openev (static link),
+ gvS57layer.h -interface to plugin (for completness --useless in real life),
+ ogrS57layer.c -handle OGR layer,
+ ex0_xwin.c -test harness for debugging (OGR path),
+ s52test.c -test harness for debuging (GV path),
+ s52test.conf -local configuration for debuging.
+
+
+REQUIREMENT:
+============
+
+-OpenEV (falcultative),
+
+-GDAL,
+
+-PROJ4,
+
+-A Presentation Library .DAI file his also required for symbolizing S57.
+As of this writing the current Official Presentation Library
+is Edition 4.2, and is available directly from the IHB
+(International Hydrographic Bureau) at info at ihb.mc.
+In the absence of an Official IHO Presentation Library
+an alternate non-conforming ECDIS library is used (S52raz-3.2.rle.)
+
+
+LINKS:
+======
+
+Frank Warmerdam web site as bunch of links:
+gdal.velocet.ca/projects/s57/
+
+
+CREDIT:
+=======
+
+Frank Warmerdam (warmerdam at pobox dot com) OpenEV/GDAL/OGR/S-57.
+Christian Gebauer Tveen (cgt at navicon dot dk) GV/OGR split.
+
+
+Comment / inquiry are welcome,
+
+Sylvain Duclos
+sduclos at users.sourceforgue.net
\ No newline at end of file
Added: packages/openev/branches/upstream/current/contrib/S52/S52.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,186 @@
+// S52.c: top-level interface to libS52.so plug-in
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview porject, a viewer of ENC.
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#include "S52.h"
+#include "S52utils.h" // PRINTF()
+#include "S52PL.h" // S52_PRIO_NUM
+#include "S57ogr.h" // S57_ogrLoadCell
+#include "S52GL.h" // S52_GL_draw()
+
+#include <glib.h> // GString, GPtrArray
+#include <string.h> // strcmp()
+
+typedef struct _cell {
+ GString *filename;
+ GPtrArray *renderBin[S52_PRIO_NUM][N_OBJ_T];//[RAD_NUM];
+} _cell;
+
+static GArray *_cellList = NULL;
+static _cell *_crntCell = NULL;
+
+static int _loadLayer()
+{
+ return 1;
+}
+
+static int _loadAux()
+{
+ return 1;
+}
+
+static int _doneAux()
+{
+ return 1;
+}
+
+static int _addCell(const char *filename)
+// add this cell if not allready loaded
+{
+ _cell cell;
+ int i = 0;
+
+ if (NULL == _cellList)
+ _cellList = g_array_new(FALSE, TRUE, sizeof(_cell));
+
+ // check if loaded
+ for (i=0; i<_cellList->len; ++i) {
+ _cell *c = &g_array_index(_cellList, _cell, i);
+
+ if (0 == strcmp(filename, c->filename->str))
+ return 0;
+ }
+
+ cell.filename = g_string_new(filename);
+ { // init renderbin
+ int i,j;
+ for (i=0; i<S52_PRIO_NUM; ++i) {
+ for (j=0; j<N_OBJ_T; ++j)
+ cell.renderBin[i][j] = g_ptr_array_new();
+ }
+ }
+
+ // if not load it
+ _cellList = g_array_append_val(_cellList, cell);
+ _crntCell = &g_array_index(_cellList, _cell, _cellList->len-1);
+
+ // load metadata
+ //S57_ogrLoadLayer("M_COVR");
+
+
+ // load data
+
+ return 1;
+}
+
+cellID S52_loadCell(const char *filename, _loadLayer_cb cb)
+{
+ // MUTEX
+
+ _addCell(filename);
+
+ S57_ogrLoadCell(filename, cb);
+
+ // done aux. data
+
+ return 1;
+}
+
+int S52_loadLayer(const char *layername, void *ogrlayer)
+{
+ PRINTF("NOTE: LAYER NAME: %s\n", layername);
+
+ S57_ogrLoadLayer(layername, ogrlayer, S52_loadObject);
+
+ return 1;
+}
+
+int S52_loadObject(const char *objname, void *shape)
+{
+ if (NULL == shape)
+ return FALSE;
+
+#ifdef S52_USE_GV
+ S57_geo *geoData = S57_gvObjectClone(objname, (srcData*)shape);
+#else
+ S57_geo *geoData = S57_ogrLoadObject(objname, (srcData*)shape);
+#endif
+
+ // debug
+ if (0 == strcmp(objname,"M_COVR"))
+ S52_GL_objectSetup(geoData);
+
+ if (NULL != geoData) {
+ int obj_t;
+ S52_Obj_t ot = S57_getObjtype(geoData);
+ S52_obj *obj = S52_PL_getObj(geoData);
+ S52_diPrio disPrioIdx = S52_PL_getDPRI(obj);
+
+ switch (ot) {
+ case _META_T: obj_t = 0; break; // meta geo stuff (ex: C_AGGR)
+ case AREAS_T: obj_t = 1; break;
+ case LINES_T: obj_t = 2; break;
+ case POINT_T: obj_t = 3; break;
+ default:
+ PRINTF("ERROR: unknown index of addressed object type\n");
+ exit(0);
+ }
+ g_ptr_array_add( (_crntCell->renderBin)[disPrioIdx][obj_t], obj);
+
+ }
+
+ return TRUE;
+}
+
+int S52_doneCell(cellID cID)
+{
+ return 1;
+}
+
+int S52_draw()
+{
+ int i;
+ // APP .. update moving object
+ // CULL
+
+ for (i=0; i<_cellList->len; ++i) {
+ int j,k;
+ _cell *c = &g_array_index(_cellList, _cell, i);
+ for (j=0; j<S52_PRIO_NUM; ++j) {
+ for (k=0; k<N_OBJ_T; ++k) {
+ int idx;
+ GPtrArray *rbin = c->renderBin[j][k];
+
+ for (idx=0; idx<rbin->len; ++idx) {
+ S52_obj *obj = g_ptr_array_index(rbin, idx);
+ S52_GL_draw(obj);
+ }
+ }
+ }
+
+ }
+ // DRAW
+
+ PRINTF("*** F I N I S H **** \n\n");
+
+ return 1;
+}
Added: packages/openev/branches/upstream/current/contrib/S52/S52.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,38 @@
+// S52.h: top-level interface to libS52.so plug-in
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview porject, a viewer of ENC.
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52_H_
+#define _S52_H_
+
+typedef int cellID;
+
+#include "S52type.h" // _loadLayer_cb()
+
+// load a chart
+extern cellID S52_loadCell(const char *filename, _loadLayer_cb cb);
+extern int S52_loadLayer(const char *layername, void *ogrLayer);
+extern int S52_loadObject(const char *objname, void *shape);
+extern int S52_doneCell(cellID cID);
+extern int S52_draw();
+#endif //_S52_H_
Added: packages/openev/branches/upstream/current/contrib/S52/S52CS.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52CS.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52CS.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2483 @@
+// S52CS.c : Conditional Symbologie procedure 3.2 (CS)
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+// NOTE: remarks commenting each CS are extracted from pslb03_2.pdf (sec. 12)
+
+// FIXME: DEPCNT02: call DB for area DEPARE & DRGARE that intersect this line
+// FIXME:_DEPVAL01: call DB for area DEPARE & UNSARE that intersect this area
+// FIXME:_UDWHAZ03: call DB for area DRGARE & DEPARE that intersect this point/area
+
+#include "S52CS.h"
+
+#include "S52utils.h" // PRINTF()
+#include "S57src.h" // S57_touche()
+//#include "S57ogr.h" // S57_ogrTouche()
+
+#include <stdlib.h> // atof()
+#include <math.h> // fabsf(), HUGE_VAL
+#include <ctype.h> // isdigit()
+#include <string.h> // strncmp(), strpbrk()
+
+#define UNKNOWN HUGE_VAL // INFINITY/NAN
+
+#define COALNE 30 // Coastline
+#define DEPARE 42 // Depth area
+#define DEPCNT 43 // Depth contour
+#define DRGARE 46 // Dredged area
+#define UWTROC 153 // Underwater rock / awash rock
+#define WRECKS 159 // Wreck
+
+// point list name
+#define LIGHTLIST 0
+#define SECTRLIST 1
+#define FLOATLIST 2 // floating platform
+#define RIGIDLIST 3 // rigid platform
+//static GPtrArray *_lightList = NULL;
+//static GPtrArray *_sectrList = NULL;
+//static GPtrArray *_flaotList = NULL;
+static GPtrArray *_ptList[] = {NULL, NULL, NULL, NULL};
+
+int S52_state = 1;
+
+// size of attributes value list buffer
+#define LISTSIZE 16 // list size
+
+#define version "3.2.0"
+char *S52_CS_version()
+{
+ return version;
+}
+
+int S52_CS_init()
+{
+ _ptList[LIGHTLIST] = g_ptr_array_new();
+ _ptList[SECTRLIST] = g_ptr_array_new();
+ _ptList[FLOATLIST] = g_ptr_array_new();
+ _ptList[RIGIDLIST] = g_ptr_array_new();
+
+ return 1;
+}
+
+int S52_CS_done()
+{
+ g_ptr_array_free(_ptList[LIGHTLIST], TRUE);
+ g_ptr_array_free(_ptList[SECTRLIST], TRUE);
+ g_ptr_array_free(_ptList[FLOATLIST], TRUE);
+ g_ptr_array_free(_ptList[RIGIDLIST], TRUE);
+
+ return 1;
+}
+
+int S52_CS_setPtPos(S57_geo *geoData, char *name)
+{
+ printf("name = %s\n", name);
+
+ if (POINT_T == S57_getObjtype(geoData)) {
+
+ // set floating platform
+ if ((0==strncmp(name, "LITFLT", 6)) ||
+ (0==strncmp(name, "LITVES", 6)) ||
+ (0==strncmp(name, "BOY", 3)))
+ g_ptr_array_add(_ptList[FLOATLIST], (gpointer) geoData);
+
+ // set rigid platform
+ if (0==strncmp(name, "BCN", 3))
+ g_ptr_array_add(_ptList[RIGIDLIST], (gpointer) geoData);
+ }
+
+ return 1;
+}
+
+static int _overlap(S57_geo *geoNew, S57_geo *geoOld)
+{
+ // check for extend arc radius
+ GString *Asectr1str = S57_getAttVal(geoOld, "SECTR1");
+ GString *Asectr2str = S57_getAttVal(geoOld, "SECTR2");
+ GString *Bsectr1str = S57_getAttVal(geoNew, "SECTR1");
+ GString *Bsectr2str = S57_getAttVal(geoNew, "SECTR2");
+
+ // check present
+ if (NULL == Asectr1str ||
+ NULL == Asectr2str ||
+ NULL == Bsectr1str ||
+ NULL == Bsectr2str)
+ return FALSE;
+
+ {
+ double Asectr1 = atof(Asectr1str->str);
+ double Asectr2 = atof(Asectr2str->str);
+ double Bsectr1 = atof(Bsectr1str->str);
+ double Bsectr2 = atof(Bsectr2str->str);
+ double Asweep = (Asectr1 > Asectr2) ?
+ Asectr2-Asectr1+360 : Asectr2-Asectr1;
+ double Bsweep = (Bsectr1 > Bsectr2) ?
+ Bsectr2-Bsectr1+360 : Bsectr2-Bsectr1;
+
+ // check sector overlap
+ if (Asectr2<=Bsectr1 || Asectr1>=Bsectr2) {
+ if (Asweep == Bsweep) {
+ g_string_truncate(Bsectr2str, 0);
+ g_string_sprintf(Bsectr2str, "%f",Bsectr2-1);
+ S57_setAtt(geoNew, "SECTR2", Bsectr2str->str);
+ }
+
+ return FALSE;
+ }
+
+ // check if other/old sector larger
+ if (Asweep >= Bsweep)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int _atPtPos(S57_geo *geoNew, int listNm)
+// TRUE if there is a light at this position
+// or overlapping sector else FALSE
+{
+ int i;
+ GPtrArray *curntList = _ptList[listNm];
+
+ for (i=0; i<curntList->len; i++) {
+ S57_geo *geoOld = g_ptr_array_index(curntList, i);
+
+ if (S57_samePtPos(geoNew, geoOld)) {
+ if (SECTRLIST != listNm)
+ return TRUE;
+
+ if (TRUE == _overlap(geoNew, geoOld))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static int _setPtPos(S57_geo *geo, int listNm)
+// TRUE if a new position of a light was set, else
+// FALSE (ie there is a light at this position)
+{
+ GPtrArray *curntList = _ptList[listNm];
+
+ if (TRUE == _atPtPos(geo, listNm))
+ return TRUE;
+ else
+ g_ptr_array_add(curntList, (gpointer) geo);
+
+ return FALSE;
+}
+
+static int _parseList(const char *str, char *buf)
+// Put a string of comma delimited number in an array (buf).
+// Return: the number of value in buf.
+// Assume: - number < 256,
+// - list size less then LISTSIZE-1 .
+// Note: buf is \0 terminated for strpbrk().
+{
+ int i = 0;
+
+ if (NULL != str && *str != '\0') {
+ do {
+ if ( i>= LISTSIZE-1) {
+ PRINTF("OVERFLOW --value in list lost!!\n");
+ break;
+ }
+
+ /*
+ if (255 < (unsigned char) atoi(str)) {
+ PRINTF("value overflow (>255)\n");
+ exit(0);
+ }
+ */
+
+ buf[i++] = (unsigned char) atoi(str);
+
+ while(isdigit(*str))
+ ++str; // next
+ //while( g_ascii_isdigit(c)); // next
+
+ } while(*str++ != '\0'); // skip ',' or exit
+ }
+
+ buf[i] = '\0';
+
+ return i;
+}
+
+static char *_selSYcol(char *buf)
+{
+ // FIXME: C1 3.1 use LIGHTS0x and specs 3.2 use LIGHTS1x
+
+ char *sym = ";SY(LIGHTDEF"; //sym = ";SY(LITDEF11";
+
+ // max 1 color
+ if ('\0' == buf[1]) {
+ if (strpbrk(buf, "\003"))
+ sym = ";SY(LIGHTS01"; //sym = ";SY(LIGHTS11";
+ else if (strpbrk(buf, "\004"))
+ sym = ";SY(LIGHTS02"; //sym = ";SY(LIGHTS12";
+ else if (strpbrk(buf, "\001\006\013"))
+ sym = ";SY(LIGHTS03"; //sym = ";SY(LIGHTS13";
+ } else {
+ // max 2 color
+ if ('\0' == buf[2]) {
+ if (strpbrk(buf, "\001") && strpbrk(buf, "\003"))
+ sym = ";SY(LIGHTS01"; //sym = ";SY(LIGHTS11";
+ else if (strpbrk(buf, "\001") && strpbrk(buf, "\004"))
+ sym = ";SY(LIGHTS02"; //sym = ";SY(LIGHTS12";
+ }
+ }
+
+ return sym;
+}
+
+static GString *CLRLIN01 (S57_geo *geo)
+// Remarks: A clearing line shows a single arrow head at one of its ends. The direction
+// of the clearing line must be calculated from its line object in order to rotate
+// the arrow head symbol and place it at the correct end. This cannot be
+// achieved with a complex linestyle since linestyle symbols cannot be sized
+// to the length of the clearing line. Instead a linestyle with a repeating pattern
+// of arrow symbols had to be used which does not comply with the required
+// symbolization.
+{
+
+ PRINTF("Mariner's object not drawn\n");
+
+ return NULL;
+}
+
+static GString *DATCVR01 (S57_geo *geo)
+// Remarks: This conditional symbology procedure describes procedures for:
+// - symbolizing the limit of ENC coverage;
+// - symbolizing navigational purpose boundaries ("scale boundarie"); and
+// - indicating overscale display.
+//
+// Note that the mandatory meta object CATQUA is symbolized by the look-up table.
+//
+// Because the methods adopted by an ECDIS to meet the IMO and IHO requirements
+// listed on the next page will depend on the manufacturer's software, and cannot be
+// described in terms of a flow chart in the same way as other conditional procedures,
+// this procedure is in the form of written notes.
+{
+ //GString *datcvr01 = NULL;
+
+ // debug --return empty command for now
+ GString *datcvr01 = g_string_new(";OP(----)");
+
+ ///////////////////////
+ // 1- REQUIREMENT
+ // (IMO/IHO specs. explenation)
+
+ ///////////////////////
+ // 2- ENC COVERAGE
+ //
+ // 2.1- Limit of ENC coverage
+ //datcvr01 = g_string_new(";OP(3OD11060);LC(HODATA01)");
+ // FIXME: get cell extend
+
+ // 2.2- No data areas
+ // This can be done outside of CS (ie when clearing the screen in Mesa)
+ // FIXME: ";OP(0---);AC(NODATA)"
+ // FIXME: set geo to cover earth (!)
+
+ //////////////////////
+ // 3- SCALE BOUNDARIES
+ //
+ // 3.1- Chart scale boundaties
+ // FIXME;
+ //g_string_append(datcvr01, ";LS(SOLD,1,CHGRD)");
+ // -OR- LC(SCLBDYnn) (?)
+ //
+ // ;OP(3OS21030)
+
+ // 3.2- Graphical index of navigational purpose
+ // FIXME: draw extent of available SENC in DB
+
+ //////////////////////
+ // 4- OVERSCALE
+ //
+ // FIXME: get meta date CSCL of DSPM field
+ // FIXME: get object M_CSCL or CSCALE
+ //
+ // 4.1- Overscale indication
+ // FIXME: compute, scale = [denominator of the compilation scale] /
+ // [denominator of the display scale]
+ // FIXME: draw overscale indication (ie TX("X%3.1f",scale))
+ //
+ // 4.2- Ovescale area at a chart scale boundary
+ // FIXME: test if next chart is over scale (ie going from large scale chart
+ // to a small scale chart)
+ // FIXME: draw AP(OVERSC01) on overscale part of display
+ //g_string(";OP(3OS21030)");
+
+ //
+ // 4.3- Larger scale data available
+ // FIXME: display indication of better scale available (?)
+
+ // FIXME
+ //PRINTF("NOTE: not computed\n");
+
+ return datcvr01;
+}
+
+static GString *_SEABED01(double drval1, double drval2);
+static GString *_RESCSP01(S57_geo *geo);
+static GString *DEPARE01 (S57_geo *geo)
+// Remarks: An object of the class "depth area" is coloured and covered with fill patterns
+// according to the mariners selections of shallow contour, safety contour and
+// deep contour. This requires a decision making process provided by the sub-procedure
+// "SEABED01" which is called by this symbology procedure.
+// Objects of the class "dredged area" are handled by this routine as well to
+// ensure a consistent symbolization of areas that represent the surface of the
+// seabed.
+{
+ GString *depare01 = NULL;
+ int objl = 0;
+ GString *objlstr = NULL;
+ GString *drval1str = S57_getAttVal(geo, "DRVAL1");
+ double drval1 = UNKNOWN;
+ GString *drval2str = S57_getAttVal(geo, "DRVAL2");
+ double drval2 = UNKNOWN;
+
+ drval1 = (NULL == drval1str) ? -1.0 : atof(drval1str->str);
+ drval2 = (NULL == drval2str) ? drval1+0.01 : atof(drval2str->str);
+
+ depare01 = _SEABED01(drval1, drval2);
+
+ objlstr = S57_getAttVal(geo, "OBJL");
+ objl = (NULL == objlstr) ? 0 : atoi(objlstr->str);
+
+ if (DRGARE == objl) {
+ g_string_append(depare01, ";AP(DRGARE01)");
+ g_string_append(depare01, ";LS(DASH,1,CHGRF)");
+
+ if (NULL != S57_getAttVal(geo, "RESTRN")) {
+ GString *rescsp01 = _RESCSP01(geo);
+ if (NULL != rescsp01) {
+ g_string_append(depare01, rescsp01->str);
+ g_string_free(rescsp01, TRUE);
+ }
+ }
+
+ }
+
+ return depare01;
+}
+
+static GString *_SNDFRM02(S57_geo *geo, double depth_value);
+static GString *DEPCNT02 (S57_geo *geo)
+// Remarks: An object of the class "depth contour" or "line depth area" is highlighted and must
+// be shown under all circumstances if it matches the safety contour depth value
+// entered by the mariner (see IMO PS 3.6). But, while the mariner is free to enter any
+// safety contour depth value that he thinks is suitable for the safety of his ship, the
+// SENC only contains a limited choice of depth contours. This symbology procedure
+// determines whether a contour matches the selected safety contour. If the selected
+// safety contour does not exist in the data, the procedure will default to the next deeper
+// contour. The contour selected is highlighted as the safety contour and put in
+// DISPLAYBASE. The procedure also identifies any line segment of the spatial
+// component of the object that has a "QUAPOS" value indicating unreliable
+// positioning, and symbolizes it with a double dashed line.
+//
+// Note: Depth contours are not normally labeled. The ECDIS may provide labels, on demand
+// only as with other text, or provide the depth value on cursor picking
+{
+ GString *depcnt02 = NULL;
+ int safe = FALSE; // initialy not a safety contour
+ GString *objlstr = NULL;
+ int objl = 0;
+ GString *quaposstr = NULL;
+ int quapos = 0;
+ double depth_value;
+
+ objlstr = S57_getAttVal(geo, "OBJL");
+ objl = (NULL == objlstr) ? 0 : atoi(objlstr->str);
+
+ if (DEPARE==objl && LINES_T==S57_getObjtype(geo)) {
+ GString *drval1str = S57_getAttVal(geo, "DRVAL1");
+ double drval1 = (NULL == drval1str) ? 0.0 : atof(drval1str->str);
+ GString *drval2str = S57_getAttVal(geo, "DRVAL2");
+ double drval2 = (NULL == drval2str) ? drval1 : atof(drval2str->str);
+
+ if (drval1 <= S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ if (drval2 >= S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR))
+ safe = TRUE;
+ } else {
+ S57_geo *geoTmp = geo;
+
+ // collect group 1 area DEPARE & DRGARE that touche this line
+ S57_ogrTouche(geoTmp, GRP_1_T);
+ while (NULL != (geoTmp = S57_nextObj(geoTmp))) {
+ drval1str = S57_getAttVal(geoTmp, "DRVAL1");
+ drval1 = (NULL == drval1str) ? 0.0 : atof(drval1str->str);
+
+ if (NULL == drval1str) {
+ safe = TRUE;
+ break;
+ }
+
+ if (drval1 < S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ safe = TRUE;
+ break;
+ }
+ //}
+ // debug trace
+ //if (safe) PRINTF("** DEPARE: SAFE FOUND**\n");
+ }
+ S57_unlinkObj(geo);
+
+ }
+
+ depth_value = drval1;
+
+ } else {
+ // continuation A (DEPCNT)
+ GString *valdcostr = S57_getAttVal(geo, "VALDCO");
+ double valdco = (NULL == valdcostr) ? 0.0 : atof(valdcostr->str);
+
+ depth_value = valdco;
+
+ if (valdco == S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR))
+ safe = TRUE; // this is useless !?!?
+ else {
+ if (valdco > S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ //if (1 == S52_state)
+ // return NULL;
+ //else {
+ S57_geo *geoTmp = geo;
+
+ // collect area DEPARE & DRGARE that touche this line
+ S57_ogrTouche(geoTmp, GRP_1_T);
+ while (NULL != (geoTmp = S57_nextObj(geoTmp))){
+ GString *drval1str = S57_getAttVal(geoTmp, "DRVAL1");
+ double drval1 = (NULL == drval1str) ? 0.0 : atof(drval1str->str);
+
+ if (NULL == drval1str) {
+ safe = TRUE;
+ break;
+ }
+
+ if (drval1 < S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ safe = TRUE;
+ break;
+ }
+ //}
+ // debug trace
+ //if (safe) PRINTF("** DEPCN: SAFE FOUND**\n");
+ }
+ S57_unlinkObj(geo);
+
+ }
+ }
+ }
+
+ // Continuation B
+ // ASSUME: OGR split lines to preserv different QUAPOS for a given line
+ // FIXME: check that the assumtion above is valid!
+ quaposstr = S57_getAttVal(geo, "QUAPOS");
+ if (NULL != quaposstr) {
+ quapos = atoi(quaposstr->str);
+ if ( 2 <= quapos && quapos < 10) {
+ if (safe)
+ depcnt02 = g_string_new(";LS(DASH,2,DEPSC)");
+ else
+ depcnt02 = g_string_new(";LS(DASH,1,DEPCN)");
+ }
+ } else {
+ if (safe)
+ depcnt02 = g_string_new(";LS(SOLD,2,DEPSC)");
+ else
+ depcnt02 = g_string_new(";LS(SOLD,1,DEPCN)");
+ }
+
+ if (safe) {
+ S57_setAtt(geo, "SCAMIN", "INFINITE");
+ depcnt02 = g_string_prepend(depcnt02, ";OP(8OD13010)");
+ } else
+ depcnt02 = g_string_prepend(depcnt02, ";OP(---33020)");
+
+ // facultative in S-52
+ //if (TRUE == S52_getMarinerParam(S52_MAR_SHOW_TEXT)) {
+ // GString *sndfrm02 = _SNDFRM02(geo, depth_value);
+ // depcnt02 = g_string_append(depcnt02, sndfrm02->str);
+ // g_string_free(sndfrm02, TRUE);
+ //}
+
+ // debug
+ //PRINTF("depth= %f\n", depth_value);
+
+ //S57_unlinkObj(geo);
+
+ return depcnt02;
+}
+
+static double _DEPVAL01(S57_geo *geo, double least_depth)
+// Remarks: S-57 Appendix B1 Annex A requires in Section 6 that areas of rocks be
+// encoded as area obstruction, and that area OBSTRNs and area WRECKS
+// be covered by either group 1 object DEPARE or group 1 object UNSARE.
+// If the value of the attribute VALSOU for an area OBSTRN or WRECKS
+// is missing, the DRVAL1 of an underlying DEPARE is the preferred default
+// for establishing a depth vale. This procedure either finds the shallowest
+// DRVAL1 of the one or more underlying DEPAREs, or returns an
+// "unknown"" depth value to the main procedure for the next default
+// procedure.
+
+// NOTE: UNSARE test is useless since least_depth is already UNKNOWN
+{
+ least_depth = UNKNOWN;
+
+ S57_geo *geoTmp = geo;
+
+ // NOTE: change procedure to use any incomming geometry
+ // on area DEPARE & DRGARE (S52 say to use area UNSARE & DEPARE
+ // but this sound awkward since USARE do not have any depth!
+ // so it has to default to UNKNOWN implicitly!!)
+
+ // collect group 1 area DEPARE & DRGARE that touch this point/line/area
+ S57_ogrTouche(geoTmp, GRP_1_T);
+ while (NULL != (geoTmp = S57_nextObj(geoTmp))) {
+ GString *drval1str = S57_getAttVal(geoTmp, "DRVAL1");
+ double drval1 = (NULL == drval1str) ? UNKNOWN : atof(drval1str->str);
+
+ if (NULL != drval1str) {
+ if (UNKNOWN==least_depth || least_depth<drval1)
+ least_depth = drval1;
+ }
+ }
+ S57_unlinkObj(geo);
+
+ return least_depth;
+}
+
+static GString *LEGLIN02 (S57_geo *geo)
+
+// Remarks: The course of a leg is given by its start and end point. Therefore this
+// conditional symbology procedure calculates the course and shows it
+// alongside the leg. It also places the "distance to run" labels and cares for the
+// different presentation of planned & alternate legs.
+{
+ PRINTF("Mariner's object not drawn\n");
+ return NULL;
+}
+
+static GString *_LITDSN01(S57_geo *geo);
+static GString *LIGHTS05 (S57_geo *geo)
+// Remarks: A light is one of the most complex S-57 objects. Its presentation depends on
+// whether it is a light on a floating or fixed platform, its range, it's colour and
+// so on. This conditional symbology procedure derives the correct
+// presentation from these parameters and also generates an area that shows the
+// coverage of the light.
+//
+// Notes on light sectors:
+// 1.) The radial leg-lines defining the light sectors are normally drawn to only 25mm
+// from the light to avoid clutter (see Part C). However, the mariner should be able to
+// select "full light-sector lines" and have the leg-lines extended to the nominal range
+// of the light (VALMAR).
+//
+// 2.) Part C of this procedure symbolizes the sectors at the light itself. In addition,
+// it should be possible, upon request, for the mariner to be capable of identifying
+// the colour and sector limit lines of the sectors affecting the ship even if the light
+// itself is off the display.
+// [ed. last sentence in bold]
+
+// NOTE: why is this relationship not already encoded in S57 (ei. C_AGGR or C_STAC) ?
+
+{
+ GString *lights05 = NULL;
+ GString *valnmrstr = S57_getAttVal(geo, "VALNMR");
+ double valnmr = 0.0;
+ GString *catlitstr = S57_getAttVal(geo, "CATLIT");
+ char catlit[LISTSIZE] = {'\0'};
+ int flare_at_45 = FALSE;
+ int extend_arc_radius = TRUE;
+ GString *sectr1str = NULL;
+ GString *sectr2str = NULL;
+ double sectr1 = 0.0;
+ double sectr2 = 0.0;
+ GString *colourstr = NULL;
+ char colist[LISTSIZE] = {'\0'}; // colour list
+ GString *orientstr = NULL;
+ double sweep = 0.0;
+
+
+ lights05 = g_string_new("");
+
+ valnmr = (NULL == valnmrstr) ? 9.0 : atof(valnmrstr->str);
+
+ if ( NULL != catlitstr) {
+ _parseList(catlitstr->str, catlit);
+
+ // FIXME: OR vs AND/OR
+ if (strpbrk(catlit, "\010\013")) {
+ g_string_append(lights05, ";SY(LIGHTS82)");
+ return lights05;
+ }
+
+ if (strpbrk(catlit, "\011")) {
+ g_string_append(lights05, ";SY(LIGHTS81)");
+ return lights05;
+ }
+
+ if (strpbrk(catlit, "\001\020")) {
+ orientstr = S57_getAttVal(geo, "ORIENT");
+ if (NULL != orientstr) {
+ // FIXME: create a geo object (!?) LINE of lenght VALNMR
+ // using ORIENT (from seaward) & POINT_T position
+ g_string_append(lights05, ";LS(DASH,1,CHBLK)");
+ }
+ }
+ }
+
+ // Continuation A
+ colourstr = S57_getAttVal(geo, "COLOUR");
+ if (NULL != colourstr)
+ _parseList(colourstr->str, colist);
+ else {
+ colist[0] = '\014'; // maganta (12)
+ colist[1] = '\000';
+ }
+
+ sectr1str = S57_getAttVal(geo, "SECTR1");
+ sectr1 = (NULL == sectr1str) ? 0.0 : atof(sectr1str->str);
+ sectr2str = S57_getAttVal(geo, "SECTR2");
+ sectr2 = (NULL == sectr2str) ? 0.0 : atof(sectr2str->str);
+
+ if (NULL==sectr1str || NULL==sectr2str) {
+ // not a sector light
+ char *sym;
+
+ //if (1==S52_state) {
+ // _setPtPos(geo, LIGHTLIST);
+ // g_string_free(lights05, TRUE);
+ // return NULL;
+ //} else
+ // flare_at_45 = _atPtPos(geo, LIGHTLIST);
+
+ flare_at_45 = _setPtPos(geo, LIGHTLIST);
+
+ sym = _selSYcol(colist);
+
+ if (strpbrk(catlit, "\001\020")) {
+ if (NULL != orientstr){
+ g_string_append(lights05, sym);
+ g_string_sprintfa(lights05, ",%s)", orientstr->str);
+ g_string_append(lights05, ";TE('%03.0lf deg','ORIENT',3,3,3,'15110',3,1,CHBLK,23)" );
+ } else
+ g_string_append(lights05, ";SY(QUSMRK1)");
+ } else {
+ g_string_append(lights05, sym);
+ if (flare_at_45)
+ g_string_append(lights05, ",145)");
+ else
+ g_string_append(lights05, ",135)");
+ }
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SHOW_TEXT)) {
+ GString *litdsn01 = _LITDSN01(geo);
+ if (NULL != litdsn01){
+ g_string_append(lights05, ";TX('");
+ g_string_append(lights05, litdsn01->str);
+ g_string_free(litdsn01, TRUE);
+
+ if (flare_at_45)
+ g_string_append(lights05, "',3,3,3,'15110',2,-1,CHBLK,23)" );
+ else
+ g_string_append(lights05, "',3,2,3,'15110',2,0,CHBLK,23)" );
+ }
+ }
+
+ return lights05;
+ }
+
+ // Continuation B --sector light
+ if (NULL == sectr1str) {
+ sectr1 = 0.0;
+ sectr2 = 0.0;
+ } else
+ sweep = (sectr1 > sectr2) ? sectr2-sectr1+360 : sectr2-sectr1;
+
+
+ if (sweep<1.0 || sweep==360.0) {
+ // handle all round light
+ char *sym = _selSYcol(colist);;
+
+ g_string_append(lights05, sym);
+ g_string_append(lights05, ",135)");
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SHOW_TEXT)) {
+ GString *litdsn01 = _LITDSN01(geo);
+ if (NULL != litdsn01) {
+ g_string_append(lights05, ";TX('");
+ g_string_append(lights05, litdsn01->str);
+ g_string_append(lights05, "',3,2,3,'15110',2,0,CHBLK,23)" );
+ g_string_free(litdsn01, TRUE);
+ }
+
+ }
+
+ return lights05;
+ }
+
+ // scan for other lights with sector overlap at this position
+ // compute light sector radius according to other sector
+ //if (1 == S52_state) {
+ // _setPtPos(geo, SECTRLIST);
+ // g_string_free(lights05, TRUE);
+ // return NULL;
+ //} else {
+ // extend_arc_radius = _atPtPos(geo, SECTRLIST);
+
+
+ extend_arc_radius = _setPtPos(geo, SECTRLIST);
+
+ // passe value via attribs to _renderAC
+ if (extend_arc_radius)
+ // FIXME: draw radius 25 mm
+ S57_setAtt(geo, "extend_arc_radius", "Y");
+ else
+ // FIXME: draw radius 20 mm
+ S57_setAtt(geo, "extend_arc_radius", "N");
+
+ // setup sector
+ {
+ char litvis[LISTSIZE] = {'\0'}; // list visibility
+ GString *litvisstr = S57_getAttVal(geo, "LITVIS");
+
+ // sector leg --logic is _renderLS()
+ g_string_append(lights05, ";LS(DASH,1,CHBLK)");
+
+ // get light vis.
+ if (NULL != litvisstr) _parseList(litvisstr->str, litvis);
+
+ // faint light
+ // FIXME: spec say OR (ie 1 number) the code is AND/OR
+ if (strpbrk(litvis, "\003\007\010")) {
+ // NOTE: LS(DASH,1,CHBLK)
+ // pass flag to _renderAC()
+ g_string_append(lights05, ";AC(CHBLK)");
+ S57_setAtt(geo, "faint_light", "Y");
+
+ } else {
+ // set arc colour
+ char *sym = ";AC(CHMGD)"; // other
+
+ // max 1 color
+ if ('\0' == colist[1]) {
+ if (strpbrk(colist, "\003"))
+ sym = ";AC(LITRD)";
+ else if (strpbrk(colist, "\004"))
+ sym = ";AC(LITGN)";
+ else if (strpbrk(colist, "\001\006\013"))
+ sym = ";AC(LITYW)";
+ } else {
+ // max 2 color
+ if ('\0' == colist[2]) {
+ if (strpbrk(colist, "\001") && strpbrk(colist, "\003"))
+ sym = ";AC(LITRD)";
+ else if (strpbrk(colist, "\001") && strpbrk(colist, "\004"))
+ sym = ";AC(LITGN)";
+ }
+ }
+
+ g_string_append(lights05, sym);
+ }
+ }
+
+ return lights05;
+}
+
+static GString *_LITDSN01(S57_geo *geo)
+// Remarks: In S-57 the light characteristics are held as a series of attributes values. The
+// mariner may wish to see a light description text string displayed on the
+// screen similar to the string commonly found on a paper chart. This
+// conditional procedure, reads the attribute values from the above list of
+// attributes and composes a light description string which can be displayed.
+// This procedure is provided as a C function which has as input, the above
+// listed attribute values and as output, the light description.
+{
+ GString *litdsn01 = g_string_new("");
+ GString *gstr = NULL; // tmp
+ GString *catlitstr = S57_getAttVal(geo, "CATLIT");
+ char catlit[LISTSIZE] = {'\0'};
+ GString *litchrstr = S57_getAttVal(geo, "LITCHR");
+ char litchr[LISTSIZE] = {'\0'};
+ GString *colourstr = S57_getAttVal(geo, "COLOUR");
+ char colour[LISTSIZE] = {'\0'};
+ GString *statusstr = S57_getAttVal(geo, "STATUS");
+ char status[LISTSIZE] = {'\0'};
+
+ // FIXME: need grammar to create light's text
+
+ // CATLIT, LITCHR, COLOUR, HEIGHT, LITCHR, SIGGRP, SIGPER, STATUS, VALNMR
+
+ // CATLIT
+ //gstr = S57_getAttVal(geo, "CATLIT");
+ //g_string_append(litdsn01, gstr->str);
+ if (NULL != catlitstr) {
+ char *tmp = NULL;
+
+ if (1 < _parseList(catlitstr->str, catlit))
+ PRINTF("ERROR: more then one 'category of light' (CATLIT), other not displayed\n");
+
+ switch (catlit[0]) {
+ //1: directional function IP 30.1-3; 475.7;
+ case 1: tmp = "Dir "; break;
+
+ //2: rear/upper light
+ //3: front/lower light
+ //4: leading light IP 20.1-3; 475.6;
+
+ //5: aero light IP 60; 476.1;
+ case 5: tmp = "Aero "; break;
+
+ //6: air obstruction light IP 61; 476.2;
+ //7: fog detector light IP 62; 477;
+ //8: flood light IP 63; 478.2;
+ //9: strip light IP 64; 478.5;
+ //10: subsidiary light IP 42; 471.8;
+ //11: spotlight
+ //12: front
+ //13: rear
+ //14: lower
+ //15: upper
+ //16: moire' effect IP 31; 475.8;
+ //17: emergency
+ //18: bearing light 478.1;
+ //19: horizontally disposed
+ //20: vertically disposed
+
+ default:
+ // FIXME: what is a good default
+ // or should it be left empty!
+ tmp = "? ";
+ PRINTF("ERROR: no abreviation for CATLIT\n");
+ }
+ g_string_append(litdsn01, tmp);
+ }
+
+
+ // LITCHR
+ //gstr = S57_getAttVal(geo, "LITCHR");
+ //if (NULL != gstr)
+ // g_string_append(litdsn01, gstr->str);
+
+ if (NULL != litchrstr) {
+ char *tmp = NULL;
+
+ if (1 < _parseList(litchrstr->str, litchr))
+ PRINTF("ERROR: more then one 'light characteristic' (LITCHR), other not displayed\n");
+
+ switch (litchr[0]) {
+ //1: fixed IP 10.1;
+ case 1: tmp = "F "; break;
+ //2: flashing IP 10.4;
+ case 2: tmp = "Fl "; break;
+ //3: long-flashing IP 10.5;
+ case 3: tmp = "LFl "; break;
+ //4: quick-flashing IP 10.6;
+ case 4: tmp = "Q "; break;
+ //5: very quick-flashing IP 10.7;
+ case 5: tmp = "VQ "; break;
+ //6: ultra quick-flashing IP 10.8;
+ case 6: tmp = "UQ "; break;
+ //7: isophased IP 10.3;
+ case 7: tmp = "Iso "; break;
+ //8: occulting IP 10.2;
+ case 8: tmp = "Oc "; break;
+ //9: interrupted quick-flashing IP 10.6;
+ case 9: tmp = "IQ "; break;
+ //10: interrupted very quick-flashing IP 10.7;
+ case 10: tmp = "IVQ "; break;
+ //11: interrupted ultra quick-flashing IP 10.8;
+ case 11: tmp = "IUQ "; break;
+ //12: morse IP 10.9;
+ case 12: tmp = "Mo "; break;
+ //13: fixed/flash IP 10.10;
+ case 13: tmp = "FFl "; break;
+ //14: flash/long-flash
+ case 14: tmp = "Fl+LFl "; break;
+ // FIXME: not mention of 'alternating' occulting/flash in S57 attributes
+ // but S52 say 'alternating occulting/flash' (p. 188)
+ //15: occulting/flash
+ case 15: tmp = "AlOc Fl "; break;
+ //16: fixed/long-flash
+ case 16: tmp = "FLFl "; break;
+ //17: occulting alternating
+ case 17: tmp = "AlOc "; break;
+ //18: long-flash alternating
+ case 18: tmp = "AlLFl "; break;
+ //19: flash alternating
+ case 19: tmp = "AlFl "; break;
+ //20: group alternating
+ case 20: tmp = "Al "; break;
+
+ //21: 2 fixed (vertical)
+ //22: 2 fixed (horizontal)
+ //23: 3 fixed (vertical)
+ //24: 3 fixed (horizontal)
+
+ //25: quick-flash plus long-flash
+ case 25: tmp = "Q+LFl "; break;
+ //26: very quick-flash plus long-flash
+ case 26: tmp = "VQ+LFl "; break;
+ //27: ultra quick-flash plus long-flash
+ case 27: tmp = "UQ+LFl "; break;
+ //28: alternating
+ case 28: tmp = "Al "; break;
+ //29: fixed and alternating flashing
+ case 29: tmp = "AlF Fl "; break;
+
+ default:
+ // FIXME: what is a good default
+ // or should it be left empty!
+ tmp = "? ";
+ PRINTF("ERROR: no abreviation for LITCHR\n");
+ }
+ g_string_append(litdsn01, tmp);
+ }
+
+ // COLOUR,
+ //gstr = S57_getAttVal(geo, "COLOUR");
+ //if (NULL != gstr)
+ // g_string_append(litdsn01, gstr->str);
+
+ if (NULL != colourstr) {
+ char *tmp = NULL;
+
+ if (1 < _parseList(colourstr->str, colour))
+ PRINTF("ERROR: more then one 'colour' (COLOUR), other not displayed\n");
+
+ switch (colour[0]) {
+ //1: white IP 11.1; 450.2-3;
+ case 1: tmp = "W "; break;
+
+ //2: black
+
+ //3: red IP 11.2; 450.2-3;
+ case 3: tmp = "R "; break;
+ //4: green IP 11.3; 450.2-3;
+ case 4: tmp = "G "; break;
+
+ //5: blue IP 11.4; 450.2-3;
+
+ //6: yellow IP 11.6; 450.2-3;
+ case 6: tmp = "Y "; break;
+
+ //7: grey
+ //8: brown
+ //9: amber IP 11.8; 450.2-3;
+ //10: violet IP 11.5; 450.2-3;
+ //11: orange IP 11.7; 450.2-3;
+ //12: magenta
+ //13: pink
+
+ default:
+ // FIXME: what is a good default
+ // or should it be left empty!
+ tmp = "? ";
+ PRINTF("ERROR: no abreviation for COLOUR\n");
+ }
+ g_string_append(litdsn01, tmp);
+ }
+
+ // HEIGHT, xxx.x
+ gstr = S57_getAttVal(geo, "HEIGHT");
+ if (NULL != gstr) {
+ g_string_append(litdsn01, gstr->str);
+ g_string_append(litdsn01, "m ");
+ }
+
+
+ // SIGGRP, (c)(c) ...
+ gstr = S57_getAttVal(geo, "SIGGRP");
+ if (NULL != gstr) {
+ PRINTF("WARNING: SIGGRP not translated into text\n");
+ //g_string_append(litdsn01, gstr->str);
+ }
+
+ // SIGPER, xx.xx
+ gstr = S57_getAttVal(geo, "SIGPER");
+ if (NULL != gstr) {
+ PRINTF("WARNING: SIGPER not translated into text\n");
+ //g_string_append(litdsn01, gstr->str);
+ }
+
+ // STATUS,
+ //gstr = S57_getAttVal(geo, "STATUS");
+ //if (NULL != gstr)
+ // g_string_append(litdsn01, gstr->str);
+
+ if (NULL != statusstr) {
+ char *tmp = NULL;
+
+ if (1 < _parseList(statusstr->str, status))
+ PRINTF("ERROR: more then one 'status' (STATUS), other not displayed\n");
+
+ switch (status[0]) {
+ //1: permanent
+
+ //2: occasional IP 50; 473.2;
+ case 2: tmp = "occas"; break;
+
+ //3: recommended IN 10; 431.1;
+ //4: not in use IL 14, 44; 444.7;
+ //5: periodic/intermittent IC 21; IQ 71; 353.3; 460.5;
+ //6: reserved IN 12.9;
+
+ //7: temporary IP 54;
+ case 7: tmp = "temp"; break;
+ //8: private IQ 70;
+ case 8: tmp = "priv"; break;
+
+ //9: mandatory
+ //10: destroyed/ruined
+
+ //11: extinguished
+ case 11: tmp = "exting"; break;
+
+ //12: illuminated
+ //13: historic
+ //14: public
+ //15: synchronized
+ //16: watched
+ //17: un-watched
+ //18: existence doubtful
+ default:
+ // FIXME: what is a good default
+ // or should it be left empty!
+ tmp = "? ";
+ PRINTF("ERROR: no abreviation for STATUS\n");
+ }
+ g_string_append(litdsn01, tmp);
+ }
+
+ // VALNMR, xx.x
+ gstr = S57_getAttVal(geo, "VALNMR");
+ if (NULL != gstr) {
+ g_string_append(litdsn01, gstr->str);
+ // FIXME: conflict in specs, nominal range in nautical miles in S57
+ // S52 imply that it can be express in meter
+ g_string_append(litdsn01, "M");
+ }
+
+
+ //PRINTF("FIXME: lights description not translated into text\n");
+
+ return litdsn01;
+}
+
+static GString *_UDWHAZ03(S57_geo *geo, double depth_value);
+static GString *_QUAPNT01(S57_geo *geo);
+
+static GString *OBSTRN04 (S57_geo *geo)
+// Remarks: Obstructions or isolated underwater dangers of depths less than the safety
+// contour which lie within the safe waters defined by the safety contour are
+// to be presented by a specific isolated danger symbol and put in IMO
+// category DISPLAYBASE (see (3), App.2, 1.3). This task is performed
+// by the sub-procedure "UDWHAZ03" which is called by this symbology
+// procedure. Objects of the class "under water rock" are handled by this
+// routine as well to ensure a consistent symbolization of isolated dangers on
+// the seabed.
+//
+// NOTE: updated to Cs1_md.pdf (ie was OBSTRN03)
+
+{
+ GString *obstrn04str = g_string_new("");
+ GString *sndfrm02str = NULL;
+ GString *udwhaz03str = NULL;
+ GString *valsoustr = S57_getAttVal(geo, "VALSOU");
+ double valsou = UNKNOWN;
+ double depth_value = UNKNOWN;
+ double least_depth = UNKNOWN;
+
+ // exit if not in drawing state
+ //if (1 == S52_state)
+ // return NULL;
+
+ if (NULL != valsoustr) {
+ valsou = atof(valsoustr->str);
+ depth_value = valsou;
+ sndfrm02str = _SNDFRM02(geo, depth_value);
+ } else {
+ if (AREAS_T == S57_getObjtype(geo))
+ least_depth = _DEPVAL01(geo, least_depth);
+
+ if (UNKNOWN != least_depth) {
+ GString *catobsstr = S57_getAttVal(geo, "CATOBS");
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL != catobsstr && '6' == *catobsstr->str)
+ depth_value = 0.01;
+ else
+ if (NULL == watlevstr) // default
+ depth_value = -15.0;
+ else {
+ switch (*watlevstr->str){
+ case '5': depth_value = 0.0 ; break;
+ case '3': depth_value = 0.01; break;
+ case '4':
+ case '1':
+ case '2':
+ default : depth_value = -15.0 ; break;
+ }
+ }
+ } else
+ depth_value = least_depth;
+ }
+
+ udwhaz03str = _UDWHAZ03(geo, depth_value);
+
+ if (POINT_T == S57_getObjtype(geo)) {
+ // Continuation A
+ int sounding = FALSE;
+ GString *quapnt01str = _QUAPNT01(geo);
+
+ if (NULL != udwhaz03str){
+ g_string_append(obstrn04str, udwhaz03str->str);
+ if (NULL != quapnt01str)
+ g_string_append(obstrn04str, quapnt01str->str);
+
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+ if (NULL != quapnt01str) g_string_free(quapnt01str, TRUE);
+
+ return obstrn04str;
+ }
+
+ if (UNKNOWN != valsou) {
+ if (valsou <= 20.0) {
+ GString *objlstr = S57_getAttVal(geo, "OBJL");
+ int objl = (NULL == objlstr)? 0 : atoi(objlstr->str);
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (UWTROC == objl) {
+ if (NULL == watlevstr) { // default
+ g_string_append(obstrn04str, ";SY(DANGER01)");
+ sounding = TRUE;
+ } else {
+ switch (*watlevstr->str){
+ case '3': g_string_append(obstrn04str, ";SY(DANGER01)"); sounding = TRUE ; break;
+ case '4':
+ case '5': g_string_append(obstrn04str, ";SY(UWTROC04)"); sounding = FALSE; break;
+ default : g_string_append(obstrn04str, ";SY(DANGER01)"); sounding = TRUE ; break;
+ }
+ }
+ } else { // OBSTRN
+ if (NULL == watlevstr) { // default
+ g_string_append(obstrn04str, ";SY(DANGER01)");
+ sounding = TRUE;
+ } else {
+ switch (*watlevstr->str) {
+ case '1':
+ case '2': g_string_append(obstrn04str, ";SY(OBSTRN11)"); sounding = FALSE; break;
+ case '3': g_string_append(obstrn04str, ";SY(DANGER01)"); sounding = TRUE; break;
+ case '4':
+ case '5': g_string_append(obstrn04str, ";SY(DANGER03)"); sounding = TRUE; break;
+ default : g_string_append(obstrn04str, ";SY(DANGER01)"); sounding = TRUE; break;
+ }
+ }
+ }
+ } else { // valsou > 20.0
+ g_string_append(obstrn04str, ";SY(DANGER02)");
+ sounding = FALSE;
+ }
+
+ } else { // NO valsou
+ GString *objlstr = S57_getAttVal(geo, "OBJL");
+ int objl = (NULL == objlstr)? 0 : atoi(objlstr->str);
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (UWTROC == objl) {
+ if (NULL == watlevstr) // default
+ g_string_append(obstrn04str, ";SY(UWTROC04)");
+ else {
+ if ('3' == *watlevstr->str)
+ g_string_append(obstrn04str, ";SY(UWTROC03)");
+ else
+ g_string_append(obstrn04str, ";SY(UWTROC04)");
+ }
+
+ } else { // OBSTRN
+ if ( NULL == watlevstr) // default
+ g_string_append(obstrn04str, ";SY(OBSTRN01)");
+ else {
+ switch (*watlevstr->str) {
+ case '1':
+ case '2': g_string_append(obstrn04str, ";SY(OBSTRN11)"); break;
+ case '3': g_string_append(obstrn04str, ";SY(OBSTRN01)"); break;
+ case '4':
+ case '5':
+ default : g_string_append(obstrn04str, ";SY(OBSTRN01)"); break;
+ }
+ }
+ }
+
+ }
+
+ if (sounding && NULL != sndfrm02str)
+ g_string_append(obstrn04str, sndfrm02str->str);
+
+ if (NULL != quapnt01str)
+ g_string_append(obstrn04str, quapnt01str->str);
+
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+ if (NULL != quapnt01str) g_string_free(quapnt01str, TRUE);
+
+ return obstrn04str;
+
+ } else {
+ if (LINES_T == S57_getObjtype(geo)) {
+ // Continuation B
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = 0;
+
+ if (NULL != quaposstr) {
+ quapos = atoi(quaposstr->str);
+ if ( 2 <= quapos && quapos < 10){
+ if (NULL != udwhaz03str)
+ g_string_append(obstrn04str, ";LC(LOWACC41)");
+ else
+ g_string_append(obstrn04str, ";LC(LOWACC31)");
+ }
+ }
+
+ if (NULL != udwhaz03str)
+ g_string_append(obstrn04str, ";LS(DOTT,2,CHBLK)");
+
+ if (UNKNOWN != valsou) {
+ if (valsou <= 20.0)
+ g_string_append(obstrn04str, ";LS(DOTT,2,CHBLK)");
+ else
+ g_string_append(obstrn04str, ";LS(DASH,2,CHBLK)");
+ } else
+ g_string_append(obstrn04str, ";LS(DOTT,2,CHBLK)");
+
+
+ if (NULL != udwhaz03str)
+ g_string_append(obstrn04str, udwhaz03str->str);
+ else {
+ if (UNKNOWN != valsou)
+ if (valsou <= 20.0)
+ g_string_append(obstrn04str, sndfrm02str->str);
+ }
+
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+
+ return obstrn04str;
+
+ } else {
+ // Continuation C (AREAS_T)
+ GString *quapnt01str = _QUAPNT01(geo);
+ if (NULL != udwhaz03str) {
+ g_string_append(obstrn04str, ";AC(DEPVS);AP(FOULAR01)");
+ g_string_append(obstrn04str, ";LS(DOTT,2,CHBLK)");
+ g_string_append(obstrn04str, udwhaz03str->str);
+ if (NULL != quapnt01str)
+ g_string_append(obstrn04str, quapnt01str->str);
+
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+ if (NULL != quapnt01str) g_string_free(quapnt01str, TRUE);
+
+ return obstrn04str;
+ }
+
+ if (UNKNOWN != valsou) {
+ // BUG in CA49995B.000 if we get here because there is no color
+ // beside NODATA (ie there is a hole in group 1 area!)
+ //g_string_append(obstrn04, ";AC(UINFR)");
+
+ if (valsou <= 20.0)
+ g_string_append(obstrn04str, ";LS(DOTT,2,CHBLK)");
+ else
+ g_string_append(obstrn04str, ";LS(DASH,2,CHBLK)");
+
+ g_string_append(obstrn04str, sndfrm02str->str);
+
+ } else {
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL == watlevstr) // default
+ g_string_append(obstrn04str, ";AC(DEPVS);LS(DOTT,2,CHBLK)");
+ else {
+ if ('3' == *watlevstr->str) {
+ GString *catobsstr = S57_getAttVal(geo, "CATOBS");
+ if (NULL != catobsstr && '6' == *catobsstr->str)
+ g_string_append(obstrn04str, ";AC(DEPVS);AP(FOULAR01);LS(DOTT,2,CHBLK)");
+ } else {
+ switch (*watlevstr->str) {
+ case '1':
+ case '2': g_string_append(obstrn04str, ";AC(CHBRN);LS(SOLD,2,CSTLN)"); break;
+ case '4': g_string_append(obstrn04str, ";AC(DEPIT);LS(DASH,2,CSTLN)"); break;
+ case '5':
+ case '3':
+ default : g_string_append(obstrn04str, ";AC(DEPVS);LS(DOTT,2,CHBLK)"); break;
+ }
+ }
+ }
+ }
+
+ g_string_append(obstrn04str, quapnt01str->str);
+
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+ if (NULL != quapnt01str) g_string_free(quapnt01str, TRUE);
+
+ return obstrn04str;
+ }
+ }
+
+ // FIXME: check if one exit point could do!!!
+ return NULL;
+}
+
+static GString *OWNSHP02 (S57_geo *geo)
+// Remarks:
+// 1. CONNING POSITION
+// 1.1 When own-ship is drawn to scale, the conning position must be correctly located in
+// relation to the ship's outline. The conning position then serves as the pivot point for
+// the own-ship symbol, to be located by the ECDIS at the correct latitude, longitude
+// for the conning point, as computed from the positioning system, correcting for
+// antenna offset.
+// 1.2 In this procedure it is assumed that the heading line, beam bearing line and course
+// and speed vector originate at the conning point. If another point of origin is used,
+// for example to account for the varying position of the ships turning centre, this must
+// be made clear to the mariner.
+//
+// 2. DISPLAY OPTIONS
+// 2.1 Only the ship symbol is mandatory for an ECDIS. The mariner should be prompted
+// to select from the following additional optional features:
+// - display own-ship as:
+// 1. symbol, or
+// 2. scaled outline
+// - select time period determining vector length for own-ship and other vessel course and speed
+// vectors, (all vectors must be for the same time period),
+// - display own-ship vector,
+// - select ground or water stabilization for all vectors, and select whether to display the type of
+// stabilization, (by arrowhead),
+// - select one-minute or six-minute vector time marks,
+// - select whether to show a heading line, to the edge of the display window,
+// - select whether to show a beam bearing line, and if so what length (default: 10mm total
+// length).
+{
+ PRINTF("Mariner's object not drawn\n");
+ return NULL;
+}
+
+static GString *PASTRK01 (S57_geo *geo)
+// Remarks: This conditional symbology procedure was designed to allow the mariner
+// to select time labels at the pasttrack (see (3) 10.5.11.1). The procedure also
+// cares for the presentation of primary and secondary pasttrack.
+//
+// The manufacturer should define his own data class (spatial primitive) in xyt
+// (position and time) in order to represent Pastrk.
+{
+
+ PRINTF("Mariner's object not drawn\n");
+ return NULL;
+}
+
+static GString *_QUALIN01(S57_geo *geo);
+static GString *QUAPOS01 (S57_geo *geo)
+// Remarks: The attribute QUAPOS, which identifies low positional accuracy, is attached
+// to the spatial object, not the feature object.
+//
+// This procedure passes the object to procedure QUALIN01 or QUAPNT01,
+// which traces back to the spatial object, retrieves any QUAPOS attributes,
+// and returns the appropriate symbolization to QUAPOS01.
+{
+ GString *quapos01 = NULL;
+
+ if (LINES_T == S57_getObjtype(geo))
+ quapos01 = _QUALIN01(geo);
+ else
+ quapos01 = _QUAPNT01(geo);
+
+ return quapos01;
+}
+
+static GString *_QUALIN01(S57_geo *geo)
+// Remarks: The attribute QUAPOS, which identifies low positional accuracy, is attached
+// only to the spatial component(s) of an object.
+//
+// A line object may be composed of more than one spatial object.
+//
+// This procedure looks at each of the spatial
+// objects, and symbolizes the line according to the positional accuracy.
+{
+ GString *qualino1 = NULL;
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = 0;
+ char *line = NULL;
+
+ if (NULL != quaposstr) {
+ quapos = atoi(quaposstr->str);
+ if ( 2 <= quapos && quapos < 10)
+ line = ";LC(LOWACC21)";
+ } else {
+ GString *objlstr = S57_getAttVal(geo, "OBJL");
+ int objl = (NULL == objlstr)? 0 : atoi(objlstr->str);
+
+ if (COALNE == objl) {
+ GString *conradstr = S57_getAttVal(geo, "CONRAD");
+
+ if (NULL != conradstr) {
+ if ('1' == *conradstr->str)
+ line = ";LS(SOLD,3,CHMGF);LS(SOLD,1,CSTLN)";
+ else
+ line = ";LS(SOLD,1,CSTLN)";
+ } else
+ line = ";LS(SOLD,1,CSTLN)";
+
+ } else //LNDARE
+ line = ";LS(SOLD,1,CSTLN)";
+ }
+
+ if (NULL != line)
+ qualino1 = g_string_new(line);
+
+ return qualino1;
+}
+
+static GString *_QUAPNT01(S57_geo *geo)
+// Remarks: The attribute QUAPOS, which identifies low positional accuracy, is attached
+// only to the spatial component(s) of an object.
+//
+// This procedure retrieves any QUAPOS attributes, and returns the
+// appropriate symbols to the calling procedure.
+{
+ GString *quapnt01 = NULL;
+ int accurate = TRUE;
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = (NULL == quaposstr)? 0 : atoi(quaposstr->str);
+
+ if (NULL != quaposstr) {
+ if ( 2 <= quapos && quapos < 10)
+ accurate = FALSE;
+ }
+
+ if (accurate)
+ quapnt01 = g_string_new(";SY(LOWACC01)");
+
+ return quapnt01;
+}
+
+static GString *SLCONS03 (S57_geo *geo)
+// Remarks: Shoreline construction objects which have a QUAPOS attribute on their
+// spatial component indicating that their position is unreliable are symbolized
+// by a special linestyle in the place of the varied linestyles normally used.
+// Otherwise this procedure applies the normal symbolization.
+{
+ GString *slcons03 = NULL;
+ GString *valstr = NULL;
+ char *cmdw = NULL; // command word
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = (NULL == quaposstr)? 0 : atoi(quaposstr->str);
+
+ if (POINT_T == S57_getObjtype(geo)) {
+ if (NULL != quaposstr) {
+ if (2 <= quapos && quapos < 10)
+ cmdw =";SY(LOWACC01)";
+ }
+ } else {
+ // LINE_T and AREA_T are the same
+ if (NULL != quaposstr) {
+ if (2 <= quapos && quapos < 10)
+ cmdw =";LC(LOWACC01)";
+ } else {
+ valstr = S57_getAttVal(geo, "CONDTN");
+
+ if (NULL != valstr && ( '1' == *valstr->str || '2' == *valstr->str))
+ cmdw = ";LS(DASH,1,CSTLN)";
+ else {
+ int val = 0;
+ valstr = S57_getAttVal(geo, "CATSLC");
+ val = (NULL == valstr)? 0 : atoi(valstr->str);
+
+ if (NULL != valstr && ( 6 == val || 15 == val || 16 == val ))
+ cmdw = ";LS(SOLD,4,CSTLN)";
+ else {
+ valstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL != valstr && '2' == *valstr->str)
+ cmdw = ";LS(SOLD,2,CSTLN)";
+ else
+ if (NULL != valstr && ('3' == *valstr->str || '4' == *valstr->str))
+ cmdw = ";LS(DASH,2,CSTLN)";
+ else
+ cmdw = ";LS(SOLD,2,CSTLN)"; // default
+
+ }
+ }
+ }
+ }
+
+ // WARNING: not explicitly specified in S-52 !!
+ // FIXME: this is to put AC(DEPIT) --intertidal area
+
+ /*
+ if (AREAS_T == S57_getObjtype(geo)) {
+ GString *seabed01 = NULL;
+ GString *drval1str = S57_getAttVal(geo, "DRVAL1");
+ double drval1 = (NULL == drval1str)? -UNKNOWN : atof(drval1str->str);
+ GString *drval2str = S57_getAttVal(geo, "DRVAL2");
+ double drval2 = (NULL == drval2str)? -UNKNOWN : atof(drval2str->str);
+ // NOTE: change sign of infinity (minus) to get out of bound in seabed01
+
+
+ PRINTF("***********drval1=%f drval2=%f \n", drval1, drval2);
+ seabed01 = _SEABED01(drval1, drval2);
+ slcons03 = g_string_new(seabed01->str);
+ g_string_free(seabed01, TRUE);
+
+ }
+ */
+
+
+ if (NULL != cmdw) {
+ if (NULL == slcons03)
+ slcons03 = g_string_new(cmdw);
+ else
+ g_string_append(slcons03, cmdw);
+ }
+
+ return slcons03;
+}
+
+static GString *RESARE02 (S57_geo *geo)
+// Remarks: A list-type attribute is used because an area of the object class RESARE may
+// have more than one category (CATREA). For example an inshore traffic
+// zone might also have fishing and anchoring prohibition and a prohibited
+// area might also be a bird sanctuary or a mine field.
+//
+// This conditional procedure is set up to ensure that the categories of most
+// importance to safe navigation are prominently symbolized, and to pass on
+// all given information with minimum clutter. Only the most significant
+// restriction is symbolized, and an indication of further limitations is given by
+// a subscript "!" or "I". Further details are given under conditional
+// symbology procedure RESTRN01
+//
+// Other object classes affected by attribute RESTRN are handled by
+// conditional symbology procedure RESTRN01.
+{
+ GString *resare02 = g_string_new("");
+ GString *restrnstr = S57_getAttVal(geo, "RESTRN");
+ char restrn[LISTSIZE] = {'\0'};
+ GString *catreastr = S57_getAttVal(geo, "CATREA");
+ char catrea[LISTSIZE] = {'\0'};
+ char *symb = NULL;
+ char *line = NULL;
+ char *prio = NULL;
+
+ if ( NULL != restrnstr) {
+ _parseList(restrnstr->str, restrn);
+
+ if (NULL != catreastr) _parseList(catreastr->str, catrea);
+
+ if (strpbrk(restrn, "\007\010\016")) {
+ // Continuation A
+ if (strpbrk(restrn, "\001\002\003\004\005\006"))
+ symb = ";SY(ENTRES61)";
+ else {
+ if (NULL != catreastr && strpbrk(catrea, "\001\010\011\014\016\023\025\031"))
+ symb = ";SY(ENTRES61)";
+ else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(ENTRES71)";
+ else {
+ if (NULL != catreastr && strpbrk(catrea, "\004\005\006\007\012\022\024\026\027\030"))
+ symb = ";SY(ENTRES71)";
+ else
+ symb = ";SY(ENTRES51)";
+ }
+ }
+ }
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SYMBOLIZED_BND))
+ line = ";LC(CTYARE51)";
+ else
+ line = ";LS(DASH,2,CHMGD)";
+
+ prio = ";OP(6---)"; // display prio set to 6
+
+ } else {
+ if (strpbrk(restrn, "\001\002")) {
+ // Continuation B
+ if (strpbrk(restrn, "\003\004\005\006"))
+ symb = ";SY(ACHRES61)";
+ else {
+ if (NULL != catreastr && strpbrk(catrea, "\001\010\011\014\016\023\025\031"))
+ symb = ";SY(ACHRES61)";
+ else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(ACHRES71)";
+ else {
+ if (NULL != catreastr && strpbrk(catrea, "\004\005\006\007\012\022\024\026\027\030"))
+ symb = ";SY(ACHRES71)";
+ else
+ symb = ";SY(ACHRES51)";
+ }
+ }
+ }
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SYMBOLIZED_BND))
+ line = ";LC(ACHRE51)";
+ else
+ line = ";LS(DASH,2,CHMGD)";
+
+ prio = ";OP(6---)"; // display prio set to 6
+
+ } else {
+ if (strpbrk(restrn, "\003\004\005\006")) {
+ // Continuation C
+ if (NULL != catreastr && strpbrk(catrea, "\001\010\011\014\016\023\025\031"))
+ symb = ";SY(FSHRES51)";
+ else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(FSHRES71)";
+ else{
+ if (NULL != catreastr && strpbrk(catrea, "\004\005\006\007\012\022\024\026\027\030"))
+ symb = ";SY(FSHRES71)";
+ else
+ symb = ";SY(FSHRES51)";
+ }
+ }
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SYMBOLIZED_BND))
+ line = ";LC(FSHRES51)";
+ else
+ line = ";LS(DASH,2,CHMGD)";
+
+ prio = ";OP(6---)"; // display prio set to 6
+
+ } else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(INFARE51)";
+ else
+ symb = ";SY(RSRDEF51)";
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SYMBOLIZED_BND))
+ line = ";LC(CTYARE51)";
+ else
+ line = ";LS(DASH,2,CHMGD)";
+
+ }
+ }
+ }
+
+ } else {
+ // Continuation D
+ if (NULL != catreastr) {
+ if (strpbrk(catrea, "\001\010\011\014\016\023\025\031")) {
+ if (strpbrk(catrea, "\004\005\006\007\012\022\024\026\027\030"))
+ symb = ";SY(CTYARE71)";
+ else
+ symb = ";SY(CTYARE51)";
+ } else {
+ if (strpbrk(catrea, "\004\005\006\007\012\022\024\026\027\030"))
+ symb = ";SY(INFARE71)";
+ else
+ symb = ";SY(RSRDEF51)";
+ }
+ } else
+ symb = ";SY(RSRDEF51)";
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_SYMBOLIZED_BND))
+ line = ";LC(CTYARE51)";
+ else
+ line = ";LS(DASH,2,CHMGD)";
+ }
+
+ // create command word
+ if (NULL != prio)
+ g_string_append(resare02, prio);
+ g_string_append(resare02, line);
+ g_string_append(resare02, symb);
+
+ return resare02;
+}
+
+static GString *RESTRN01 (S57_geo *geo)
+// Remarks: Objects subject to RESTRN01 are actually symbolised in sub-process
+// RESCSP01, since the latter can also be accessed from other conditional
+// symbology procedures. RESTRN01 merely acts as a "signpost" for
+// RESCSP01.
+//
+// Object class RESARE is symbolised for the effect of attribute RESTRN in a separate
+// conditional symbology procedure called RESARE02.
+//
+// Since many of the areas concerned cover shipping channels, the number of symbols used
+// is minimised to reduce clutter. To do this, values of RESTRN are ranked for significance
+// as follows:
+// "Traffic Restriction" values of RESTRN:
+// (1) RESTRN 7,8: entry prohibited or restricted
+// RESTRN 14: IMO designated "area to be avoided" part of a TSS
+// (2) RESTRN 1,2: anchoring prohibited or restricted
+// (3) RESTRN 3,4,5,6: fishing or trawling prohibited or restricted
+// (4) "Other Restriction" values of RESTRN are:
+// RESTRN 9, 10: dredging prohibited or restricted,
+// RESTRN 11,12: diving prohibited or restricted,
+// RESTRN 13 : no wake area.
+{
+ GString *restrn01str = S57_getAttVal(geo, "RESTRN");
+ GString *restrn01 = NULL;
+
+ if (NULL != restrn01str)
+ restrn01 = _RESCSP01(geo);
+ else
+ restrn01 = g_string_new(";OP(----)"); // return NOOP to silence error msg
+
+ return restrn01;
+}
+
+static GString *_RESCSP01(S57_geo *geo)
+// Remarks: See procedure RESTRN01
+{
+ GString *rescsp01 = NULL;
+ GString *restrnstr = S57_getAttVal(geo, "RESTRN");
+ char restrn[LISTSIZE] = {'\0'}; // restriction list
+ char *symb = NULL;
+
+ if ( NULL != restrnstr) {
+ _parseList(restrnstr->str, restrn);
+
+ if (strpbrk(restrn, "\007\010\016")) {
+ // continuation A
+ if (strpbrk(restrn, "\001\002\003\004\005\006"))
+ symb = ";SY(ENTRES61)";
+ else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(ENTRES71)";
+ else
+ symb = ";SY(ENTRES51)";
+
+ }
+ } else {
+ if (strpbrk(restrn, "\001\002")) {
+ // continuation B
+ if (strpbrk(restrn, "\003\004\005\006"))
+ symb = ";SY(ACHRES61)";
+ else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(ACHRES71)";
+ else
+ symb = ";SY(ACHRES51)";
+ }
+
+
+ } else {
+ if (strpbrk(restrn, "\003\004\005\006")) {
+ // continuation C
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(FSHRES71)";
+ else
+ symb = ";SY(FSHRES51)";
+
+
+ } else {
+ if (strpbrk(restrn, "\011\012\013\014\015"))
+ symb = ";SY(INFARE51)";
+ else
+ symb = ";SY(RSRDEF51)";
+
+ }
+ }
+ }
+
+ rescsp01 = g_string_new(symb);
+ }
+
+ return rescsp01;
+}
+
+static GString *_SEABED01(double drval1, double drval2)
+// Remarks: An area object that is part of the seabed is coloured as necessary according
+// to the mariners selection of two shades, (shallow contour, safety contour,
+// deep contour), or four shades (safety contour only). This requires a decision
+// making process provided by this conditional symbology procedure. Note
+// that this procedure is called as a sub-procedure by other conditional
+// symbology procedures.
+//
+// Note: The requirement to show four depth shades is not mandatory. Also,
+// the requirement to show the shallow pattern is not mandatory. However,
+// both these features are strongly recommended.
+
+// return: is never NULL
+
+{
+ GString *seabed01 = NULL;
+ gboolean shallow = TRUE;
+ char *arecol = ";AC(DEPIT)";
+
+ if (drval1 >= 0.0 && drval2 > 0.0)
+ arecol = ";AC(DEPVS)";
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_TWO_SHADES)){
+ if (drval1 >= S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR) &&
+ drval2 > S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ arecol = ";AC(DEPDW)";
+ shallow = FALSE;
+ }
+ } else {
+ if (drval1 >= S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR) &&
+ drval2 > S52_getMarinerParam(S52_MAR_SHALLOW_CONTOUR))
+ arecol = ";AC(DEPMS)";
+
+ if (drval1 >= S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR) &&
+ drval2 > S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR)) {
+ arecol = ";AC(DEPMD)";
+ shallow = FALSE;
+ }
+
+ if (drval1 >= S52_getMarinerParam(S52_MAR_DEEP_CONTOUR) &&
+ drval2 > S52_getMarinerParam(S52_MAR_DEEP_CONTOUR)) {
+ arecol = ";AC(DEPDW)";
+ shallow = FALSE;
+ }
+
+ }
+
+ seabed01 = g_string_new(arecol);
+
+ if (TRUE==S52_getMarinerParam(S52_MAR_SHALLOW_PATTERN) && TRUE==shallow)
+ g_string_append(seabed01, ";AP(DIAMOND1)");
+
+ return seabed01;
+}
+
+static GString *SOUNDG02 (S57_geo *geo)
+// Remarks: In S-57 soundings are elements of sounding arrays rather than individual
+// objects. Thus this conditional symbology procedure examines each
+// sounding of a sounding array one by one. To symbolize the depth values it
+// calls the procedure SNDFRM02 which in turn translates the depth values
+// into a set of symbols to be shown at the soundings position.
+{
+ guint npt = 0;
+ double *ppt = NULL;
+
+ if (POINT_T != S57_getObjtype(geo)) {
+ PRINTF("invalid object type (not M_PNT_T)\n");
+ //return NULL;
+ exit(0);
+ }
+
+ S57_getGeoData(geo, 0, &npt, &ppt);
+
+ return _SNDFRM02(geo, ppt[2]);
+}
+
+static GString *_SNDFRM02(S57_geo *geo, double depth_value)
+// Remarks: Soundings differ from plain text because they have to be readable under all
+// circumstances and their digits are placed according to special rules. This
+// conditional symbology procedure accesses a set of carefully designed
+// sounding symbols provided by the symbol library and composes them to
+// sounding labels. It symbolizes swept depth and it also symbolizes for low
+// reliability as indicated by attributes QUASOU and QUAPOS.
+{
+ GString *sndfrm02 = g_string_new("");
+ char *symbol_prefix = NULL;
+ GString *tecsoustr = S57_getAttVal(geo, "TECSOU");
+ char tecsou[LISTSIZE] = {'\0'};
+ GString *quasoustr = S57_getAttVal(geo, "QUASOU");
+ char quasou[LISTSIZE] = {'\0'};
+ GString *statusstr = S57_getAttVal(geo, "STATUS");
+ char status[LISTSIZE] = {'\0'};
+ double leading_digit = 0.0;
+
+ // FIXME: test to fix the rounding error (!?)
+ depth_value += (depth_value > 0.0)? 0.01: -0.01;
+ leading_digit = (int) depth_value;
+
+ if (depth_value <= S52_getMarinerParam(S52_MAR_SAFETY_DEPTH))
+ symbol_prefix = "SOUNDS";
+ else
+ symbol_prefix = "SOUNDG";
+
+ if (NULL != tecsoustr) {
+ _parseList(tecsoustr->str, tecsou);
+ if (strpbrk(tecsou, "\006"))
+ g_string_sprintfa(sndfrm02, ";SY(%sB1)", symbol_prefix);
+ }
+
+ if (NULL != quasoustr) _parseList(quasoustr->str, quasou);
+ if (NULL != statusstr) _parseList(statusstr->str, status);
+
+ if (strpbrk(quasou, "\003\004\005\010\011") || strpbrk(status, "\022"))
+ g_string_sprintfa(sndfrm02, ";SY(%sC2)", symbol_prefix);
+ else {
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = (NULL == quaposstr)? 0 : atoi(quaposstr->str);
+
+ if (NULL != quaposstr) {
+ if (2 <= quapos && quapos < 10)
+ g_string_sprintfa(sndfrm02, ";SY(%sC2)", symbol_prefix);
+ }
+ }
+
+ // Continuation A
+ if (depth_value < 10.0) {
+ // can be above water (negative)
+ int fraction = (int)ABS((depth_value - leading_digit)*10);
+
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)ABS(leading_digit));
+ g_string_sprintfa(sndfrm02, ";SY(%s5%1i)", symbol_prefix, fraction);
+
+ // above sea level (negative)
+ if (depth_value < 0.0)
+ g_string_sprintfa(sndfrm02, ";SY(%sA1)", symbol_prefix);
+
+ return sndfrm02;
+ }
+
+ if (depth_value < 31.0) {
+ double fraction = depth_value - leading_digit;
+
+ if (fraction != 0.0) {
+ fraction = fraction * 10;
+ // FIXME: use modulus '%' instead of '/' --check this at 100m too
+ if (leading_digit >= 10.0)
+ g_string_sprintfa(sndfrm02, ";SY(%s2%1i)", symbol_prefix, (int)leading_digit/10);
+
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)leading_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s5%1i)", symbol_prefix, (int)fraction);
+
+ return sndfrm02;
+ }
+ }
+
+ // Continuation B
+ depth_value = leading_digit; // truncate to integer
+ if (depth_value < 100.0) {
+ double first_digit = leading_digit / 10;
+ double secnd_digit = leading_digit - (first_digit * 10);
+
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)first_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s0%1i)", symbol_prefix, (int)secnd_digit);
+
+ return sndfrm02;
+ }
+
+ if (depth_value < 1000.0) {
+ double first_digit = leading_digit / 100;
+ double secnd_digit = leading_digit - (first_digit * 100);
+ double third_digit = leading_digit - (first_digit * 100) - (secnd_digit * 10);
+
+ g_string_sprintfa(sndfrm02, ";SY(%s2%1i)", symbol_prefix, (int)first_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)secnd_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s0%1i)", symbol_prefix, (int)third_digit);
+
+ return sndfrm02;
+ }
+
+ if (depth_value < 10000.0) {
+ double first_digit = leading_digit / 1000;
+ double secnd_digit = leading_digit - (first_digit * 1000);
+ double third_digit = leading_digit - (first_digit * 1000) - (secnd_digit * 100);
+ double last_digit = leading_digit - (first_digit * 1000) - (secnd_digit * 100) - (third_digit * 100) ;
+
+ g_string_sprintfa(sndfrm02, ";SY(%s2%1i)", symbol_prefix, (int)first_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)secnd_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s0%1i)", symbol_prefix, (int)third_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s4%1i)", symbol_prefix, (int)last_digit);
+
+ return sndfrm02;
+ }
+
+ // Continuation C
+ {
+ double first_digit = leading_digit / 10000;
+ double secnd_digit = leading_digit - (first_digit * 10000);
+ double third_digit = leading_digit - (first_digit * 10000) - (secnd_digit * 1000);
+ double fourth_digit = leading_digit - (first_digit * 10000) - (secnd_digit * 1000) - (third_digit * 100) ;
+ double last_digit = leading_digit - (first_digit * 10000) - (secnd_digit * 1000) - (third_digit * 100) - (fourth_digit * 10) ;
+
+ g_string_sprintfa(sndfrm02, ";SY(%s3%1i)", symbol_prefix, (int)first_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s2%1i)", symbol_prefix, (int)secnd_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s1%1i)", symbol_prefix, (int)third_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s0%1i)", symbol_prefix, (int)fourth_digit);
+ g_string_sprintfa(sndfrm02, ";SY(%s4%1i)", symbol_prefix, (int)last_digit);
+
+ return sndfrm02;
+ }
+
+ return sndfrm02;
+}
+
+static GString *TOPMAR01 (S57_geo *geo)
+// Remarks: Topmark objects are to be symbolized through consideration of their
+// platforms e.g. a buoy. Therefore this conditional symbology procedure
+// searches for platforms by looking for other objects that are located at the
+// same position.. Based on the finding whether the platform is rigid or
+// floating, the respective upright or sloping symbol is selected and presented
+// at the objects location. Buoy symbols and topmark symbols have been
+// carefully designed to fit to each other when combined at the same position.
+// The result is a composed symbol that looks like the traditional symbols the
+// mariner is used to.
+{
+ GString *topshpstr = S57_getAttVal(geo, "TOPSHP");
+ GString *topmar = NULL;
+ char *sy = NULL;
+
+ if (NULL == topshpstr)
+ sy = ";SY(QUESMRK1)";
+ else {
+ int floating = FALSE; // not a floating platform
+ int topshp = (NULL==topshpstr) ? 0 : atoi(topshpstr->str);
+
+ if (TRUE == _atPtPos(geo, FLOATLIST))
+ floating = TRUE;
+ else
+ // FIXME: this test is wierd since it doesn't affect 'floating'
+ if (TRUE == _atPtPos(geo, RIGIDLIST))
+ floating = FALSE;
+
+
+ if (floating) {
+ // floating platform
+ switch (topshp) {
+ case 1 : sy = ";SY(TOPMAR02)"; break;
+ case 2 : sy = ";SY(TOPMAR04)"; break;
+ case 3 : sy = ";SY(TOPMAR10)"; break;
+ case 4 : sy = ";SY(TOPMAR12)"; break;
+
+ case 5 : sy = ";SY(TOPMAR13)"; break;
+ case 6 : sy = ";SY(TOPMAR14)"; break;
+ case 7 : sy = ";SY(TOPMAR65)"; break;
+ case 8 : sy = ";SY(TOPMAR17)"; break;
+
+ case 9 : sy = ";SY(TOPMAR16)"; break;
+ case 10: sy = ";SY(TOPMAR08)"; break;
+ case 11: sy = ";SY(TOPMAR07)"; break;
+ case 12: sy = ";SY(TOPMAR14)"; break;
+
+ case 13: sy = ";SY(TOPMAR05)"; break;
+ case 14: sy = ";SY(TOPMAR06)"; break;
+ case 17: sy = ";SY(TMARDEF2)"; break;
+ case 18: sy = ";SY(TOPMAR10)"; break;
+
+ case 19: sy = ";SY(TOPMAR13)"; break;
+ case 20: sy = ";SY(TOPMAR14)"; break;
+ case 21: sy = ";SY(TOPMAR13)"; break;
+ case 22: sy = ";SY(TOPMAR14)"; break;
+
+ case 23: sy = ";SY(TOPMAR14)"; break;
+ case 24: sy = ";SY(TOPMAR02)"; break;
+ case 25: sy = ";SY(TOPMAR04)"; break;
+ case 26: sy = ";SY(TOPMAR10)"; break;
+
+ case 27: sy = ";SY(TOPMAR17)"; break;
+ case 28: sy = ";SY(TOPMAR18)"; break;
+ case 29: sy = ";SY(TOPMAR02)"; break;
+ case 30: sy = ";SY(TOPMAR17)"; break;
+
+ case 31: sy = ";SY(TOPMAR14)"; break;
+ case 32: sy = ";SY(TOPMAR10)"; break;
+ case 33: sy = ";SY(TMARDEF2)"; break;
+ default: sy = ";SY(TMARDEF2)"; break;
+ }
+ } else {
+ // not a floating platform
+ switch (topshp) {
+ case 1 : sy = ";SY(TOPMAR22)"; break;
+ case 2 : sy = ";SY(TOPMAR24)"; break;
+ case 3 : sy = ";SY(TOPMAR30)"; break;
+ case 4 : sy = ";SY(TOPMAR32)"; break;
+
+ case 5 : sy = ";SY(TOPMAR33)"; break;
+ case 6 : sy = ";SY(TOPMAR34)"; break;
+ case 7 : sy = ";SY(TOPMAR85)"; break;
+ case 8 : sy = ";SY(TOPMAR86)"; break;
+
+ case 9 : sy = ";SY(TOPMAR36)"; break;
+ case 10: sy = ";SY(TOPMAR28)"; break;
+ case 11: sy = ";SY(TOPMAR27)"; break;
+ case 12: sy = ";SY(TOPMAR14)"; break;
+
+ case 13: sy = ";SY(TOPMAR25)"; break;
+ case 14: sy = ";SY(TOPMAR26)"; break;
+ case 15: sy = ";SY(TOPMAR88)"; break;
+ case 16: sy = ";SY(TOPMAR87)"; break;
+
+ case 17: sy = ";SY(TMARDEF1)"; break;
+ case 18: sy = ";SY(TOPMAR30)"; break;
+ case 19: sy = ";SY(TOPMAR33)"; break;
+ case 20: sy = ";SY(TOPMAR34)"; break;
+
+ case 21: sy = ";SY(TOPMAR33)"; break;
+ case 22: sy = ";SY(TOPMAR34)"; break;
+ case 23: sy = ";SY(TOPMAR34)"; break;
+ case 24: sy = ";SY(TOPMAR22)"; break;
+
+ case 25: sy = ";SY(TOPMAR24)"; break;
+ case 26: sy = ";SY(TOPMAR30)"; break;
+ case 27: sy = ";SY(TOPMAR86)"; break;
+ case 28: sy = ";SY(TOPMAR89)"; break;
+
+ case 29: sy = ";SY(TOPMAR22)"; break;
+ case 30: sy = ";SY(TOPMAR86)"; break;
+ case 31: sy = ";SY(TOPMAR14)"; break;
+ case 32: sy = ";SY(TOPMAR30)"; break;
+ case 33: sy = ";SY(TMARDEF1)"; break;
+ default: sy = ";SY(TMARDEF1)"; break;
+ }
+ }
+
+ }
+
+ topmar = g_string_new(sy);
+
+ return topmar;
+}
+
+static GString *_UDWHAZ03(S57_geo *geo, double depth_value)
+// Remarks: Obstructions or isolated underwater dangers of depths less than the safety
+// contour which lie within the safe waters defined by the safety contour are
+// to be presented by a specific isolated danger symbol as hazardous objects
+// and put in IMO category DISPLAYBASE (see (3), App.2, 1.3). This task
+// is performed by this conditional symbology procedure.
+{
+ GString *udwhaz03str = NULL;
+ int danger = FALSE;
+ double safety_contour = S52_getMarinerParam(S52_MAR_SAFETY_CONTOUR);
+
+ if (depth_value <= safety_contour) {
+ // that intersect this point/line/area for OBSTRN04
+ // that intersect this point/area for WRECKS02
+ S57_geo *geoTmp = geo;
+
+ // collect area/line DEPARE & area DRGARE that touche this point/line/area
+ S57_ogrTouche(geoTmp, N_OBJ_T);
+ while (NULL != (geoTmp = S57_nextObj(geoTmp))) {
+
+ if (LINES_T == S57_getObjtype(geoTmp)) {
+ GString *drval2str = S57_getAttVal(geoTmp, "DRVAL2");
+ double drval2 = (NULL == drval2str) ? 0.0 : atof(drval2str->str);
+
+ if (drval2 > safety_contour) {
+ danger = TRUE;
+ break;
+ }
+
+ } else {
+ // area DEPARE or DRGARE
+ GString *drval1str = S57_getAttVal(geoTmp, "DRVAL1");
+ double drval1 = (NULL == drval1str) ? 0.0 : atof(drval1str->str);
+
+ if (drval1 >= safety_contour) {
+ danger = TRUE;
+ break;
+ }
+ }
+
+ }
+ S57_unlinkObj(geo);
+
+
+
+ //danger = TRUE; // true
+ if (TRUE == danger) {
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+ if (NULL != watlevstr && ('1' == *watlevstr->str || '2' == *watlevstr->str))
+ udwhaz03str = g_string_new(";OP(--D14050");
+ else {
+ udwhaz03str = g_string_new(";OP(8OD14010);SY(ISODGR01)");
+ S57_setAtt(geo, "SCAMIN", "INFINITE");
+ }
+ }
+ }
+
+ return udwhaz03str;
+}
+
+static GString *VESSEL01 (S57_geo *geo)
+// Remarks: The mariner should be prompted to select from the following options:
+// - ARPA target or AIS report (overall decision or vessel by vessel) (vesrce)
+// - *time-period determining vector-length for all vectors (vecper)
+// - whether to show a vector (overall or vessel by vessel) (vestat)
+// - *whether to symbolize vector stabilization (vecstb)
+// - *whether to show one-minute or six-minute vector time marks (vecmrk)
+// - whether to show heading line on AIS vessel reports (headng)
+// * Note that the same vector parameters should be used for own-ship and all vessel
+// vectors.
+{
+ PRINTF("Mariner's object not drawn\n");
+ return NULL;
+}
+
+static GString *VRMEBL01 (S57_geo *geo)
+// Remarks: This conditional symbology procedure symbolizes the three cases of range
+// circle, bearing line and range/bearing line. VRM's and EBL's can be ship-centred
+// or freely movable, and two line-styles are available
+{
+ PRINTF("Mariner's object not drawn\n");
+ return NULL;
+}
+
+static GString *WRECKS02 (S57_geo *geo)
+// Remarks: Wrecks of depths less than the safety contour which lie within the safe waters
+// defined by the safety contour are to be presented by a specific isolated
+// danger symbol and put in IMO category DISPLAYBASE (see (3), App.2,
+// 1.3). This task is performed by the sub-procedure "UDWHAZ03" which is
+// called by this symbology procedure.
+{
+ GString *wrecks02str = NULL;
+ GString *sndfrm02str = NULL;
+ GString *udwhaz03str = NULL;
+ GString *quapnt01str = NULL;
+ double least_depth = UNKNOWN;
+ double depth_value = UNKNOWN;
+ GString *valsoustr = S57_getAttVal(geo, "VALSOU");
+ double valsou = UNKNOWN;
+
+ // exit if not in drawing state
+ //if (1 == S52_state)
+ // return NULL;
+
+ if (NULL != valsoustr) {
+ valsou = atof(valsoustr->str);
+ depth_value = valsou;
+ sndfrm02str = _SNDFRM02(geo, depth_value);
+ } else {
+ if (AREAS_T == S57_getObjtype(geo))
+ least_depth = _DEPVAL01(geo, least_depth);
+
+ if (least_depth == UNKNOWN) {
+ // WARNING: ambiguity removed in WRECKS03 (see update)
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+ GString *catwrkstr = S57_getAttVal(geo, "CATWRK");
+
+ if (NULL == watlevstr) // default
+ depth_value = -15.0;
+ else
+ switch (*watlevstr->str) { // ambiguous
+ case '1':
+ case '2': depth_value = -15.0 ; break;
+ case '3': depth_value = 0.01; break;
+ case '4': depth_value = -15.0 ; break;
+ case '5': depth_value = 0.0 ; break;
+ case '6': depth_value = -15.0 ; break;
+ default :{
+ if (NULL != catwrkstr) {
+ switch (*catwrkstr->str) {
+ case '1': depth_value = 20.0; break;
+ case '2': depth_value = 0.0; break;
+ case '4':
+ case '5': depth_value = -15.0; break;
+ }
+ }
+ }
+ }
+ } else
+ depth_value = least_depth;
+
+
+ }
+
+ udwhaz03str = _UDWHAZ03(geo, depth_value);
+ quapnt01str = _QUAPNT01(geo);
+
+ if (POINT_T == S57_getObjtype(geo)) {
+ if (NULL != udwhaz03str) {
+ wrecks02str = g_string_new(udwhaz03str->str);
+
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+
+ } else {
+ // Continuation A (POINT_T)
+ if (UNKNOWN != valsou) {
+
+ if (valsou <= 20.0) {
+ wrecks02str = g_string_new(";SY(DANGER01)");
+ if (NULL != sndfrm02str)
+ g_string_append(wrecks02str, sndfrm02str->str);
+
+ } else
+ wrecks02str = g_string_new(";SY(DANGER02)");
+
+ if (NULL != udwhaz03str)
+ g_string_append(wrecks02str, udwhaz03str->str);
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+
+ } else {
+ char *sym = NULL;
+ GString *catwrkstr = S57_getAttVal(geo, "CATWRK");
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL!=catwrkstr && NULL!=watlevstr) {
+ if ('1' == *catwrkstr->str && '3' == *watlevstr->str)
+ sym =";SY(WRECKS04)";
+ else
+ if ('2' == *catwrkstr->str && '3' == *watlevstr->str)
+ sym = ";SY(WRECKS05)";
+ } else {
+ if (NULL!=catwrkstr && ('4' == *catwrkstr->str || '5' == *catwrkstr->str)) {
+ sym = ";SY(WRECKS01)";
+ } else {
+ if (NULL != watlevstr) {
+ if ('1' == *watlevstr->str ||
+ '2' == *watlevstr->str ||
+ '5' == *watlevstr->str ||
+ '4' == *watlevstr->str )
+ sym = ";SY(WRECKS01)";
+ } else
+ sym = ";SY(WRECKS05)"; // default
+
+ }
+ }
+
+ wrecks02str = g_string_new(sym);
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+
+ }
+
+ }
+
+
+ } else {
+ // Continuation B (AREAS_T)
+ GString *quaposstr = S57_getAttVal(geo, "QUAPOS");
+ int quapos = (NULL == quaposstr)? 0 : atoi(quaposstr->str);
+ char *line = NULL;
+
+ if (2 <= quapos && quapos < 10)
+ line = ";LC(LOWACC41)";
+ else {
+ if ( NULL != udwhaz03str)
+ line = ";LS(DOTT,2,CHBLK)";
+ else {
+ if (UNKNOWN != valsou){
+ if (valsou <= 20)
+ line = ";LS(DOTT,2,CHBLK)";
+ else
+ line = ";LS(DASH,2,CHBLK)";
+ } else {
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL == watlevstr)
+ line = ";LS(DOTT,2,CSTLN)";
+ else {
+ switch (*watlevstr->str){
+ case '1':
+ case '2': line = ";LS(SOLD,2,CSTLN)"; break;
+ case '4': line = ";LS(DASH,2,CSTLN)"; break;
+ case '3':
+ case '5':
+
+ default : line = ";LS(DOTT,2,CSTLN)"; break;
+ }
+ }
+
+ }
+ }
+ }
+ wrecks02str = g_string_new(line);
+
+ if (UNKNOWN != valsou) {
+ if (valsou <= 20) {
+ if (NULL != udwhaz03str)
+ g_string_append(wrecks02str, udwhaz03str->str);
+
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+
+ if (NULL != sndfrm02str)
+ g_string_append(wrecks02str, sndfrm02str->str);
+
+ } else {
+ // NOTE: ??? same as above ???
+ if (NULL != udwhaz03str)
+ g_string_append(wrecks02str, udwhaz03str->str);
+
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+ }
+ } else {
+ char *ac = NULL;
+ GString *watlevstr = S57_getAttVal(geo, "WATLEV");
+
+ if (NULL == watlevstr)
+ ac = ";AC(DEPVS)";
+ else
+ switch (*watlevstr->str) {
+ case '1':
+ case '2': ac = ";AC(CHBRN)"; break;
+ case '4': ac = ";AC(DEPIT)"; break;
+ case '5':
+ case '3':
+ default : ac = ";AC(DEPVS)"; break;
+ }
+
+ g_string_append(wrecks02str, ac);
+
+ if (NULL != udwhaz03str)
+ g_string_append(wrecks02str, udwhaz03str->str);
+
+ if (NULL != quapnt01str)
+ g_string_append(wrecks02str, quapnt01str->str);
+ }
+ }
+
+ if (NULL != sndfrm02str) g_string_free(sndfrm02str, TRUE);
+ if (NULL != udwhaz03str) g_string_free(udwhaz03str, TRUE);
+ if (NULL != quapnt01str) g_string_free(quapnt01str, TRUE);
+
+ return wrecks02str;
+}
+
+
+//--------------------------------
+//
+// JUMP TABLE SECTION
+//
+//--------------------------------
+
+
+CondSymb condTable[] = {
+ // name call Sub-Procedure
+ {"CLRLIN01", CLRLIN01}, //
+ {"DATCVR01", DATCVR01}, //
+ {"DEPARE01", DEPARE01}, // _RESCSP01, _SEABED01
+ {"DEPCNT02", DEPCNT02}, //
+ {"LEGLIN02", LEGLIN02}, // str
+ {"LIGHTS05", LIGHTS05}, // _LITDSN01
+ {"OBSTRN04", OBSTRN04}, // _DEPVAL01, _QUAPNT01, _SNDFRM02, _UDWHAZ03
+ {"OWNSHP02", OWNSHP02}, //
+ {"PASTRK01", PASTRK01}, //
+ {"QUAPOS01", QUAPOS01}, // _QUALIN01, _QUAPNT01
+ {"SLCONS03", SLCONS03}, //
+ {"RESARE02", RESARE02}, //
+ {"RESTRN01", RESTRN01}, // _RESCSP01
+ {"SOUNDG02", SOUNDG02}, // _SNDFRM02
+ {"TOPMAR01", TOPMAR01}, //
+ {"VESSEL01", VESSEL01}, //
+ {"VRMEBL01", VRMEBL01}, //
+ {"WRECKS02", WRECKS02}, // _DEPVAL01, _QUAPNT01, _SNDFRM02, _UDWHAZ03
+
+ {"########",NULL}
+};
+
Added: packages/openev/branches/upstream/current/contrib/S52/S52CS.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52CS.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52CS.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,55 @@
+// S52cs.h: interface to Conditional Symbology (CS) instruction
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview porject, a viewer of ENC.
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52CS_H_
+#define _S52CS_H_
+
+#include "S57data.h" // S57_geo
+#include <glib.h> // GString, GData
+
+// get/set state LOAD or RENDER
+extern int S52_state;
+
+// Cond. Symb. callback
+// WARNING: caller of the callback has to free the returned GString
+typedef GString *(*CScb_t)(S57_geo *geoData);
+
+// Conditional Symbologie
+typedef struct _CondSymb {
+ char *name; // [9] '\0' terminated !?
+ CScb_t CScb;
+} CondSymb;
+
+extern CondSymb condTable[];
+
+extern char *S52_CS_version();
+
+extern int S52_CS_init();
+
+extern int S52_CS_done();
+
+// set position of floating and rigid platform
+extern int S52_CS_setPtPos(S57_geo *geoData, char *name);
+
+#endif //_S52CS_H_
Added: packages/openev/branches/upstream/current/contrib/S52/S52GL.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52GL.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52GL.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,3791 @@
+// S52GL.c: display S57 data using S52 symbology and OpenGL.
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC.
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+//#define INDEXMODE
+
+#include "S52GL.h"
+#include "S52utils.h" // S52_getConfig(), PRINTF()
+
+#ifdef S52_USE_OSG
+ #include "S52OSG.h" // glDrawArrays(), ...
+#else
+ #include <GL/gl.h>
+#endif
+
+#include <GL/glu.h> // tess, quadric,...
+#include <GL/glx.h> // glXUseXFont()
+#include <stdlib.h> // atoi()
+#include <string.h> // strncmp()
+#include <math.h> // ceil()
+#include <assert.h> // assert()
+
+#include <glib.h>
+
+// FIXME: mutex this!
+// experimental --cursor pick
+GLdouble dx = 3.0;
+GLdouble dy = 3.0;
+GStaticMutex sobj_mutex = G_STATIC_MUTEX_INIT;
+
+
+static GLenum _modes[8] = {GL_RENDER}; // assume we're rendering
+static int _topMode = 0;
+
+#include <X11/Xcms.h>
+#include <X11/Intrinsic.h>
+
+static Display *_display = 0;
+
+// debug --global for now, wiil move to a per-view struct
+// static
+Colormap _cmap = 0;
+
+static int currentScreen = 0;
+static S52_obj *_M_COVR = NULL;
+
+/////////////////////////////////////////////////////
+// object rasterazing cmd
+/*
+typedef struct instruction{
+ // !!! data common to all oject of this class with same attributes
+ S52_LUP *LUP;
+
+ // !!! data specific to this object
+ GString *CSinst; // LUP Cond. Symb. inst. command list (per object)
+ S52_CmdL *cmdList; // LUP list of command word (per object)
+ S52_Text *text; // text formating info
+ S57_geo *geoData; // coordinate & attributes
+
+} instruction;
+*/
+
+typedef struct _glCtx {
+ GArray *dispList; // hold names of lists for this context
+} _glCtx;
+
+static S52_diPrio _dprio = 0; // current dip. prio.
+static GPtrArray *instrucL[S52_PRIO_NUM][S52_LUP_NUM];//[RAD_NUM];
+static GPtrArray *switchPrio = NULL;
+static int _redraw = FALSE; // TRUE will force redraw
+
+
+//////////////////////////////////////////////////////
+// tessalisation & quadric
+static GLUtriangulatorObj *tobj = NULL;
+static GLUquadricObj *qobj = NULL;
+static GPtrArray *tmpV = NULL; // place holder during tesssalation
+
+// display list
+static int patternList = FALSE; // switch mode flag in _renderHPGL
+static GLuint _listIndex = 0; // GL display index (0==error)
+
+// transparency factor
+#define TRNSP_FAC 255 * 0.25
+
+////////////////////////////////////////////////
+// feedback buffer object
+typedef struct _feedbackObj {
+ int n; // nbr of floats in buf
+ GLsizei sz; // size of buf
+ GLsizei hint; // nbr of pt that *will* be requested
+ int cnt; // number of floats read
+ //GLfloat *buf; // feedback buffer
+ GLdouble *buf; // feedback buffer
+ GLfloat tok; // current token (see note)
+ gboolean read_tok; // TRUE read next buffer value as token
+ int poly_n; // total number of vertex in polygon
+ int poly_cnt; // number of polygon vertex read
+ int nvalue; // number of value per vertex GL_2D/GL_3D
+ gboolean eob; // TRUE if end of buffer reached
+
+} fObj;
+static fObj fobj;
+
+#define FB_EMPTY_TOK 0x0000
+
+/* NOTE: tok is 0x0000 for no value (FB_EMPTY_TOK)
+ or one of:
+
+ GL_POINT_TOKEN 0x0701
+ GL_LINE_TOKEN 0x0702
+ GL_LINE_RESET_TOKEN 0x0707
+ GL_POLYGON_TOKEN 0x0703
+ GL_BITMAP_TOKEN 0x0704
+ GL_DRAW_PIXEL_TOKEN 0x0705
+ GL_COPY_PIXEL_TOKEN 0x0706
+ GL_PASS_THROUGH_TOKEN 0x0700
+*/
+
+////////////////////////////////////////////////
+// selection buffer object
+typedef struct _selectionObj {
+ GLsizei sz; // size of buf
+ GLuint *buf; // selection buffer
+ GLuint *acc; // accumulation buffer
+ GLsizei nac; // number (of GLuint) accumulated
+ GPtrArray *geoV; // vector of pointer to object processed
+ // during selection
+ GLuint name;
+ GLint hits;
+
+ // to protect mouse event
+ //GStaticMutex mutex;
+ GLdouble x;
+ GLdouble y;
+ int doPick;
+
+} sObj;
+static sObj sobj;
+
+
+/////////////////////////////////////////////////////
+// projection (PROJ4)
+//static projPJ pj = NULL;
+//static projPJ pjsrc = NULL; // projection source
+//static projPJ pjdst = NULL; // projection destination
+
+static projUV pmin = {0.0, 0.0}; // projected view extend
+static projUV pmax = {0.0, 0.0}; // projected view extend
+
+// viewport of current openev gldraw signal
+static GLint vp[4]; // x,y,width,height
+
+typedef enum _VP{ // set GL_PROJECTION matrix to
+ VP_PRJ, // projected coordinate
+ VP_PRJ_ZCLIP, // same but short depth volume for line clipping
+ VP_WIN, // window coordinate
+ VP_REC // rectangular coord. (deg)
+}VP;
+
+// line mask plane
+#define Z_CLIP_PLANE 10000 // clipped beyon this plane
+
+//////////////////////////////////////////////////////
+// font
+#define PICA 0.351
+static char *_font[] = {
+// "-*-fixed-*-*-*-*-*-*-*-*-*-*-iso8859-*",
+// "-*-times-*-*-*-*-20-*-*-*-*-*-iso8859-*",
+// "-*-times-*-*-*-*-14-*-*-*-*-*-iso8859-*",
+// "-*-helvetica-medium-r-*-*-*-80-*-*-*-*-iso8859-*",
+
+ "-*-helvetica-medium-r-narrow-*-*-*-*-*-*-*-iso8859-*",
+ "-*-helvetica-medium-r-*-*-17-*-*-*-*-*-iso8859-*",
+ "-*-helvetica-bold-r-*-*-17-*-*-*-*-*-iso8859-*"
+};
+
+static gint _fontDList[3];
+//#include <gdk/gdk.h>
+//static GdkFont *gdkfont = NULL;
+//static GdkGLContext *_glcontext = NULL;
+//static GdkVisual *_visual;
+//static GvViewArea *view; // already commented out by SD
+//static GtkWidget *view;
+
+// debug
+//static int segNo = 1;
+static int countseg = 0;
+static int found = 0;
+
+// debug GL crash
+//extern GMutex * mutex;
+
+// assume round pixel (mm)
+// FIXME: get dot pitch from system (?)
+static double dotpitch_x = 0.3;
+static double dotpitch_y = 0.3;
+static double _scale = 0.0;
+
+typedef GLdouble coor3d[3];
+typedef struct _pt3{ GLdouble x,y,z; } pt3;
+typedef struct _pt2{ GLdouble x,y; } pt2;
+
+// pattern reference point, all pattern are aligned to this point
+// so that pattern cliped on adjacent area are complete
+//typedef struct _point { double x,y; } Point;
+//static Point patt_ref = {0.0, 0.0};
+
+// line mask
+static GTree *_vertexSet = NULL;
+static int _loadV = 1; // will load vertex
+
+// assoc object to hit record
+static GPtrArray *_objHitVec = NULL; // hold object used during SELECT
+
+//-----------------------------------
+//
+// GL TESS, QUADRIC, ... SECTION
+//
+//-----------------------------------
+
+static GLvoid _checkError(char *msg)
+{
+ GLenum err = glGetError();
+ if (GL_NO_ERROR != err) {
+ char *name;
+
+ switch(err) {
+ case GL_INVALID_ENUM: name = "GL_INVALID_ENUM"; break;
+ case GL_INVALID_VALUE: name = "GL_INVALID_VALUE"; break;
+ case GL_INVALID_OPERATION: name = "GL_INVALID_OPERATION"; break;
+ default:
+ name = "GL_NO_ERROR";
+ }
+
+ PRINTF("from %s: %s (%d:%s)\n", msg, gluErrorString(err), err, name);
+ exit(0);
+ }
+}
+
+static GLvoid _tessError(GLenum err)
+{
+
+// int len,i;
+ const GLubyte *str = gluErrorString(err);
+ PRINTF("%s (%d)\n", str,err);
+
+ exit(0);
+
+// glColor3f(0.9,0.9,0.9);
+// glRasterPos2i(5,5);
+// len = strlen(str);
+// for(i=0; i<len; i++)
+// glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[i]);
+
+}
+
+static GLvoid _quadricError(GLenum err)
+{
+
+ const GLubyte *str = gluErrorString(err);
+
+ PRINTF("%s (%d) (%0x)\n", str,err, err);
+ //exit(0);
+
+ /*
+ {
+ int len,i;
+ glColor3f(0.9,0.9,0.9);
+ glRasterPos2i(5,5);
+ len = strlen(str);
+ for(i=0; i<len; i++)
+ glutBitmapCharacter(GLUT_BITMAP_9_BY_15,str[i]);
+ }
+ */
+}
+
+static GLvoid _glEdgeFlag(GLboolean flag)
+{
+ //printf("_glEdgeFlag() called\n");
+ //glEdgeFlag(flag);
+ //glEdgeFlag(GL_FALSE);
+}
+
+
+static GLvoid _combineCallback(GLdouble coords[3],
+ GLdouble *vertex_data[4],
+ GLfloat weight[4],
+ GLdouble **dataOut )
+{
+ // optimisation: alloc once --keep pos. of current index
+ pt3 *p = g_new(pt3, 1);
+ p->x = coords[0];
+ p->y = coords[1];
+ p->z = coords[2];
+ *dataOut = (GLdouble*)p;
+ g_ptr_array_add(tmpV, (gpointer) p);
+
+/*
+ if (intess) {
+ pt3 *p = (pt3*) *dataOut; //coords;
+ PRINTF("combineCallback():");
+ printf("%f %f %f \n", p->x, p->y, p->z);
+ //printf("_combineCallback exiting ..\n");
+ //exit(0);
+ }
+*/
+
+}
+
+static GLvoid _glBegin(GLenum data, S57_prim *prim)
+{
+ S57_begPrim(prim, data);
+}
+
+static GLvoid _glEnd(S57_prim *prim)
+{
+ S57_endPrim(prim);
+}
+
+static GLvoid _vertex3d(GLvoid *data, S57_prim *prim)
+{
+
+ //pt3 p = *(pt3*) data;
+
+ //p.z = (double) (_dprio /100000.0);
+
+ S57_addPrimVertex(prim, data);
+ //S57_addPrimVertex(prim, &p);
+
+ //printf("%f %f %f \n", p->x, p->y, p->z);
+}
+
+static int _Xerror(Display *display, XErrorEvent* err)
+{
+
+ char buf[80];
+ XGetErrorText(display, err->error_code, buf, 80);
+
+ PRINTF("*** X error *** %d 0x%x %ld %d %d\n",
+ err->type ,
+ (unsigned int)err->resourceid,
+ (long int)err->error_code ,
+ (int)err->request_code,
+ err->minor_code
+ );
+ PRINTF("txt: %s\n", buf);
+ return 1;
+}
+
+#ifdef INDEXMODE
+static int initScreen[] = {0,0};
+#endif
+
+static int _toRGB(Display *dpy, Colormap cmap, GArray *colorTbl)
+{
+ int i = 0;
+
+ //int status = 0;
+ //unsigned long newCell, dummy1;
+ const int MAX_FREE_COL = 200;
+ unsigned long numFreeColors[MAX_FREE_COL];
+ //XColor colorss[150];
+ memset(numFreeColors, 0, sizeof(numFreeColors[MAX_FREE_COL]));
+
+ // test
+#ifdef INDEXMODE
+ if(initScreen[DefaultScreen(dpy)])
+ return 1;
+ else
+ initScreen[DefaultScreen(dpy)] += 1;
+#endif
+
+
+ for (i=0; i<colorTbl->len; ++i) {
+ char s[64];
+ S52_Color *c = &g_array_index(colorTbl, S52_Color, i);
+ Status sta = 0;
+ XcmsColor color_in_out;
+ XColor color_exact_return;
+ XColor color_screen_return;
+
+ // xyL --> XYZ
+ float Y = c->L;
+ float X = (c->x/c->y) * Y;
+ float Z = ((1 - c->x - c->y)/c->y) * Y;
+
+ color_in_out.pixel = 0;
+ color_in_out.format = XcmsCIEXYZFormat;
+ color_in_out.spec.CIEXYZ.X = X/100.0;
+ color_in_out.spec.CIEXYZ.Y = Y/100.0;
+ color_in_out.spec.CIEXYZ.Z = Z/100.0;
+
+ sprintf(s, "CIEXYZ:%f/%f/%f",
+ color_in_out.spec.CIEXYZ.X,
+ color_in_out.spec.CIEXYZ.Y,
+ color_in_out.spec.CIEXYZ.Z);
+
+ //sta = XcmsQueryColor(dpy, cmap, &color_in_out, XcmsRGBFormat);
+ sta = XLookupColor(dpy, _cmap, s, &color_exact_return, &color_screen_return);
+
+#ifdef INDEXMODE
+
+ status = XAllocColorCells(display, _cmap, 1, &dummy1, 0, &newCell, 1);
+ if (status == 0)
+ printf("COULD NOT ALLOCATE !! \n");
+ else
+ ; //printf("Allocated cell: %d \n", newCell);
+ colorss[i] = color_exact_return;
+
+ colorss[i].pixel = newCell;
+ // TODO check on status
+// int a = XAllocColor(dpy, cmap, &color_exact_return);
+// printf("Setting %s: idx: %d \n", c->colName, color_exact_return.pixel);
+ c->idx[currentScreen] = colorss[i].pixel;
+ printf("Setting %s: idx: %ld \n", c->colName, colorss[i].pixel);
+#endif
+ if (XcmsFailure == sta)
+ PRINTF("lookup color failure\n");
+ else {
+ c->R = (guchar) rint((color_exact_return.red + 1)/256);
+ c->G = (guchar) rint((color_exact_return.green + 1)/256);
+ c->B = (guchar) rint((color_exact_return.blue + 1)/256);
+// c->idx = color_exact_return.pixel;
+
+#ifdef INDEXMODE
+ c->idx = colorss[i].pixel;
+ printf("Setting %s: RGB: %d %d %d idx: %dn", c->colName, c->R, c->G, c->B, c->idx);
+#else
+ c->idx = 0;
+// printf("Setting %s: idx: %d RGB: %d %d %d \n", c->colName, c->R, c->G, c->B);
+#endif
+ }
+ }
+
+#ifdef INDEXMODE
+ XStoreColors(dpy, _cmap, colorss,i );
+ XInstallColormap(dpy, _cmap);
+ printf("Using and storing into Cmap: 0x%x\n", _cmap);
+#endif
+
+ return 1;
+}
+
+static GLint _initGLobj()
+// initialize various GL object
+// replace glcontext if current one not valid
+// if NULL assume that the caller has a valid context
+{
+ typedef void(*f)();
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // init tess stuff
+ //
+ {
+ // hold vertex comming from GLU_TESS_COMBINE callback
+ //tmpV = g_array_new(FALSE, FALSE, sizeof(coor3d));
+ tmpV = g_ptr_array_new();
+
+ tobj = gluNewTess();
+
+ gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (f) _glBegin);
+ gluTessCallback(tobj, GLU_TESS_END_DATA, (f) _glEnd);
+ gluTessCallback(tobj, GLU_TESS_ERROR, (f) _tessError);
+ gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,(f) _vertex3d);
+ gluTessCallback(tobj, GLU_TESS_COMBINE, (f) _combineCallback);
+ // NOTE: _not_ NULL to trigger GL_TRIANGLES tessallation
+ //gluTessCallback(tobj, GLU_TESS_EDGE_FLAG, (f) glEdgeFlag);
+ //gluTessCallback(tobj, GLU_TESS_EDGE_FLAG, (f) _glEdgeFlag);
+ gluTessCallback(tobj, GLU_TESS_EDGE_FLAG, (f) NULL);
+
+
+ // no GL_LINE_LOOP
+ //gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
+
+ //gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
+ // ODD needed for symb. ISODGR01
+ gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
+ //gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
+ //gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NEGATIVE);
+
+ // set poly in x-y plane normal is Z (for performance)
+ gluTessNormal(tobj, 0.0, 0.0, 1.0);
+ }
+
+ ///////////////////////////////////////////////////////////////
+ //
+ // misc GL stuff
+ //
+ {
+ g_assert(sizeof(double) == sizeof(GLdouble));
+
+ glShadeModel(GL_FLAT); // same color between vertex
+
+ //glEnable(GL_LINE_SMOOTH); // antialiase needed for line stippled
+ }
+
+ ////////////////////////////////////////////////////////////////
+ //
+ // init quadric stuff
+ //
+ {
+ qobj = gluNewQuadric();
+ gluQuadricCallback(qobj, GLU_ERROR, (f) _quadricError);
+
+ /*
+ _tessError(0);
+
+ str = gluGetString(GLU_VERSION);
+ printf("GLU version:%s\n",str);
+ str = glGetString(GL_VERSION);
+ printf("GL version:%s\n",str);
+ */
+ }
+
+ /////////////////////////////////////////////////////////////////
+ //
+ // init feedback buffer stuff
+ //
+ {
+ fobj.n = 0;
+ fobj.sz = 0;
+ fobj.hint = 0;
+ fobj.cnt = 0;
+ fobj.buf = NULL;
+ fobj.tok = FB_EMPTY_TOK;
+ fobj.read_tok = TRUE;
+ fobj.poly_n = 0;
+ fobj.poly_cnt = 0;
+ fobj.nvalue = 0;
+ fobj.eob = FALSE;
+ }
+
+ ///////////////////////////////////
+ //
+ // init selection buffer stuff
+ //
+ {
+ sobj.sz = 4096;
+ sobj.buf = g_new0(GLuint, sobj.sz); // hits
+ sobj.acc = g_new0(GLuint, sobj.sz); // hits accumulated
+ sobj.nac = 0;
+ sobj.geoV = g_ptr_array_new(); // hits index this
+ sobj.name = 0;
+ sobj.hits = 0;
+
+ sobj.x = 0.0;
+ sobj.y = 0.0;
+ sobj.doPick = FALSE;
+ }
+
+ ////////////////////////////////////
+ //
+ // X stuff
+ //
+
+ {
+ //extern GtkWidget *win;
+ Window root = 0;
+ Status sta = 0;
+ int screen = 0; //DefaultScreen(display);
+ Visual *visual = NULL;
+
+ //XcmsColor cms_color;
+ // display = GDK_DISPLAY();//GDK_WINDOW_XDISPLAY(win);
+ screen = DefaultScreen(_display);
+ root = RootWindow(_display, screen); //GDK_WINDOW_XWINDOW(win);
+
+ {
+ Window root_return;
+ Window parent_return;
+ Window *children_return;
+ unsigned int nchildren_return;
+ XWindowAttributes window_attributes_return;
+ // GTK_WIDGET(win)->window;
+
+ sta = XQueryTree(_display, root, &root_return, &parent_return,
+ &children_return, &nchildren_return);
+
+ if (sta == BadDrawable)
+ PRINTF("BadDrawable\n");
+ if (sta == BadWindow)
+ PRINTF("BadWindow\n");
+
+ sta = XGetWindowAttributes(_display, root, &window_attributes_return);
+
+ if (sta == BadDrawable)
+ PRINTF("BadDrawable\n");
+ if (sta == BadWindow)
+ PRINTF("BadWindow\n");
+
+ visual = DefaultVisual(_display, screen);
+
+ {
+ // Colormap cmap;
+ XVisualInfo vinfo_template;
+ XVisualInfo *vinfo;
+ long vinfo_mask = VisualClassMask;
+ //long vinfo_mask = VisualClassMask | VisualColormapSizeMask;
+ int nitems_return;
+#ifdef INDEXMODE
+ vinfo_template.class = PseudoColor;
+#else
+ vinfo_template.class = DirectColor;
+ //vinfo_template.class = TrueColor;
+#endif
+ // vinfo_mask = VisualIDMask; vinfo_template.visualid = 0x2d;
+ vinfo = XGetVisualInfo(_display, vinfo_mask,
+ &vinfo_template, &nitems_return);
+
+ XSetErrorHandler(_Xerror);
+
+ XSynchronize(_display, True);
+
+ // get a direct color visual
+ if (nitems_return > 0) {
+ if (_cmap == 0) {
+ // FIXME: scan for one with color map size >= 64
+ _cmap = XCreateColormap(_display, root,
+ vinfo->visual, AllocAll);
+ // for TrueColor
+ //_cmap = XCreateColormap(_display, root,
+ // vinfo->visual, AllocNone);
+ }
+ XFree(vinfo);
+
+ _toRGB(_display, _cmap, S52_PL_getColorTable());
+ }
+
+ XSynchronize(_display, False);
+ }
+
+ }
+
+ }
+
+ return 1;
+}
+
+static GLint _doneGLobj()
+{
+// int i;
+ g_ptr_array_free(tmpV , TRUE);
+ g_ptr_array_free(_objHitVec, TRUE);
+
+ gluDeleteTess(tobj);
+ gluDeleteQuadric(qobj);
+
+ // delete feedback buffer object
+ g_free(fobj.buf);
+
+ // selection
+ g_free(sobj.buf);
+ g_free(sobj.acc);
+ g_ptr_array_free(sobj.geoV, TRUE);
+ //g_static_mutex_free(sobj_mutex);
+ return 1;
+}
+
+static int _initGLmodule()
+// init GL module
+{
+ int i = 0;
+ int j = 0;
+
+ for (i=0; i<S52_PRIO_NUM; ++i) {
+ for (j=0; j<S52_LUP_NUM; ++j)
+ instrucL[i][j] = g_ptr_array_new();
+ }
+
+ switchPrio = g_ptr_array_new();
+
+ if (0 == _initGLobj()) {
+ exit(0);
+ }
+
+ return 1;
+}
+
+
+static double _get_area(int npt, double *ppt)
+// return area; CW (+) or CCW (-)
+{
+ int i;
+ double *d = ppt;
+ double a = 0.0;
+
+ for (i=0; i<npt-1; ++i) {
+ a += *d * *(d+4) - *(d+3) * *(d+1);
+ d += 3;
+ //a = x1 * y2 - x2 * y1;
+ }
+ d+=3;
+ a += *d * *(ppt+1) - *ppt * *(d+1);
+
+ printf("ring: %i = %s\n", i, (a<0)? "CCW":"CW");
+ return a;
+}
+
+static GLint _tessd(GLUtriangulatorObj *tobj, S52_obj *obj)
+// WARNING: not re-entrant (tmpV)
+{
+ guint i, j;
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ guint nr = S57_getRingNbr(geoData);
+ //GArray *XY = S57_getXY(geoData);
+ S57_prim *prim = S57_initPrimGeo(geoData);
+
+ // assume vertex place holder existe and is empty
+ g_assert(NULL != tmpV);
+ g_assert(0 == tmpV->len);
+
+ gluTessBeginPolygon(tobj, prim);
+ for (i=0; i<nr; ++i) {
+ guint npt;
+ pt3 *ppt;
+
+ S57_getGeoData(geoData, i, &npt, (double**)&ppt);
+ gluTessBeginContour(tobj);
+ for (j=0; j<npt; ++j, ++ppt)
+ gluTessVertex(tobj, (GLdouble*)ppt, (void*)ppt);
+ gluTessEndContour(tobj);
+ }
+ gluTessEndPolygon(tobj);
+
+ // empty vertex but keep array memory allocated
+ for (i=0; i<tmpV->len; ++i)
+ g_free(g_ptr_array_index(tmpV, i));
+ g_ptr_array_set_size(tmpV, 0);
+
+ return 1;
+}
+
+static GLint _glMatrixSet(VP vpcoord)
+// push & reset matrix GL_PROJECTION & GL_MODELVIEW
+{
+ GLdouble left, right, bottom, top, near, far;
+
+ // debug
+ //if (VP_WIN != vpcoord) return 1;
+
+ switch (vpcoord) {
+ case VP_PRJ:
+ left = pmin.u, right = pmax.u,
+ bottom = pmin.v, top = pmax.v,
+ near = Z_CLIP_PLANE, far = -Z_CLIP_PLANE;
+ break;
+
+ case VP_PRJ_ZCLIP:
+ left = pmin.u, right = pmax.u,
+ bottom = pmin.v, top = pmax.v,
+ near = Z_CLIP_PLANE, far = 1 - Z_CLIP_PLANE;
+ break;
+
+ case VP_WIN:
+ left = vp[0], right = vp[2],
+ bottom = vp[1], top = vp[3];
+ near = Z_CLIP_PLANE, far = -Z_CLIP_PLANE;
+ break;
+ default:
+ PRINTF("ERROR: unknown viewport coodinate\n");
+ return 0;
+ }
+
+ _checkError("_glMatrixSet -a");
+ glMatrixMode(GL_PROJECTION);
+ _checkError("_glMatrixSet -b");
+ glPushMatrix();
+ _checkError("_glMatrixSet -1");
+ glLoadIdentity();
+
+ if (TRUE==sobj.doPick && GL_SELECT==_modes[_topMode])
+ gluPickMatrix(sobj.x, vp[3] - sobj.y, dx, dy, vp);
+
+ //if (VP_WIN == vpcoord)
+ //glOrtho(left, right, bottom, top, 2, -2);
+ glOrtho(left, right, bottom, top, near, far);
+ //else
+ // gluPerspective(90.0, 1 /*(left-right)/(top-bottom)*/, 10.0, 3000000.0);
+ //glFrustum(left, right, bottom, top, 10, 0);
+
+ //printf("l/r, b/t: %f/%f, %f/%f\n", left, right, bottom, top);
+
+ _checkError("_glMatrixSet -2");
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ _checkError("_glMatrixSet -3");
+ glLoadIdentity();
+ _checkError("_glMatrixSet -4");
+
+ return 1;
+}
+
+static GLint _glMatrixDel(VP vpcoord)
+// pop matrix GL_PROJECTION & GL_MODELVIEW
+// param vpcoord use for completness only
+{
+ //if (VP_WIN != vpcoord) return 1;
+
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ _checkError("_glMatrixDel -B- ");
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ _checkError("_glMatrixDel -A- ");
+
+ return 1;
+}
+
+static GLint _glMatrixDump(GLenum matrix)
+// debug
+{
+ double m1[16];
+ double m2[16];
+
+ glGetDoublev(matrix, m1);
+
+ memcpy(m2 ,m1, sizeof(m1));
+
+ if (0 == memcmp(m2, m1, sizeof(m1))) {
+ printf("%f\t %f\t %f\t %f \n",m2[0], m2[1], m2[2], m2[3]);
+ printf("%f\t %f\t %f\t %f \n",m2[4], m2[5], m2[6], m2[7]);
+ printf("%f\t %f\t %f\t %f \n",m2[8], m2[9], m2[10],m2[11]);
+ printf("%f\t %f\t %f\t %f \n",m2[12],m2[13],m2[14],m2[15]);
+ printf("-------------------\n");
+ }
+ return 1;
+}
+
+//-----------------------------------
+//
+// PROJECTION SECTION
+//
+//-----------------------------------
+
+
+static projXY _prj2win(projXY p)
+// convert coordinate: projected --> window (pixel)
+{
+ GLdouble mvm[16]; // modelview matrix
+ GLdouble pjm[16]; // projection matrix
+ GLdouble z = 0; // dummy
+
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvm);
+ glGetDoublev(GL_PROJECTION_MATRIX, pjm);
+
+ if (GL_FALSE == gluProject(p.u, p.v, z, mvm, pjm, vp, &p.u, &p.v, &z)) {
+ PRINTF("ERROR\n");
+ exit(0);
+ }
+
+ return p;
+}
+
+static projXY _win2prj(projXY p)
+// convert coordinate: window --> projected
+{
+ GLdouble mvm[16]; // modelview matrix
+ GLdouble pjm[16]; // projection matrix
+ GLdouble x,y,z; // geo coordinate
+
+// _glMatrixDump(GL_MODELVIEW_MATRIX);
+
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvm);
+ glGetDoublev(GL_PROJECTION_MATRIX, pjm);
+
+ if (GL_TRUE == gluUnProject(p.u, p.v, 0.0, mvm, pjm, vp, &x, &y, &z)) {
+ //printf("%f %f %f \n", x, y, z);
+ p.u = x;
+ p.v = y;
+ } else {
+ printf("glUnProject() FAILED!\n");
+ exit(0);
+ }
+
+ /*
+ if (ABS(y) > 90.0 || ABS(x) > 180.0) {
+ PRINTF("ERROR: lat/lon %f/%f\n", y, x);
+
+ printf("GL_MODELVIEW_MATRIX:\n");
+ _glMatrixDump(GL_MODELVIEW_MATRIX);
+
+ printf("GL_PROJECTION_MATRIX:\n");
+ _glMatrixDump(GL_PROJECTION_MATRIX);
+ }
+ */
+
+ return p;
+}
+
+static GLvoid _glVertex3d(guint npt, GLdouble *ppt)
+{
+ // debug
+ guint i = 0;
+ double *p = ppt;
+ for (i=0; i<npt; ++i) {
+ //GLdouble z;
+ //projUV p;
+ //p.u = *ppt++;
+ //p.v = *ppt++;
+ //z = *ppt++;
+ p += 2;
+ *p++ = (double) (_dprio /10000.0);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_DOUBLE, 0, ppt);
+ glDrawArrays(GL_LINE_STRIP, 0, npt);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+
+ return;
+}
+
+static int _DrawArrays(S57_prim *prim)
+{
+ int i = 0;
+ int primNbr = 0;
+ double *vertex;
+
+ prim = S57_getPrimData(prim, &primNbr, &vertex);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_DOUBLE, 0, vertex);
+
+ for (i=0; i<primNbr; ++i) {
+ int mode = 0;
+ int first = 0;
+ int count = 0;
+
+ S57_getPrimIdx(prim, i, &mode, &first, &count);
+
+ glDrawArrays(mode, first, count);
+ //PRINTF("i:%i mode:%i first:%i count: %i\n", i, mode, first, count);
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ return i;
+}
+
+static int _fillarea(S52_obj *obj)
+{
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ //GArray *XY = S57_getXY(geoData);
+ S57_prim *prim = S57_getPrimGeo(geoData);
+
+ if (NULL == prim) {
+ _tessd(tobj, obj);
+ }
+
+ _glMatrixSet(VP_PRJ);
+ _DrawArrays(S57_getPrimGeo(geoData));
+ _glMatrixDel(VP_PRJ);
+
+ return TRUE;
+}
+
+
+static int _initPROJ()
+// get curent extend using the
+// current GL_PROJECTION & GL_MODELVIEW matrix
+{
+ projUV pc1, pc2; // pixel center
+
+ int c_pixel_x; // center pixel X
+ int c_pixel_y; // center pixel Y
+ double pixel_w_m; // pixel width in meter
+ double pixel_h_m; // pixel height in meter
+ double win_w_m; // window width in meter
+ projUV p1;
+ projUV p2;
+
+ // screen
+ /*
+ printf("screen witdth/height: %i/%i (mm) %i/%i (pixels) \n",
+ w_mm, h_mm, w_pixel, h_pixel);
+ printf("pixel size x/y: %f/%f (mm)\n", w_pixel_mm, h_pixel_mm);
+ printf("slope: %f\n", (float)w_pixel_mm/(float)h_pixel_mm);
+ printf("window x/y: %f/%f (mm)\n", (float)492*w_pixel_mm, (float)492*h_pixel_mm);
+ */
+
+ // window
+ glGetIntegerv(GL_VIEWPORT, vp);
+ // printf("ViewPort: %i %i %i %i (pixels)\n",
+ // vp[0], vp[1], vp[2], vp[3]);
+
+
+ return 1;
+
+ c_pixel_x = (int)floor((double)vp[2]/2.0);
+ c_pixel_y = (int)floor((double)vp[3]/2.0);
+
+ // --- LAT -----------------------------
+
+ // get lat bottom screen
+ p1.u = 0.0;
+ p1.v = 0.0;
+ p1 = _win2prj(p1);
+
+ // get lat top screen
+ p2.u = (double)vp[2];
+ p2.v = (double)vp[3];
+ p2 = _win2prj(p2);
+
+ //printf("top/bot lat (meter): %f / %f\n", p2.v, p1.v);
+ //printf("delta lat (meter): %f\n", ABS(p1.v - p2.v));
+
+ // --- LON ------------------------------
+
+ // get window center of current GL projection
+ pc1.u = c_pixel_x;
+ pc1.v = c_pixel_y;
+ pc1 = _win2prj(pc1);
+
+ // test equator
+ //pc1.u = 0.0;
+ //pc1.v = 0.0;
+
+ // get pixel cartesian diagonal
+ // FIXME: use width or height or booth
+ pc2.u = (double)c_pixel_x + 1.0;
+ pc2.v = (double)c_pixel_y + 1.0;
+ pc2 = _win2prj(pc2);
+
+ pixel_h_m = ABS(pc1.v - pc2.v);
+ pixel_w_m = ABS(pc1.u - pc2.u);
+
+ /*
+ printf("window center XY (x/y): %i / %i\n", c_pixel_x, c_pixel_x);
+ printf("geo center XY (u/v): %f / %f\n", pc1.u, pc1.v);
+ printf("pixel width (meter) : %f\n" , pixel_w_m);
+ printf("pixel height (meter) : %f\n" , pixel_h_m);
+ printf("pixel w/h ratio (m) : %f\n" , pixel_w_m/pixel_h_m);
+ */
+
+ // --- SET -----------------------------
+
+ // set proj lat (meter)
+ pmin.v = p1.v;
+ pmax.v = p2.v;
+
+ // set proj lon (meter)
+ //win_w_m = pixel_w_m * (double)vp[2];
+ win_w_m = pixel_h_m * (double)vp[2];
+ //printf("win_w_m: %f\n", win_w_m);
+ pmin.u = pc1.u - (win_w_m / 2);
+ pmax.u = pmin.u + win_w_m;
+
+ //printf("cartesian extend l/r/t/b: %f / %f / %f / %f\n",
+ // pmin.u, pmax.u, pmin.v, pmax.v);
+ //printf("cartesian width/height: %f/%f\n", pmin.u-pmax.u, pmin.v-pmax.v);
+
+ // --- SCALE ---------------------------
+ _scale = dotpitch_x / (pixel_w_m*1000);
+ //printf("scale: %f, pixel_w: %f\n", _scale, pixel_w_m);
+
+ return 1;
+}
+
+
+//---------------------------
+//
+// GL FEEDBACK BUFFER SECTION
+//
+//---------------------------
+
+static GLint _fb_alloc()
+{
+ fobj.sz += fobj.hint;
+
+ if (NULL == fobj.buf)
+ fobj.buf = g_new0(GLdouble, fobj.sz);
+ else
+ fobj.buf = g_renew(GLdouble, fobj.buf, fobj.sz);
+
+ return TRUE;
+}
+
+static GLint _fb_init(int hint)
+// set/resize buffer before calling the real glFeedbackBuffer()
+{
+ fobj.hint = hint;
+
+ fobj.n = 0;
+ fobj.cnt = 0;
+ fobj.tok = FB_EMPTY_TOK;
+ fobj.poly_n = 0;
+ fobj.poly_cnt = 0;
+ fobj.read_tok = TRUE;
+ //fobj.nvalue = 2; // GL_2D
+ fobj.nvalue = 3; // GL_3D
+ fobj.eob = FALSE;
+
+ return TRUE;
+}
+
+static GLint _fb_reset()
+// set feedback buffer for rereading
+{
+ fobj.cnt = 0;
+ fobj.read_tok = TRUE;
+ fobj.tok = FB_EMPTY_TOK;
+ fobj.poly_n = 0;
+ fobj.poly_cnt = 0;
+ fobj.eob = FALSE;
+
+ return 1;
+}
+
+static GLint _fb_flush()
+// empty feedback buffer
+{
+ fobj.tok = FB_EMPTY_TOK;
+ return 1;
+}
+
+static GLint _fb_addLine(double *pptA, double *pptB)
+{
+ if (fobj.n+6 > fobj.sz)
+ _fb_alloc();
+
+ fobj.tok = GL_LINE_TOKEN;
+
+ fobj.buf[fobj.n++] = *pptA++;
+ fobj.buf[fobj.n++] = *pptA++;
+ fobj.buf[fobj.n++] = *pptA++;
+
+ fobj.buf[fobj.n++] = *pptB++;
+ fobj.buf[fobj.n++] = *pptB++;
+ fobj.buf[fobj.n++] = *pptB++;
+
+ if (fobj.n > fobj.sz) {
+ PRINTF("FATAL ERROR: buffer overflow\n");
+ exit(0);
+ }
+
+ return TRUE;
+}
+
+
+/*
+static int _pushMode(GLenum newMode);
+static GLenum _popMode(GLenum mode);
+static GLint _fb_geo2winClip(S57_geo *geoData, S52_CmdL *cmd)
+// feedback buffer coordinate to screen transform and clip
+{
+ guint npt = 0;
+ GLdouble *ppt = NULL;
+
+ // check if FB need to be filled
+ if (FB_EMPTY_TOK != fobj.tok)
+ return 1;
+
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+
+ // setup feedback buffer mode
+ fobj.hint = npt;
+ _pushMode(GL_FEEDBACK);
+
+ // fill feedback buffer according to command type
+ switch (S52_PL_getCmdWord(cmd)) {
+ // LINES_T/AREAS_T
+ case S52_CMD_SIM_LN:
+ case S52_CMD_COM_LN:
+ _glMatrixSet(VP_PRJ_ZCLIP);
+ glBegin(GL_LINE_STRIP);
+ _glVertex3d(npt, ppt);
+ glEnd();
+ _glMatrixDel(VP_PRJ_ZCLIP);
+ break;
+
+ // POINT_T/AREAS_T
+ case S52_CMD_TXT_TX:
+ case S52_CMD_TXT_TE:
+ case S52_CMD_SYM_PT:
+ if (POINT_T == S57_getObjtype(geoData)) {
+ _glMatrixSet(VP_PRJ);
+ glBegin(GL_POINTS);
+ _glVertex3d(npt, ppt);
+ glEnd();
+ _glMatrixDel(VP_PRJ);
+ break;
+ }
+
+ // AREAS_T
+ case S52_CMD_ARE_CO:
+ case S52_CMD_ARE_PA:
+ _glMatrixSet(VP_PRJ);
+ _fillarea(geoData, NULL);
+ _glMatrixDel(VP_PRJ);
+ break;
+
+ default:
+ PRINTF("ERROR: command type (%i) \n", S52_PL_getCmdWord(cmd));
+
+ }
+
+ // finish with feedback buffer mode
+ _popMode(GL_FEEDBACK);
+
+ _checkError("_fb_geo2winClip()");
+
+ return TRUE;
+}
+*/
+
+
+static GLint _needClip(double segAbeg, double segAend,
+ double segBbeg, double segBend)
+{
+ if (segAbeg < segBbeg) return TRUE;
+ if (segAend > segBend) return TRUE;
+
+ return FALSE;
+}
+
+static GLint _intersec(double segAbeg, double segAend,
+ double segBbeg, double segBend)
+// TRUE if A overlap B
+{
+ if (segAend < segBbeg) return FALSE;
+ if (segAbeg > segBend) return FALSE;
+
+ return TRUE;
+}
+
+
+static GLint _fb_clipLine(int npt, double *ppt)
+{
+ int i = 0;
+ for (i=0; i<npt-1; ++i, ppt+=3) {
+ // check if segemnt overlap window
+ if (TRUE == _intersec(ppt[0], ppt[3], pmin.u, pmax.u) ||
+ TRUE == _intersec(ppt[1], ppt[4], pmin.v, pmax.v) )
+ _fb_addLine(ppt, ppt+3);
+ }
+
+ return TRUE;
+}
+
+static GLint _fb_geo2winClip(S52_obj *obj)
+// coordinate to screen clip
+{
+ //guint npt = 0;
+ //GLdouble *ppt = NULL;
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ //projUV xy1, xy2; // LL UR
+ int i = 0;
+ guint nr = S57_getRingNbr(geoData);
+
+
+ // check if FB need to be filled
+ if (FB_EMPTY_TOK != fobj.tok)
+ return 1;
+
+ //S57_getExt(geoData, &xy1.u, &xy1.v, &xy2.u, &xy2.v);
+
+ // check if all inside
+ //if (TRUE == _needClip(xy1.u, xy2.u, pmin.u, pmax.u) ||
+ // TRUE == _needClip(xy1.v, xy2.v, pmin.v, pmax.v) ) {
+
+ _fb_init(100);
+ for (i=0; i<nr; ++i) {
+ guint npt;
+ double *ppt;
+ S57_getGeoData(geoData, i, &npt, &ppt);
+ _fb_clipLine(npt, ppt);
+ }
+
+ return TRUE;
+}
+
+static GLint _fb_getNextPoint(GLfloat *x, GLfloat *y)
+{
+ // this is the end ..
+ if (fobj.n<=fobj.cnt) {
+ //_fb_reset();
+ fobj.eob = TRUE;
+ return FALSE;
+ }
+
+ *x = fobj.buf[fobj.cnt+1];
+ *y = fobj.buf[fobj.cnt+2];
+
+ return TRUE;
+}
+
+/*
+static GLint _fb_getNextSeg(GLfloat *x1, GLfloat *y1, GLfloat *x2, GLfloat *y2)
+// get next segment from feedback buffer
+// Doesn't assume homogenous type of token in buffer
+// return 0 --scan completed
+// return 1 --coords
+// return 2 --last poly seg or line reset
+// WARNING: not reentrant
+{
+ int offset = 0;
+ gboolean line = FALSE;
+ int ret = 1;
+
+ // only GL_2D mode --for now
+ g_assert(fobj.nvalue == 2);
+
+ // this is the end ..
+ if (fobj.n<=fobj.cnt) {
+ //_fb_reset();
+ fobj.eob = TRUE;
+ return FALSE;
+ }
+
+ // start new
+ if (TRUE == fobj.read_tok) {
+ fobj.tok = fobj.buf[fobj.cnt++];
+ //fobj.read_tok = FALSE;
+ }
+
+ // find next position
+ switch((int)fobj.tok) {
+ case GL_POLYGON_TOKEN:
+ // start of a new poly
+ if (TRUE == fobj.read_tok) {
+ fobj.read_tok = FALSE;
+ fobj.poly_n = (int) fobj.buf[fobj.cnt++];
+ fobj.poly_cnt = 0;
+ //printf("new poly...\n");
+ }
+
+ // set next vertex
+ if (fobj.poly_cnt < fobj.poly_n-1) {
+ ++fobj.poly_cnt;
+ } else {
+ // last segment of loop
+ fobj.read_tok = TRUE;
+ offset = -(fobj.poly_n * fobj.nvalue);
+ ret = 2;
+ }
+ break;
+
+ case GL_LINE_TOKEN:
+ line = TRUE;
+ ret = 1;
+ break;
+ case GL_LINE_RESET_TOKEN:
+ line = TRUE;
+ ret = 2;
+ break;
+
+ case GL_POINT_TOKEN:
+ line = FALSE;
+ break;
+
+ default:
+ PRINTF("ERROR unknown feedbak buffer token (%f)\n", fobj.tok);
+ //g_return_val_if_fail(FALSE, FALSE);
+ {
+ float f = GL_POINT_TOKEN;
+ printf("GL_POINT_TOKEN = %f \n", f);
+ f = GL_LINE_TOKEN;
+ printf("GL_LINE_TOKEN = %f \n", f);
+ f = GL_LINE_RESET_TOKEN;
+ printf("GL_LINE_RESET_TOKEN = %f \n", f);
+ f = GL_POLYGON_TOKEN;
+ printf("GL_POLYGON_TOKEN = %f \n", f);
+
+ exit(0);
+ }
+ }
+
+ // get vertex start
+ *x1 = fobj.buf[fobj.cnt+0];
+ *y1 = fobj.buf[fobj.cnt+1];
+
+ // move to next vertex
+ fobj.cnt += fobj.nvalue;
+
+ // get vertex end --could be first vertex of a loop
+ *x2 = fobj.buf[fobj.cnt+offset+0];
+ *y2 = fobj.buf[fobj.cnt+offset+1];
+
+ // advance past last vertex --line
+ if (TRUE == line)
+ fobj.cnt += fobj.nvalue;
+
+ //return TRUE;
+ return ret;
+}
+*/
+
+static GLint _fb_getNextSeg(GLfloat *x1, GLfloat *y1, GLfloat *x2, GLfloat *y2)
+// get next segment from feedback buffer
+// Doesn't assume homogenous type of token in buffer
+// return 0 --scan completed
+// return 1 --coords
+// return 2 --last poly seg or line reset
+// WARNING: not reentrant
+{
+ //int offset = 0;
+ //gboolean line = FALSE;
+ int ret = 1;
+
+ // only GL_2D mode --for now
+ g_assert(fobj.nvalue == 3);
+
+ // this is the end ..
+ if (fobj.n<=fobj.cnt) {
+ //_fb_reset();
+ fobj.eob = TRUE;
+ return FALSE;
+ }
+
+
+
+ // get vertex start
+ *x1 = fobj.buf[fobj.cnt+0];
+ *y1 = fobj.buf[fobj.cnt+1];
+
+ // move to next vertex
+ fobj.cnt += fobj.nvalue;
+
+ *x2 = fobj.buf[fobj.cnt+0];
+ *y2 = fobj.buf[fobj.cnt+1];
+
+ // advance past last vertex --line
+ //if (TRUE == line)
+
+ fobj.cnt += fobj.nvalue;
+
+ //return TRUE;
+ return ret;
+}
+
+
+static GLint _fb_getCentroid(GLfloat *x, GLfloat *y)
+// return TRUE and centroid else FALSE
+{
+ GLfloat x1, y1, x2=-1.0, y2=-1.0;
+ GLfloat ai;
+ GLfloat area;
+ GLfloat atmp = 0.0;
+ GLfloat xtmp = 0.0;
+ GLfloat ytmp = 0.0;
+ //GLfloat r = 0.0, g = 0.0, b = 0.0;
+
+ if (TRUE == fobj.eob || fobj.n<=fobj.cnt)
+ return FALSE;
+
+ //glColor3f(0.0, 1.0, 0.0);
+ //glBegin(GL_LINES);
+
+ // compute area
+ while (_fb_getNextSeg(&x1, &y1, &x2, &y2)) {
+
+ //printf("t:0x%04x :: %6.2f %6.2f || %6.2f %6.2f \n",
+ // (int)fobj.tok, x1, y1, x2, y2);
+ //glColor3f(r, g, 1.0);
+ //glVertex2f(x1, y1);
+ //glVertex2f(x2, y2);
+
+ // no area to compute --break loop
+ if (GL_POINT_TOKEN == fobj.tok) {
+ *x = x1;
+ *y = y1;
+ break;
+ }
+
+ ai = x1 * y2 - x2 * y1;
+ atmp += ai;
+ xtmp += (x2 + x1) * ai;
+ ytmp += (y2 + y1) * ai;
+ }
+
+ // compute center fo area
+ if (atmp != 0.0) {
+ area = atmp / 2;
+
+ // CW = 1, CCW = 2
+ //ret (atmp >= 0.0) ? 1 : 2;
+
+ *x = xtmp / (3 * atmp);
+ *y = ytmp / (3 * atmp);
+ }
+
+ //glEnd();
+
+ //printf("_getCentroid x = %f, y = %f \n", *x, *y);
+
+ return TRUE;
+}
+
+static GLint _fb_getNextCenterPos(S52_obj *obj, GLfloat *x, GLfloat *y)
+// get center in screen coordinate for different primitive
+{
+ int ret = FALSE;
+
+ //return 0;
+
+ //if (NULL == geoData)
+ // return 0;
+
+ // send data to feedback buffer
+ _fb_geo2winClip(obj);
+
+ switch (S57_getObjtype(S52_PL_getGeo(obj))) {
+ case LINES_T: {
+ GLfloat x1,y1,x2,y2;
+ ret = _fb_getNextSeg(&x1, &y1, &x2, &y2);
+ *x = x2 - x1;
+ *y = y2 - y1;
+ break;
+ }
+
+ case POINT_T: //PRINTF(" POINT_T not computed \n");
+ break;
+
+ case AREAS_T:
+ ret = _fb_getCentroid(x, y);
+ break;
+
+ default:
+ PRINTF("ERROR: unknown object type\n");
+ exit(0);
+ }
+
+ return ret;
+}
+
+static int _initSobj(int szfac);
+static int _accuSobj();
+static int _pushMode(GLenum newMode)
+// handle mutual exclusive GL rendering mode
+// newMode will become the current mode
+// previous mode will resume when this one is poped
+{
+ _checkError("start _pushMode()");
+
+ // can't handle a stack of similar mode at the moment
+ g_assert(newMode != _modes[_topMode]);
+
+ // suspend current mode
+ switch (_modes[_topMode]) {
+ case GL_RENDER:
+ // do nothing here
+ break;
+
+ case GL_SELECT: // accumulate the number of hits
+ sobj.hits = glRenderMode(GL_RENDER);
+ _accuSobj();
+ break;
+
+ case GL_FEEDBACK: // this can't happen at the moment
+ PRINTF("ERROR: feedback mode interrupted!\n");
+ break;
+
+ default:
+ PRINTF("ERROR: unknown GL mode\n");
+ return 0;
+ }
+
+ _modes[++_topMode] = newMode;
+
+ // start new mode
+ switch (newMode) {
+
+ case GL_RENDER:
+ // do nothing
+ break;
+
+ case GL_SELECT:
+ _initSobj(0);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(sobj.name);
+ break;
+
+ case GL_FEEDBACK:
+ //_fb_init();
+ //glRenderMode(GL_FEEDBACK);
+ break;
+
+ default:
+ PRINTF("ERROR: unknown GL mode\n");
+ return 0;
+ }
+
+ _checkError("_pushMode()");
+
+ return 1;
+}
+
+static GLenum _popMode(GLenum mode)
+{
+ // sanity check
+ g_assert(_topMode > 0); // something to pop
+ g_assert(mode == _modes[_topMode]); // poping the right thing
+
+ // handle completion of current mode
+ switch (_modes[_topMode]) {
+
+ case GL_RENDER:
+ // do nothing
+ break;
+
+ case GL_SELECT:
+ // switch off selection
+ sobj.hits = glRenderMode(GL_RENDER);
+ _accuSobj();
+ break;
+
+ case GL_FEEDBACK:
+ fobj.n = glRenderMode(GL_RENDER);
+ if (fobj.n < 0) {
+ PRINTF("ERROR feedback buffer overflow (%i)\n", fobj.n);
+ printf("fobj.sz=%i npt=%i \n", fobj.sz, fobj.hint);
+ exit(0);
+ }
+ break;
+
+ default:
+ PRINTF("ERROR: unknown GL mode\n");
+ return 0;
+ }
+
+ // pop the stack
+ _topMode--;
+
+ // resume previous mode
+ switch (_modes[_topMode]) {
+
+ case GL_RENDER:
+ glRenderMode(GL_RENDER);
+ break;
+
+ case GL_SELECT:
+ //glSelectBuffer(sobj.sz, sobj.buf);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(sobj.name);
+ _checkError("GL_SELECT");
+ break;
+
+ case GL_FEEDBACK:
+ glRenderMode(GL_FEEDBACK);
+ break;
+
+ default:
+ PRINTF("ERROR: unknown GL mode\n");
+ return 0;
+ }
+
+ _checkError("_popMode()");
+
+ return _modes[_topMode];
+}
+
+
+//---------------------------------------
+//
+// SYMBOLOGY INSTRUCTION RENDERER SECTION
+//
+//---------------------------------------
+
+static int _glCallList(S52_subListData *sld)
+{
+ int i = 0;
+ GLuint lst = sld->startList;
+ S52_Color *col = (S52_Color *) sld->col;
+
+ for (i=0; i<sld->nSubList; ++i, ++lst) {
+ glColor4ub(col[i].R,
+ col[i].G,
+ col[i].B,
+ (4 - (col[i].trans - '0'))*TRNSP_FAC);
+
+ glCallList(lst);
+ //PRINTF("list no: %i\n", lst);
+ }
+
+ _checkError("_glCallList()");
+
+ return 1;
+}
+static int _renderEX(S52_obj *obj)
+//static S52_CmdL *_renderTEXT(S52_obj *obj)
+// render TE or TX
+// NOTE: could use later: "void glutStrokeString(void *font, char *string);"
+
+{
+ //GLfloat x = 0.0;
+ //GLfloat y = 0.0;
+ S52_Color *col = NULL;
+ int xoffs = 0;
+ int yoffs = 0;
+ int bsize = 0;
+ int weight= 0;
+ char *str;
+
+ //if (NULL == instruc || NULL == instruc->text)
+ // return cmd;
+
+ //S52_PL_getTEXT(instruc->text, &col, &xoffs, &yoffs, &bsize, &weight, &str);
+ str = S52_PL_getEX(obj, &col, &xoffs, &yoffs, &bsize, &weight);
+ //printf("xoffs/yoffs/bsize/weight: %i/%i/%i/%i\n", xoffs, yoffs, bsize, weight);
+ if (NULL == str)
+ return 0;
+
+#ifdef INDEXMODE
+ glIndexi(col->idx[currentScreen]);
+#else
+ glColor4ub(col->R, col->G, col->B, 255);
+#endif
+ //_fb_geo2winClip(instruc->geoData, cmd);
+
+ //glPushAttrib(GL_LIST_BASE);
+ glPushAttrib(GL_LIST_BIT);
+ glListBase(_fontDList[weight-'4']);
+
+ _glMatrixSet(VP_PRJ);
+ //while (_fb_getNextCenterPos(instruc->geoData, cmd, &x, &y)) {
+ {
+ guint npt;
+ double *ppt;
+ S57_getGeoData(S52_PL_getGeo(obj), 0, &npt, &ppt);
+
+ //glRasterPos2f(x /*+ xoffs*PICA*bsize*/, y /* + yoffs*PICA*bsize*/ );
+
+ // FIXME: scale offset X/Y
+ glRasterPos2d(ppt[0] /*+ xoffs*PICA*bsize*/, ppt[1] /* + yoffs*PICA*bsize*/ );
+ //glRasterPos2d(50 /*+ xoffs*PICA*bsize*/, 50 /* + yoffs*PICA*bsize*/ );
+ glCallLists(strlen(str), GL_UNSIGNED_BYTE, (GLubyte*)str);
+ //printf("(%f,%f) off %f/%f : %s \n", x, y, xoffs*PICA*bsize, yoffs*PICA*bsize, str);
+ //printf("(%f,%f) \n", ppt[0], ppt[1]);
+ }
+
+ _glMatrixDel(VP_PRJ);
+
+ glPopAttrib();
+
+ _checkError("_renderEX()");
+
+ return 1;
+}
+
+//static S52_CmdL *_renderTX(S52_obj *obj)
+// TeXt
+//{
+// if (NULL == instruc->text)
+// instruc->text = S52_PL_parseTX(instruc->geoData, cmd);
+//
+// _renderTEXT(obj);
+//
+// return cmd;
+//}
+
+//static S52_CmdL *_renderTE(S52_obj *obj)
+// TExt formatted
+//{
+// if (NULL == instruc->text)
+// instruc->text = S52_PL_parseTE(instruc->geoData, cmd);
+//
+// _renderTEXT(instruc, cmd);
+//
+// return cmd;
+//}
+
+
+
+static int _renderSY(S52_obj *obj)
+//static S52_CmdL *_renderSY(S57_geo *geoData, S52_CmdL *cmd)
+// SYmbol
+{
+ //GLfloat x = 0.0;
+ //GLfloat y = 0.0;
+ //static int first= 0;
+
+ S57_geo *geoData= S52_PL_getGeo(obj);
+ GLdouble orient = S52_PL_getSYorient(obj);
+ S52_subListData subListData;
+
+ // filter out all but ..
+ //if (0 != S52_PL_cmpCmdParam(obj, "BOYLAT23") &&
+ // 0 != S52_PL_cmpCmdParam(obj, "BOYLAT14")) {
+ // return TRUE;
+ //}
+ //PRINTF("BOYLAT23 found\n");
+
+ // cursor pick --fill stencil
+ if (NULL==geoData /* && NULL==cmd */ ) {
+#ifdef INDEXMODE
+ // printf("Should do transparency _rendersy (STENCILL): %f\n", 255);
+ glIndexi(1); // TODO
+#else
+ //glColor4ub(255,0,0, 255);
+ glColor4ub(255,0,0,255);
+#endif
+ //glColor3ub(255,0,0);
+ //glLineWidth(5);
+ glPointSize(1); // FIXME: what is a good value?
+
+ _glMatrixSet(VP_WIN);
+ glBegin(GL_LINES);
+ glVertex3d(sobj.x, sobj.y, 0);
+ glVertex3d(sobj.x+50, sobj.y+50, 0);
+ glEnd();
+ _glMatrixDel(VP_WIN);
+
+ PRINTF("mouse x: %f y: %f\n", sobj.x, sobj.y);
+
+ _checkError("_renderSY()");
+
+ return TRUE;
+ }
+
+ // error handling case or CS for wreck (point) we don't know what to draw
+ // so here we're drawing something conspic. if it ever reach the screen.
+ if (-1==orient /* || NULL==cmd */ ) {
+ guint npt = 0;
+ GLdouble *ppt = NULL;
+ S52_Color *c = S52_PL_getColor("DNGHL");
+
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+#ifdef INDEXMODE
+ glIndexi(c->idx[currentScreen]);
+#else
+ glColor4ub(c->R, c->G, c->B, 255);
+#endif
+ //glPointSize(3); // FIXME: what is a good value?
+ glPointSize(1); // FIXME: what is a good value?
+
+ _glMatrixSet(VP_PRJ);
+ glBegin(GL_POINTS);
+ //_glVertex3d(npt, ppt);
+ glEnd();
+ _glMatrixDel(VP_PRJ);
+
+ _checkError("_renderSY()");
+
+ return TRUE;
+ }
+
+ {
+ guint npt = 0;
+ GLdouble *ppt = NULL;
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+ S52_PL_getSubListData(obj, &subListData);
+
+ //PRINTF("%s ++++++++\n", S57_getName(geoData));
+
+ //_glMatrixSet(VP_WIN);
+ _glMatrixSet(VP_PRJ);
+ //while (_fb_getNextCenterPos(geoData, cmd, &x, &y)) {
+ //PRINTF("x/y: %f/%f\n", x, y);
+ //PRINTF("x/y: %f/%f\n", ppt[0], ppt[1]);
+
+ // move screen coord origine at symbol position
+ //glTranslatef(x, y, 0.0);
+ //glLoadIdentity();
+
+ glTranslated(ppt[0], ppt[1], 0.0);
+ //glTranslated(ppt[0], ppt[1], _dprio);
+
+ //glScaled(1.0, -1.0, 1.0);
+ glScaled(0.0001, -0.0001, 1.0);
+ glRotated(orient, 0.0, 0.0, 1.0); // rotate coord sys. on Z
+
+ //glScaled(1.0, -1.0, 1.0);
+
+ _glCallList(&subListData);
+
+ //glLoadIdentity();
+ //}
+ //_glMatrixDel(VP_WIN);
+ _glMatrixDel(VP_PRJ);
+
+ _checkError("_renderSY()");
+ }
+
+ return TRUE;
+}
+
+static int _renderLS_LIGHTS05(S52_obj *obj)
+//static int _renderLS_LIGHTS05(S57_geo *geoData, S52_CmdL *cmd)
+{
+ //GLdouble pt[6] = {ppt[0], ppt[1], ppt[2], 0.0, 0.0, 0.0};
+
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ GString *orientstr = S57_getAttVal(geoData, "ORIENT");
+ GString *sectr1str = S57_getAttVal(geoData, "SECTR1");
+ double sectr1 = (NULL==sectr1str) ? 0.0 : atof(sectr1str->str);
+ GString *sectr2str = S57_getAttVal(geoData, "SECTR2");
+ double sectr2 = (NULL==sectr2str) ? 0.0 : atof(sectr2str->str);
+ double leglen = 25.0;
+ projUV p; // = {ppt[0], ppt[1]};
+ double z = 0.0;
+
+ GLdouble *ppt = NULL;
+ guint npt = 0;
+
+ //PRINTF("S1: %f, S2:%f\n", sectr1, sectr2);
+
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+ p.u = ppt[0];
+ p.v = ppt[1];
+
+ //p = S57_geo2prj(p);
+ p = _prj2win(p);
+
+ if (TRUE == S52_getMarinerParam(S52_MAR_FULL_SECTORS)) {
+ GString *valnmrstr = S57_getAttVal(geoData, "VALNMR");
+ if (NULL != valnmrstr) {
+ PRINTF("FIXME: compute leglen to scale (NM)\n");
+ leglen = atof(valnmrstr->str) *10;
+ }
+ }
+
+ //glDisable(GL_LINE_SMOOTH);
+
+ _glMatrixSet(VP_WIN);
+
+ if (NULL != orientstr) {
+ GLdouble o = atof(orientstr->str);
+
+ glLoadIdentity();
+ glTranslated(p.u, p.v, z);
+ glScaled(1.0, -1.0, 1.0);
+ glRotated(o+90.0, 0.0, 0.0, 1.0);
+
+ glBegin(GL_LINES);
+ glVertex3d(0.0, 0.0, 0.0);
+ glVertex3d(leglen, 0.0, 0.0);
+ glEnd();
+ }
+
+ if (NULL != sectr1str) {
+ glLoadIdentity();
+ glTranslated(p.u, p.v, z);
+ glScaled(1.0, -1.0, 1.0);
+ glRotated(sectr1+90.0, 0.0, 0.0, 1.0);
+
+ glBegin(GL_LINES);
+ glVertex3d(0.0, 0.0, 0.0);
+ glVertex3d(leglen, 0.0, 0.0);
+ glEnd();
+ }
+
+ if (NULL != sectr2str) {
+ glLoadIdentity();
+ glTranslated(p.u, p.v, z);
+ glScaled(1.0, -1.0, 1.0);
+ glRotated(sectr2+90.0, 0.0, 0.0, 1.0);
+
+ glBegin(GL_LINES);
+ glVertex3d(0.0, 0.0, 0.0);
+ glVertex3d(leglen, 0.0, 0.0);
+ glEnd();
+ }
+
+ //glEnable(GL_LINE_SMOOTH);
+
+ _glMatrixDel(VP_WIN);
+
+ return TRUE;
+}
+
+static int _renderLS(S52_obj *obj)
+// Line Style
+{
+ S52_Color *col;
+ char style; // L/S/T
+ char pen_w;
+
+ //2_PL_getLSdata(cmd, &pen_w, &style, &col);
+ S52_PL_getLSdata(obj, &pen_w, &style, &col);
+ glLineWidth(pen_w - '0');
+
+#ifdef INDEXMODE
+ glIndexi(col->idx[currentScreen]);
+#else
+ glColor4ub(col->R, col->G, col->B, 255);
+#endif
+
+ // debug
+ //glLineWidth(5);
+ //glColor3ub(255, 0, 0);
+
+ // Assuming pixel size at 0.3 mm.
+ // Note: we can draw coded depth line because
+ // pattern start is not reset a each new lines in a strip.
+ glEnable(GL_LINE_STIPPLE);
+ //glEnable(GL_LINE_SMOOTH); // antialiase needed for line stippled
+ switch (style) {
+ // SOLD --correct
+ case 'L': glLineStipple(1, 0xFFFF); break;
+ // DASH --incorrect (last space 1.8mm instead of 1.2mm)
+ //case 'S': glLineStipple(2, 0x9248); break;
+ // bit better !
+ case 'S': glLineStipple(3, 0x7777); break;
+ // DOTT --correct
+ case 'T': glLineStipple(1, 0xFFF0); break;
+
+ default:
+ PRINTF("ERROR: invalid line style\n");
+ }
+
+ {
+ GLdouble *ppt = NULL;
+ guint npt = 0;
+ S57_geo *geoData = S52_PL_getGeo(obj);
+
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+
+ // this code is specific to CS LIGHTS05
+ if (POINT_T == S57_getObjtype(geoData))
+ _renderLS_LIGHTS05(obj);
+ //;
+ else {
+ _glMatrixSet(VP_PRJ_ZCLIP);
+ //glBegin(GL_LINE_STRIP);
+ _glVertex3d(npt, ppt);
+ //glEnd();
+ _glMatrixDel(VP_PRJ_ZCLIP);
+ }
+ }
+
+ glDisable(GL_LINE_STIPPLE);
+
+ _checkError("_renderLS()");
+
+ return TRUE;
+}
+
+
+static int _renderLC(S52_obj *obj)
+// Line Complex
+{
+ GLdouble symlen;
+ //GTimeVal start, end;
+ GLfloat x1,y1,x2,y2;
+ //GLuint list = S52_PL_getDisplayList(cmd);
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ S52_Obj_t ot = S57_getObjtype(geoData);
+ char pen_w;
+ S52_subListData subListData;
+ S52_Color *c;
+
+ S52_PL_getSubListData(obj, &subListData);
+
+ c = (S52_Color*) &subListData.col;
+
+ // set pen color & size here because values might not
+ // be set via call list --short line
+ //symlen = S52_PL_getLCdata(cmd, dotpitch_x, &pen_w);
+ symlen = S52_PL_getLCdata(obj, dotpitch_x, &pen_w);
+
+#ifdef INDEXMODE
+ glIndexi(c->idx[currentScreen]);
+#else
+ glColor4ub(c->R, c->G, c->B, 255);
+#endif
+ //glLineWidth(pen_w - '0');
+ glLineWidth(1);
+
+ // FIXME: problem if feedback buffer containe line clipped
+ // via ZCLIP and then thos line are used to compute center of symbol
+ // tha area might not work! Maybe compute area from triangle!
+ // compute object to screen representation
+ //_fb_geo2winClip(geoData, cmd);
+ _fb_geo2winClip(obj);
+
+ //_glMatrixSet(VP_WIN);
+ //glPushMatrix();
+
+ while (_fb_getNextSeg(&x1, &y1, &x2, &y2)) {
+ GLdouble run = 0.0;
+ GLdouble seglen = sqrt(pow(x1-x2, 2) + pow(y1-y2, 2));
+ GLdouble segang = atan2(y2-y1, x2-x1) * RAD_TO_DEG;
+
+ //printf("segang: %f seglen: %f symlen:%f \n", segang, seglen, symlen);
+ //printf(">> x1: %f y1: %f \n",x1, y1);
+ //printf(">> x2: %f y2: %f \n",x2, y2);
+
+ // FIXME: compute grid offset so that the sarting symbol
+ // doesn't start at the clipped border at every redraw
+ // when scrolling
+ /*
+ if (x1 == vp[0] ||
+ y1 == vp[1] ||
+ x1 == vp[2] ||
+ y1 == vp[3]) {
+ // compute offset
+ // compute extend off screen
+ // update xy and start drawing for there
+ // so that it gets clipped at different place
+ // when scrolling
+ }
+ */
+
+ //glLoadIdentity(); // reset origine
+
+ /*
+ if (LINES_T == ot) {
+ glTranslated(x1, y1, 0.0); // move coord sys. at symb pos.
+ //glScaled(1.0, -1.0, 1.0);
+ glRotated(segang, 0.0, 0.0, 1.0); // rotate coord sys. on Z
+ } else {
+ // FIXME: line of area is in reverse so rot/scale in reverse !?
+ // something is not right :/
+ //glTranslated(x1, y1, 0.0); // move coord sys. at symb pos.
+ glTranslated(x2, y2, 0.0); // move coord sys. at symb pos.
+ glRotated(segang+180, 0.0, 0.0, 1.0); // rotate coord sys. on Z
+ //glScaled(1.0, -1.0, 1.0);
+ }
+ glScaled(1.0, -1.0, 1.0);
+
+ // draw symb's as long as it fit the line length
+ for (run=0.0; run<(seglen-symlen); run+=symlen) {
+ //_glCallList(list); // draw symbol
+ _glCallList(&subListData);
+
+ glTranslated(symlen, 0.0, 0.0); // move coord sys.
+ //printf("x:%f y:%f run:%f \n", x1, y1, run);
+ }
+ */
+ // complete the rest of the line
+ glBegin(GL_LINES);
+ //glVertex3d(0.0, 0.0, 0.0);
+ //glVertex3d(seglen-run, 0.0, 0.0);
+ glVertex3d(x1, y1, 0.0);
+ glVertex3d(x2, y2, 0.0);
+ glEnd();
+ }
+ //_glMatrixDel(VP_WIN);
+
+ //glEnable(GL_LINE_SMOOTH);
+
+/*
+ g_get_current_time(&end);
+ { // elapse time
+ glong dsec = end.tv_sec - start.tv_sec;
+ glong dusec;
+
+ if (end.tv_usec < start.tv_usec) {
+ dsec--;
+ end.tv_usec += 1000000;
+ }
+ dusec = end.tv_usec - start.tv_usec;
+
+ PRINTF("sec = %li usec = %li\n", dsec, dusec);
+ }
+*/
+ //glPopMatrix();
+
+ _checkError("_renderLC()");
+
+ return TRUE;
+}
+
+static int _gluPartialDisk(GLdouble inner, GLdouble outer, GLint slices,
+ GLint loops, GLdouble start, GLdouble sweep)
+{
+ GLint loop = 0;
+ GLint slice = 0;
+ GLdouble radius = inner;
+ GLdouble delta_radius = (outer - inner) / loops;;
+ GLdouble angle = start * DEG_TO_RAD;
+ GLdouble delta_angle = (sweep / slices) * DEG_TO_RAD;
+ S57_prim *vertex = S57_initPrim(NULL);
+
+ for (loop=0; loop<loops; ++loop) {
+ _glBegin(GL_QUAD_STRIP, vertex);
+
+ for (slice=0; slice<=slices; ++slice) {
+ struct {double x,y,z;} pt3 = {0,0,0};
+ //if (qobj->Orientation == GLU_OUTSIDE) {
+ pt3.x = (radius + delta_radius) * sin(angle);
+ pt3.y = (radius + delta_radius) * cos(angle);
+ _vertex3d(&pt3, vertex);
+ pt3.x = radius * sin(angle);
+ pt3.y = radius * cos(angle);
+ _vertex3d(&pt3, vertex);
+ //}
+ //else {
+ // glVertex2d(radius * sin(angle), radius * cos(angle));
+ // glVertex2d((radius + delta_radius) * sin(angle),
+ // (radius + delta_radius) * cos(angle));
+ //}
+ angle += delta_angle;
+ }
+ _glEnd(vertex);
+ radius += delta_radius;
+ }
+ _DrawArrays(vertex);
+ S57_donePrim(vertex);
+
+ return 1;
+}
+
+static int _renderAC_LIGHTS05(S52_obj *obj)
+// this code is specific to CS LIGHTS05
+{
+ S52_Color *col = S52_PL_getACdata(obj);
+ S57_geo *geoData = S52_PL_getGeo(obj);
+ GString *sectr1str = S57_getAttVal(geoData, "SECTR1");
+ GString *sectr2str = S57_getAttVal(geoData, "SECTR2");
+
+ if (NULL != sectr1str && NULL != sectr2str) {
+ GLdouble *ppt = NULL;
+ guint npt = 0;
+
+ GLdouble sectr1 = atof(sectr1str->str);
+ GLdouble sectr2 = atof(sectr2str->str);
+ double sweep = (sectr1 > sectr2) ? sectr2-sectr1+360 : sectr2-sectr1;
+ GString *extradstr = S57_getAttVal(geoData, "extend_arc_radius");
+ double radius;
+ S52_Color *black = S52_PL_getColor("CHBLK");
+ projUV p;
+ double z;
+
+ S57_getGeoData(geoData, 0, &npt, &ppt);
+ p.u = ppt[0];
+ p.v = ppt[1];
+
+ //p = S57_geo2prj(p);
+ p = _prj2win(p);
+
+ if (NULL!=extradstr && 'Y'==*extradstr->str)
+ radius = 25 / dotpitch_x; // (25 mm)
+ else
+ radius = 20 / dotpitch_x; // (20 mm)
+
+ gluQuadricDrawStyle(qobj, GLU_FILL) ;
+
+ _glMatrixSet(VP_WIN);
+ //_glMatrixSet(VP_PRJ);
+ //glPushMatrix();
+ //glLoadIdentity(); // reset origine
+
+ glTranslated(p.u, p.v, z);
+
+ // FIXME: 4 pixel @ 0.3mm/pixel --arc thickness depend on the pixel size
+#ifdef INDEXMODE
+ glIndexi(black->idx[currentScreen]);
+#else
+ glColor4ub(black->R, black->G, black->B, 255);
+#endif
+ //gluPartialDisk(qobj, radius, radius+8, sweep/2.0, 2,
+ // sectr1+180, sweep);
+ _gluPartialDisk(radius, radius+8, sweep/2.0, 2,
+ sectr1+180, sweep);
+
+#ifdef INDEXMODE
+ glIndexi(col->idx[currentScreen]);
+#else
+ glColor4ub(col->R, col->G, col->B, 255);
+#endif
+ //gluPartialDisk(qobj, radius+2, radius+6, sweep/2.0, 2,
+ // sectr1+180, sweep);
+ _gluPartialDisk(radius+2, radius+6, sweep/2.0, 2,
+ sectr1+180, sweep);
+
+ //glPopMatrix();
+ _glMatrixDel(VP_WIN);
+ }
+
+ return TRUE;
+}
+
+static int _renderAC(S52_obj *obj)
+// Area Col7or (also light sector)
+{
+ S52_Color *col = S52_PL_getACdata(obj);
+ S57_geo *geoData = S52_PL_getGeo(obj);
+
+ //PRINTF("%s\n", S57_getName(geoData));
+
+ if (POINT_T == S57_getObjtype(geoData)) {
+ _renderAC_LIGHTS05(obj);
+ return TRUE;
+ }
+
+#ifdef INDEXMODE
+ // printf("Should do transparency _renderAC: %f\n", (4-col->trans)*TRNSP_FAC);
+ glIndexi(col->idx[currentScreen]);
+#else
+ glColor4ub(col->R, col->G, col->B, (4-col->trans)*TRNSP_FAC);
+#endif
+
+ // FIXME: check transparancy handling in:
+ // AC(TRFCF,3), AC(DNGHL,3), AC(ADINF,3)
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ _fillarea(obj);
+ glDisable(GL_BLEND);
+
+ _checkError("_renderAC()");
+
+ return TRUE;
+}
+
+static int _loadStencil()
+{
+ glClear(GL_STENCIL_BUFFER_BIT);
+ //glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // debug:flush all
+ glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ // treate color as transparent
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+
+ return 1;
+}
+
+static int _freezStencil()
+{
+ // all color to pass stencil filter
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+ // clip pattern pixel that lie outside of poly --clip if != 1
+ glStencilFunc(GL_EQUAL, 0x1, 0x1);
+
+ // freeze stencil state
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ return 1;
+}
+
+//typedef S52_CmdL *(*renderfunc)(S52_obj *obj);
+typedef int (*renderfunc)(S52_obj *obj);
+static int _setStencil(S52_obj *obj, renderfunc f)
+// set filter in stencil ready for selection
+{
+#ifdef INDEXMODE
+ return 1;
+#endif
+
+ glEnable(GL_STENCIL_TEST);
+
+ _loadStencil();
+
+ // fill stencil with 1 in the shape drawn
+ //geoData);
+ f(obj);
+
+ _freezStencil();
+
+ return 1;
+}
+
+static int _renderAP(S52_obj *obj)
+//static S52_CmdL *_renderAP(S57_geo *geoData, S52_CmdL *cmd)
+// Area Pattern
+{
+ // NOTE: S52 define pattern rotation but doesn't use that in specs.
+ //GvRect rect; // lat/lon
+ GLdouble x,y; // tile pos (pixel)
+
+ //GLdouble z = 0.0;
+ GLdouble x0=0.0, y0=0.0; // pattern alignment (origine of geo. sys in pixel)
+ GLdouble x1=0.0, y1=0.0; // LL of region from polygone (pixel)
+ GLdouble x2=0.0, y2=0.0; // UR of region from polygone (pixel)
+ //GLdouble xx=0.0, yy=0.0; // dummy
+ GLdouble tw=0.0, th=0.0; // tile width/height 1 = 01 mm
+ GLdouble dx = 0.0; // run length offset for STG pattern
+ int stag = 0; // 0-1 true/false add dx for stagged pattern
+ GLdouble offset_x = 0.0,
+ offset_y = 0.0;
+ //GLuint list = S52_PL_getDisplayList(obj);
+ projUV p;
+ S52_subListData subListData;
+ //S52_Color *c;
+
+ S52_PL_getSubListData(obj, &subListData);
+
+
+
+ //if (1 != found++) return cmd;
+
+ //if (0 == list) {
+ // PRINTF("ERROR: pattern unknown! \n");
+ // return cmd;
+ //}
+
+ _setStencil(obj, _fillarea);
+
+ // pattern aligned to origin of geo coord
+ // FIXME: rectangular coord is used because of distortion when
+ // projecting the 'grid' in mercator
+ p.u = 0.0; //vp[2]/2;
+ p.v = 0.0; //vp[3]/2;
+ //p = _win2prj(p);
+ p = _prj2win(p);
+ x0 = p.u; //-vp[2]/2;
+ y0 = p.v; //-vp[3]/2;
+
+ //p.u = 0.0;
+ //p.v = 0.0;
+ //p = _geo2prj(p);
+ //p = _prj2win(p);
+ //x0 = p.u;
+ //y0 = p.v;
+
+ // get area's upper right corner in pixel
+ //S57_getExt(geoData, &xx, &yy, &x2, &y2);
+ p.u = x2;
+ p.v = y2;
+ //p = S57_geo2prj(p);
+ p = _prj2win(p);
+ //p = _win2prj(p);
+ x2 = p.u;
+ y2 = p.v;
+ // no need to draw beyon window
+ //if (x2 > vp[2]) x2 = vp[2] + th;
+ //if (y2 > vp[3]) y2 = vp[3] + tw;
+
+ //S52_PL_getAPdata(cmd, dotpitch_x, dotpitch_y, &tw, &th, &dx);
+
+ // Reposition pattern alignment to screen origine 'grid'.
+ x1 = floor(x0 / tw) * tw;
+ offset_x = x0 - x1;
+
+ y1 = (int)(y0 / (2*th)) * 2*th; // 2X to allow for stag
+ //y1 = (int)(y0 / (1*th)) * 1*th; // 2X to allow for stag
+ offset_y = y0 - y1; // ie the grid is made of 1tw x 2th cell
+
+ _glMatrixSet(VP_WIN);
+
+ // NOTE: pattern that do not fit entirely inside an area
+ // are displayed (hence pattern are clipped) because ajacent area
+ // filled with same pattern will complete the clipped pattern.
+ // No test y+th<y2 and x+tw<x2 to check for the end of a row/collum.
+
+ //printf("offset x/y; %f/%f\n", offset_x, offset_y);
+ //printf("x0/y0: %f/%f\n", x0, y0);
+ for (y=offset_y; y<y2; y+=th) {
+ glLoadIdentity(); // reset to screen origin
+ glTranslated(offset_x + (dx*stag), y, 0.0);
+ glScaled(1.0, -1.0, 1.0);
+
+ for (x=offset_x; x<x2; x+=tw) {
+ _glCallList(&subListData);
+ glTranslated(tw, 0.0, 0.0);
+ }
+ stag = !stag;
+ }
+ _glMatrixDel(VP_WIN);
+
+ glDisable(GL_STENCIL_TEST);
+
+ _checkError("_renderAP()");
+
+ return TRUE;
+}
+static void _processHits(int hits, GLuint buffer[], S57_geo *geoData)
+{
+ unsigned int i = 0;
+ GLuint *ptr = NULL;
+ //S57_geo *crntGeo = geoData;
+
+ //PRINTF("number hits record: %d\n", hits);
+ ptr = (GLuint *) buffer;
+ for (i=0; i<hits; i++) {
+ unsigned int j = 0;
+ GLuint nnames = *ptr;
+
+ //printf(" number of names in this hit record stack: %d \n", nnames);
+ ptr++;
+ //printf(" min win-coord z is %g;", (float) *ptr/0x7fffffff);
+ //printf("first: %d, ", *ptr);
+ ptr++;
+ //printf(" max win-coord z is %g\n", (float) *ptr/0x7fffffff);
+ //printf("last: %d\n", *ptr);
+ ptr++;
+ //printf(" name(s) in stack (bottom first): ");
+
+ if (1 < nnames) {
+ PRINTF("ERROR: selection names stack is >1 \n");
+ exit(0);
+ } else
+ S57_linkObj(geoData, g_ptr_array_index(sobj.geoV, *ptr));
+
+ for (j=0; j<nnames; j++) {
+ //printf("%d ", *ptr);
+ ptr++;
+ }
+
+ //printf("\n\n");
+ }
+}
+
+static int _initSobj(int szfac)
+// init/grow selection buffer
+{
+ if (szfac > 1) {
+ sobj.sz *= szfac;
+ sobj.buf = g_renew(GLuint, sobj.buf, sobj.sz);
+ sobj.acc = g_renew(GLuint, sobj.acc, sobj.sz);
+ }
+
+ g_ptr_array_set_size(sobj.geoV, 0);
+ sobj.name = 0;
+ sobj.hits = 0;
+ sobj.nac = 0;
+
+ glSelectBuffer(sobj.sz, sobj.buf);
+
+ return 1;
+}
+
+static int _accuSobj()
+// accumulate partial result, reurn FALSE if fail
+{
+ // check buffers overflow
+ if (sobj.hits < 0) {
+ PRINTF("ERROR: selection buffer overflow, cursorpick failed\n");
+ return FALSE;
+ } else {
+ if (sobj.nac + sobj.hits*4 >= sobj.sz) {
+ PRINTF("ERROR: selection accumulation buffer overflow: %i\n",
+ sobj.nac + sobj.hits*4);
+ return FALSE;
+ }
+ }
+
+ if (0 != sobj.hits) {
+ int i;
+
+ if (0 == *sobj.buf) {
+ PRINTF("NOTE: selection return a hit with an empty stack!\n");
+ return TRUE;
+ }
+
+ for (i=0; i<sobj.hits; i++) {
+ // stack of more then one name should occur
+ g_assert(1 == *(sobj.buf+i*4));
+
+ sobj.acc[sobj.nac++] = *(sobj.buf+i*4+3);
+ }
+ }
+
+ return TRUE;
+}
+
+
+static int _renderCS(S52_obj *obj)
+{
+ GString *newCS = NULL;
+
+ if (0 == S52_PL_cmpCmdParam(obj, "DEPCNT02")) {
+ PRINTF("DEPCNT02\n"); // do nothig for now --will be handled next
+ //_renderCS_DEPCNT02(obj);
+ }
+
+ if (0 == S52_PL_cmpCmdParam(obj, "LIGHTS05"))
+ PRINTF("LIGHTS05\n"); // do nothig for now --will be handled next
+
+ PRINTF("FATAL ERROR: should not get here!\n");
+ exit(0);
+
+ //newCS = S52_PL_parseCS(obj);
+ if (NULL == newCS)
+ return TRUE;
+
+ return TRUE;
+}
+
+
+//-----------------------------------
+//
+// SYMBOL CREATION SECTION
+//
+//-----------------------------------
+
+static GLint _renderHPGL(gpointer key, gpointer value, gpointer data)
+// display list generator
+{
+ // Select pen Width unit = .32 mm.
+ // Assume: a width of 1 unit is 1 pixel.
+ // WARNING: offet might need adjustemnt since bounding box
+ // doesn't include line tickness but moment all pattern,
+ // upto PLib 3.2, use a line width of 1.
+
+ // BUG: instruction EP (Edge Polygon), AA (Arc Angle) and SC (Symbol Call)
+ // are not used in current PLib/Chart-1, so not implemented.
+
+ // NOTE: transparency: 0=0%(opaque), 1=25%, 2=50%, 3=75%
+
+ GLdouble scaleFac = dotpitch_x * 100;
+ GLenum fillMode = GLU_SILHOUETTE;
+
+ // hold tesselated vertex, also accumulate GL primitive
+ S57_prim *vertex = S57_initPrim(NULL);
+ S52_vCmd vcmd = S52_VC_NEW;
+ S52_vec *vecObj = S52_PL_initVOCmd((S52_cmdDef*)value);
+ int inList = FALSE; // TRUE if we're already building a list
+ int nlist = 0;
+
+ // debug
+ //if (70 == _listIndex) {
+ // PRINTF("%i\n",_listIndex);
+ //}
+ //if (0==strncmp("OBSTRN11",S52_PL_getVOname(vecObj), 8))
+ // PRINTF("OBSTRN11 found\n");
+
+ //glNewList(_listIndex, GL_COMPILE);
+ S52_PL_setDisplayList((S52_cmdDef*)value, _listIndex);
+ //_listIndex++;
+
+ while (S52_VC_NONE != vcmd) {
+ vcmd = S52_PL_getVOCmd(vecObj);
+
+ switch (vcmd) {
+
+ case S52_VC_NONE: continue;
+
+ case S52_VC_NEW:
+ if (TRUE == inList)
+ glEndList();
+
+ inList = TRUE;
+ glNewList(_listIndex, GL_COMPILE);
+ _listIndex++;
+ nlist++;
+ continue;
+
+ case S52_VC_SW: { // pen width
+ char pen_w = S52_PL_getVOwidth(vecObj);
+ glLineWidth(pen_w - '0');
+ glPointSize(pen_w - '0');
+ continue;
+ }
+
+ case S52_VC_PM: // poly mode PM0/PM2, fill disk when not in PM
+ fillMode = (GLU_FILL==fillMode) ? GLU_SILHOUETTE : GLU_FILL;
+ continue;
+
+ case S52_VC_CI: { // circle --draw immediatly
+ GLdouble radius = S52_PL_getVOradius(vecObj);
+ GArray *vec = S52_PL_getVOdata(vecObj);
+ GLdouble *d = (GLdouble *)vec->data;
+ GLint i = 0;
+ GLint slices = 100;
+ GLint loops = 2;
+ GLdouble inner = 0.0; // radius
+ GLdouble outer = radius/scaleFac; // radius
+ GLdouble dr = (outer-inner) / (GLdouble) loops;
+ //GLdouble M_PI = 3.1415926;
+ GLdouble da = 2.0 * M_PI / slices;
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glTranslated(d[0], d[1], d[2]);
+ //gluQuadricDrawStyle(qobj, fillMode);
+ //gluDisk(qobj, inner, outer, slices, loops);
+
+ if (GLU_FILL == fillMode) {
+ for (i = 0; i<loops; ++i) {
+ GLdouble r2 = inner + dr;
+ GLint s = 0;
+
+ _glBegin(GL_QUAD_STRIP, vertex);
+ for (s = 0; s <= slices; s++) {
+ struct {double x,y,z;} pt3 = {0,0,0};
+ GLdouble sa = 0.0;
+ GLdouble ca = 0.0;
+ GLdouble a = (s == slices)? 0.0 : s * da;
+
+ sa = sin(a);
+ ca = cos(a);
+ pt3.x = r2 * sa;
+ pt3.y = r2 * ca;
+ _vertex3d(&pt3, vertex);
+ pt3.x = inner * sa;
+ pt3.y = inner * ca;
+ _vertex3d(&pt3, vertex);
+ }
+ _glEnd(vertex);
+ inner = r2;
+ }
+
+ } else { // GLU_SILHOUETTE
+ GLdouble a;
+ if (inner != 0.0) {
+ _glBegin(GL_LINE_LOOP, vertex);
+ for (a = 0.0; a < 2.0 * M_PI; a += da) {
+ struct {double x,y,z;} pt3 = {0,0,0};
+ pt3.x = inner * sin(a);
+ pt3.y = inner * cos(a);
+ _vertex3d(&pt3, vertex);
+ }
+ _glEnd(vertex);
+ }
+ _glBegin(GL_LINE_LOOP, vertex);
+ for (a = 0; a < 2.0 * M_PI; a += da) {
+ struct {double x,y,z;} pt3 = {0,0,0};
+ pt3.x = outer * sin(a);
+ pt3.y = outer * cos(a);
+ _vertex3d(&pt3, vertex);
+ }
+ _glEnd(vertex);
+ }
+
+ _DrawArrays(vertex);
+ glPopMatrix();
+
+ S57_initPrim(vertex); //reset
+
+ continue;
+ }
+
+ case S52_VC_FP: { // fill poly immediatly
+ guint i = 0;
+ GArray *vec = S52_PL_getVOdata(vecObj);
+ GLdouble *d = (GLdouble *)vec->data;
+
+ // tess
+ gluTessBeginPolygon(tobj, vertex);
+ gluTessBeginContour(tobj);
+ for (i=0; i<vec->len; ++i, d+=3) {
+ gluTessVertex(tobj, d, d);
+ //printf("x/y/z %f/%f/%f\n", d[0],d[1],d[2]);
+ }
+ gluTessEndContour(tobj);
+ gluTessEndPolygon(tobj);
+
+ // draw
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ _DrawArrays(vertex);
+ glDisable(GL_BLEND);
+
+ // clean up
+ for (i=0; i<tmpV->len; ++i)
+ g_free(g_ptr_array_index(tmpV, i)); // free vertex malloc'd, keep array
+ g_ptr_array_set_size(tmpV, 0);
+
+ S57_initPrim(vertex); //reset
+
+ continue;
+ }
+
+ case S52_VC_PD: // pen down
+ case S52_VC_PU: { // pen up
+ int i = 0;
+ GArray *vec = S52_PL_getVOdata(vecObj);
+ GLdouble *d = (GLdouble *)vec->data;
+
+ if (1 == vec->len)
+ _glBegin(GL_POINTS, vertex);
+ else
+ _glBegin(GL_LINE_STRIP, vertex);
+
+ for (i=0; i<vec->len; ++i, d+=3)
+ _vertex3d(d, vertex);
+
+ _glEnd(vertex);
+
+ _DrawArrays(vertex);
+ S57_initPrim(vertex); //reset
+ continue;
+ }
+
+ case S52_VC_ST: // transparancy
+ case S52_VC_SP: // color
+ default:
+ PRINTF("ERROR: invalid vector command: (%c)\n", vcmd);
+
+ }
+ } /* while */
+
+ S57_donePrim(vertex);
+
+ // paranoia: this could happen if there is no vector command
+ // (ex only color, pen width, ..)
+ if (TRUE == inList)
+ glEndList();
+
+ // save some data for later
+ {
+ char pen_w = S52_PL_getVOwidth(vecObj);
+ if (patternList)
+ S52_PL_setAPcover((S52_cmdDef*)value, dotpitch_x, dotpitch_y, pen_w);
+ else
+ S52_PL_setLCdata((S52_cmdDef*)value, pen_w);
+ }
+
+ // debug
+ if (nlist != S52_PL_getSubDisplayListNbr((S52_cmdDef*)value)) {
+ PRINTF("FATAL ERROR: mismatch of sub-list number..exiting\n");
+ exit(0);
+ }
+
+ _checkError("_renderHPGL()");
+
+ // debuf
+
+ return 0; // return 0 to continue BTree traversal
+ //return 1; // return 1 to stop BTree traversal
+}
+
+
+static GLint _createSymb()
+// WARNING: this must be done from inside the main loop!
+{
+ //GLuint nDisplayList = S52_PL_getTableSz(S52_SMB_PATT)
+ // + S52_PL_getTableSz(S52_SMB_LINE)
+ // + S52_PL_getTableSz(S52_SMB_SYMB);
+ GLuint nDisplayList = S52_PL_getSubListNbr();
+ //PRINTF("number of new display list = %i \n", nDisplayList);
+
+ _listIndex = glGenLists(nDisplayList);
+ if (0 == _listIndex) {
+ PRINTF("FATAL ERROR: glGenLists() failed .. exiting\n");
+ exit(0);
+ }
+ //PRINTF("total number of display list = %i \n", _listIndex+nDisplayList);
+
+ _glMatrixSet(VP_WIN);
+
+ patternList = TRUE;
+ S52_PL_traverse(S52_SMB_PATT, _renderHPGL);
+ patternList = FALSE;
+ //PRINTF("PATT symbol finish\n");
+
+ S52_PL_traverse(S52_SMB_SYMB, _renderHPGL);
+ //PRINTF("SYMB symbol finish\n");
+
+ S52_PL_traverse(S52_SMB_LINE, _renderHPGL);
+ //PRINTF("LINE symbol finish\n");
+
+ _glMatrixDel(VP_WIN);
+
+ //_fontDList = glGenLists(256);
+ //gdkfont = gdk_font_load(font[4]);
+ //gdk_gl_use_gdk_font(gdkfont, 0, 256, _fontDList);
+
+ _checkError("_createSymb()");
+
+ return 1;
+}
+
+static GLint _isONscreen(S52_obj *obj)
+// return TRUE if geo intersec window
+{
+ projUV xy1, xy2; // LL UR
+ projXY w1, w2;
+
+
+ // bail out if supression is ON (display supressed)
+ if (S52_SUP_ON == S52_PL_getToggleState(obj))
+ return FALSE;
+
+ // draw light sector even if the light itself is outside
+ if (0==strncmp(S52_PL_getOBCL(obj), "LIGHTS", S52_LUP_NMLN))
+ return TRUE;
+
+ // debug
+ return 1;
+
+ // **************************************
+ // FIXME: THIS IS BROKEN FOR POINT OBJECT
+ //
+
+ S57_getExt(S52_PL_getGeo(obj), &xy1.u, &xy1.v, &xy2.u, &xy2.v);
+ xy1 = S57_geo2prj(xy1);
+ xy2 = S57_geo2prj(xy2);
+
+ w1.u = vp[0];
+ w1.v = vp[1];
+ w2.u = vp[2];
+ w2.v = vp[3];
+
+ _glMatrixSet(VP_PRJ);
+ w1 = _win2prj(w1);
+ w2 = _win2prj(w2);
+ _glMatrixDel(VP_PRJ);
+
+ if (_intersec((w1.u), (w2.u), (xy1.u), (xy2.u)) &&
+ _intersec((w1.v), (w2.v), (xy1.v), (xy2.v)) ) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//static void _draw(instruction *instruc, gpointer data)
+static void _draw(S52_obj *obj)
+{
+ //if ( NULL == cmd) {
+ //PRINTF("ERROR no 'command word' for obj:%s\n", instruc->LUP->OBCL);
+ //}
+
+ // debug
+ /*
+ if (0 == strcmp("HRBFAC", S52_PL_getOBCL(obj))) {
+ PRINTF("HRBFAC found\n");
+ //return;
+ }
+ */
+ //if (0 == strcmp("LNDARE", S52_PL_getOBCL(obj))) {
+ // PRINTF("LNDARE found\n");
+ // //return;
+ //}
+
+
+ if (_isONscreen(obj)) {
+ S52_Cmd cmd = S52_PL_getCmdNext(obj);
+
+ _fb_flush();
+ while (S52_CMD_NONE != cmd) {
+ switch (cmd) {
+ case S52_CMD_TXT_TX:
+ case S52_CMD_TXT_TE: _renderEX(obj); break; // TE&TX
+ case S52_CMD_SYM_PT: _renderSY(obj); break; // SY
+ case S52_CMD_SIM_LN: _renderLS(obj); break; // LS
+ case S52_CMD_COM_LN: _renderLC(obj); break; // LC
+ case S52_CMD_ARE_CO: _renderAC(obj); break; // AC
+#ifndef INDEXMODE
+ case S52_CMD_ARE_PA: _renderAP(obj); break; // AP
+#endif
+ //case S52_CMD_CND_SY: _renderCS(obj); break; // CS
+
+
+ // this is already handled
+ case S52_CMD_OVR_PR: break;
+ /*
+ if (_dprio != S52_PL_getOPprio(obj)) {
+ g_ptr_array_add(switchPrio, obj);
+ PRINTF("object %s has shifted from %i to %i\n",
+ S52_PL_getOBCL(obj),
+ _dprio,
+ S52_PL_getOPprio(obj));
+ }
+ PRINTF("ERROR");
+ exit(0);
+ break;
+ */
+
+ case S52_CMD_NONE:
+ default:
+ //PRINTF("ERROR: no cmd for XXX\n");
+ break;
+
+ }
+ _fb_reset();
+ cmd = S52_PL_getCmdNext(obj);
+ //cmd = S52_PL_getCmdNext(cmd);
+ }
+ }
+
+
+ //glMatrixMode(GL_MODELVIEW);
+
+ //gtk_gl_area_swap_buffers(GTK_GL_AREA(view));
+
+ _checkError("_draw()");
+
+ return;
+}
+
+
+//---------------------------------------------
+//
+// LINE REMOVAL SECTION
+//
+//---------------------------------------------
+
+static gint _cmpVertex(gconstpointer A, gconstpointer B)
+// compare lookup name
+{
+ // debug: to check for "allmost" overlaping vertex
+
+
+ //double *d1 = (double*) A;
+ //double lonA = *d1++;
+ //double latA = *d1;
+ //double *d2 = (double*) B;
+ //double lonB = *d2++;
+ //double latB = *d2;
+
+ /*
+ int xa = latA * 10000.0;
+ int ya = lonA * 10000.0;
+ int xb = latB * 10000.0;
+ int yb = lonB * 10000.0;
+
+ latA = (double) xa / 10000.0;
+ lonA = (double) ya / 10000.0;
+ latB = (double) xb / 10000.0;
+ lonB = (double) yb / 10000.0;
+
+ if (lonA == lonB) {
+ if (latA == latB)
+ return 0;
+
+ if (latA > latB)
+ return 1;
+ else
+ return -1;
+
+ } else {
+ if (lonA > lonB)
+ return 1;
+ else
+ return -1;
+ }
+ */
+
+ return memcmp(A, B, 2 * sizeof(GLdouble));
+
+ //turn comp;
+}
+
+/*
+static int _loadVertex(instruction *instruc)
+// load vertex of lines (line and area object)
+// FIXME: do area's hole
+{
+ //guint i = 0;
+ //guint nr = S57_getRingNbr(instruc->geoData);
+ static void *value = (void*) 0;
+
+ if (NULL == _vertexSet)
+ _vertexSet = g_tree_new(_cmpVertex);
+
+ //for (i=0; i<nr; ++i) {
+ guint j;
+ guint npt;
+ pt3 *ppt;
+
+ //S57_getGeoData(instruc->geoData, i, &npt, (double**)&ppt);
+ S57_getGeoData(instruc->geoData, 0, &npt, (double**)&ppt);
+ if (0 == ++countseg)
+ PRINTF("countseg\n");
+
+ for (j=0; j<npt; ++j, ++ppt) {
+ void *tmp = g_tree_lookup(_vertexSet, ppt);
+
+ if (NULL == tmp)
+ g_tree_insert(_vertexSet, ppt, ++value);
+ }
+ //}
+
+ return 1;
+}
+*/
+/*
+static int _computeMask(instruction *instruc)
+// eliminate line of lower priority that are masked by line
+// of higher priority by moving them outside of the view volume.
+// NOTE: GL depth test wont do since it work at the pixel level
+// and this need to work at geometrical level because
+// of complex line style varing width.
+{
+ static pt3 **m = NULL;
+ static gint nnode = 0;
+ static int m_sz = 0;
+
+ // create matrix of mask
+ if (NULL == m) {
+ nnode = g_tree_nnodes(_vertexSet);
+ m_sz = (nnode*nnode - nnode) / 2;
+ // start form extreme case of 2 vertex only
+ PRINTF("matrix: n=%i, m_sz=%i\n", nnode, m_sz);
+ if (nnode > 1)
+ m = calloc(m_sz, sizeof(pt3*));
+ else
+ return 1;
+ }
+
+ // load matrix
+ {
+ guint i = 0;
+ guint npt;
+ pt3 *ppt;
+
+ S57_getGeoData(instruc->geoData, 0, &npt, (double**)&ppt);
+ ++countseg;
+
+ for (i=0; i<npt-1; ++i) {
+ int n = nnode - 1;
+ int x, y;
+ int off = 0;
+ int index1 = (int) g_tree_lookup(_vertexSet, &ppt[i]);
+ int index2 = (int) g_tree_lookup(_vertexSet, &ppt[i+1]);
+
+ if (0==index1 || 0==index2 || index1==index2) {
+ PRINTF("ERROR: index == 0 (NULL) or index1==index2\n");
+ exit(0);
+ }
+
+ if (index1 > index2)
+ x = index1-1, y = index2-1;
+ else
+ y = index1-1, x = index2-1;
+
+ // compute unique offset for all (x,y) and y<x
+ off = ((n-y) * (n-y) - (n-y)) / 2 + (n-x);
+
+ // paranoia check
+ if (off > m_sz) {
+ PRINTF("FATAL ERROR: matrix overflow!\n");
+ exit(0);
+ }
+
+ pt3 *p = m[off];
+
+ // mask segment --put depth outsize view volume
+ if (NULL != p) {
+ //if (p->z < 15000)
+ p->z = -Z_CLIP_PLANE;
+
+ //PRINTF("MASKING off:%i x1:%f y1:%f \n", off, p->x, p->y);
+ ++p;
+ //PRINTF("MASKING x2:%f y2:%f \n", p->x, p->y);
+
+ //if (p->z < 15000)
+ p->z = -Z_CLIP_PLANE;
+ }
+
+ m[off] = &ppt[i];
+ }
+ }
+
+ return 1;
+}
+*/
+static int _loadLine(S52_obj *obj)
+//static int _loadLine(instruction *instruc)
+{
+ //S52_CmdL *cmdL = instruc->cmdList;
+ S52_Cmd cmd = S52_PL_getCmdNext(obj);
+
+ while (S52_CMD_NONE == cmd) {
+ //switch (S52_PL_getCmdWord(cmdL)) {
+ switch (cmd) {
+ case S52_CMD_SIM_LN:
+ case S52_CMD_COM_LN:
+ //if (1 == _loadV)
+ //_loadVertex(instruc);
+ //else
+ //_computeMask(instruc);
+ break;
+
+ // do nothing
+ case S52_CMD_TXT_TX:
+ case S52_CMD_TXT_TE:
+ case S52_CMD_SYM_PT:
+ case S52_CMD_ARE_CO:
+ case S52_CMD_ARE_PA:
+ case S52_CMD_CND_SY:
+ case S52_CMD_OVR_PR:
+ break;
+
+ // error
+ case S52_CMD_NONE:
+ default:
+ PRINTF("ERROR no cmd for XXX\n");
+ break;
+
+ }
+ //cmdL = S52_PL_getCmdNext(cmdL);
+ cmd = S52_PL_getCmdNext(obj);
+ }
+
+ return 1;
+}
+
+//static GLint _pick(instruction *instruc)
+static GLint _pick(S52_obj *obj)
+// recorde name of object 'drawn' in selection mode
+{
+ g_ptr_array_add(sobj.geoV, (gpointer)obj);
+ glLoadName(sobj.name);
+ _draw(obj);
+ ++sobj.name;
+ return 1;
+}
+
+static int _doPending(GPtrArray *L)
+// handle pending object priority switch
+{
+ while (switchPrio->len > 0) {
+ S52_diPrio disPrioIdx = 0;
+ S52_LUPtnm LUPtypeIdx = 0;
+ //instruction *instruc = g_ptr_array_remove_index(switchPrio, 0);
+ S52_obj *obj = g_ptr_array_remove_index(switchPrio, 0);
+
+ if (FALSE == g_ptr_array_remove_fast(L, obj)) {
+ PRINTF("ERROR: instrction not in list\n");
+ exit(0);
+ }
+
+ // find new display priority index
+ //disPrioIdx = S52_PL_getDPRI(instruc->LUP);
+ disPrioIdx = S52_PL_getDPRI(obj);
+
+ // find new lookup type index
+ //LUPtypeIdx = S52_PL_getTNAM(instruc->LUP);
+ LUPtypeIdx = S52_PL_getTNAM(obj);
+
+ //g_ptr_array_add(instrucL[disPrioIdx][LUPtypeIdx], instruc);
+ g_ptr_array_add(instrucL[disPrioIdx][LUPtypeIdx], obj);
+
+ if (_dprio > disPrioIdx)
+ _redraw = TRUE;
+ }
+
+ return 1;
+}
+
+/*
+typedef GLint (*f)(instruction *instruc, gpointer user_data);
+static int _forEachObject(f func, gpointer user_data)
+// call this function on every object
+{
+ int prio = S52_PRIO_NUM;
+ if(getenv("PRIO"))
+ prio = atoi(getenv("PRIO"));
+ if (prio == 0)
+ prio = S52_PRIO_NUM;
+
+ for (_dprio=0; _dprio<prio; ++_dprio) {
+ int i = 0;
+
+ // areas
+
+ for (i=0; i<instrucL[_dprio][S52_LUP_SYMBO]->len; ++i)
+ func(g_ptr_array_index(instrucL[_dprio][S52_LUP_SYMBO], i), NULL);
+
+ _doPending(instrucL[_dprio][S52_LUP_SYMBO]);
+
+ // lines
+ for (i=0; i<instrucL[_dprio][S52_LUP_LINES]->len; ++i)
+ func(g_ptr_array_index(instrucL[_dprio][S52_LUP_LINES], i), NULL);
+
+ _doPending(instrucL[_dprio][S52_LUP_LINES]);
+
+ // points
+ for (i=0; i<instrucL[_dprio][S52_LUP_SIMPL]->len; ++i)
+ func(g_ptr_array_index(instrucL[_dprio][S52_LUP_SIMPL], i), NULL);
+
+ _doPending(instrucL[_dprio][S52_LUP_SIMPL]);
+ }
+
+ // FIXME: can we loop here for ever
+ // if an object constantly switch layer
+ if (TRUE == _redraw) {
+ _forEachObject(func, NULL);
+ _redraw = FALSE;
+ }
+
+ return 1;
+}
+*/
+
+/*
+static S57_geo *_doPick()
+{
+ int i = 0;
+ S57_geo *geoData = NULL;
+ S57_geo *current = NULL;
+
+ _pushMode(GL_SELECT);
+ _forEachObject((gpointer) _pick, NULL);
+ _popMode(GL_SELECT);
+
+ printf("OBJECT FOUND: %i TOTAL SEARCHED: %i\n\n",
+ sobj.nac, sobj.geoV->len);
+
+ //for (i=0; i<sobj.hits; i++) {
+ //for (i=0; i<sobj.nac; i++) {
+ for (i=sobj.nac-1; i>=0; --i) {
+ //int idx = _getHit(sobj.acc, i);
+ //int idx = *(sobj.buf+4*i+3);
+ int idx = *(sobj.acc + i);
+ //int idx = *(sobj.acc+4*i+3);
+ instruction *instruc = g_ptr_array_index(sobj.geoV, idx);
+ //S52_LUP *LUP = instruc->LUP;
+
+ if (NULL == geoData)
+ geoData = instruc->geoData;
+ else
+ S57_linkObj(current, instruc->geoData);
+
+ current = instruc->geoData;
+
+
+ S52_PL_dumpData();
+
+ printf("%s\t%i/%i DPRI:%i DISC:%c (%s)\n",
+ S52_PL_getOBCL(LUP),
+ idx, sobj.geoV->len,
+ S52_PL_getDPRI(obj),
+ S52_PL_getDISC(obj),
+ S52_PL_infoLUP(obj)
+ );
+
+
+ printf("\tatt name : att value\n");
+ S57_dumpData(instruc->geoData);
+ printf("\n");
+
+ }
+ return geoData;
+}
+*/
+static gint _printVertex(gpointer key, gpointer value, gpointer data )
+// print vertex
+{
+ int i = (int) value;
+ double *d = (double*) key;
+ double lon = *d++;
+ double lat = *d;
+
+ PRINTF("%i \t lon/lat: %f %f \n", i, lon, lat);
+
+ return 0;
+}
+
+//---------------------------
+//
+// LIB ENTRY POINT SECTION
+//
+//---------------------------
+
+
+int S52_GL_draw(S52_obj *obj)
+// draw all
+// later redraw only dirty region
+// later redraw only Group 2 object
+// later ...
+{
+ int numBuffers[2];
+
+ // debug
+ countseg = 0;
+ //found = 0;
+
+ // RIVA 4096/4096
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, (int*)&numBuffers);
+ // RIVE 0 (no aux buf!)
+ glGetIntegerv(GL_AUX_BUFFERS, (int*)&numBuffers);
+ //glDrawBuffer();
+ //glViewPort();
+ //glXCreateGLXPixmap();
+ //numBuffers[1] = glXIsDirect(0, data);
+ //view = data;
+
+ if (FALSE == g_static_mutex_trylock(&sobj_mutex)) {
+ PRINTF("TRYLOCK failed\n");
+ return 1;
+ }
+
+ //glEnable(GL_LINE_SMOOTH); // antialiase is needed for line stippled
+ //glEnable(GL_ALPHA_TEST);
+ /*
+ if (glIsEnabled(GL_ALPHA_TEST)) {
+ GLenum ret;
+
+ PRINTF("GL_ALPHA_TEST = ON \n");
+
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, &ret);
+ PRINTF("GL_ALPHA_TEST_FUNC = %i \n", ret);
+
+ glGetIntegerv(GL_ALPHA_TEST_REF, &ret);
+ PRINTF("GL_ALPHA_TEST_REF = %i \n", ret);
+ } else
+ PRINTF("GL_ALPHA_TEST = OFF \n");
+ */
+
+ glPushAttrib(GL_ENABLE_BIT);
+
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_DITHER);
+ glShadeModel(GL_FLAT);
+
+ // draw both side
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ if (_initPROJ()) {
+
+ // FIXME: check that this work with Mesa!
+ //if (NULL != _glcontext)
+ // gdk_gl_make_current(GTK_WIDGET(data)->window, _glcontext);
+
+ // now that the main loop and projection is up ..
+ // whe create all symbol
+#ifdef INDEXMODE
+ _createSymb();
+#else
+ if (0==_listIndex) {
+
+ _createSymb();
+
+ /*
+ _loadV = 1; // create vertex set
+ _forEachObject(_loadLine);
+ //g_tree_foreach(_vertexSet, _printVertex, NULL);
+ //g_tree_traverse(_vertexSet, _printVertex, G_IN_ORDER, NULL);
+ //exit(0);
+ _loadV = 0; // compute line mask
+ _forEachObject(_loadLine);
+ */
+ }
+#endif
+
+ // APP ...
+ //
+ // CULL...
+ //
+ // DRAW...
+ if (TRUE == sobj.doPick) {
+ //_doPick();
+
+ //PRINTF("doPick .. returning ..\n");
+ sobj.doPick = FALSE;
+
+ } else {
+ _draw(obj);
+ //_glMatrixSet(VP_PRJ);
+ //_forEachObject((gpointer) _draw, NULL);
+ //_glMatrixDel(VP_PRJ);
+ }
+
+ // check that we're not returning GL in a bizard state
+ g_assert(0 == _topMode);
+ }
+
+ //glDisable(GL_ALPHA_TEST);
+
+ //glDisable(GL_LINE_SMOOTH);
+
+ //glMatrixMode(GL_PROJECTION);
+ //glPopMatrix();
+
+ //glMatrixMode(GL_MODELVIEW);
+ //glPopMatrix();
+
+ glPopAttrib();
+
+ glFlush();
+
+ _checkError("S52_GL_draw()");
+
+ g_static_mutex_unlock(&sobj_mutex);
+
+#ifdef S52_USE_OSG
+ S52_OSG_done();
+ exit(0);
+#endif
+
+ // debug
+ //S52_setMarinerParam(S52_MAR_COLOR_PALETTE, found);
+ //if (++found > 4)
+ // found = 0;
+
+ return 1;
+}
+
+int S52_GL_objectSetup(S57_geo *geoData)
+{
+ // WARNING: this will go into a per view handling module
+ // its definitly not related to GL
+ S52_diPrio disPrioIdx = 0;
+ S52_LUPtnm LUPtypeIdx = 0;
+ S52_obj *obj = NULL;
+
+ if (NULL == geoData) {
+ PRINTF("ERROR: no geoData object insert!!\n");
+ return 0;
+ }
+
+ obj = S52_PL_getObj(geoData);
+
+ // try to guess extend
+ if (0==strcmp(S57_getName(geoData), "M_COVR")) {
+ S57_getExt(geoData, &pmin.u, &pmin.v, &pmax.u, &pmax.v);
+ _M_COVR = obj;
+ }
+
+ g_assert(S52_PL_getFTYP(obj) == S57_getObjtype(S52_PL_getGeo(obj)));
+
+ // find display priority index
+ disPrioIdx = S52_PL_getDPRI(obj);
+
+ // find lookup type index
+ LUPtypeIdx = S52_PL_getTNAM(obj);
+
+ g_ptr_array_add(instrucL[disPrioIdx][LUPtypeIdx], obj);
+
+ return 1;
+}
+
+S57_geo* S52_GL_doPick(double x, double y)
+{
+ if (FALSE == g_static_mutex_trylock(&sobj_mutex)) {
+ PRINTF("TRYLOCK failed\n");
+ return 0;
+ }
+ //_initPROJ();
+
+//#ifdef INDEXMODE
+// _createSymb();
+//#else
+// if (0==_listIndex) {
+// _createSymb();
+// }
+//#endif
+
+
+ sobj.x = x;
+ sobj.y = y;
+ sobj.doPick = TRUE;
+
+ //S57_geo *geoData = _doPick();
+
+ //PRINTF("doPick .. returning ..\n");
+ sobj.doPick = FALSE;
+ g_static_mutex_unlock(&sobj_mutex);
+
+ //return geoData;
+ return NULL;
+}
+
+int S52_GL_validCtx()
+// return TRUE if current GL context support S52 rendering
+// NOTE: for now check for stencil buffer (needed to clip pattern)
+{
+ GLint r=0,g=0,b=0,a=0,s=0; // bool true if in RGBA mode
+ GLboolean m=0;
+
+ glGetBooleanv(GL_RGBA_MODE, &m);
+ // glGetBooleanv(GL_INDEX_MODE, &m);
+ glGetIntegerv(GL_RED_BITS, &r);
+ glGetIntegerv(GL_GREEN_BITS, &g);
+ glGetIntegerv(GL_BLUE_BITS, &b);
+ glGetIntegerv(GL_ALPHA_BITS, &a);
+ glGetIntegerv(GL_STENCIL_BITS,&s);
+ //PRINTF("mode,r,g,b,a,s: %d %d %d %d %d %d \n",m,r,g,b,a,s);
+ // 16 bits:mode,r,g,b,a,s: 1 5 6 5 0 8
+ // 24 bits:mode,r,g,b,a,s: 1 8 8 8 0 8
+ if (s <= 0) {
+ PRINTF("ERROR no stencil buffer for pattern!\n");
+ //exit(0);
+ return 0;
+ }
+
+ // force something
+ // _glcontext = (GdkGLContext*) 1;
+
+ //return 0; // force init code
+ return 1;
+}
+
+int S52_GL_init(Display * dpy, Colormap colormap)
+{
+ int i = 0;
+
+ Font font;
+ _display = dpy;
+ _cmap = colormap;
+
+ S52_PL_load(NULL);
+
+ _initGLmodule();
+
+#ifdef S52_USE_OSG
+ S52_OSG_init();
+#endif
+
+ for (i=0; i<3; ++i) {
+
+ _fontDList[i] = glGenLists(256);
+
+ font = XLoadFont(dpy, _font[i]);
+ glXUseXFont(font, 0, 256, _fontDList[i]);
+ }
+
+/*
+#ifndef INDEXMODE
+ {
+ int old = S52_getMarinerParam(S52_MAR_COLOR_PALETTE);
+
+ currentScreen = DefaultScreen(dpy);
+ printf("CurrentScreen: %d\n", currentScreen);
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, 0);
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, 1);
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, 2);
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, 3);
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, 4);
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+
+ S52_setMarinerParam(S52_MAR_COLOR_PALETTE, old);
+ }
+#else
+ _toRGB(dpy, colormap, S52_PL_getColorTable());
+#endif
+*/
+ return 1;
+}
+
+int S52_GL_done()
+{
+ int j,k;
+ GPtrArray *crnt = NULL;
+
+ //S52_OSG_done();
+
+ S52_PL_done();
+ S57_donePROJ();
+ //old_glcontext;
+ _doneGLobj();
+
+ /*
+ for (_dprio=0; _dprio<S52_PRIO_NUM; ++_dprio) {
+ for (j=0; j<S52_LUP_NUM; ++j) {
+ GPtrArray *instL = instrucL[_dprio][j];
+
+ for (k=0; k<crnt->len; ++k) {
+ instruction *instruc = g_ptr_array_index(instL, k);
+
+ // FIXME: trace this when shuting-down signal will be connected
+
+ //S52_PL_doneCSinst(instruc->CSinst);
+ //S52_PL_doneCmdList(instruc->cmdList);
+ //S52_PL_doneTXT(instruc->text);
+ //S57_doneObject(instruc->geoData);
+
+ g_free(instruc);
+ }
+
+ g_ptr_array_free(crnt, FALSE);
+ }
+ }
+ */
+
+ return 1;
+}
+
+
+//---------------------------
+//
+// MAIN SECTION
+//
+//---------------------------
+
+
+#ifdef S52_GL_TEST
+int S52_GL_start(char *catalogPath, int checkConfigFile)
+{
+ int i;
+ GtkGLArea *glarea;
+ Extent *ext;
+ double dx,dy;
+ double latPix,lonPix;
+ double pix_w,pix_h;
+ int cellNum = 0;
+ char *catPath = NULL;
+
+ if (checkConfigFile)
+ catPath = _getGonfig(CATALOG);
+
+ if (catPath)
+ cellNum = S57_loadCell(catPath);
+ else
+ cellNum = S57_loadCell(catalogPath);
+
+ _linkObj2cmd();
+ ext = S57_getExtent(0);
+
+ dx = ext->ELON - ext->WLON;
+ dy = ext->NLAT - ext->SLAT;
+
+ // fixme: assume a spherical earth --for the moment.
+ // Also since mercator preserve angle
+ // assume that MercatorPixel(TM) are round!
+ //if (dx<dy){
+
+ pix_h = 500.0;
+ latPix = dy / pix_h;
+ lonPix = latPix;
+ pix_w = dx / lonPix;
+
+ /*
+ }else{
+ pix_w = 1000.0;
+ lonPix = dx / pix_w;
+ latPix = lonPix;
+ pix_h = dy / latPix;
+ }
+ */
+
+
+
+// _initGtkFmaps((int)pix_w,(int)pix_h);
+// _initGtkFmaps((int)1000,(int)500);
+
+ glarea = &fmaps->glarea;
+ // not an OpenGL widget
+ g_return_val_if_fail(
+ gtk_gl_area_make_current(GTK_GL_AREA(glarea)),FALSE);
+
+ // symb creation need some sort scaling
+ // also test for pattern initialisation
+ _createSymb();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+
+
+ //gluOrtho2D( ext->WLON, ext->ELON, ext->SLAT, ext->NLAT);
+
+ //glMatrixMode(GL_MODELVIEW);
+ //glLoadIdentity();
+
+ // glViewport(0,0,1000, 500);
+ //glViewport(0,0,(int)pix_w, (int)pix_h);
+
+ // glDrawBuffer(GL_BACK);
+ // glDrawBuffer(GL_FRONT);
+
+
+ // glClearColor(0,0,100,0); // BLUE
+ glClearColor(0,0,0.7,1); // BLUE
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+
+ // draw here ...
+
+
+ glFlush();
+ glFinish();
+
+ printf("CTRL-C to exit ... \n");
+ gtk_main();
+ printf("exiting ... \n");
+
+ return 1;
+}
+
+int main(int argc, char** argv)
+{
+ _GL_init();
+
+ S52_GL_start(argv[1], FALSE);
+
+ // gtk_main();
+
+ S52_GL_done();
+
+ return 1;
+}
+#endif
+
+
Added: packages/openev/branches/upstream/current/contrib/S52/S52GL.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52GL.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52GL.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,53 @@
+// S52GL.h: display S57 data using S52 symbology and OpenGL.
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC.
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52GL_H_
+#define _S52GL_H_
+
+#include "S52PL.h" // S52_LUP
+#include "S57data.h" // S57_geo
+#include <X11/Xlib.h> // Display, Colormap
+
+// initialises the dpy and cmap. If cmap is 0, a new one is created.
+extern int S52_GL_validCtx();
+extern int S52_GL_init(Display * dpy, Colormap cmap);
+// register S57 object for rendering
+//extern int S52_GL_objectSetup(S52_LUP *LUP, S57_geo *geoData, void *instruc);
+extern int S52_GL_objectSetup(S57_geo *geoData);
+// render object
+extern int S52_GL_draw(S52_obj *obj);
+// next S52_GL_draw call will do cursor pick instead of rendering
+extern S57_geo* S52_GL_doPick(double x, double y);
+// flush objects, clean up mem
+extern int S52_GL_done();
+
+
+// Christian stuff
+// determine which priorities to draw(should use enumerationxo).
+extern void S52_setPrio(int prio, int state);
+
+// apply changes being set by marinerparams
+extern void S52_changeLUP();
+
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,389 @@
+// S52OSG.cpp: translate and export S52/S57 to OSG (OpenSceneGraph)
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC.
+ Copyright (C) 2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#include "S52OSG.cpp.h"
+
+/*
+#include "S52OSG.h"
+#include "S52utils.h"
+//#undef glVertexPointer(size, type, stride, ptr)
+
+#include <osg/Group>
+//#include <osg/Node>
+#include <osg/PositionAttitudeTransform>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/Drawable>
+#include <osg/Array>
+//#include <osg/ref_ptr>
+#include <osg/PrimitiveSet>
+#include <osg/StateSet>
+#include <osg/StateAttribute>
+
+#include <osgDB/WriteFile>
+
+#include <osgProducer/Viewer>
+
+#include <osg/MatrixTransform>
+
+#include <osg/Depth>
+
+#include <osg/Projection>
+
+#include <string.h>
+
+#include <glib.h> // g_ptr_array()
+*/
+
+// nodes
+static osg::Group *_root = NULL;
+static osg::Group *_symb = NULL;
+static osg::Geode *_geode = NULL;
+static osg::Geode *_geodeSym = NULL;
+static osg::Geometry *_geo = NULL;
+static osg::Geometry *_geoSym = NULL;
+
+static osg::MatrixTransform *_transform = NULL;
+//static osg::PositionAttitudeTransform *_transform = NULL;
+static osg::MatrixTransform *_rootnode = NULL;
+//static osg::Group *_rootnode = NULL;
+
+// helper
+static osg::Vec3Array *_coords = NULL;
+static osg::Vec3Array *_coordsSym = NULL;
+
+//typedef GLdouble _cood
+static struct _vertex { GLdouble x,y,z; } *_vertex;
+static GLsizei _vertexCount = 0;
+
+static osg::Vec4Array *_color = NULL;
+
+static int _inList = FALSE; // TRUE if w're loading a call list
+static GPtrArray *_geoArray = NULL;
+static GLsizei _rangeList = 0;
+static GLuint _baseList = 0;
+
+//static osg::Node *node = NULL;
+//osg::ref_ptr<osg::Vec3Array> coords;
+
+//static osgProducer::Viewer viewer;
+
+int S52_OSG_init() /*fold00*/
+{
+ // tilt the scene so the default eye position is looking down on the model.
+ _rootnode = new osg::MatrixTransform();
+ //_rootnode = new osg::Group();
+ //_rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
+ //_rootnode->setMatrix(osg::Matrix::scale(0.01f, 0.01f, 1.0f));
+ //_rootnode->setMatrix(osg::Matrix::scale(10.0f, 10.0f, 1.0f));
+ _rootnode->setMatrix(osg::Matrix::translate(68.5f, -48.5f, 10.0f));
+ _rootnode->postMult(osg::Matrix::scale(100.0, 100.0, 1.0));
+
+ _root = new osg::Group();
+ _root->ref(); // (!)
+ _rootnode->addChild(_root);
+
+ osg::Depth* depth = new osg::Depth;
+ depth->setFunction(osg::Depth::ALWAYS);
+
+ _geode = new osg::Geode();
+ _geode->ref();
+ osg::StateSet *bin1 = new osg::StateSet;
+ bin1->setRenderBinDetails(1, "RenderBin");
+ //bin1->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+ //bin1->setAttribute(depth);
+ _geode->setStateSet(bin1);
+ _root->addChild(_geode);
+
+ _symb = new osg::Group();
+ _symb->ref();
+
+ osg::StateSet *bin2 = new osg::StateSet;
+ bin2->setRenderBinDetails(2, "RenderBin");
+ //bin2->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+ bin2->setAttribute(depth);
+ _symb->setStateSet(bin2);
+
+ _rootnode->addChild(_symb);
+
+ //_geodeSym = new osg::Geode();
+ //_geodeSym->ref();
+ //_root->addChild(_geodeSym);
+
+
+ return 1;
+}
+
+void _setNorth() /*FOLD00*/
+{
+ osg::Geode* geode = new osg::Geode();
+ osg::StateSet* stateset = geode->getOrCreateStateSet();
+ //stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
+ stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
+ stateset->setRenderBinDetails(9, "RenderBin");
+ osg::Vec3 position(50.0f,50.0f,0.0f);
+
+ osg::Geometry *geoSym = (osg::Geometry*) g_ptr_array_index(_geoArray, 105);
+ _color->push_back(osg::Vec4(255.0, 0.0, 0.0, 255.0));
+ geoSym->setColorArray(_color);
+ geoSym->setColorBinding(osg::Geometry::BIND_OVERALL);
+ //_geodeSym = new osg::Geode();
+ //_geodeSym->addDrawable(geoSym);
+ geode->addDrawable(geoSym);
+
+ // create the hud.
+ osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
+ modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
+ modelview_abs->setMatrix(osg::Matrix::identity());
+ //modelview_abs->addChild(_geodeSym);
+ modelview_abs->addChild(geode);
+
+ osg::Projection* projection = new osg::Projection;
+ projection->setMatrix(osg::Matrix::ortho2D(0,1024,0,768));
+ projection->addChild(modelview_abs);
+
+ _symb->addChild(projection);
+}
+
+int S52_OSG_done() /*FOLD00*/
+{
+ osgProducer::Viewer viewer;
+
+ std::string *fname = new std::string("test.osg");
+ //_setNorth();
+
+ viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
+ viewer.setSceneData(_rootnode);
+
+ viewer.realize();
+
+ while (!viewer.done()) {
+ viewer.sync();
+ viewer.update();
+ viewer.frame();
+ }
+
+ //if (!osgDB::writeNodeFile(*_geode, *fname))
+ if (!osgDB::writeNodeFile(*_rootnode, *fname))
+ //if (!osgDB::writeNodeFile(*_root, *fname))
+ printf("write failed\n");
+
+ return 1;
+}
+
+void S52_OSG_glVertexPointer(GLint size, GLenum type, /*FOLD00*/
+ GLsizei stride, const GLvoid *ptr)
+{
+ _vertex = (struct _vertex*) ptr;
+ _vertexCount = 0;
+
+ // normal
+ osg::Vec3Array *normals = new osg::Vec3Array();
+ normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
+
+ if (TRUE == _inList) {
+ _geoSym = new osg::Geometry();
+ //_geoSym->ref();
+
+ _coordsSym = new osg::Vec3Array();
+ //_coordsSym->ref();
+ _geoSym->setVertexArray(_coordsSym);
+
+ _geoSym->setNormalArray(normals);
+ _geoSym->setNormalBinding(osg::Geometry::BIND_OVERALL);
+
+ } else {
+ _geo = new osg::Geometry();
+ _geo->ref();
+
+ _coords = new osg::Vec3Array();
+ _coords->ref();
+ _geo->setVertexArray(_coords);
+
+ _geo->setNormalArray(normals);
+ _geo->setNormalBinding(osg::Geometry::BIND_OVERALL);
+ }
+
+ // this will draw all symb
+ //_geode->addDrawable(_geo);
+
+}
+
+void S52_OSG_glDrawArrays(GLenum mode, GLint first, GLsizei count) /*fold00*/
+{
+ int n = first + count;
+
+ osg::DrawArrays *osgDrawArrays =
+ new osg::DrawArrays(mode, first, count);
+
+
+ // don't set color if building list
+ // skip the rest --will be picked up later
+ if (TRUE == _inList) {
+ _coordsSym->resize(n);
+
+ for (int i=first; i<n; i++) {
+ (*_coordsSym)[i].set(_vertex[i].x, _vertex[i].y, _vertex[i].z);
+ //(*_coordsSym)[i][0] = _vertex[i].x;
+ //(*_coordsSym)[i][1] = _vertex[i].y;
+ //(*_coordsSym)[i][2] = _vertex[i].z;
+ }
+ _geoSym->addPrimitiveSet(osgDrawArrays);
+ //_geodeSym->addDrawable(_geoSym);
+
+ } else {
+ _coords->resize(n);
+
+ for (int i=first; i<n; i++) {
+ (*_coords)[i][0] = _vertex[i].x;
+ (*_coords)[i][1] = _vertex[i].y;
+ (*_coords)[i][2] = _vertex[i].z;
+ }
+ _geo->addPrimitiveSet(osgDrawArrays);
+ _geo->setColorArray(_color);
+ _geo->setColorBinding(osg::Geometry::BIND_OVERALL);
+
+ _geode->addDrawable(_geo);
+ }
+}
+
+
+void S52_OSG_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) /*fold00*/
+{
+ //osg::Vec4Array *color = new osg::Vec4Array();
+ _color = new osg::Vec4Array();
+ //_color->ref();
+ _color->push_back(osg::Vec4(red/255.0, green/255.0, blue/255.0, alpha/255.0));
+ //PRINTF(" %f %f %f %f \n", red/255.0, green/255.0, blue/255.0, alpha/255.0);
+}
+
+
+void S52_OSG_glNewList(GLuint list, GLenum mode) /*fold00*/
+{
+ _inList = TRUE;
+ //_listNo = list;
+}
+
+void S52_OSG_glEndList() /*fold00*/
+{
+ //osg::Geode geodeSym;
+ //_geoSym.clone(geodeSym);
+
+ _inList = FALSE;
+
+ g_ptr_array_add(_geoArray, (gpointer) _geoSym);
+}
+
+void S52_OSG_glCallList(GLuint list) /*FOLD00*/
+{
+ GLuint idx = list - _baseList;
+
+ g_assert(_geoArray->len > idx);
+
+ PRINTF("listNo: %i\n", idx);
+
+ osg::Geometry *geoSym = (osg::Geometry*) g_ptr_array_index(_geoArray, idx);
+ if (NULL == geoSym) {
+ PRINTF("ERROR: no display list at %i\n", idx);
+ return;
+ }
+
+ geoSym->setColorArray(_color);
+ geoSym->setColorBinding(osg::Geometry::BIND_OVERALL);
+
+
+ //osg::Geode *geode = new osg::Geode();
+ //geode->addDrawable(geoSym);
+ //_transform->addChild(geode);
+
+ _geodeSym->addDrawable(geoSym);
+ _transform->addChild(_geodeSym);
+}
+
+GLuint S52_OSG_glGenLists(GLsizei range, GLuint base) /*fold00*/
+{
+ if (NULL == _geoArray) {
+ _rangeList = range;
+ _baseList = base;
+ _geoArray = g_ptr_array_new();
+ } else {
+ printf("to much gen list");
+ exit(0);
+ }
+
+ return base;
+}
+
+void S52_OSG_glTranslated(GLdouble x, GLdouble y, GLdouble z) /*fold00*/
+{
+ _transform = new osg::MatrixTransform();
+ _transform->setMatrix(osg::Matrix::translate(x, y, z));
+
+ //_root->addChild(_transform);
+
+
+ _geodeSym = new osg::Geode();
+ _transform->addChild(_geodeSym);
+
+ //osg::Group *symbGrp = new osg::Group();
+ //symbGrp->addChild(_transform);
+
+ _symb->addChild(_transform);
+}
+
+void S52_OSG_glScaled(GLdouble x, GLdouble y, GLdouble z) /*fold00*/
+{
+ //osg::MatrixTransform *transform = new osg::MatrixTransform();
+ //_transform->setMatrix(osg::Matrix::scale(x, y, z));
+
+ //_geodeSym = new osg::Geode();
+ //transform->addChild(_geodeSym);
+
+ //_transform->addChild(transform);
+
+
+
+ //_transform->setMatrix(osg::Matrix::scale(x, y, z));
+ //_transform->postMult(osg::Matrix::scale(x, y, z));
+ _transform->preMult(osg::Matrix::scale(x, y, z));
+ //_transform *= osg::Matrix::scale(x, y, z);
+}
+
+void S52_OSG_glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) /*fold00*/
+{
+ //_transform->setMatrix(osg::Matrix::rotate(angle, x, y, z));
+ //_transform->postMult(osg::Matrix::rotate(angle, x, y, z));
+ //_transform->preMult(osg::Matrix::rotate(angle, x, y, z));
+}
+
+
+//========================= S C R A P ================================
+ // set line width
+ /*
+ if (GL_LINE_STRIP == mode) {
+ osg::StateSet* lineStateSet = new osg::StateSet;
+ lineStateSet->setMode(mode, osg::StateAttribute::ON);
+
+ _geo->setStateSet(lineStateSet);
+ }
+ */
Added: packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52OSG.cpp.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,52 @@
+// S52OSG.cpp.h: precompile header S52OSG.cpp
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC.
+ Copyright (C) 2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#include "S52OSG.h"
+#include "S52utils.h"
+//#undef glVertexPointer(size, type, stride, ptr)
+
+#include <osg/Group>
+//#include <osg/Node>
+#include <osg/PositionAttitudeTransform>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/Drawable>
+#include <osg/Array>
+//#include <osg/ref_ptr>
+#include <osg/PrimitiveSet>
+#include <osg/StateSet>
+#include <osg/StateAttribute>
+
+#include <osgDB/WriteFile>
+
+#include <osgProducer/Viewer>
+
+#include <osg/MatrixTransform>
+
+#include <osg/Depth>
+
+#include <osg/Projection>
+
+#include <string.h>
+
+#include <glib.h> // g_ptr_array()
Added: packages/openev/branches/upstream/current/contrib/S52/S52OSG.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52OSG.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52OSG.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,89 @@
+// S52OSG.h: translate and export S52/S57 to OSG (OpenSceneGraph)
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC.
+ Copyright (C) 2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#ifndef _S52OSG_H_
+#define _S52OSG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <GL/gl.h>
+
+#define glVertexPointer(size, type, stride, ptr) \
+ glVertexPointer(size, type, stride, ptr), \
+ S52_OSG_glVertexPointer(size, type, stride, ptr);
+
+#define glDrawArrays(mode, first, count) \
+ glDrawArrays(mode, first, count), \
+ S52_OSG_glDrawArrays(mode, first, count);
+
+#define glColor4ub(red, green, blue, alpha) \
+ glColor4ub(red, green, blue, alpha), \
+ S52_OSG_glColor4ub(red, green, blue, alpha);
+
+#define glNewList(_listIndex, GL_COMPILE) \
+ glNewList(_listIndex, GL_COMPILE), \
+ S52_OSG_glNewList(_listIndex, GL_COMPILE);
+
+#define glEndList() \
+ glEndList(), \
+ S52_OSG_glEndList();
+
+#define glCallList(list) \
+ glCallList(list), \
+ S52_OSG_glCallList(list);
+
+#define glGenLists(range) \
+ S52_OSG_glGenLists(range, glGenLists(range));
+
+#define glTranslated(x, y, z) \
+ glTranslated(x, y, z), \
+ S52_OSG_glTranslated(x, y, z);
+
+#define glScaled(x, y, z) \
+ glScaled(x, y, z), \
+ S52_OSG_glScaled(x, y, z);
+
+#define glRotated(angle, x, y, z) \
+ glRotated(angle, x, y, z), \
+ S52_OSG_glRotated(angle, x, y, z);
+
+ extern int S52_OSG_init();
+ extern int S52_OSG_done();
+ extern void S52_OSG_glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
+ extern void S52_OSG_glDrawArrays(GLenum mode, GLint first, GLsizei count );
+ extern void S52_OSG_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+ extern void S52_OSG_glNewList(GLuint list, GLenum mode);
+ extern void S52_OSG_glEndList();
+ extern void S52_OSG_glCallList(GLuint list);
+ extern GLuint S52_OSG_glGenLists(GLsizei range, GLuint base);
+ extern void S52_OSG_glTranslated(GLdouble x, GLdouble y, GLdouble z);
+ extern void S52_OSG_glScaled(GLdouble x, GLdouble y, GLdouble z);
+ extern void S52_OSG_glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_S52OSG_H_
Added: packages/openev/branches/upstream/current/contrib/S52/S52PL.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52PL.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52PL.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+<html><head>
+<title>502 Bad Gateway</title>
+</head><body>
+<h1>Bad Gateway</h1>
+<p>The proxy server received an invalid
+response from an upstream server.<br />
+</p>
+</body></html>
Added: packages/openev/branches/upstream/current/contrib/S52/S52PL.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52PL.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52PL.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,289 @@
+// S52PL.h: interface to S52 Presentation Library Parser
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52PLIB_H_
+#define _S52PLIB_H_
+
+#include "S52type.h" // S52_Obj_t
+#include "S57data.h" // S57_geo
+#include <glib.h> // GString, GData, GArray
+
+#define S52_LUP_NMLN 6 // lookup name lenght
+
+// S52 lookup table name (fifth letter)
+typedef enum _S52_LUPtnm {
+ S52_LUP_PLAIN = 0, //'N', // areas --PLAIN_BOUNDARIES
+ S52_LUP_SYMBO = 1, //'O', // areas --SYMBOLIZED_BOUNDARIES
+ S52_LUP_LINES = 2, //'S', // lines --LINES
+ S52_LUP_SIMPL = 3, //'L', // points --SIMPLIFIED
+ S52_LUP_PAPER = 4, //'R', // points --PAPER_CHART
+ //S52_LUP_NUM = 0 , // unknown LUP (META)
+ S52_LUP_NUM = 5 // number of lookup name
+} S52_LUPtnm;
+
+// S52 symbology table name
+typedef enum _S52_SMBtblName {
+ S52_SMB_LINE = 0, // Complex Linestyle --line
+ S52_SMB_PATT, // Pattern --area
+ S52_SMB_SYMB, // Symbol --point
+ S52_SMB_COND, // Conditional --point,line,area
+ S52_SMB_NUM // number of tables
+} S52_SMBtblName;
+
+// S52 Display Priority
+typedef enum _S52_diPrio {
+ S52_PRIO_NODATA = 0, //'0', // no data fill area pattern
+ S52_PRIO_GROUP1 = 1, //'1', // S57 group 1 filled areas
+ S52_PRIO_AREA_1 = 2, //'2', // superimposed areas
+ S52_PRIO_AREA_2 = 3, //'3', // superimposed areas also water features
+ S52_PRIO_SYM_PT = 4, //'4', // point symbol also land features
+ S52_PRIO_SYM_LN = 5, //'5', // line symbol also restricted areas
+ S52_PRIO_SYM_AR = 6, //'6', // area symbol also traffic areas
+ S52_PRIO_ROUTES = 7, //'7', // routeing lines
+ S52_PRIO_HAZRDS = 8, //'8', // hazards
+ S52_PRIO_MARINR = 9, //'9', // VRM & EBL, own ship
+ S52_PRIO_NUM = 10, // number of priority levels
+ S52_PRIO_NOPRIO = '-' // use default prio (CS)
+} S52_diPrio;
+
+// RADAR Priority
+typedef enum _RadPrio {
+ RAD_OVER = 'O', // presentation on top of RADAR
+ RAD_SUPP = 'S', // presentation suppressed by RADAR
+ RAD_NUM = 2,
+ RAD_NPPR = '-' // use default prio (CS)
+} S52_RadPrio;
+
+// display categorie type
+typedef enum S52_DisCat {
+ DISPLAYBASE = 'D', //
+ STANDARD = 'S', //
+ OTHER = '0', //
+ MARINERS_STANDARD, // value not defined
+ MARINERS_OTHER, // value not defined
+ DISP_CAT_NUM, // value not defined
+ NO_DISP_CAT = '-' // use default categorie (CS)
+} S52_DisCat;
+
+// Command Word
+typedef enum S52_Cmd {
+ S52_CMD_NONE, // no rule type (init)
+ S52_CMD_TXT_TX, // TX --SHOWTEXT (formated)
+ S52_CMD_TXT_TE, // TE --SHOWTEXT
+ S52_CMD_SYM_PT, // SY --SHOWPOINT
+ S52_CMD_SIM_LN, // LS --SHOWLINE
+ S52_CMD_COM_LN, // LC --SHOWLINE
+ S52_CMD_ARE_CO, // AC --SHOWAREA`
+ S52_CMD_ARE_PA, // AP --SHOWAREA
+ S52_CMD_CND_SY, // CS --CALLSYMPROC
+
+ S52_CMD_OVR_PR // OVERRIDE PRIORITY (not in S52specs).
+ // Used 8 char to passe data from S52CS ('-' = field not used):
+ // 0 -S52_diPrio,
+ // 1 -S52_RadPrio,
+ // 2 -S52_DisCat,
+ // 3-7 -viewing group,
+} S52_Cmd;
+
+// color definition
+typedef struct S52_Color {
+ char colName[5];
+ float x;
+ float y;
+ float L;
+ guchar R;
+ guchar G;
+ guchar B;
+
+ //--- not S52 field --------
+ int idx;
+ guchar i; // index of this color in array,
+ guchar trans; // place holder --may vary
+} S52_Color;
+
+// display list sub list for color switch
+#define MAX_SUBLIST 10 // SCALEB10 need to switch color (2 colors)
+//struct _S52_subListData {
+
+typedef struct S52_subListData {
+ // can't tell before hand if trans will
+ char col[sizeof(S52_Color) * MAX_SUBLIST];
+ guint startList;
+ guint nSubList;
+} S52_subListData; // be the same for all color C
+
+// Vector Command (a la HPGL)
+typedef enum S52_vCmd {
+ S52_VC_NONE = 0, // initial / no (more) command
+ S52_VC_NEW = 'X', // start new sub-list
+
+ // second character
+ S52_VC_ST = 'T', // transparency
+ S52_VC_SW = 'W', // width
+ S52_VC_PU = 'U', // pen up
+ S52_VC_PD = 'D', // pen down
+ S52_VC_CI = 'I', // circle
+ S52_VC_AA = 'A', // arc
+ S52_VC_SC = 'C', // call symbol
+
+ S52_VC_PM = 'M', // polygone mode
+
+ // first charater
+ S52_VC__P = 'P', // check first character
+ S52_VC_SP = 'S', // color
+ S52_VC_EP = 'E', // outline polygone
+ S52_VC_FP = 'F' // fill polygone
+} S52_vCmd;
+
+// display supression flag
+typedef enum S52_objSup {
+ S52_SUP_OFF = 0, // initial object not supressed
+ S52_SUP_ON = 1, // display of object is supressed
+ S52_SUP_ERR = 2 // object not found or not toggled (displaybase)
+
+} S52_objSup;
+
+typedef struct _S52_CmdL S52_CmdL;
+typedef struct _S52_cmdDef S52_cmdDef;
+typedef struct _S52_LUP S52_LUP;
+typedef struct _S52_Text S52_Text;
+typedef struct _S52_vec S52_vec;
+typedef struct _S52_obj S52_obj;
+
+// load/init presentation library
+extern int S52_PL_load(char *PLib);
+// free presentation library
+extern int S52_PL_done();
+
+// get RGB from color name, for the currently selected color table
+extern S52_Color *S52_PL_getColor(char *colorName);
+// get currently selected color table
+extern GArray *S52_PL_getColorTable();
+// return color at index, for the currently selected color table
+extern S52_Color *S52_PL_getColorAt(guchar index);
+
+// get a rasterising rules for this S57 object
+//extern S52_LUP *S52_PL_getLUP(const char * objectName, S57_geo *geoData);
+//extern S52_LUP *S52_PL_getLUP(S57_geo *geoData);
+extern S52_obj *S52_PL_getObj(S57_geo *geoData);
+extern S57_geo *S52_PL_getGeo(S52_obj *obj);
+
+// get LUP name
+extern char *S52_PL_getOBCL(S52_obj *obj);
+// get addressed object TYPe
+extern S52_Obj_t S52_PL_getFTYP(S52_obj *obj);
+// get Display PRIority
+extern S52_diPrio S52_PL_getDPRI(S52_obj *obj);
+// get DISplay Category
+extern S52_DisCat S52_PL_getDISC(S52_obj *obj);
+// get LUP table name
+extern S52_LUPtnm S52_PL_getTNAM(S52_obj *obj);
+// return plain text info for this type (TNAM) of lookup
+extern char *S52_PL_infoLUP(S52_obj *obj);
+// get Condition Symbology instruction
+//extern GString *S52_PL_getCSinst(S52_LUP *LUP);
+//extern S52_CmdL *S52_PL_getCSinst(S52_LUP *LUP);
+//extern int S52_PL_doneCSinst(GString *CSinst);
+
+// command word list handling
+// get next command word in the list
+extern S52_Cmd S52_PL_getCmdNext(S52_obj *obj);
+// get current command word
+extern S52_Cmd S52_PL_getCmdWord(S52_obj *obj);
+// compare name to parameter of current command word
+extern int S52_PL_cmpCmdParam(S52_obj *obj, char *name);
+
+// set (save) display list name (OpenGL)
+extern int S52_PL_setDisplayList(S52_cmdDef *def, guint listIndex);
+// debug: return the number of sublist for this command
+extern int S52_PL_getSubDisplayListNbr(S52_cmdDef *def);
+// get display list name (OpenGL)
+extern guint S52_PL_getDisplayList(S52_obj *obj);
+
+// init vector commands parser
+extern S52_vec *S52_PL_initVOCmd(S52_cmdDef *def);
+// get next vector command, width in ASCII (1 pixel=0.32 mm)
+extern S52_vCmd S52_PL_getVOCmd(S52_vec *vecObj);
+// get vextor for this command
+extern S57_prim *S52_PL_getVOprim(S52_vec *vecObj);
+// get pen width
+extern char S52_PL_getVOwidth(S52_vec *vecObj);
+// get disk radius
+extern double S52_PL_getVOradius(S52_vec *vecObj);
+// get vextex array
+extern GArray *S52_PL_getVOdata(S52_vec *vecObj);
+// get name --debug
+extern char *S52_PL_getVOname(S52_vec *vecObj);
+
+
+// return symbol orientation [0..360[
+extern double S52_PL_getSYorient(S52_obj *obj);
+// get Line Style data, width in ASCII (1 pixel=0.32 mm)
+extern int S52_PL_getLSdata(S52_obj *obj, char *pen_w, char *style, S52_Color **color);
+// set Line Complex data, width in ASCII (1 pixel=0.32 mm)
+extern int S52_PL_setLCdata(S52_cmdDef *def, char pen_w);
+// get Line Complex data, width in ASCII (1 pixel=0.32 mm), return symbol lenght
+extern double S52_PL_getLCdata(S52_obj *obj, double dotpitch_x, char *pen_w);
+// get Area Color data
+extern S52_Color *S52_PL_getACdata(S52_obj *obj);
+// get Area Pattern data
+extern int S52_PL_getAPdata(S52_obj *obj, double dotpitch_x, double dotpitch_y,
+ double *tw, double *th, double *dx);
+// set Area Pattern cover data
+extern int S52_PL_setAPcover(S52_cmdDef *def, double dotpitch_x, double dotpitch_y, char pen_w);
+// get symbol offset
+//extern int S52_PL_getSymOff(S52_cmdDef* def, int patt, int *off_x, int *off_y);
+// traverse a symbology table calling 'callback' for each entree
+extern gint S52_PL_traverse(S52_SMBtblName tableNm, GTraverseFunc callBack);
+// return the number of entree in a symbology table
+//extern gint S52_PL_getTableSz(S52_SMBtblName tableNm);
+
+// return total number of sub-vector
+extern guint S52_PL_getSubListData(S52_obj *obj, S52_subListData *subListData);
+extern guint S52_PL_getSubListNbr();
+
+// text parser
+//extern S52_Text *S52_PL_parseTX(S57_geo *geoData, S52_CmdL *cmd);
+//extern S52_Text *S52_PL_parseTE(S57_geo *geoData, S52_CmdL *cmd);
+//extern gint S52_PL_getTEXT(S52_Text *text, S52_Color **col,
+extern char *S52_PL_getEX(S52_obj *obj, S52_Color **col,
+ int *xoffs, int *yoffs, int *bsize, int *weight);
+//extern gint S52_PL_doneTXT(S52_Text *text);
+
+// parse/compute/expand cond. symb.
+//extern GString *S52_PL_parseCS(S52_obj *obj);
+
+// compare symbology instruction againt name (0==match)
+//extern int S52_PL_cmpCSname(S52_obj *obj, char *name);
+// get new display priority
+extern S52_diPrio S52_PL_getOPprio(S52_obj *obj);
+
+// toggle display supression of this type of object
+extern S52_objSup S52_PL_toggleObjType(S52_obj *obj);
+// toggle display suppression of this class of object
+extern S52_objSup S52_PL_toggleObjClass(char *className);
+// get display state for this type of object
+extern S52_objSup S52_PL_getToggleState(S52_obj *obj);
+
+#endif // _S52PL_H_
Added: packages/openev/branches/upstream/current/contrib/S52/S52glxsimple.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52glxsimple.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52glxsimple.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,191 @@
+// S52glxsimple.c: simple S52 driver using only GLX and OGR.
+//
+// Inspired from glxsimple.c
+//
+//
+
+#include "ogr_api.h" // OGR*
+
+#include "S52.h"
+#include "S52utils.h" // PRINTF()
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#include <stdio.h>
+#include <stdlib.h> // exit()
+
+
+static int _dblBuf[] = {
+ GLX_RGBA,
+ //GLX_DEPTH_SIZE, 4,
+ GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 3,
+ GLX_GREEN_SIZE, 3,
+ GLX_BLUE_SIZE, 3,
+ GLX_STENCIL_SIZE, 1,
+ None
+};
+
+static Display *_dpy;
+static Window _win;
+static XVisualInfo *_vi;
+static GLXContext _cx;
+
+static int _ogr_loadLayer_cb(const char *layername, void *ogrLayer)
+{
+ S52_loadLayer(layername, ogrLayer);
+
+ return 1;
+}
+
+static int _loadCell(const char *filename)
+{
+ S52_loadCell(filename, _ogr_loadLayer_cb);
+
+ return 1;
+}
+
+
+static int _setupData(int loadData)
+{
+ // setup env. var for OGR/S57
+ char *env = g_getenv("OGR_S57_OPTIONS");
+
+ if (!env ||
+ NULL == strstr(env, "UPDATES:ON") ||
+ NULL == strstr(env, "LNAM_REFS:ON") ||
+ NULL == strstr(env, "SPLIT_MULTIPOINT:ON"))
+ {
+#ifdef SOLARIS
+ putenv("OGR_S57_OPTIONS=LNAM_REFS:ON,UPDATES:ON,SPLIT_MULTIPOINT:ON");
+#else
+ setenv("OGR_S57_OPTIONS", "LNAM_REFS:ON,UPDATES:ON,SPLIT_MULTIPOINT:ON", 1);
+#endif
+ }
+
+
+ valueBuf chartPath = {'\0'};
+ if (0 == S52_getConfig(CONF_CHART, &chartPath)) {
+ printf(" .. exiting !\n");
+ exit(0);
+ } else {
+ _loadCell(chartPath);
+ }
+
+ return 1;
+}
+
+static int _initX()
+{
+ Colormap cmap;
+ XSetWindowAttributes swa;
+
+ // create an X colormap since probably not using default visual
+ cmap = XCreateColormap(_dpy, RootWindow(_dpy, _vi->screen),
+ _vi->visual, AllocNone);
+ swa.colormap = cmap;
+ swa.border_pixel = 0;
+ swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
+ // create an X window with the selected visual
+ _win = XCreateWindow(_dpy, RootWindow(_dpy, _vi->screen),
+ 0, 0, 493, 493, 0, _vi->depth,
+ InputOutput, _vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &swa);
+ XSetStandardProperties(_dpy, _win, "S52glxsimple", "S52glxsimple",
+ //None, argv, argc, NULL);
+ None, NULL, 0, NULL);
+
+
+ // request the X window to be displayed on the screen
+ XMapWindow(_dpy, _win);
+
+ return TRUE;
+}
+
+static int _initGLX()
+{
+ int dummy;
+
+ // make sure OpenGL's GLX extension supported
+ if (!glXQueryExtension(_dpy, &dummy, &dummy)) {
+ perror("X server has no OpenGL GLX extension");
+ exit(0);
+ }
+
+ // find an appropriate visual
+ // find an OpenGL-capable RGB visual with depth buffer
+ _vi = glXChooseVisual(_dpy, DefaultScreen(_dpy), _dblBuf);
+ if (_vi == NULL) {
+ PRINTF("ERROR: no RGBA visual");
+ exit(0);
+ }
+
+ if (_vi->class != TrueColor) {
+ perror("TrueColor visual required for this program");
+ exit(0);
+ }
+
+ // create an OpenGL rendering context
+ _cx = glXCreateContext(_dpy, _vi,
+ None, // no sharing of display lists
+ GL_TRUE); // direct rendering if possible
+ if (_cx == NULL) {
+ perror("could not create GLX rendering context");
+ exit(0);
+ }
+
+ _initX();
+
+ return TRUE;
+}
+
+int main(int argc, char* argv[])
+{
+ // open a connection to the X server
+ _dpy = XOpenDisplay(NULL);
+ if (_dpy == NULL) {
+ perror("could not open display");
+ exit(0);
+ }
+
+ _initGLX();
+
+ // bind the rendering context to the window
+ glXMakeCurrent(_dpy, _win, _cx);
+
+ S52_GL_init(_dpy, 0);
+ _setupData(1);
+
+ if (!S52_GL_validCtx()) {
+ printf("not a proper context. Exiting ...");
+ exit(1);
+ }
+
+ // main loop
+ while (1) {
+ XEvent event;
+
+ do {
+ XNextEvent(_dpy, &event);
+ switch (event.type) {
+ case ConfigureNotify:
+ ;// glViewport(0, 0, event.xconfigure.width, event.xconfigure.height);
+ }
+ } while (XPending(_dpy));
+
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ S52_draw();
+
+ glXSwapBuffers(_dpy, _win);
+ //glXMakeCurrent(_dpy, _win, _cx);
+ //glFlush();
+ }
+
+ return 1;
+}
+
+
+
Added: packages/openev/branches/upstream/current/contrib/S52/S52raz-3.2.rle
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52raz-3.2.rle (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52raz-3.2.rle 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,16123 @@
+; S52raz-3.2.rle: rasterazing rule
+;
+;
+;
+COLS 21CS00002NILDAY_BRIGHT
+CCIE 30NODTA0.28000.310045.00grey
+CCIE 32CURSR0.50000.400032.00orange
+CCIE 30CHBLK0.28000.31000.00black
+CCIE 30CHGRD0.28000.310025.00grey
+CCIE 30CHGRF0.28000.310045.00grey
+CCIE 29CHRED0.48000.300025.00red
+CCIE 31CHGRN0.30000.520060.00green
+CCIE 32CHYLW0.41000.470070.00yellow
+CCIE 33CHMGD0.30000.170020.00magenta
+CCIE 33CHMGF0.28000.240048.00magenta
+CCIE 31CHBRN0.42000.450030.00brown
+CCIE 31CHWHT0.28000.310080.00white
+CCIE 32SCLBR0.50000.400032.00orange
+CCIE 32CHCOR0.50000.400032.00orange
+CCIE 29LITRD0.48000.300025.00red
+CCIE 31LITGN0.30000.520060.00green
+CCIE 32LITYW0.41000.470070.00yellow
+CCIE 33ISDNG0.30000.170020.00magenta
+CCIE 29DNGHL0.48000.300025.00red
+CCIE 33TRFCD0.30000.170020.00magenta
+CCIE 33TRFCF0.28000.240048.00magenta
+CCIE 31LANDA0.36000.400049.00brown
+CCIE 31LANDF0.45000.450015.00brown
+CCIE 30CSTLN0.28000.310010.00grey
+CCIE 30SNDG10.28000.310025.00grey
+CCIE 30SNDG20.28000.31000.00black
+CCIE 30DEPSC0.28000.310010.00grey
+CCIE 30DEPCN0.28000.310025.00grey
+CCIE 31DEPDW0.28000.310080.00white
+CCIE 35DEPMD0.27000.300065.00pale_blue
+CCIE 36DEPMS0.24000.260055.00light_blue
+CCIE 37DEPVS0.22000.240045.00medium_blue
+CCIE 38DEPIT0.28000.360040.00yellow-green
+CCIE 31RADHI0.30000.520060.00green
+CCIE 31RADLO0.30000.520020.00green
+CCIE 36ARPAT0.26000.420030.00blue-green
+CCIE 32NINFO0.50000.400032.00orange
+CCIE 30RESBL0.18000.150022.00blue
+CCIE 32ADINF0.41000.470035.00yellow
+CCIE 30RESGR0.28000.310025.00grey
+CCIE 30SHIPS0.28000.31000.00black
+CCIE 30PSTRK0.28000.31000.00black
+CCIE 30SYTRK0.28000.310025.00grey
+CCIE 29PLRTE0.58000.350018.00red
+CCIE 32APLRT0.50000.400032.00orange
+CCIE 30UINFD0.28000.31000.00black
+CCIE 30UINFF0.28000.310025.00grey
+CCIE 31UIBCK0.28000.310080.00white
+CCIE 37UIAFD0.22000.240045.00medium_blue
+CCIE 29UINFR0.48000.300025.00red
+CCIE 31UINFG0.30000.520060.00green
+CCIE 32UINFO0.50000.400032.00orange
+CCIE 30UINFB0.18000.150022.00blue
+CCIE 33UINFM0.30000.170020.00magenta
+CCIE 30UIBDR0.28000.310025.00grey
+CCIE 31UIAFF0.36000.400049.00brown
+CCIE 30OUTLW0.28000.31000.00black
+CCIE 31OUTLL0.36000.400049.00brown
+CCIE 30RES010.28000.310045.00grey
+CCIE 30RES020.28000.310045.00grey
+CCIE 30RES030.28000.310045.00grey
+CCIE 31BKAJ10.28000.31000.000black
+CCIE 30BKAJ20.28000.31001.600grey
+**** 0
+0001 500003
+COLS 24CS00003NILDAY_BLACKBACK
+CCIE 30NODTA0.28000.310025.00grey
+CCIE 32CURSR0.50000.400028.00orange
+CCIE 30CHBLK0.28000.310045.00grey
+CCIE 30CHGRD0.28000.310045.00grey
+CCIE 30CHGRF0.28000.310025.00grey
+CCIE 29CHRED0.48000.300025.00red
+CCIE 31CHGRN0.30000.520060.00green
+CCIE 32CHYLW0.41000.470070.00yellow
+CCIE 33CHMGD0.28000.240053.00magenta
+CCIE 33CHMGF0.30000.170015.00magenta
+CCIE 31CHBRN0.42000.450025.00brown
+CCIE 31CHWHT0.28000.310080.00white
+CCIE 32SCLBR0.50000.400028.00orange
+CCIE 32CHCOR0.50000.400028.00orange
+CCIE 29LITRD0.48000.300025.00red
+CCIE 31LITGN0.30000.520060.00green
+CCIE 32LITYW0.41000.470070.00yellow
+CCIE 33ISDNG0.28000.240053.00magenta
+CCIE 29DNGHL0.48000.300025.00red
+CCIE 33TRFCD0.28000.240053.00magenta
+CCIE 33TRFCF0.30000.170015.00magenta
+CCIE 31LANDA0.36000.400020.00brown
+CCIE 31LANDF0.45000.450045.00brown
+CCIE 30CSTLN0.28000.310045.00grey
+CCIE 30SNDG10.28000.310025.00grey
+CCIE 31SNDG20.28000.310080.00white
+CCIE 30DEPSC0.28000.310045.00grey
+CCIE 30DEPCN0.28000.310025.00grey
+CCIE 30DEPDW0.28000.31000.00black
+CCIE 34DEPMD0.27000.30002.00dark_blue
+CCIE 36DEPMS0.24000.26008.00medium_blue
+CCIE 36DEPVS0.22000.240014.00light_blue
+CCIE 38DEPIT0.26000.360014.00yellow-green
+CCIE 31RADHI0.30000.520060.00green
+CCIE 31RADLO0.30000.520020.00green
+CCIE 36ARPAT0.26000.420050.00blue-green
+CCIE 32NINFO0.50000.400028.00orange
+CCIE 30RESBL0.18000.150022.00blue
+CCIE 32ADINF0.41000.470035.00yellow
+CCIE 30RESGR0.28000.310025.00grey
+CCIE 31SHIPS0.28000.310080.00white
+CCIE 31PSTRK0.28000.310080.00white
+CCIE 30SYTRK0.28000.310025.00grey
+CCIE 29PLRTE0.58000.350018.00red
+CCIE 32APLRT0.50000.400028.00orange
+CCIE 31UINFD0.28000.310080.00white
+CCIE 30UINFF0.28000.310025.00grey
+CCIE 30UIBCK0.28000.31000.00black
+CCIE 36UIAFD0.22000.240014.00light_blue
+CCIE 29UINFR0.48000.300025.00red
+CCIE 31UINFG0.30000.520060.00green
+CCIE 32UINFO0.50000.400028.00orange
+CCIE 30UINFB0.18000.150022.00blue
+CCIE 33UINFM0.30000.170015.00magenta
+CCIE 30UIBDR0.28000.310045.00grey
+CCIE 31UIAFF0.36000.400020.00brown
+CCIE 30OUTLW0.28000.31000.00black
+CCIE 31OUTLL0.36000.400020.00brown
+CCIE 30RES010.28000.310025.00grey
+CCIE 30RES020.28000.310025.00grey
+CCIE 30RES030.28000.310025.00grey
+CCIE 31BKAJ10.28000.31000.000black
+CCIE 30BKAJ20.28000.31001.600grey
+**** 0
+0001 500004
+COLS 24CS00004NILDAY_WHITEBACK
+CCIE 31NODTA0.28000.310031.500grey
+CCIE 33CURSR0.50000.400022.400orange
+CCIE 31CHBLK0.28000.31000.000black
+CCIE 31CHGRD0.28000.310017.500grey
+CCIE 31CHGRF0.28000.310031.500grey
+CCIE 30CHRED0.48000.300017.500red
+CCIE 32CHGRN0.30000.520042.000green
+CCIE 33CHYLW0.41000.470049.000yellow
+CCIE 34CHMGD0.30000.170014.000magenta
+CCIE 34CHMGF0.28000.240033.600magenta
+CCIE 32CHBRN0.42000.450021.000brown
+CCIE 32CHWHT0.28000.310056.000white
+CCIE 33SCLBR0.50000.400022.400orange
+CCIE 33CHCOR0.50000.400022.400orange
+CCIE 30LITRD0.48000.300017.500red
+CCIE 32LITGN0.30000.520042.000green
+CCIE 33LITYW0.41000.470049.000yellow
+CCIE 34ISDNG0.30000.170014.000magenta
+CCIE 30DNGHL0.48000.300017.500red
+CCIE 34TRFCD0.30000.170014.000magenta
+CCIE 34TRFCF0.28000.240033.600magenta
+CCIE 32LANDA0.36000.400034.300brown
+CCIE 32LANDF0.45000.450010.500brown
+CCIE 30CSTLN0.28000.31007.000grey
+CCIE 31SNDG10.28000.310017.500grey
+CCIE 31SNDG20.28000.31000.000black
+CCIE 30DEPSC0.28000.31007.000grey
+CCIE 31DEPCN0.28000.310017.500grey
+CCIE 32DEPDW0.28000.310056.000white
+CCIE 36DEPMD0.27000.300045.500pale_blue
+CCIE 37DEPMS0.24000.260038.500light_blue
+CCIE 38DEPVS0.22000.240031.500medium_blue
+CCIE 39DEPIT0.28000.360028.000yellow-green
+CCIE 32RADHI0.30000.520042.000green
+CCIE 32RADLO0.30000.520014.000green
+CCIE 37ARPAT0.26000.420021.000blue-green
+CCIE 33NINFO0.50000.400022.400orange
+CCIE 31RESBL0.18000.150015.400blue
+CCIE 33ADINF0.41000.470024.500yellow
+CCIE 31RESGR0.28000.310017.500grey
+CCIE 31SHIPS0.28000.31000.000black
+CCIE 31PSTRK0.28000.31000.000black
+CCIE 31SYTRK0.28000.310017.500grey
+CCIE 30PLRTE0.58000.350018.000red
+CCIE 33APLRT0.50000.400022.400orange
+CCIE 31UINFD0.28000.31000.000black
+CCIE 31UINFF0.28000.310017.500grey
+CCIE 32UIBCK0.28000.310056.000white
+CCIE 38UIAFD0.22000.240031.500medium_blue
+CCIE 30UINFR0.48000.300017.500red
+CCIE 32UINFG0.30000.520042.000green
+CCIE 33UINFO0.50000.400022.400orange
+CCIE 31UINFB0.18000.150015.400blue
+CCIE 34UINFM0.30000.170014.000magenta
+CCIE 31UIBDR0.28000.310017.500grey
+CCIE 32UIAFF0.36000.400034.300brown
+CCIE 30OUTLW0.28000.31000.00black
+CCIE 32OUTLL0.36000.400034.300brown
+CCIE 31RES010.28000.310031.500grey
+CCIE 31RES020.28000.310031.500grey
+CCIE 31RES030.28000.310031.500grey
+CCIE 32BKAJ10.28000.31000.0000black
+CCIE 31BKAJ20.28000.31001.1200grey
+**** 0
+0001 500005
+COLS 15CS00005NILDUSK
+CCIE 30NODTA0.28000.31002.250grey
+CCIE 32CURSR0.50000.39002.520orange
+CCIE 30CHBLK0.28000.31004.050grey
+CCIE 30CHGRD0.28000.31004.050grey
+CCIE 30CHGRF0.28000.31002.250grey
+CCIE 29CHRED0.48000.30002.250red
+CCIE 31CHGRN0.30000.52005.400green
+CCIE 32CHYLW0.41000.47006.300yellow
+CCIE 33CHMGD0.28000.24004.770magenta
+CCIE 34CHMGF0.30000.17001.3500magenta
+CCIE 31CHBRN0.42000.45002.250brown
+CCIE 31CHWHT0.28000.31007.200white
+CCIE 32SCLBR0.50000.39002.520orange
+CCIE 32CHCOR0.50000.39002.520orange
+CCIE 29LITRD0.48000.30002.250red
+CCIE 31LITGN0.30000.52005.400green
+CCIE 32LITYW0.41000.47006.300yellow
+CCIE 33ISDNG0.28000.24004.770magenta
+CCIE 29DNGHL0.48000.30002.250red
+CCIE 33TRFCD0.28000.24004.770magenta
+CCIE 34TRFCF0.30000.17001.3500magenta
+CCIE 31LANDA0.36000.40001.800brown
+CCIE 31LANDF0.45000.45004.050brown
+CCIE 30CSTLN0.28000.31004.050grey
+CCIE 31SNDG10.28000.31002.2500grey
+CCIE 31SNDG20.28000.31007.200white
+CCIE 30DEPSC0.28000.31004.050grey
+CCIE 30DEPCN0.28000.31002.250grey
+CCIE 31DEPDW0.28000.31000.000black
+CCIE 35DEPMD0.27000.30000.180dark_blue
+CCIE 37DEPMS0.24000.26000.720medium_blue
+CCIE 36DEPVS0.22000.24001.260light_blue
+CCIE 38DEPIT0.26000.36001.260yellow-green
+CCIE 31RADHI0.30000.52005.400green
+CCIE 31RADLO0.30000.52001.800green
+CCIE 36ARPAT0.26000.42004.500blue-green
+CCIE 32NINFO0.50000.39002.520orange
+CCIE 30RESBL0.18000.15001.980blue
+CCIE 32ADINF0.41000.47003.150yellow
+CCIE 30RESGR0.28000.31002.250grey
+CCIE 31SHIPS0.28000.31007.200white
+CCIE 31PSTRK0.28000.31007.200white
+CCIE 31SYTRK0.28000.31002.2500grey
+CCIE 29PLRTE0.58000.35001.620red
+CCIE 32APLRT0.50000.39002.520orange
+CCIE 31UINFD0.28000.31007.200white
+CCIE 31UINFF0.28000.31002.2500grey
+CCIE 31UIBCK0.28000.31000.000black
+CCIE 36UIAFD0.22000.24001.260light_blue
+CCIE 29UINFR0.48000.30002.250red
+CCIE 31UINFG0.30000.52005.400green
+CCIE 32UINFO0.50000.39002.520orange
+CCIE 30UINFB0.18000.15001.980blue
+CCIE 34UINFM0.30000.17001.3500magenta
+CCIE 30UIBDR0.28000.31004.050grey
+CCIE 31UIAFF0.36000.40001.800brown
+CCIE 30OUTLW0.28000.31000.00black
+CCIE 31OUTLL0.36000.40001.800brown
+CCIE 30RES010.28000.31002.250grey
+CCIE 30RES020.28000.31002.250grey
+CCIE 30RES030.28000.31002.250grey
+CCIE 31BKAJ10.28000.31000.000black
+CCIE 30BKAJ20.28000.31000.144grey
+**** 0
+0001 500006
+COLS 16CS00006NILNIGHT
+CCIE 30NODTA0.28000.31000.00black
+CCIE 31CURSR0.50000.40001.20orange
+CCIE 29CHBLK0.28000.31001.20grey
+CCIE 29CHGRD0.28000.31001.20grey
+CCIE 29CHGRF0.28000.31000.30grey
+CCIE 28CHRED0.58000.35001.00red
+CCIE 30CHGRN0.34000.54001.00green
+CCIE 31CHYLW0.43000.46001.20yellow
+CCIE 32CHMGD0.30000.17001.10magenta
+CCIE 32CHMGF0.30000.17001.10magenta
+CCIE 30CHBRN0.42000.45000.15brown
+CCIE 30CHWHT0.28000.31001.74white
+CCIE 31SCLBR0.50000.40001.20orange
+CCIE 31CHCOR0.50000.40001.20orange
+CCIE 28LITRD0.58000.35001.00red
+CCIE 30LITGN0.34000.54001.00green
+CCIE 31LITYW0.43000.46001.20yellow
+CCIE 32ISDNG0.30000.17001.10magenta
+CCIE 28DNGHL0.58000.35001.00red
+CCIE 32TRFCD0.30000.17001.40magenta
+CCIE 32TRFCF0.30000.17001.10magenta
+CCIE 30LANDA0.36000.36000.10brown
+CCIE 30LANDF0.45000.45000.30brown
+CCIE 30CSTLN0.28000.31001.74white
+CCIE 29SNDG10.28000.31001.20grey
+CCIE 30SNDG20.28000.31002.46white
+CCIE 30DEPSC0.28000.31001.74white
+CCIE 29DEPCN0.28000.31001.20grey
+CCIE 30DEPDW0.28000.31000.00black
+CCIE 30DEPMD0.28000.31000.00black
+CCIE 34DEPMS0.16000.08000.04dark-blue
+CCIE 34DEPVS0.16000.08000.04dark-blue
+CCIE 37DEPIT0.28000.36000.10yellow-green
+CCIE 30RADHI0.34000.54001.00green
+CCIE 30RADLO0.34000.54000.20green
+CCIE 35ARPAT0.26000.42000.80blue-green
+CCIE 31NINFO0.50000.40001.20orange
+CCIE 29RESBL0.18000.13001.20blue
+CCIE 31ADINF0.43000.46001.20yellow
+CCIE 29RESGR0.28000.31000.30grey
+CCIE 30SHIPS0.28000.31001.74white
+CCIE 30PSTRK0.28000.31001.74white
+CCIE 29SYTRK0.28000.31001.20grey
+CCIE 28PLRTE0.58000.35001.30red
+CCIE 31APLRT0.50000.40001.20orange
+CCIE 29UINFD0.28000.31002.46grey
+CCIE 30UINFF0.28000.31001.20white
+CCIE 30UIBCK0.28000.31000.00black
+CCIE 34UIAFD0.16000.08000.04dark-blue
+CCIE 28UINFR0.58000.35001.00red
+CCIE 30UINFG0.34000.54001.00green
+CCIE 31UINFO0.50000.40001.20orange
+CCIE 29UINFB0.18000.13001.20blue
+CCIE 32UINFM0.30000.17001.10magenta
+CCIE 29UIBDR0.28000.31001.20grey
+CCIE 30UIAFF0.36000.36000.10brown
+CCIE 30OUTLW0.28000.31000.00black
+CCIE 30OUTLL0.36000.36000.10brown
+CCIE 30RES010.28000.31000.00black
+CCIE 30RES020.28000.31000.00black
+CCIE 30RES030.28000.31000.00black
+CCIE 30BKAJ10.28000.31000.00black
+CCIE 29BKAJ20.28000.31000.05grey
+**** 0
+0001 500007
+LUPT 40LU00007NIL######A00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 30AP(QUESMRK1);LS(DASH,1,CHMGD)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500008
+LUPT 40LU00008NILACHAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(ACHARE51);LS(DASH,2,CHMGF);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500009
+LUPT 40LU00009NILACHAREA00003SPLAIN_BOUNDARIES
+ATTC 8CATACH8
+INST 43SY(ACHARE02);LS(DASH,2,CHMGF);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500010
+LUPT 40LU00010NILACHBRTA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 78SY(ACHBRT07);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29);LS(DASH,2,CHMGF)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500011
+LUPT 40LU00011NILADMAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500012
+LUPT 40LU00012NILAIRAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30AP(AIRARE02);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500013
+LUPT 40LU00013NILAIRAREA00002SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 40AC(LANDA);AP(AIRARE02);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500014
+LUPT 40LU00014NILBERTHSA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 61SY(BRTHNO01);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500015
+LUPT 40LU00015NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 1
+INST 108TX(OBJNAM,3,1,2,'15110',1,0,CHBLK,21);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500016
+LUPT 40LU00016NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG2
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500017
+LUPT 40LU00017NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG3
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500018
+LUPT 40LU00018NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG4
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500019
+LUPT 40LU00019NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG5
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500020
+LUPT 40LU00020NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG7
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500021
+LUPT 40LU00021NILBRIDGEA00008OPLAIN_BOUNDARIES
+ATTC 8CATBRG8
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500022
+LUPT 40LU00022NILBUAAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622240
+**** 0
+0001 500023
+LUPT 40LU00023NILBUISGLA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500024
+LUPT 40LU00024NILBUISGLA00004SPLAIN_BOUNDARIES
+ATTC 17FUNCTN33CONVIS1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500025
+LUPT 40LU00025NILBUISGLA00004SPLAIN_BOUNDARIES
+ATTC 9FUNCTN33
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500026
+LUPT 40LU00026NILBUISGLA00004SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500027
+LUPT 40LU00027NILCANALSA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500028
+LUPT 40LU00028NILCANALSA00002SPLAIN_BOUNDARIES
+ATTC 7CONDTN
+INST 27AC(DEPVS);LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500029
+LUPT 40LU00029NILCAUSWYA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,CSTLN)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500030
+LUPT 40LU00030NILCAUSWYA00005SPLAIN_BOUNDARIES
+ATTC 8WATLEV4
+INST 27AC(DEPIT);LS(DASH,2,CSTLN)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500031
+LUPT 40LU00031NILCBLAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(CBLARE51);LS(DASH,2,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500032
+LUPT 40LU00032NILCHKPNTA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13SY(POSGEN04)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500033
+LUPT 40LU00033NILCONVYRA00008OPLAIN_BOUNDARIES
+ATTC 1
+INST 70TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500034
+LUPT 40LU00034NILCONVYRA00008OPLAIN_BOUNDARIES
+ATTC 8CONRAD1
+INST 83SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500035
+LUPT 40LU00035NILCONVYRA00008OPLAIN_BOUNDARIES
+ATTC 8CONRAD3
+INST 83SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500036
+LUPT 40LU00036NILCONZNEA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500037
+LUPT 40LU00037NILCOSAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636010
+**** 0
+0001 500038
+LUPT 40LU00038NILCRANESA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500039
+LUPT 40LU00039NILCRANESA00004SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500040
+LUPT 40LU00040NILCTNAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(CTNARE51);LS(DASH,2,TRFCD)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500041
+LUPT 40LU00041NILCTSAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(INFARE51);LS(DASH,1,CHMGF)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500042
+LUPT 40LU00042NILCUSZNEA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRF)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500043
+LUPT 40LU00043NILDAMCONA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500044
+LUPT 40LU00044NILDAMCONA00006SPLAIN_BOUNDARIES
+ATTC 8CATDAM3
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500045
+LUPT 40LU00045NILDEPAREA00001SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(DEPARE01)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500046
+LUPT 40LU00046NILDEPAREA00001SPLAIN_BOUNDARIES
+ATTC 16DRVAL1?DRVAL2?
+INST 40AC(NODTA);AP(PRTSUR01);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500047
+LUPT 40LU00047NILDMPGRDA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(INFARE51);LS(DASH,1,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 500048
+LUPT 40LU00048NILDMPGRDA00003SPLAIN_BOUNDARIES
+ATTC 8CATDPG5
+INST 30LS(DASH,1,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 500049
+LUPT 40LU00049NILDOCAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 65AC(DEPVS);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500050
+LUPT 40LU00050NILDOCAREA00002SPLAIN_BOUNDARIES
+ATTC 7CONDTN
+INST 65AC(DEPVS);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500051
+LUPT 40LU00051NILDRGAREA00001SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(DEPARE01)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500052
+LUPT 40LU00052NILDRYDOCA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(LANDA);LS(SOLD,1,CSTLN)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500053
+LUPT 40LU00053NILDWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 56SY(TSLDEF51);SY(DWRTPT51);LS(DASH,3,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500054
+LUPT 40LU00054NILDWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 63SY(TSSLPT51,ORIENT);SY(DWRTPT51);LS(DASH,3,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500055
+LUPT 40LU00055NILDWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 63SY(TSSLPT51,ORIENT);SY(DWRTPT51);LS(DASH,3,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500056
+LUPT 40LU00056NILDWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 63SY(TSSLPT51,ORIENT);SY(DWRTPT51);LS(DASH,3,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500057
+LUPT 40LU00057NILDWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 63SY(DWRUTE51,ORIENT);SY(DWRTPT51);LS(DASH,3,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500058
+LUPT 40LU00058NILDYKCONA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500059
+LUPT 40LU00059NILEXEZNEA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500060
+LUPT 40LU00060NILFAIRWYA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500061
+LUPT 40LU00061NILFAIRWYA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 50SY(FAIRWY51,ORIENT);LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500062
+LUPT 40LU00062NILFAIRWYA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 50SY(FAIRWY51,ORIENT);LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500063
+LUPT 40LU00063NILFAIRWYA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 50SY(FAIRWY51,ORIENT);LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500064
+LUPT 40LU00064NILFAIRWYA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 50SY(FAIRWY52,ORIENT);LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500065
+LUPT 40LU00065NILFERYRTA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(FRYARE51);LS(DASH,2,CHMGD)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500066
+LUPT 40LU00066NILFERYRTA00003SPLAIN_BOUNDARIES
+ATTC 8CATFRY2
+INST 30SY(FRYARE52);LS(DASH,2,CHBLK)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500067
+LUPT 40LU00067NILFLODOCA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500068
+LUPT 40LU00068NILFORSTCA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500069
+LUPT 40LU00069NILFORSTCA00004SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500070
+LUPT 40LU00070NILFRPAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500071
+LUPT 40LU00071NILFSHFACA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30AP(FSHHAV02);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500072
+LUPT 40LU00072NILFSHFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATFIF1
+INST 30AP(FSHFAC03);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500073
+LUPT 40LU00073NILFSHFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATFIF2
+INST 30AP(FSHFAC04);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500074
+LUPT 40LU00074NILFSHFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATFIF3
+INST 30AP(FSHFAC04);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500075
+LUPT 40LU00075NILFSHFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATFIF4
+INST 30AP(FSHFAC04);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500076
+LUPT 40LU00076NILFSHGRDA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(FSHGRD01);LS(DASH,2,CHGRF)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500077
+LUPT 40LU00077NILFSHZNEA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636040
+**** 0
+0001 500078
+LUPT 40LU00078NILGATCONA00008SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500079
+LUPT 40LU00079NILGRIDRNA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 632460
+**** 0
+0001 500080
+LUPT 40LU00080NILHRBAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500081
+LUPT 40LU00081NILHRBFACA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500082
+LUPT 40LU00082NILHRBFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATHAF1
+INST 13SY(ROLROL01)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500083
+LUPT 40LU00083NILHRBFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATHAF4
+INST 13SY(HRBFAC09)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500084
+LUPT 40LU00084NILHRBFACA00004SPLAIN_BOUNDARIES
+ATTC 8CATHAF5
+INST 13SY(SMCFAC02)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500085
+LUPT 40LU00085NILHULKESA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500086
+LUPT 40LU00086NILICEAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 40AC(NODTA);AP(ICEARE04);LS(DASH,1,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500087
+LUPT 40LU00087NILICNAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(INFARE51);LS(DASH,1,CHMGF);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500088
+LUPT 40LU00088NILISTZNEA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(ITZARE51);LS(DASH,1,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500089
+LUPT 40LU00089NILLAKAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500090
+LUPT 40LU00090NILLNDAREA00001SPLAIN_BOUNDARIES
+ATTC 1
+INST 10AC(LANDA)
+DISC 12DISPLAYBASE
+LUCM 612010
+**** 0
+0001 500091
+LUPT 40LU00091NILLNDMRKA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500092
+LUPT 40LU00092NILLNDMRKA00004SPLAIN_BOUNDARIES
+ATTC 26CATLMK17FUNCTN33CONVIS1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500093
+LUPT 40LU00093NILLNDMRKA00004SPLAIN_BOUNDARIES
+ATTC 18CATLMK17FUNCTN33
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500094
+LUPT 40LU00094NILLNDMRKA00004SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500095
+LUPT 40LU00095NILLNDRGNA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500096
+LUPT 40LU00096NILLNDRGNA00003SPLAIN_BOUNDARIES
+ATTC 8CATLND2
+INST 13AP(MARSHES1)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500097
+LUPT 40LU00097NILLNDRGNA00003SPLAIN_BOUNDARIES
+ATTC 9CATLND12
+INST 13AP(MARSHES1)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500098
+LUPT 40LU00098NILLOCMAGA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(LOCMAG51);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500099
+LUPT 40LU00099NILLOGPONA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500100
+LUPT 40LU00100NILLOKBSNA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500101
+LUPT 40LU00101NILM_ACCYA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500102
+LUPT 40LU00102NILM_COVRA00001SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(DATCVR01)
+DISC 6OTHER
+LUCM 631040
+**** 0
+0001 500103
+LUPT 40LU00103NILM_CSCLA00001SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(DATCVR01)
+DISC 6OTHER
+LUCM 631040
+**** 0
+0001 500104
+LUPT 40LU00104NILM_HOPAA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500105
+LUPT 40LU00105NILM_NPUBA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500106
+LUPT 40LU00106NILM_NSYSA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13LC(MARSYS51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500107
+LUPT 40LU00107NILM_NSYSA00004SPLAIN_BOUNDARIES
+ATTC 15MARSYS1ORIENT
+INST 37SY(DIRBOYA1,ORIENT);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500108
+LUPT 40LU00108NILM_NSYSA00004SPLAIN_BOUNDARIES
+ATTC 15MARSYS2ORIENT
+INST 37SY(DIRBOYB1,ORIENT);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500109
+LUPT 40LU00109NILM_NSYSA00004SPLAIN_BOUNDARIES
+ATTC 7ORIENT
+INST 37SY(DIRBOY01,ORIENT);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500110
+LUPT 40LU00110NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30AP(NODATA03);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500111
+LUPT 40LU00111NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC1
+INST 30AP(DQUALA11);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500112
+LUPT 40LU00112NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC2
+INST 30AP(DQUALA21);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500113
+LUPT 40LU00113NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC3
+INST 30AP(DQUALB01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500114
+LUPT 40LU00114NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC4
+INST 30AP(DQUALC01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500115
+LUPT 40LU00115NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC5
+INST 30AP(DQUALD01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500116
+LUPT 40LU00116NILM_QUALA00004SPLAIN_BOUNDARIES
+ATTC 8CATZOC6
+INST 30AP(DQUALU01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500117
+LUPT 40LU00117NILM_SDATA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500118
+LUPT 40LU00118NILM_SRELA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500119
+LUPT 40LU00119NILM_VDATA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500120
+LUPT 40LU00120NILMAGVARA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13SY(MAGVAR51)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500121
+LUPT 40LU00121NILMARCULA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43AP(MARCUL02);LS(DASH,1,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500122
+LUPT 40LU00122NILMIPAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(CTYARE51);LS(DASH,2,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500123
+LUPT 40LU00123NILMORFACA00006SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500124
+LUPT 40LU00124NILOBSTRNA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500125
+LUPT 40LU00125NILOBSTRNA00004SPLAIN_BOUNDARIES
+ATTC 8CATOBS6
+INST 43CS(OBSTRN04);AP(FOULAR01);LS(DOTT,2,CHBLK)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500126
+LUPT 40LU00126NILOBSTRNA00004SPLAIN_BOUNDARIES
+ATTC 8CATOBS7
+INST 30SY(FOULGND1);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500127
+LUPT 40LU00127NILOFSPLFA00005OPLAIN_BOUNDARIES
+ATTC 1
+INST 78AC(CHBRN);LS(SOLD,4,CSTLN);TE('Prod %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500128
+LUPT 40LU00128NILOSPAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(CTYARE51);LS(DASH,2,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500129
+LUPT 40LU00129NILPILBOPA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(PILBOP02);LS(DASH,2,TRFCF)
+DISC 9STANDARD
+LUCM 628010
+**** 0
+0001 500130
+LUPT 40LU00130NILPIPAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(INFARE51);LS(DASH,2,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500131
+LUPT 40LU00131NILPIPAREA00003SPLAIN_BOUNDARIES
+ATTC 8CATPIP2
+INST 43SY(INFARE51);LS(DASH,2,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500132
+LUPT 40LU00132NILPIPAREA00003SPLAIN_BOUNDARIES
+ATTC 8CATPIP3
+INST 43SY(INFARE51);LS(DASH,2,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500133
+LUPT 40LU00133NILPIPAREA00003SPLAIN_BOUNDARIES
+ATTC 8PRODCT3
+INST 43SY(INFARE51);LS(DASH,2,CHGRD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500134
+LUPT 40LU00134NILPONTONA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500135
+LUPT 40LU00135NILPRCAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(PRCARE51);LS(DASH,2,TRFCD);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500136
+LUPT 40LU00136NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500137
+LUPT 40LU00137NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 16CATPRA5CONVIS1
+INST 30SY(RFNERY11);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500138
+LUPT 40LU00138NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 16CATPRA8CONVIS1
+INST 30SY(TNKFRM11);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500139
+LUPT 40LU00139NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 16CATPRA9CONVIS1
+INST 30SY(WNDFRM61);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500140
+LUPT 40LU00140NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 8CATPRA1
+INST 30SY(QUARRY01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500141
+LUPT 40LU00141NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 8CATPRA5
+INST 30SY(RFNERY01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500142
+LUPT 40LU00142NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 8CATPRA6
+INST 30SY(TMBYRD01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500143
+LUPT 40LU00143NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 8CATPRA8
+INST 30SY(TNKFRM01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500144
+LUPT 40LU00144NILPRDAREA00004SPLAIN_BOUNDARIES
+ATTC 8CATPRA9
+INST 30SY(WNDFRM51);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500145
+LUPT 40LU00145NILPYLONSA00008SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500146
+LUPT 40LU00146NILRADRNGA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,TRFCF)
+DISC 9STANDARD
+LUCM 625040
+**** 0
+0001 500147
+LUPT 40LU00147NILRAPIDSA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 10AC(CHGRD)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500148
+LUPT 40LU00148NILRCTLPTA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13SY(RTLDEF51)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500149
+LUPT 40LU00149NILRCTLPTA00004SPLAIN_BOUNDARIES
+ATTC 7ORIENT
+INST 20SY(RCTLPT52,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500150
+LUPT 40LU00150NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(RECDEF51);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500151
+LUPT 40LU00151NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC1
+INST 91SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500152
+LUPT 40LU00152NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC2
+INST 91SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500153
+LUPT 40LU00153NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC3
+INST 91SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500154
+LUPT 40LU00154NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC4
+INST 91SY(RECTRC56,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500155
+LUPT 40LU00155NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC1
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500156
+LUPT 40LU00156NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC2
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500157
+LUPT 40LU00157NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC3
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500158
+LUPT 40LU00158NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC4
+INST 91SY(RECTRC55,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500159
+LUPT 40LU00159NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500160
+LUPT 40LU00160NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500161
+LUPT 40LU00161NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 91SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500162
+LUPT 40LU00162NILRECTRCA00006SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 91SY(RECTRC55,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500163
+LUPT 40LU00163NILRESAREA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(RESARE02)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 500164
+LUPT 40LU00164NILRIVERSA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500165
+LUPT 40LU00165NILROADWYA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(LANDA);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500166
+LUPT 40LU00166NILRUNWAYA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 10AC(CHBRN)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500167
+LUPT 40LU00167NILRUNWAYA00005SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500168
+LUPT 40LU00168NILSBDAREA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500169
+LUPT 40LU00169NILSBDAREA00003SPLAIN_BOUNDARIES
+ATTC 15WATLEV3NATSUR
+INST 55TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500170
+LUPT 40LU00170NILSBDAREA00003SPLAIN_BOUNDARIES
+ATTC 16WATLEV4NATSUR9
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500171
+LUPT 40LU00171NILSBDAREA00003SPLAIN_BOUNDARIES
+ATTC 17WATLEV4NATSUR11
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500172
+LUPT 40LU00172NILSBDAREA00003SPLAIN_BOUNDARIES
+ATTC 17WATLEV4NATSUR14
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500173
+LUPT 40LU00173NILSBDAREA00003SPLAIN_BOUNDARIES
+ATTC 15WATLEV4NATSUR
+INST 55TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500174
+LUPT 40LU00174NILSEAAREA00003SPLAIN_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500175
+LUPT 40LU00175NILSILTNKA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500176
+LUPT 40LU00176NILSILTNKA00004SPLAIN_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500177
+LUPT 40LU00177NILSLCONSA00007OPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(SLCONS03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500178
+LUPT 40LU00178NILSLOGRDA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500179
+LUPT 40LU00179NILSLOGRDA00003SPLAIN_BOUNDARIES
+ATTC 8CATSLO6
+INST 10AC(CHGRD)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500180
+LUPT 40LU00180NILSMCFACA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 40AC(CHBRN);SY(SMCFAC02);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 638210
+**** 0
+0001 500181
+LUPT 40LU00181NILSNDWAVA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30AP(SNDWAV01);LS(DASH,2,CHGRD)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500182
+LUPT 40LU00182NILSPLAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(CTYARE51);LS(DASH,1,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500183
+LUPT 40LU00183NILSUBTLNA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 43SY(CTYARE51);LS(DASH,1,CHMGD);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500184
+LUPT 40LU00184NILSWPAREA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 88SY(SWPARE51);TE('swept to %5.1lf','DRVAL1',1,2,2,'15110',0,1,CHBLK,27);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 623030
+**** 0
+0001 500185
+LUPT 40LU00185NILT_HMONA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDEHT01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500186
+LUPT 40LU00186NILT_NHMNA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDEHT01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500187
+LUPT 40LU00187NILT_TIMSA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDEHT01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500188
+LUPT 40LU00188NILTS_FEBA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(CURDEF01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500189
+LUPT 40LU00189NILTS_FEBA00004SPLAIN_BOUNDARIES
+ATTC 15CAT_TS1ORIENT
+INST 73SY(FLDSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500190
+LUPT 40LU00190NILTS_FEBA00004SPLAIN_BOUNDARIES
+ATTC 15CAT_TS2ORIENT
+INST 73SY(EBBSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500191
+LUPT 40LU00191NILTS_FEBA00004SPLAIN_BOUNDARIES
+ATTC 15CAT_TS3ORIENT
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500192
+LUPT 40LU00192NILTS_PADA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDSTR01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500193
+LUPT 40LU00193NILTS_PNHA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDSTR01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500194
+LUPT 40LU00194NILTS_PRHA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDSTR01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500195
+LUPT 40LU00195NILTS_TISA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TIDSTR01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500196
+LUPT 40LU00196NILTESAREA00002SPLAIN_BOUNDARIES
+ATTC 1
+INST 30LS(DASH,2,CHGRF);CS(RESTRN01)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500197
+LUPT 40LU00197NILTIDEWYA00007SPLAIN_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,25)
+DISC 6OTHER
+LUCM 632070
+**** 0
+0001 500198
+LUPT 40LU00198NILTSEZNEA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 12AC(TRFCF,3)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500199
+LUPT 40LU00199NILTSSCRSA00006SPLAIN_BOUNDARIES
+ATTC 1
+INST 39AP(TSSJCT02);SY(TSSCRS51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500200
+LUPT 40LU00200NILTSSLPTA00006SPLAIN_BOUNDARIES
+ATTC 1
+INST 65SY(CTNARE51);TX(INFORM,1,1,2,'15110',0,-2,CHBLK,24);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500201
+LUPT 40LU00201NILTSSLPTA00006SPLAIN_BOUNDARIES
+ATTC 7ORIENT
+INST 33SY(TSSLPT51,ORIENT);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500202
+LUPT 40LU00202NILTSSRONA00006SPLAIN_BOUNDARIES
+ATTC 1
+INST 26SY(TSSRON51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500203
+LUPT 40LU00203NILTUNNELA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500204
+LUPT 40LU00204NILTUNNELA00004SPLAIN_BOUNDARIES
+ATTC 8BURDEP0
+INST 27AC(DEPVS);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500205
+LUPT 40LU00205NILTWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(TWRDEF51);LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500206
+LUPT 40LU00206NILTWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 37SY(TWRTPT53,ORIENT);LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500207
+LUPT 40LU00207NILTWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 37SY(TWRTPT53,ORIENT);LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500208
+LUPT 40LU00208NILTWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 37SY(TWRTPT53,ORIENT);LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500209
+LUPT 40LU00209NILTWRTPTA00004SPLAIN_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 37SY(TWRTPT52,ORIENT);LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500210
+LUPT 40LU00210NILUNSAREA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 40AC(NODTA);AP(NODATA03);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 611050
+**** 0
+0001 500211
+LUPT 40LU00211NILVEGATNA00000SPLAIN_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500212
+LUPT 40LU00212NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 8CATVEG7
+INST 30AP(VEGATN04);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500213
+LUPT 40LU00213NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG21
+INST 30AP(VEGATN04);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500214
+LUPT 40LU00214NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 8CATVEG3
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500215
+LUPT 40LU00215NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 8CATVEG4
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500216
+LUPT 40LU00216NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 8CATVEG5
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500217
+LUPT 40LU00217NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 8CATVEG6
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500218
+LUPT 40LU00218NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG13
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500219
+LUPT 40LU00219NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG14
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500220
+LUPT 40LU00220NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG15
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500221
+LUPT 40LU00221NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG16
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500222
+LUPT 40LU00222NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG17
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500223
+LUPT 40LU00223NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG18
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500224
+LUPT 40LU00224NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG19
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500225
+LUPT 40LU00225NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG20
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500226
+LUPT 40LU00226NILVEGATNA00003SPLAIN_BOUNDARIES
+ATTC 9CATVEG22
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500227
+LUPT 40LU00227NILWATTURA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(WATTUR02);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633040
+**** 0
+0001 500228
+LUPT 40LU00228NILWEDKLPA00003OPLAIN_BOUNDARIES
+ATTC 1
+INST 30SY(WEDKLP03);LS(DASH,1,CHGRF)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 500229
+LUPT 40LU00229NILWRECKSA00004SPLAIN_BOUNDARIES
+ATTC 1
+INST 13CS(WRECKS02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500230
+LUPT 40LU00230NILWRECKSA00004SPLAIN_BOUNDARIES
+ATTC 8CATWRK3
+INST 17LS(DASH,1,CHBLK)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500231
+LUPT 40LU00231NILdnghltA00008SPLAIN_BOUNDARIES
+ATTC 1
+INST 29AC(DNGHL,3);LS(SOLD,3,DNGHL)
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 500232
+LUPT 40LU00232NILmarfeaA00008SPLAIN_BOUNDARIES
+ATTC 1
+INST 85AC(ADINF,3);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,50);LS(SOLD,2,NINFO);LS(SOLD,1,CHBLK);
+DISC 18MARINERS STANDARD
+LUCM 653050
+**** 0
+0001 500233
+LUPT 40LU00233NILmnufeaA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,ADINF)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 500234
+LUPT 40LU00234NIL$AREASA00005SPLAIN_BOUNDARIES
+ATTC 1
+INST 13AP(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500235
+LUPT 40LU00235NIL$AREASA00005SPLAIN_BOUNDARIES
+ATTC 15$SCODECHCRDEL1
+INST 26SY(CHCRDEL1);LC(CHCRDEL1)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500236
+LUPT 40LU00236NIL$AREASA00005SPLAIN_BOUNDARIES
+ATTC 15$SCODECHCRID01
+INST 26SY(CHCRID01);LC(CHCRID01)
+DISC 9STANDARD
+LUCM 623030
+**** 0
+0001 500237
+LUPT 40LU00237NIL$AREASA00003OPLAIN_BOUNDARIES
+ATTC 15$SCODEOVERSC01
+INST 13AP(OVERSC01)
+DISC 9STANDARD
+LUCM 621030
+**** 0
+0001 500238
+LUPT 40LU00238NIL$AREASA00005SPLAIN_BOUNDARIES
+ATTC 15$SCODEQUESMRK1
+INST 30AP(QUESMRK1);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500239
+LUPT 40LU00239NIL$AREASA00003SPLAIN_BOUNDARIES
+ATTC 15$SCODEDIAMOND1
+INST 13AP(DIAMOND1)
+DISC 9STANDARD
+LUCM 623010
+**** 0
+0001 500240
+LUPT 40LU00240NIL$AREASA00002OPLAIN_BOUNDARIES
+ATTC 17$SCODEBACKGROUND
+INST 27AC(NODTA);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500241
+LUPT 40LU00241NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX1
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('1',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500242
+LUPT 40LU00242NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX2
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('2',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500243
+LUPT 40LU00243NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX3
+INST 62AC(DEPVS);LS(SOLD,1,CHGRD);TX('3',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500244
+LUPT 40LU00244NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX4
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('4',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500245
+LUPT 40LU00245NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX5
+INST 62AC(DEPVS);LS(SOLD,1,CHGRD);TX('5',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500246
+LUPT 40LU00246NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX6
+INST 62AC(LANDA);LS(SOLD,1,CHGRD);TX('6',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500247
+LUPT 40LU00247NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX7
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('7',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500248
+LUPT 40LU00248NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX8
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('8',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500249
+LUPT 40LU00249NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 11$SCODEBOX9
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('9',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500250
+LUPT 40LU00250NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX10
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('10',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500251
+LUPT 40LU00251NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX11
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('11',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500252
+LUPT 40LU00252NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX12
+INST 63AC(NODTA);LS(SOLD,1,CHGRD);TX('12',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500253
+LUPT 40LU00253NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX13
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('13',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500254
+LUPT 40LU00254NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX14
+INST 63AC(LANDA);LS(SOLD,1,CHGRD);TX('14',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500255
+LUPT 40LU00255NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX15
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('15',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500256
+LUPT 40LU00256NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX16
+INST 63AC(NODTA);LS(SOLD,1,CHGRD);TX('16',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500257
+LUPT 40LU00257NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX17
+INST 63AC(LANDA);LS(SOLD,1,CHGRD);TX('17',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500258
+LUPT 40LU00258NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX18
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('18',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500259
+LUPT 40LU00259NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX19
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('19',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500260
+LUPT 40LU00260NIL$AREASA00005OPLAIN_BOUNDARIES
+ATTC 12$SCODEBOX20
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('20',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500261
+LUPT 40LU00261NIL$TEXTSA00007OPLAIN_BOUNDARIES
+ATTC 1
+INST 59TX($TXSTR,$JUSTH=3,$JUSTV=1,$SPACE=2,'15110',0,0,CHBLK,27)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500262
+LUPT 45LU00262NIL######A00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30AP(QUESMRK1);LS(DASH,1,CHMGD)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500263
+LUPT 45LU00263NILACHAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(ACHARE51);LC(ACHARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500264
+LUPT 45LU00264NILACHAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATACH8
+INST 43SY(ACHARE02);LS(DASH,2,CHMGF);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500265
+LUPT 45LU00265NILACHBRTA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 78SY(ACHBRT07);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29);LS(DASH,2,CHMGF)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500266
+LUPT 45LU00266NILADMAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500267
+LUPT 45LU00267NILAIRAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30AP(AIRARE02);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500268
+LUPT 45LU00268NILAIRAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 40AC(LANDA);AP(AIRARE02);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500269
+LUPT 45LU00269NILBERTHSA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 61SY(BRTHNO01);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500270
+LUPT 45LU00270NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 108TX(OBJNAM,3,1,2,'15110',1,0,CHBLK,21);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500271
+LUPT 45LU00271NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG2
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500272
+LUPT 45LU00272NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG3
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500273
+LUPT 45LU00273NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG4
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500274
+LUPT 45LU00274NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG5
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500275
+LUPT 45LU00275NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG7
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500276
+LUPT 45LU00276NILBRIDGEA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CATBRG8
+INST 142SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11);LS(SOLD,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500277
+LUPT 45LU00277NILBUAAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622240
+**** 0
+0001 500278
+LUPT 45LU00278NILBUISGLA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500279
+LUPT 45LU00279NILBUISGLA00004SSYMBOLIZED_BOUNDARIES
+ATTC 17FUNCTN33CONVIS1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500280
+LUPT 45LU00280NILBUISGLA00004SSYMBOLIZED_BOUNDARIES
+ATTC 9FUNCTN33
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500281
+LUPT 45LU00281NILBUISGLA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500282
+LUPT 45LU00282NILCANALSA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500283
+LUPT 45LU00283NILCANALSA00002SSYMBOLIZED_BOUNDARIES
+ATTC 7CONDTN
+INST 27AC(DEPVS);LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500284
+LUPT 45LU00284NILCAUSWYA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,CSTLN)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500285
+LUPT 45LU00285NILCAUSWYA00005SSYMBOLIZED_BOUNDARIES
+ATTC 8WATLEV4
+INST 27AC(DEPIT);LS(DASH,2,CSTLN)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500286
+LUPT 45LU00286NILCBLAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(CBLARE51);LC(CBLARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500287
+LUPT 45LU00287NILCHKPNTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13SY(POSGEN04)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500288
+LUPT 45LU00288NILCONVYRA00008OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 70TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500289
+LUPT 45LU00289NILCONVYRA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CONRAD1
+INST 83SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500290
+LUPT 45LU00290NILCONVYRA00008OSYMBOLIZED_BOUNDARIES
+ATTC 8CONRAD3
+INST 83SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11);LS(SOLD,3,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500291
+LUPT 45LU00291NILCONZNEA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500292
+LUPT 45LU00292NILCOSAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636010
+**** 0
+0001 500293
+LUPT 45LU00293NILCRANESA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500294
+LUPT 45LU00294NILCRANESA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500295
+LUPT 45LU00295NILCTNAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(CTNARE51);LC(CTNARE51)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500296
+LUPT 45LU00296NILCTSAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(INFARE51);LC(CTYARE51)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500297
+LUPT 45LU00297NILCUSZNEA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRF)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500298
+LUPT 45LU00298NILDAMCONA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500299
+LUPT 45LU00299NILDAMCONA00006SSYMBOLIZED_BOUNDARIES
+ATTC 8CATDAM3
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500300
+LUPT 45LU00300NILDEPAREA00001SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(DEPARE01)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500301
+LUPT 45LU00301NILDEPAREA00001SSYMBOLIZED_BOUNDARIES
+ATTC 16DRVAL1?DRVAL2?
+INST 40AC(NODTA);AP(PRTSUR01);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500302
+LUPT 45LU00302NILDMPGRDA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(INFARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 500303
+LUPT 45LU00303NILDMPGRDA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATDPG5
+INST 26LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 500304
+LUPT 45LU00304NILDOCAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 65AC(DEPVS);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500305
+LUPT 45LU00305NILDOCAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 7CONDTN
+INST 65AC(DEPVS);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26);LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500306
+LUPT 45LU00306NILDRGAREA00001SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(DEPARE01)
+DISC 12DISPLAYBASE
+LUCM 613030
+**** 0
+0001 500307
+LUPT 45LU00307NILDRYDOCA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(LANDA);LS(SOLD,1,CSTLN)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500308
+LUPT 45LU00308NILDWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 52SY(TSLDEF51);SY(DWRTPT51);LC(DWRUTE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500309
+LUPT 45LU00309NILDWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 59SY(TSSLPT51,ORIENT);SY(DWRTPT51);LC(DWRUTE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500310
+LUPT 45LU00310NILDWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 59SY(TSSLPT51,ORIENT);SY(DWRTPT51);LC(DWRUTE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500311
+LUPT 45LU00311NILDWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 59SY(TSSLPT51,ORIENT);SY(DWRTPT51);LC(DWRUTE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500312
+LUPT 45LU00312NILDWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 59SY(DWRUTE51,ORIENT);SY(DWRTPT51);LC(DWRUTE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500313
+LUPT 45LU00313NILDYKCONA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500314
+LUPT 45LU00314NILEXEZNEA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500315
+LUPT 45LU00315NILFAIRWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500316
+LUPT 45LU00316NILFAIRWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 46SY(FAIRWY51,ORIENT);LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500317
+LUPT 45LU00317NILFAIRWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 46SY(FAIRWY51,ORIENT);LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500318
+LUPT 45LU00318NILFAIRWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 46SY(FAIRWY51,ORIENT);LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500319
+LUPT 45LU00319NILFAIRWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 46SY(FAIRWY52,ORIENT);LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500320
+LUPT 45LU00320NILFERYRTA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(FRYARE51);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500321
+LUPT 45LU00321NILFERYRTA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATFRY2
+INST 26SY(FRYARE52);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500322
+LUPT 45LU00322NILFLODOCA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500323
+LUPT 45LU00323NILFORSTCA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500324
+LUPT 45LU00324NILFORSTCA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500325
+LUPT 45LU00325NILFRPAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500326
+LUPT 45LU00326NILFSHFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(FSHFAC02);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500327
+LUPT 45LU00327NILFSHFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATFIF1
+INST 26SY(FSHFAC03);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500328
+LUPT 45LU00328NILFSHFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATFIF2
+INST 26SY(FSHFAC02);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500329
+LUPT 45LU00329NILFSHFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATFIF3
+INST 26SY(FSHFAC02);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500330
+LUPT 45LU00330NILFSHFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATFIF4
+INST 26SY(FSHFAC02);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500331
+LUPT 45LU00331NILFSHGRDA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30SY(FSHGRD01);LS(DASH,2,CHGRF)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500332
+LUPT 45LU00332NILFSHZNEA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 6OTHER
+LUCM 636040
+**** 0
+0001 500333
+LUPT 45LU00333NILGATCONA00008SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500334
+LUPT 45LU00334NILGRIDRNA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 632460
+**** 0
+0001 500335
+LUPT 45LU00335NILHRBAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13LC(NAVARE51)
+DISC 6OTHER
+LUCM 636020
+**** 0
+0001 500336
+LUPT 45LU00336NILHRBFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500337
+LUPT 45LU00337NILHRBFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATHAF1
+INST 13SY(ROLROL01)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500338
+LUPT 45LU00338NILHRBFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATHAF4
+INST 13SY(HRBFAC09)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500339
+LUPT 45LU00339NILHRBFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATHAF5
+INST 13SY(SMCFAC02)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500340
+LUPT 45LU00340NILHULKESA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500341
+LUPT 45LU00341NILICEAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 40AC(NODTA);AP(ICEARE04);LS(DASH,1,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500342
+LUPT 45LU00342NILICNAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(INFARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500343
+LUPT 45LU00343NILISTZNEA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(ITZARE51);LC(RESARE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500344
+LUPT 45LU00344NILLAKAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500345
+LUPT 45LU00345NILLNDAREA00001SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 10AC(LANDA)
+DISC 12DISPLAYBASE
+LUCM 612010
+**** 0
+0001 500346
+LUPT 45LU00346NILLNDMRKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500347
+LUPT 45LU00347NILLNDMRKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 26CATLMK17FUNCTN33CONVIS1
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500348
+LUPT 45LU00348NILLNDMRKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 18CATLMK17FUNCTN33
+INST 65AC(CHBRN);TX(OBJNAM,1,2,2,'15110',0,0,CHBLK,26);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500349
+LUPT 45LU00349NILLNDMRKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500350
+LUPT 45LU00350NILLNDRGNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500351
+LUPT 45LU00351NILLNDRGNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATLND2
+INST 13AP(MARSHES1)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500352
+LUPT 45LU00352NILLNDRGNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATLND12
+INST 13AP(MARSHES1)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500353
+LUPT 45LU00353NILLOCMAGA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(LOCMAG51);LC(NAVARE51)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500354
+LUPT 45LU00354NILLOGPONA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500355
+LUPT 45LU00355NILLOKBSNA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500356
+LUPT 45LU00356NILM_ACCYA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500357
+LUPT 45LU00357NILM_COVRA00001SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(DATCVR01)
+DISC 6OTHER
+LUCM 631040
+**** 0
+0001 500358
+LUPT 45LU00358NILM_CSCLA00001SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(DATCVR01)
+DISC 6OTHER
+LUCM 631040
+**** 0
+0001 500359
+LUPT 45LU00359NILM_HOPAA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500360
+LUPT 45LU00360NILM_NPUBA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500361
+LUPT 45LU00361NILM_NSYSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13LC(MARSYS51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500362
+LUPT 45LU00362NILM_NSYSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15MARSYS1ORIENT
+INST 33SY(DIRBOYA1,ORIENT);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500363
+LUPT 45LU00363NILM_NSYSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15MARSYS2ORIENT
+INST 33SY(DIRBOYB1,ORIENT);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500364
+LUPT 45LU00364NILM_NSYSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 7ORIENT
+INST 33SY(DIRBOY01,ORIENT);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500365
+LUPT 45LU00365NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30AP(NODATA03);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500366
+LUPT 45LU00366NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC1
+INST 30AP(DQUALA11);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500367
+LUPT 45LU00367NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC2
+INST 30AP(DQUALA21);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500368
+LUPT 45LU00368NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC3
+INST 30AP(DQUALB01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500369
+LUPT 45LU00369NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC4
+INST 30AP(DQUALC01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500370
+LUPT 45LU00370NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC5
+INST 30AP(DQUALD01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500371
+LUPT 45LU00371NILM_QUALA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATZOC6
+INST 30AP(DQUALU01);LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 631010
+**** 0
+0001 500372
+LUPT 45LU00372NILM_SDATA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500373
+LUPT 45LU00373NILM_SRELA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500374
+LUPT 45LU00374NILM_VDATA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500375
+LUPT 45LU00375NILMAGVARA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13SY(MAGVAR51)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500376
+LUPT 45LU00376NILMARCULA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39AP(MARCUL02);LC(NAVARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500377
+LUPT 45LU00377NILMIPAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(CTYARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500378
+LUPT 45LU00378NILMORFACA00006SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500379
+LUPT 45LU00379NILOBSTRNA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500380
+LUPT 45LU00380NILOBSTRNA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATOBS6
+INST 43CS(OBSTRN04);AP(FOULAR01);LS(DOTT,2,CHBLK)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500381
+LUPT 45LU00381NILOBSTRNA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATOBS7
+INST 26SY(FOULGND1);LC(NAVARE51)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500382
+LUPT 45LU00382NILOFSPLFA00005OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 78AC(CHBRN);LS(SOLD,4,CSTLN);TE('Prod %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500383
+LUPT 45LU00383NILOSPAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(CTYARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500384
+LUPT 45LU00384NILPILBOPA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(PILBOP02);LC(CTYARE51)
+DISC 9STANDARD
+LUCM 628010
+**** 0
+0001 500385
+LUPT 45LU00385NILPIPAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(INFARE51);LC(PIPARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500386
+LUPT 45LU00386NILPIPAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPIP2
+INST 39SY(INFARE51);LC(PIPARE61);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500387
+LUPT 45LU00387NILPIPAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPIP3
+INST 39SY(INFARE51);LC(PIPARE61);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500388
+LUPT 45LU00388NILPIPAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8PRODCT3
+INST 39SY(INFARE51);LC(PIPARE61);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500389
+LUPT 45LU00389NILPONTONA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500390
+LUPT 45LU00390NILPRCAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 52AP(TSSJCT02);SY(PRCARE51);LC(PRCARE51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500391
+LUPT 45LU00391NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500392
+LUPT 45LU00392NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 16CATPRA5CONVIS1
+INST 30SY(RFNERY11);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500393
+LUPT 45LU00393NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 16CATPRA8CONVIS1
+INST 30SY(TNKFRM11);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500394
+LUPT 45LU00394NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 16CATPRA9CONVIS1
+INST 30SY(WNDFRM61);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500395
+LUPT 45LU00395NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPRA1
+INST 30SY(QUARRY01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500396
+LUPT 45LU00396NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPRA5
+INST 30SY(RFNERY01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500397
+LUPT 45LU00397NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPRA6
+INST 30SY(TMBYRD01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500398
+LUPT 45LU00398NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPRA8
+INST 30SY(TNKFRM01);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500399
+LUPT 45LU00399NILPRDAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATPRA9
+INST 30SY(WNDFRM51);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500400
+LUPT 45LU00400NILPYLONSA00008SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500401
+LUPT 45LU00401NILRADRNGA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,TRFCF)
+DISC 9STANDARD
+LUCM 625040
+**** 0
+0001 500402
+LUPT 45LU00402NILRAPIDSA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 10AC(CHGRD)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500403
+LUPT 45LU00403NILRCTLPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13SY(RTLDEF51)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500404
+LUPT 45LU00404NILRCTLPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 7ORIENT
+INST 20SY(RCTLPT52,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500405
+LUPT 45LU00405NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(RECDEF51);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500406
+LUPT 45LU00406NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC1
+INST 87SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500407
+LUPT 45LU00407NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC2
+INST 87SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500408
+LUPT 45LU00408NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC3
+INST 87SY(RECTRC58,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500409
+LUPT 45LU00409NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK1TRAFIC4
+INST 87SY(RECTRC56,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500410
+LUPT 45LU00410NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC1
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500411
+LUPT 45LU00411NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC2
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500412
+LUPT 45LU00412NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC3
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500413
+LUPT 45LU00413NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 23ORIENTCATTRK2TRAFIC4
+INST 87SY(RECTRC55,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500414
+LUPT 45LU00414NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500415
+LUPT 45LU00415NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500416
+LUPT 45LU00416NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 87SY(RECTRC57,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500417
+LUPT 45LU00417NILRECTRCA00006SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 87SY(RECTRC55,ORIENT);TE('%03.0lf deg','ORIENT',3,2,2,'15110',4,0,CHBLK,11);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500418
+LUPT 45LU00418NILRESAREA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(RESARE02)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 500419
+LUPT 45LU00419NILRIVERSA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(DEPVS);LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500420
+LUPT 45LU00420NILROADWYA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(LANDA);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500421
+LUPT 45LU00421NILRUNWAYA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 10AC(CHBRN)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500422
+LUPT 45LU00422NILRUNWAYA00005SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500423
+LUPT 45LU00423NILSBDAREA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500424
+LUPT 45LU00424NILSBDAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 15WATLEV3NATSUR
+INST 55TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500425
+LUPT 45LU00425NILSBDAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 16WATLEV4NATSUR9
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500426
+LUPT 45LU00426NILSBDAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 17WATLEV4NATSUR11
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500427
+LUPT 45LU00427NILSBDAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 17WATLEV4NATSUR14
+INST 30AP(RCKLDG01);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500428
+LUPT 45LU00428NILSBDAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 15WATLEV4NATSUR
+INST 55TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500429
+LUPT 45LU00429NILSEAAREA00003SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500430
+LUPT 45LU00430NILSILTNKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 27AC(CHBRN);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500431
+LUPT 45LU00431NILSILTNKA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CONVIS1
+INST 27AC(CHBRN);LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500432
+LUPT 45LU00432NILSLCONSA00007OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(SLCONS03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500433
+LUPT 45LU00433NILSLOGRDA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500434
+LUPT 45LU00434NILSLOGRDA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATSLO6
+INST 27AC(CHGRD);LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500435
+LUPT 45LU00435NILSMCFACA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 40AC(CHBRN);SY(SMCFAC02);LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 638210
+**** 0
+0001 500436
+LUPT 45LU00436NILSNDWAVA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26AP(SNDWAV01);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500437
+LUPT 45LU00437NILSPLAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(CTYARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500438
+LUPT 45LU00438NILSUBTLNA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39SY(CTYARE51);LC(CTYARE51);CS(RESTRN01)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500439
+LUPT 45LU00439NILSWPAREA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 84SY(SWPARE51);TE('swept to %5.1lf','DRVAL1',1,2,2,'15110',0,1,CHBLK,27);LC(NAVARE51)
+DISC 9STANDARD
+LUCM 623030
+**** 0
+0001 500440
+LUPT 45LU00440NILT_HMONA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDEHT01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500441
+LUPT 45LU00441NILT_NHMNA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDEHT01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500442
+LUPT 45LU00442NILT_TIMSA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDEHT01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500443
+LUPT 45LU00443NILTS_FEBA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(CURDEF01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500444
+LUPT 45LU00444NILTS_FEBA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15CAT_TS1ORIENT
+INST 73SY(FLDSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500445
+LUPT 45LU00445NILTS_FEBA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15CAT_TS2ORIENT
+INST 73SY(EBBSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500446
+LUPT 45LU00446NILTS_FEBA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15CAT_TS3ORIENT
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500447
+LUPT 45LU00447NILTS_PADA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDSTR01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500448
+LUPT 45LU00448NILTS_PNHA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDSTR01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500449
+LUPT 45LU00449NILTS_PRHA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDSTR01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500450
+LUPT 45LU00450NILTS_TISA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TIDSTR01);LC(TIDINF51)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500451
+LUPT 45LU00451NILTESAREA00002SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30LS(DASH,2,CHGRF);CS(RESTRN01)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500452
+LUPT 45LU00452NILTIDEWYA00007SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,25)
+DISC 6OTHER
+LUCM 632070
+**** 0
+0001 500453
+LUPT 45LU00453NILTSEZNEA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 12AC(TRFCF,3)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500454
+LUPT 45LU00454NILTSSCRSA00006SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39AP(TSSJCT02);SY(TSSCRS51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500455
+LUPT 45LU00455NILTSSLPTA00006SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 78AP(TSSJCT02);SY(CTNARE51);TX(INFORM,1,1,2,'15110',0,-2,CHBLK,24);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500456
+LUPT 45LU00456NILTSSLPTA00006SSYMBOLIZED_BOUNDARIES
+ATTC 7ORIENT
+INST 33SY(TSSLPT51,ORIENT);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500457
+LUPT 45LU00457NILTSSRONA00006SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 39AP(TSSJCT02);SY(TSSRON51);CS(RESTRN01)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500458
+LUPT 45LU00458NILTUNNELA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500459
+LUPT 45LU00459NILTUNNELA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8BURDEP0
+INST 27AC(DEPVS);LS(DASH,1,CHBLK)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500460
+LUPT 45LU00460NILTWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 26SY(TWRDEF51);LC(CTYARE51)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500461
+LUPT 45LU00461NILTWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC1
+INST 33SY(TWRTPT53,ORIENT);LC(CTYARE51)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500462
+LUPT 45LU00462NILTWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC2
+INST 33SY(TWRTPT53,ORIENT);LC(CTYARE51)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500463
+LUPT 45LU00463NILTWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC3
+INST 33SY(TWRTPT53,ORIENT);LC(CTYARE51)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500464
+LUPT 45LU00464NILTWRTPTA00004SSYMBOLIZED_BOUNDARIES
+ATTC 15ORIENTTRAFIC4
+INST 33SY(TWRTPT52,ORIENT);LC(CTYARE51)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500465
+LUPT 45LU00465NILUNSAREA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 40AC(NODTA);AP(NODATA03);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 611050
+**** 0
+0001 500466
+LUPT 45LU00466NILVEGATNA00000SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500467
+LUPT 45LU00467NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATVEG7
+INST 30AP(VEGATN04);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500468
+LUPT 45LU00468NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG21
+INST 30AP(VEGATN04);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500469
+LUPT 45LU00469NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATVEG3
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500470
+LUPT 45LU00470NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATVEG4
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500471
+LUPT 45LU00471NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATVEG5
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500472
+LUPT 45LU00472NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 8CATVEG6
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500473
+LUPT 45LU00473NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG13
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500474
+LUPT 45LU00474NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG14
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500475
+LUPT 45LU00475NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG15
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500476
+LUPT 45LU00476NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG16
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500477
+LUPT 45LU00477NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG17
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500478
+LUPT 45LU00478NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG18
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500479
+LUPT 45LU00479NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG19
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500480
+LUPT 45LU00480NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG20
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500481
+LUPT 45LU00481NILVEGATNA00003SSYMBOLIZED_BOUNDARIES
+ATTC 9CATVEG22
+INST 30AP(VEGATN03);LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500482
+LUPT 45LU00482NILWATTURA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30SY(WATTUR02);LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 633040
+**** 0
+0001 500483
+LUPT 45LU00483NILWEDKLPA00003OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 30SY(WEDKLP03);LS(DASH,1,CHGRF)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 500484
+LUPT 45LU00484NILWRECKSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13CS(WRECKS02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500485
+LUPT 45LU00485NILWRECKSA00004SSYMBOLIZED_BOUNDARIES
+ATTC 8CATWRK3
+INST 13LC(NAVARE51)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500486
+LUPT 45LU00486NILdnghltA00008SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 29AC(DNGHL,3);LS(SOLD,3,DNGHL)
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 500487
+LUPT 45LU00487NILmarfeaA00008SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 85AC(ADINF,3);TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,50);LS(SOLD,2,NINFO);LS(SOLD,1,CHBLK);
+DISC 18MARINERS STANDARD
+LUCM 653050
+**** 0
+0001 500488
+LUPT 45LU00488NILmnufeaA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 17LS(DASH,2,ADINF)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 500489
+LUPT 45LU00489NIL$AREASA00005SSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 13AP(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500490
+LUPT 45LU00490NIL$AREASA00005SSYMBOLIZED_BOUNDARIES
+ATTC 15$SCODECHCRDEL1
+INST 26SY(CHCRDEL1);LC(CHCRDEL1)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500491
+LUPT 45LU00491NIL$AREASA00005SSYMBOLIZED_BOUNDARIES
+ATTC 15$SCODECHCRID01
+INST 26SY(CHCRID01);LC(CHCRID01)
+DISC 9STANDARD
+LUCM 623030
+**** 0
+0001 500492
+LUPT 45LU00492NIL$AREASA00003OSYMBOLIZED_BOUNDARIES
+ATTC 15$SCODEOVERSC01
+INST 13AP(OVERSC01)
+DISC 9STANDARD
+LUCM 621030
+**** 0
+0001 500493
+LUPT 45LU00493NIL$AREASA00005SSYMBOLIZED_BOUNDARIES
+ATTC 15$SCODEQUESMRK1
+INST 30AP(QUESMRK1);LS(DASH,1,CHGRD)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500494
+LUPT 45LU00494NIL$AREASA00003SSYMBOLIZED_BOUNDARIES
+ATTC 15$SCODEDIAMOND1
+INST 13AP(DIAMOND1)
+DISC 9STANDARD
+LUCM 623010
+**** 0
+0001 500495
+LUPT 45LU00495NIL$AREASA00002OSYMBOLIZED_BOUNDARIES
+ATTC 17$SCODEBACKGROUND
+INST 27AC(NODTA);LS(SOLD,2,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500496
+LUPT 45LU00496NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX1
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('1',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500497
+LUPT 45LU00497NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX2
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('2',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500498
+LUPT 45LU00498NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX3
+INST 62AC(DEPVS);LS(SOLD,1,CHGRD);TX('3',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500499
+LUPT 45LU00499NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX4
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('4',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500500
+LUPT 45LU00500NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX5
+INST 62AC(DEPVS);LS(SOLD,1,CHGRD);TX('5',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500501
+LUPT 45LU00501NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX6
+INST 62AC(LANDA);LS(SOLD,1,CHGRD);TX('6',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500502
+LUPT 45LU00502NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX7
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('7',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500503
+LUPT 45LU00503NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX8
+INST 62AC(DEPDW);LS(SOLD,1,CHGRD);TX('8',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500504
+LUPT 45LU00504NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 11$SCODEBOX9
+INST 62AC(NODTA);LS(SOLD,1,CHGRD);TX('9',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500505
+LUPT 45LU00505NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX10
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('10',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500506
+LUPT 45LU00506NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX11
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('11',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500507
+LUPT 45LU00507NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX12
+INST 63AC(NODTA);LS(SOLD,1,CHGRD);TX('12',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500508
+LUPT 45LU00508NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX13
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('13',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500509
+LUPT 45LU00509NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX14
+INST 63AC(LANDA);LS(SOLD,1,CHGRD);TX('14',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500510
+LUPT 45LU00510NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX15
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('15',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500511
+LUPT 45LU00511NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX16
+INST 63AC(NODTA);LS(SOLD,1,CHGRD);TX('16',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500512
+LUPT 45LU00512NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX17
+INST 63AC(LANDA);LS(SOLD,1,CHGRD);TX('17',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500513
+LUPT 45LU00513NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX18
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('18',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500514
+LUPT 45LU00514NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX19
+INST 63AC(DEPDW);LS(SOLD,1,CHGRD);TX('19',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500515
+LUPT 45LU00515NIL$AREASA00005OSYMBOLIZED_BOUNDARIES
+ATTC 12$SCODEBOX20
+INST 63AC(DEPVS);LS(SOLD,1,CHGRD);TX('20',2,2,3,'15110',3,2,CHBLK,30)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500516
+LUPT 45LU00516NIL$TEXTSA00007OSYMBOLIZED_BOUNDARIES
+ATTC 1
+INST 59TX($TXSTR,$JUSTH=3,$JUSTV=1,$SPACE=2,'15110',0,0,CHBLK,27)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500517
+LUPT 29LU00517NIL######L00005OLINES
+ATTC 1
+INST 13LC(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500518
+LUPT 29LU00518NILBERTHSL00005OLINES
+ATTC 1
+INST 78LS(SOLD,3,CHGRD);SY(BRTHNO01);TE('No %s','OBJNAM',1,2,2,'15110',0,0,CHBLK,29)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500519
+LUPT 29LU00519NILBRIDGEL00008OLINES
+ATTC 1
+INST 108LS(SOLD,5,CHGRD);TX(OBJNAM,3,1,2,'15110',1,0,CHBLK,21);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500520
+LUPT 29LU00520NILBRIDGEL00008OLINES
+ATTC 8CATBRG2
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500521
+LUPT 29LU00521NILBRIDGEL00008OLINES
+ATTC 8CATBRG3
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500522
+LUPT 29LU00522NILBRIDGEL00008OLINES
+ATTC 8CATBRG4
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500523
+LUPT 29LU00523NILBRIDGEL00008OLINES
+ATTC 8CATBRG5
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500524
+LUPT 29LU00524NILBRIDGEL00008OLINES
+ATTC 8CATBRG7
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500525
+LUPT 29LU00525NILBRIDGEL00008OLINES
+ATTC 8CATBRG8
+INST 142LS(SOLD,5,CHGRD);SY(BRIDGE01);TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11);TE('clr op %4.1lf','VERCOP',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500526
+LUPT 29LU00526NILCANALSL00002OLINES
+ATTC 1
+INST 17LS(SOLD,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612420
+**** 0
+0001 500527
+LUPT 29LU00527NILCAUSWYL00005OLINES
+ATTC 1
+INST 17LS(SOLD,3,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500528
+LUPT 29LU00528NILCAUSWYL00005OLINES
+ATTC 8WATLEV4
+INST 17LS(DASH,3,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500529
+LUPT 29LU00529NILCBLOHDL00008OLINES
+ATTC 1
+INST 17LS(DASH,4,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500530
+LUPT 29LU00530NILCBLOHDL00008OLINES
+ATTC 15CONRAD1VERCSA
+INST 86LS(DASH,4,CHGRD);SY(RACNSP01);TE('sf clr %4.1lf','VERCSA',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500531
+LUPT 29LU00531NILCBLOHDL00008OLINES
+ATTC 15CONRAD3VERCSA
+INST 86LS(DASH,4,CHGRD);SY(RACNSP01);TE('sf clr %4.1lf','VERCSA',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500532
+LUPT 29LU00532NILCBLOHDL00008OLINES
+ATTC 15CONRAD1VERCLR
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500533
+LUPT 29LU00533NILCBLOHDL00008OLINES
+ATTC 15CONRAD3VERCLR
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500534
+LUPT 29LU00534NILCBLOHDL00008OLINES
+ATTC 8CONRAD1
+INST 30LS(DASH,4,CHGRD);SY(RACNSP01)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500535
+LUPT 29LU00535NILCBLOHDL00008OLINES
+ATTC 8CONRAD3
+INST 30LS(DASH,4,CHGRD);SY(RACNSP01)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500536
+LUPT 29LU00536NILCBLOHDL00008OLINES
+ATTC 7VERCSA
+INST 73LS(DASH,4,CHGRD);TE('sf clr %4.1lf','VERCSA',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500537
+LUPT 29LU00537NILCBLOHDL00008OLINES
+ATTC 7VERCLR
+INST 73LS(DASH,4,CHGRD);TE('sf clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500538
+LUPT 29LU00538NILCBLSUBL00003OLINES
+ATTC 1
+INST 13LC(CBLSUB06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500539
+LUPT 29LU00539NILCBLSUBL00006OLINES
+ATTC 8CATCBL6
+INST 17LS(DASH,1,CHMGD)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500540
+LUPT 29LU00540NILCOALNEL00007OLINES
+ATTC 1
+INST 13CS(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500541
+LUPT 29LU00541NILCOALNEL00007OLINES
+ATTC 8CATCOA6
+INST 17LS(DASH,1,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500542
+LUPT 29LU00542NILCOALNEL00007OLINES
+ATTC 8CATCOA7
+INST 17LS(DASH,1,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500543
+LUPT 29LU00543NILCOALNEL00007OLINES
+ATTC 8CATCOA8
+INST 17LS(DASH,1,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500544
+LUPT 29LU00544NILCOALNEL00007OLINES
+ATTC 9CATCOA10
+INST 17LS(DASH,1,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500545
+LUPT 29LU00545NILCONVYRL00008OLINES
+ATTC 1
+INST 70LS(DASH,4,CHGRD);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500546
+LUPT 29LU00546NILCONVYRL00008OLINES
+ATTC 16CATCON1CONRAD1
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500547
+LUPT 29LU00547NILCONVYRL00008OLINES
+ATTC 16CATCON1CONRAD3
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500548
+LUPT 29LU00548NILCONVYRL00008OLINES
+ATTC 16CATCON2CONRAD1
+INST 83LS(SOLD,3,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500549
+LUPT 29LU00549NILCONVYRL00008OLINES
+ATTC 16CATCON2CONRAD3
+INST 83LS(SOLD,3,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500550
+LUPT 29LU00550NILCONVYRL00008OLINES
+ATTC 8CATCON1
+INST 70LS(DASH,4,CHGRD);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500551
+LUPT 29LU00551NILCONVYRL00008OLINES
+ATTC 8CATCON2
+INST 70LS(SOLD,3,CHGRD);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500552
+LUPT 29LU00552NILCONVYRL00008OLINES
+ATTC 8CONRAD1
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500553
+LUPT 29LU00553NILCONVYRL00008OLINES
+ATTC 8CONRAD3
+INST 83LS(DASH,4,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,0,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500554
+LUPT 29LU00554NILDAMCONL00006OLINES
+ATTC 1
+INST 17LS(SOLD,4,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500555
+LUPT 29LU00555NILDAMCONL00006OLINES
+ATTC 8CATDAM3
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500556
+LUPT 29LU00556NILDEPAREL00003OLINES
+ATTC 1
+INST 13CS(DEPCNT02)
+DISC 6OTHER
+LUCM 633020
+**** 0
+0001 500557
+LUPT 29LU00557NILDEPCNTL00005OLINES
+ATTC 1
+INST 13CS(DEPCNT02)
+DISC 6OTHER
+LUCM 633020
+**** 0
+0001 500558
+LUPT 29LU00558NILDWRTCLL00006OLINES
+ATTC 1
+INST 68LC(DWLDEF01);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500559
+LUPT 29LU00559NILDWRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC1
+INST 68LC(DWRTCL08);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500560
+LUPT 29LU00560NILDWRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC2
+INST 68LC(DWRTCL08);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500561
+LUPT 29LU00561NILDWRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC3
+INST 68LC(DWRTCL08);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500562
+LUPT 29LU00562NILDWRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC4
+INST 68LC(DWRTCL06);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500563
+LUPT 29LU00563NILDWRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC1
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500564
+LUPT 29LU00564NILDWRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC2
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500565
+LUPT 29LU00565NILDWRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC3
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500566
+LUPT 29LU00566NILDWRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC4
+INST 68LC(DWRTCL05);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500567
+LUPT 29LU00567NILDWRTCLL00006OLINES
+ATTC 8TRAFIC1
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500568
+LUPT 29LU00568NILDWRTCLL00006OLINES
+ATTC 8TRAFIC2
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500569
+LUPT 29LU00569NILDWRTCLL00006OLINES
+ATTC 8TRAFIC3
+INST 68LC(DWRTCL07);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500570
+LUPT 29LU00570NILDWRTCLL00006OLINES
+ATTC 8TRAFIC4
+INST 68LC(DWRTCL05);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500571
+LUPT 29LU00571NILDYKCONL00004OLINES
+ATTC 1
+INST 17LS(SOLD,3,LANDF)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500572
+LUPT 29LU00572NILDYKCONL00004OLINES
+ATTC 8CONRAD1
+INST 17LS(SOLD,2,CHBLK)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 500573
+LUPT 29LU00573NILFERYRTL00004OLINES
+ATTC 1
+INST 13LC(FERYRT02)
+DISC 9STANDARD
+LUCM 625030
+**** 0
+0001 500574
+LUPT 29LU00574NILFERYRTL00004OLINES
+ATTC 8CATFRY1
+INST 13LC(FERYRT01)
+DISC 9STANDARD
+LUCM 625030
+**** 0
+0001 500575
+LUPT 29LU00575NILFERYRTL00004OLINES
+ATTC 8CATFRY2
+INST 13LC(FERYRT02)
+DISC 9STANDARD
+LUCM 625030
+**** 0
+0001 500576
+LUPT 29LU00576NILFLODOCL00005OLINES
+ATTC 1
+INST 17LS(SOLD,3,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500577
+LUPT 29LU00577NILFNCLNEL00003OLINES
+ATTC 1
+INST 17LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500578
+LUPT 29LU00578NILFNCLNEL00003OLINES
+ATTC 8CONVIS1
+INST 17LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500579
+LUPT 29LU00579NILFORSTCL00004OLINES
+ATTC 1
+INST 17LS(SOLD,3,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500580
+LUPT 29LU00580NILFSHFACL00004OLINES
+ATTC 1
+INST 17LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500581
+LUPT 29LU00581NILFSHFACL00004OLINES
+ATTC 8CATFIF1
+INST 13LC(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500582
+LUPT 29LU00582NILGATCONL00008OLINES
+ATTC 1
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500583
+LUPT 29LU00583NILGATCONL00008OLINES
+ATTC 8CATGAT2
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500584
+LUPT 29LU00584NILGATCONL00008OLINES
+ATTC 8CATGAT3
+INST 30LS(SOLD,2,CSTLN);SY(GATCON04)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500585
+LUPT 29LU00585NILGATCONL00008OLINES
+ATTC 8CATGAT4
+INST 30LS(SOLD,2,CSTLN);SY(GATCON03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500586
+LUPT 29LU00586NILGATCONL00008OLINES
+ATTC 8CATGAT5
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500587
+LUPT 29LU00587NILLNDAREL00008OLINES
+ATTC 1
+INST 13CS(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612010
+**** 0
+0001 500588
+LUPT 29LU00588NILLNDELVL00004OLINES
+ATTC 1
+INST 17LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500589
+LUPT 29LU00589NILLNDMRKL00004OLINES
+ATTC 1
+INST 17LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500590
+LUPT 29LU00590NILLNDMRKL00004OLINES
+ATTC 8CONVIS1
+INST 17LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500591
+LUPT 29LU00591NILLOCMAGL00004SLINES
+ATTC 1
+INST 30LS(DASH,1,CHMGF);SY(LOCMAG01)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500592
+LUPT 29LU00592NILM_SRELL00000SLINES
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500593
+LUPT 29LU00593NILMAGVARL00004OLINES
+ATTC 1
+INST 81LS(SOLD,2,CHMGF);SY(MAGVAR51);TE('varn %s','VALMAG',3,1,2,'15110',1,-1,CHBLK,27)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500594
+LUPT 29LU00594NILMARCULL00004OLINES
+ATTC 1
+INST 17LS(DASH,2,CHGRF)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500595
+LUPT 29LU00595NILMORFACL00006OLINES
+ATTC 1
+INST 17LS(SOLD,2,CSTLN)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500596
+LUPT 29LU00596NILMORFACL00006OLINES
+ATTC 8CATMOR4
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500597
+LUPT 29LU00597NILMORFACL00006OLINES
+ATTC 8CATMOR6
+INST 17LS(DASH,1,CHMGF)
+DISC 12DISPLAYBASE
+LUCM 614010
+**** 0
+0001 500598
+LUPT 29LU00598NILNAVLNEL00004OLINES
+ATTC 1
+INST 72LS(DASH,1,CHGRD);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625010
+**** 0
+0001 500599
+LUPT 29LU00599NILOBSTRNL00004OLINES
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500600
+LUPT 29LU00600NILOBSTRNL00004OLINES
+ATTC 8CATOBS8
+INST 17LS(DASH,1,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500601
+LUPT 29LU00601NILOILBARL00004OLINES
+ATTC 1
+INST 17LS(DASH,1,CHBLK)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500602
+LUPT 29LU00602NILPIPOHDL00008OLINES
+ATTC 1
+INST 71LS(SOLD,3,CHGRD);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500603
+LUPT 29LU00603NILPIPOHDL00008OLINES
+ATTC 8CONRAD1
+INST 84LS(SOLD,3,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500604
+LUPT 29LU00604NILPIPOHDL00008OLINES
+ATTC 8CONRAD3
+INST 84LS(SOLD,3,CHGRD);SY(RACNSP01);TE('clr %4.1lf','VERCLR',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500605
+LUPT 29LU00605NILPIPSOLL00006OLINES
+ATTC 1
+INST 13LC(PIPSOL05)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500606
+LUPT 29LU00606NILPIPSOLL00006OLINES
+ATTC 8PRODCT3
+INST 13LC(PIPSOL06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500607
+LUPT 29LU00607NILPIPSOLL00006OLINES
+ATTC 8CATPIP2
+INST 13LC(PIPSOL06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500608
+LUPT 29LU00608NILPIPSOLL00006OLINES
+ATTC 8CATPIP3
+INST 13LC(PIPSOL06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500609
+LUPT 29LU00609NILPIPSOLL00006OLINES
+ATTC 8CATPIP4
+INST 13LC(PIPSOL06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500610
+LUPT 29LU00610NILPIPSOLL00006OLINES
+ATTC 8CATPIP5
+INST 13LC(PIPSOL06)
+DISC 6OTHER
+LUCM 634070
+**** 0
+0001 500611
+LUPT 29LU00611NILPONTONL00005OLINES
+ATTC 1
+INST 17LS(SOLD,2,CSTLN)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500612
+LUPT 29LU00612NILRADLNEL00006OLINES
+ATTC 1
+INST 72LS(DASH,2,TRFCD);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625040
+**** 0
+0001 500613
+LUPT 29LU00613NILRAILWYL00004OLINES
+ATTC 1
+INST 17LS(SOLD,2,LANDF)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500614
+LUPT 29LU00614NILRAPIDSL00003OLINES
+ATTC 1
+INST 17LS(SOLD,3,CHGRD)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500615
+LUPT 29LU00615NILRCRTCLL00006OLINES
+ATTC 1
+INST 68LC(RCRDEF01);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500616
+LUPT 29LU00616NILRCRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC1
+INST 68LC(RCRTCL04);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500617
+LUPT 29LU00617NILRCRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC2
+INST 68LC(RCRTCL04);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500618
+LUPT 29LU00618NILRCRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC3
+INST 68LC(RCRTCL04);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500619
+LUPT 29LU00619NILRCRTCLL00006OLINES
+ATTC 16CATTRK1TRAFIC4
+INST 68LC(RCRTCL03);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500620
+LUPT 29LU00620NILRCRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC1
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500621
+LUPT 29LU00621NILRCRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC2
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500622
+LUPT 29LU00622NILRCRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC3
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500623
+LUPT 29LU00623NILRCRTCLL00006OLINES
+ATTC 16CATTRK2TRAFIC4
+INST 68LC(RCRTCL01);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500624
+LUPT 29LU00624NILRCRTCLL00006OLINES
+ATTC 8TRAFIC1
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500625
+LUPT 29LU00625NILRCRTCLL00006OLINES
+ATTC 8TRAFIC2
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500626
+LUPT 29LU00626NILRCRTCLL00006OLINES
+ATTC 8TRAFIC3
+INST 68LC(RCRTCL02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500627
+LUPT 29LU00627NILRCRTCLL00006OLINES
+ATTC 8TRAFIC4
+INST 68LC(RCRTCL01);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500628
+LUPT 29LU00628NILRDOCALL00006OLINES
+ATTC 1
+INST 79LS(DASH,1,TRFCD);SY(RCLDEF01);TE('No %s','OBJNAM',3,2,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500629
+LUPT 29LU00629NILRDOCALL00006OLINES
+ATTC 15TRAFIC1ORIENT
+INST 134LS(DASH,1,TRFCD);SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500630
+LUPT 29LU00630NILRDOCALL00006OLINES
+ATTC 15TRAFIC2ORIENT
+INST 134LS(DASH,1,TRFCD);SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500631
+LUPT 29LU00631NILRDOCALL00006OLINES
+ATTC 15TRAFIC3ORIENT
+INST 134LS(DASH,1,TRFCD);SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500632
+LUPT 29LU00632NILRDOCALL00006OLINES
+ATTC 15TRAFIC4ORIENT
+INST 134LS(DASH,1,TRFCD);SY(RDOCAL03,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500633
+LUPT 29LU00633NILRECTRCL00006OLINES
+ATTC 1
+INST 68LC(RECDEF02);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500634
+LUPT 29LU00634NILRECTRCL00006OLINES
+ATTC 16CATTRK1TRAFIC1
+INST 68LC(RECTRC12);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500635
+LUPT 29LU00635NILRECTRCL00006OLINES
+ATTC 16CATTRK1TRAFIC2
+INST 68LC(RECTRC12);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500636
+LUPT 29LU00636NILRECTRCL00006OLINES
+ATTC 16CATTRK1TRAFIC3
+INST 68LC(RECTRC12);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500637
+LUPT 29LU00637NILRECTRCL00006OLINES
+ATTC 16CATTRK1TRAFIC4
+INST 68LC(RECTRC10);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500638
+LUPT 29LU00638NILRECTRCL00006OLINES
+ATTC 16CATTRK2TRAFIC1
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500639
+LUPT 29LU00639NILRECTRCL00006OLINES
+ATTC 16CATTRK2TRAFIC2
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500640
+LUPT 29LU00640NILRECTRCL00006OLINES
+ATTC 16CATTRK2TRAFIC3
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500641
+LUPT 29LU00641NILRECTRCL00006OLINES
+ATTC 16CATTRK2TRAFIC4
+INST 68LC(RECTRC09);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500642
+LUPT 29LU00642NILRECTRCL00006OLINES
+ATTC 8TRAFIC1
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500643
+LUPT 29LU00643NILRECTRCL00006OLINES
+ATTC 8TRAFIC2
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500644
+LUPT 29LU00644NILRECTRCL00006OLINES
+ATTC 8TRAFIC3
+INST 68LC(RECTRC11);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500645
+LUPT 29LU00645NILRECTRCL00006OLINES
+ATTC 8TRAFIC4
+INST 68LC(RECTRC09);TE('%03.0lf deg','ORIENT',3,1,2,'15110',1,-1,CHBLK,11)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 500646
+LUPT 29LU00646NILRIVERSL00002OLINES
+ATTC 1
+INST 17LS(SOLD,1,CHBLK)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500647
+LUPT 29LU00647NILROADWYL00004OLINES
+ATTC 1
+INST 17LS(SOLD,2,LANDF)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500648
+LUPT 29LU00648NILRUNWAYL00006OLINES
+ATTC 1
+INST 17LS(SOLD,3,LANDF)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500649
+LUPT 29LU00649NILSBDAREL00004OLINES
+ATTC 1
+INST 55LS(SOLD,1,CHGRD);TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500650
+LUPT 29LU00650NILSLCONSL00007OLINES
+ATTC 1
+INST 13CS(SLCONS03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500651
+LUPT 29LU00651NILSLOTOPL00004OLINES
+ATTC 1
+INST 17LS(SOLD,1,LANDF)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500652
+LUPT 29LU00652NILSLOTOPL00004OLINES
+ATTC 16CATSLO2CONRAD1
+INST 17LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 500653
+LUPT 29LU00653NILSLOTOPL00004OLINES
+ATTC 16CATSLO6CONRAD1
+INST 17LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 500654
+LUPT 29LU00654NILSLOTOPL00004OLINES
+ATTC 16CATSLO6CONVIS1
+INST 17LS(SOLD,1,CHBLK)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 500655
+LUPT 29LU00655NILSLOTOPL00004OLINES
+ATTC 8CATSLO2
+INST 17LS(SOLD,1,CHGRD)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500656
+LUPT 29LU00656NILSLOTOPL00004OLINES
+ATTC 8CATSLO6
+INST 17LS(SOLD,1,CHGRD)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500657
+LUPT 29LU00657NILSNDWAVL00004OLINES
+ATTC 1
+INST 30LS(DASH,2,CHGRD);SY(SNDWAV02)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500658
+LUPT 29LU00658NILSTSLNEL00003OLINES
+ATTC 1
+INST 17LS(DASH,1,CHGRF)
+DISC 6OTHER
+LUCM 636050
+**** 0
+0001 500659
+LUPT 29LU00659NILTIDEWYL00003OLINES
+ATTC 1
+INST 17LS(SOLD,1,CHGRF)
+DISC 6OTHER
+LUCM 632070
+**** 0
+0001 500660
+LUPT 29LU00660NILTSELNEL00008OLINES
+ATTC 1
+INST 17LS(SOLD,6,TRFCF)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500661
+LUPT 29LU00661NILTSSBNDL00007OLINES
+ATTC 1
+INST 17LS(DASH,4,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500662
+LUPT 29LU00662NILTUNNELL00004OLINES
+ATTC 1
+INST 17LS(DASH,1,CHGRD)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500663
+LUPT 29LU00663NILTUNNELL00004OLINES
+ATTC 8BURDEP0
+INST 17LS(DASH,2,CHBLK)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500664
+LUPT 29LU00664NILVEGATNL00003OLINES
+ATTC 1
+INST 17LS(DASH,1,LANDF)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 500665
+LUPT 29LU00665NILWATFALL00003OLINES
+ATTC 1
+INST 17LS(SOLD,3,CHGRF)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500666
+LUPT 29LU00666NILWATFALL00003OLINES
+ATTC 8CONVIS1
+INST 17LS(SOLD,3,CHWHT)
+DISC 6OTHER
+LUCM 632050
+**** 0
+0001 500667
+LUPT 29LU00667NILWATTURL00004OLINES
+ATTC 1
+INST 30LS(DASH,1,CHGRD);SY(WATTUR02)
+DISC 6OTHER
+LUCM 633040
+**** 0
+0001 500668
+LUPT 29LU00668NILclrlinL00009OLINES
+ATTC 1
+INST 13CS(CLRLIN01)
+DISC 15MARINERS OTHER
+LUCM 653020
+**** 0
+0001 500669
+LUPT 29LU00669NILeblineL00009OLINES
+ATTC 1
+INST 13CS(VRMEBL01)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 500670
+LUPT 29LU00670NILleglinL00008OLINES
+ATTC 1
+INST 13CS(LEGLIN02)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 500671
+LUPT 29LU00671NILmarfeaL00008OLINES
+ATTC 1
+INST 55LS(SOLD,2,NINFO);TX(OBJNAM,3,3,2,'15110',0,1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 653050
+**** 0
+0001 500672
+LUPT 29LU00672NILmnufeaL00005OLINES
+ATTC 1
+INST 17LS(SOLD,1,ADINF)
+DISC 15MARINERS OTHER
+LUCM 655010
+**** 0
+0001 500673
+LUPT 29LU00673NILpastrkL00003OLINES
+ATTC 1
+INST 13CS(PASTRK01)
+DISC 18MARINERS STANDARD
+LUCM 652430
+**** 0
+0001 500674
+LUPT 29LU00674NILposlinL00003OLINES
+ATTC 1
+INST 56LS(SOLD,1,NINFO);TX(loctim,3,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662020
+**** 0
+0001 500675
+LUPT 29LU00675NILposlinL00003OLINES
+ATTC 8transf2
+INST 93LS(SOLD,1,NINFO);TX(loctim,3,1,2,'15110',0,-1,CHBLK,50);TX('TPL',3,3,2,'15110',0,1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662020
+**** 0
+0001 500676
+LUPT 29LU00676NILrngrngL00009OLINES
+ATTC 1
+INST 17LS(SOLD,1,CURSR)
+DISC 15MARINERS OTHER
+LUCM 661030
+**** 0
+0001 500677
+LUPT 29LU00677NILvrmarkL00009OLINES
+ATTC 1
+INST 13CS(VRMEBL01)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 500678
+LUPT 29LU00678NILwholinL00008OLINES
+ATTC 1
+INST 94LS(SOLD,2,NINFO);TX(loctim,3,3,2,'15110',0,1,CHBLK,50);TX(usrmrk,3,1,2,'15110',0,-1,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 652010
+**** 0
+0001 500679
+LUPT 29LU00679NIL$LINESL00005SLINES
+ATTC 1
+INST 13LC(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500680
+LUPT 29LU00680NIL$LINESL00003OLINES
+ATTC 15$SCODESCLBDY51
+INST 13LC(SCLBDY51)
+DISC 9STANDARD
+LUCM 621030
+**** 0
+0001 500681
+LUPT 29LU00681NIL$LINESL00005SLINES
+ATTC 15$SCODEQUESMRK1
+INST 13LC(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500682
+LUPT 29LU00682NIL$LINESL00006OLINES
+ATTC 15$SCODECHCRID01
+INST 13LC(CHCRID01)
+DISC 6OTHER
+LUCM 633020
+**** 0
+0001 500683
+LUPT 29LU00683NIL$LINESL00006OLINES
+ATTC 15$SCODECHCRDEL1
+INST 13LC(CHCRDEL1)
+DISC 6OTHER
+LUCM 633020
+**** 0
+0001 500684
+LUPT 29LU00684NIL$LINESL00009OLINES
+ATTC 15$SCODEUNITMTR1
+INST 13LC(UNITMTR1)
+DISC 12DISPLAYBASE
+LUCM 611080
+**** 0
+0001 500685
+LUPT 29LU00685NIL$LINESL00003OLINES
+ATTC 15$SCODEHODATA01
+INST 13LC(HODATA01)
+DISC 12DISPLAYBASE
+LUCM 611060
+**** 0
+0001 500686
+LUPT 29LU00686NIL$LINESL00005OLINES
+ATTC 15$SCODEGRIDLINE
+INST 17LS(SOLD,1,CHGRD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500687
+LUPT 29LU00687NIL$LINESL00002SLINES
+ATTC 15$SCODETIDINF51
+INST 13LC(TIDINF51)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500688
+LUPT 29LU00688NIL$LINESL00005OLINES
+ATTC 15$SCODELOWACC41
+INST 13LC(LOWACC41)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500689
+LUPT 29LU00689NIL$LINESL00000OLINES
+ATTC 13$SCODEDANGER
+INST 17LS(DOTT,2,CHBLK)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500690
+LUPT 29LU00690NIL$LINESL00000OLINES
+ATTC 13$SCODEOBSTRN
+INST 17LS(DASH,2,CHGRD)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500691
+LUPT 29LU00691NIL$LINESL00004SLINES
+ATTC 15$SCODEMARSYS51
+INST 13LC(MARSYS51)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 500692
+LUPT 29LU00692NIL$LINESL00009OLINES
+ATTC 10$SCODEAIS
+INST 17LS(SOLD,2,ARPAT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 500693
+LUPT 29LU00693NIL$LINESL00009OLINES
+ATTC 14$SCODEAISHEAD
+INST 17LS(SOLD,1,ARPAT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 500694
+LUPT 29LU00694NIL$LINESL00009OLINES
+ATTC 11$SCODEARPA
+INST 17LS(SOLD,2,ARPAT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 500695
+LUPT 29LU00695NIL$LINESL00009OLINES
+ATTC 15$SCODEERBLNB01
+INST 13LC(ERBLNB01)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 500696
+LUPT 29LU00696NIL$LINESL00009OLINES
+ATTC 15$SCODEERBLNA01
+INST 13LC(ERBLNA01)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 500697
+LUPT 29LU00697NIL$LINESL00009OLINES
+ATTC 12$SCODEHEDNG
+INST 17LS(SOLD,1,SHIPS)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 500698
+LUPT 29LU00698NIL$LINESL00009OLINES
+ATTC 10$SCODESOG
+INST 17LS(SOLD,1,SHIPS)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 500699
+LUPT 29LU00699NIL$LINESL00003OLINES
+ATTC 12$SCODEPSTRK
+INST 17LS(SOLD,2,PSTRK)
+DISC 18MARINERS STANDARD
+LUCM 652430
+**** 0
+0001 500700
+LUPT 29LU00700NIL$LINESL00003OLINES
+ATTC 12$SCODESYTRK
+INST 17LS(SOLD,1,SYTRK)
+DISC 18MARINERS STANDARD
+LUCM 652460
+**** 0
+0001 500701
+LUPT 29LU00701NIL$LINESL00009OLINES
+ATTC 10$SCODEERB
+INST 17LS(DASH,2,NINFO)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 500702
+LUPT 29LU00702NIL$LINESL00005OLINES
+ATTC 15$SCODEPLNRTE03
+INST 13LC(PLNRTE03)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 500703
+LUPT 29LU00703NIL$LINESL00005OLINES
+ATTC 13$SCODEALPLRT
+INST 17LS(DOTT,2,APLRT)
+DISC 18MARINERS STANDARD
+LUCM 652210
+**** 0
+0001 500704
+LUPT 29LU00704NIL$LINESL00009OLINES
+ATTC 13$SCODECLRLIN
+INST 17LS(SOLD,2,NINFO)
+DISC 18MARINERS STANDARD
+LUCM 653020
+**** 0
+0001 500705
+LUPT 29LU00705NIL$LINESL00005OLINES
+ATTC 12$SCODELINE1
+INST 17LS(SOLD,3,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500706
+LUPT 29LU00706NIL$LINESL00005OLINES
+ATTC 12$SCODELINE2
+INST 17LS(SOLD,3,RESBL)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500707
+LUPT 29LU00707NIL$LINESL00005OLINES
+ATTC 12$SCODELINE3
+INST 17LS(SOLD,3,DEPSC)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500708
+LUPT 29LU00708NIL$LINESL00005OLINES
+ATTC 12$SCODELINE4
+INST 17LS(SOLD,3,RADLO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500709
+LUPT 29LU00709NIL$LINESL00005OLINES
+ATTC 12$SCODELINE5
+INST 17LS(SOLD,3,NINFO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500710
+LUPT 29LU00710NIL$LINESL00005OLINES
+ATTC 12$SCODELINE6
+INST 17LS(SOLD,3,RADLO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500711
+LUPT 29LU00711NIL$LINESL00005OLINES
+ATTC 12$SCODELINE7
+INST 17LS(SOLD,3,RESBL)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500712
+LUPT 29LU00712NIL$LINESL00005OLINES
+ATTC 12$SCODELINE8
+INST 17LS(SOLD,3,NINFO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500713
+LUPT 29LU00713NIL$LINESL00005OLINES
+ATTC 12$SCODELINE9
+INST 17LS(SOLD,3,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500714
+LUPT 29LU00714NIL$LINESL00005OLINES
+ATTC 13$SCODELINE10
+INST 17LS(SOLD,3,DEPSC)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500715
+LUPT 29LU00715NIL$LINESL00005OLINES
+ATTC 13$SCODELINE11
+INST 17LS(SOLD,3,TRFCD)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500716
+LUPT 29LU00716NIL$LINESL00005OLINES
+ATTC 13$SCODELINE12
+INST 17LS(SOLD,3,ADINF)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500717
+LUPT 29LU00717NIL$LINESL00005OLINES
+ATTC 13$SCODELINE13
+INST 17LS(SOLD,3,RADLO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500718
+LUPT 29LU00718NIL$LINESL00005OLINES
+ATTC 13$SCODELINE14
+INST 17LS(SOLD,3,NINFO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500719
+LUPT 29LU00719NIL$LINESL00005OLINES
+ATTC 13$SCODELINE15
+INST 17LS(SOLD,3,ADINF)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500720
+LUPT 29LU00720NIL$LINESL00005OLINES
+ATTC 13$SCODELINE16
+INST 17LS(SOLD,3,NINFO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500721
+LUPT 29LU00721NIL$LINESL00005OLINES
+ATTC 13$SCODELINE17
+INST 17LS(SOLD,3,DEPSC)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500722
+LUPT 29LU00722NIL$LINESL00005OLINES
+ATTC 13$SCODELINE18
+INST 17LS(SOLD,3,RADLO)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500723
+LUPT 29LU00723NIL$LINESL00005OLINES
+ATTC 13$SCODELINE19
+INST 17LS(SOLD,3,ADINF)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500724
+LUPT 29LU00724NIL$LINESL00005OLINES
+ATTC 13$SCODELINE20
+INST 17LS(SOLD,3,RESBL)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500725
+LUPT 29LU00725NIL$TEXTSL00008OLINES
+ATTC 1
+INST 59TX($TXSTR,$JUSTH=3,$JUSTV=1,$SPACE=2,'15110',0,0,CHBLK,27)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 500726
+LUPT 34LU00726NIL######P00005OSIMPLIFIED
+ATTC 1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 500727
+LUPT 34LU00727NILACHAREP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(ACHARE02)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500728
+LUPT 34LU00728NILACHBRTP00005OSIMPLIFIED
+ATTC 1
+INST 61SY(ACHBRT07);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 500729
+LUPT 34LU00729NILAIRAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(AIRARE02)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 500730
+LUPT 34LU00730NILBCNCARP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BCNDEF13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500731
+LUPT 34LU00731NILBCNCARP00008OSIMPLIFIED
+ATTC 8CATCAM4
+INST 63SY(BCNCAR04);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500732
+LUPT 34LU00732NILBCNCARP00008OSIMPLIFIED
+ATTC 8CATCAM3
+INST 63SY(BCNCAR03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500733
+LUPT 34LU00733NILBCNCARP00008OSIMPLIFIED
+ATTC 8CATCAM2
+INST 63SY(BCNCAR02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500734
+LUPT 34LU00734NILBCNCARP00008OSIMPLIFIED
+ATTC 8CATCAM1
+INST 63SY(BCNCAR01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500735
+LUPT 34LU00735NILBCNISDP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BCNISD21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500736
+LUPT 34LU00736NILBCNLATP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BCNDEF13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500737
+LUPT 34LU00737NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP1
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500738
+LUPT 34LU00738NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP2
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500739
+LUPT 34LU00739NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP7
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500740
+LUPT 34LU00740NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP1
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500741
+LUPT 34LU00741NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP2
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500742
+LUPT 34LU00742NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP7
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500743
+LUPT 34LU00743NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP3
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500744
+LUPT 34LU00744NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP4
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500745
+LUPT 34LU00745NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR3,4,3BCNSHP5
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500746
+LUPT 34LU00746NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP3
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500747
+LUPT 34LU00747NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP4
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500748
+LUPT 34LU00748NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP5
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500749
+LUPT 34LU00749NILBCNLATP00008OSIMPLIFIED
+ATTC 20COLOUR4,3,4BCNSHP6
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500750
+LUPT 34LU00750NILBCNLATP00008OSIMPLIFIED
+ATTC 12COLOUR3,4,3
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500751
+LUPT 34LU00751NILBCNLATP00008OSIMPLIFIED
+ATTC 12COLOUR4,3,4
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500752
+LUPT 34LU00752NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP1
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500753
+LUPT 34LU00753NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP2
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500754
+LUPT 34LU00754NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP7
+INST 63SY(BCNLAT21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500755
+LUPT 34LU00755NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP1
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500756
+LUPT 34LU00756NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP2
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500757
+LUPT 34LU00757NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP7
+INST 63SY(BCNLAT22);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500758
+LUPT 34LU00758NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP3
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500759
+LUPT 34LU00759NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP4
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500760
+LUPT 34LU00760NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR3BCNSHP5
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500761
+LUPT 34LU00761NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP3
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500762
+LUPT 34LU00762NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP4
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500763
+LUPT 34LU00763NILBCNLATP00008OSIMPLIFIED
+ATTC 16COLOUR4BCNSHP5
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500764
+LUPT 34LU00764NILBCNLATP00008OSIMPLIFIED
+ATTC 8COLOUR3
+INST 63SY(BCNLAT15);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500765
+LUPT 34LU00765NILBCNLATP00008OSIMPLIFIED
+ATTC 8COLOUR4
+INST 63SY(BCNLAT16);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500766
+LUPT 34LU00766NILBCNSAWP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BCNSAW13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500767
+LUPT 34LU00767NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP1
+INST 63SY(BCNSAW21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500768
+LUPT 34LU00768NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP2
+INST 63SY(BCNSAW21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500769
+LUPT 34LU00769NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP7
+INST 63SY(BCNSAW21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500770
+LUPT 34LU00770NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP3
+INST 63SY(BCNSAW13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500771
+LUPT 34LU00771NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP4
+INST 63SY(BCNSAW13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500772
+LUPT 34LU00772NILBCNSAWP00008OSIMPLIFIED
+ATTC 8BCNSHP5
+INST 63SY(BCNSAW13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500773
+LUPT 34LU00773NILBCNSPPP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BCNSPP21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500774
+LUPT 34LU00774NILBCNSPPP00008OSIMPLIFIED
+ATTC 16BCNSHP6CONVIS1
+INST 63SY(CAIRNS11);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500775
+LUPT 34LU00775NILBCNSPPP00008OSIMPLIFIED
+ATTC 9CATSPM18
+INST 63SY(NOTBRD11);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500776
+LUPT 34LU00776NILBCNSPPP00008OSIMPLIFIED
+ATTC 9CATSPM44
+INST 63SY(BCNSPP13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500777
+LUPT 34LU00777NILBCNSPPP00008OSIMPLIFIED
+ATTC 9CATSPM52
+INST 63SY(BCNDEF13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500778
+LUPT 34LU00778NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP1
+INST 63SY(BCNSPP21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500779
+LUPT 34LU00779NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP3
+INST 63SY(BCNSPP13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500780
+LUPT 34LU00780NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP4
+INST 63SY(BCNSPP13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500781
+LUPT 34LU00781NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP5
+INST 63SY(BCNSPP13);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500782
+LUPT 34LU00782NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP6
+INST 63SY(CAIRNS01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500783
+LUPT 34LU00783NILBCNSPPP00008OSIMPLIFIED
+ATTC 8BCNSHP7
+INST 63SY(BCNSPP21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 500784
+LUPT 34LU00784NILBERTHSP00003OSIMPLIFIED
+ATTC 1
+INST 61SY(BRTHNO01);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500785
+LUPT 34LU00785NILBOYCARP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYDEF03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500786
+LUPT 34LU00786NILBOYCARP00008OSIMPLIFIED
+ATTC 8CATCAM4
+INST 63SY(BOYCAR04);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500787
+LUPT 34LU00787NILBOYCARP00008OSIMPLIFIED
+ATTC 8CATCAM3
+INST 63SY(BOYCAR03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500788
+LUPT 34LU00788NILBOYCARP00008OSIMPLIFIED
+ATTC 8CATCAM2
+INST 63SY(BOYCAR02);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500789
+LUPT 34LU00789NILBOYCARP00008OSIMPLIFIED
+ATTC 8CATCAM1
+INST 63SY(BOYCAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500790
+LUPT 34LU00790NILBOYINBP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYMOR11);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500791
+LUPT 34LU00791NILBOYISDP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYISD12);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500792
+LUPT 34LU00792NILBOYLATP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYDEF03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500793
+LUPT 34LU00793NILBOYLATP00008OSIMPLIFIED
+ATTC 20BOYSHP1COLOUR3,4,3
+INST 63SY(BOYLAT14);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500794
+LUPT 34LU00794NILBOYLATP00008OSIMPLIFIED
+ATTC 20BOYSHP1COLOUR4,3,4
+INST 63SY(BOYLAT13);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500795
+LUPT 34LU00795NILBOYLATP00008OSIMPLIFIED
+ATTC 20BOYSHP2COLOUR3,4,3
+INST 63SY(BOYLAT24);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500796
+LUPT 34LU00796NILBOYLATP00008OSIMPLIFIED
+ATTC 20BOYSHP2COLOUR4,3,4
+INST 63SY(BOYLAT23);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500797
+LUPT 34LU00797NILBOYLATP00008OSIMPLIFIED
+ATTC 20CATLAM3COLOUR3,4,3
+INST 63SY(BOYLAT24);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500798
+LUPT 34LU00798NILBOYLATP00008OSIMPLIFIED
+ATTC 20CATLAM3COLOUR4,3,4
+INST 63SY(BOYLAT23);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500799
+LUPT 34LU00799NILBOYLATP00008OSIMPLIFIED
+ATTC 20CATLAM4COLOUR3,4,3
+INST 63SY(BOYLAT14);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500800
+LUPT 34LU00800NILBOYLATP00008OSIMPLIFIED
+ATTC 20CATLAM4COLOUR4,3,4
+INST 63SY(BOYLAT13);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500801
+LUPT 34LU00801NILBOYLATP00008OSIMPLIFIED
+ATTC 16BOYSHP1COLOUR3
+INST 63SY(BOYLAT14);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500802
+LUPT 34LU00802NILBOYLATP00008OSIMPLIFIED
+ATTC 16BOYSHP1COLOUR4
+INST 63SY(BOYLAT13);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500803
+LUPT 34LU00803NILBOYLATP00008OSIMPLIFIED
+ATTC 16BOYSHP2COLOUR3
+INST 63SY(BOYLAT24);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500804
+LUPT 34LU00804NILBOYLATP00008OSIMPLIFIED
+ATTC 16BOYSHP2COLOUR4
+INST 63SY(BOYLAT23);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500805
+LUPT 34LU00805NILBOYLATP00008OSIMPLIFIED
+ATTC 16CATLAM1COLOUR3
+INST 63SY(BOYLAT24);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500806
+LUPT 34LU00806NILBOYLATP00008OSIMPLIFIED
+ATTC 16CATLAM1COLOUR4
+INST 63SY(BOYLAT23);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500807
+LUPT 34LU00807NILBOYLATP00008OSIMPLIFIED
+ATTC 16CATLAM2COLOUR3
+INST 63SY(BOYLAT14);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500808
+LUPT 34LU00808NILBOYLATP00008OSIMPLIFIED
+ATTC 16CATLAM2COLOUR4
+INST 63SY(BOYLAT13);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500809
+LUPT 34LU00809NILBOYSAWP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYSAW12);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500810
+LUPT 34LU00810NILBOYSPPP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(BOYSPP11);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500811
+LUPT 34LU00811NILBOYSPPP00008OSIMPLIFIED
+ATTC 17CATSPM19BOYSHP1
+INST 63SY(BOYSPP15);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500812
+LUPT 34LU00812NILBOYSPPP00008OSIMPLIFIED
+ATTC 17CATSPM19BOYSHP2
+INST 63SY(BOYSPP25);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500813
+LUPT 34LU00813NILBOYSPPP00008OSIMPLIFIED
+ATTC 8CATSPM9
+INST 63SY(BOYSUP02);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500814
+LUPT 34LU00814NILBOYSPPP00008OSIMPLIFIED
+ATTC 9CATSPM15
+INST 63SY(BOYSUP02);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500815
+LUPT 34LU00815NILBOYSPPP00008OSIMPLIFIED
+ATTC 9CATSPM52
+INST 63SY(BOYDEF03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500816
+LUPT 34LU00816NILBOYSPPP00008OSIMPLIFIED
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP02);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500817
+LUPT 34LU00817NILBRIDGEP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500818
+LUPT 34LU00818NILBUAAREP00003OSIMPLIFIED
+ATTC 1
+INST 51SY(BUAARE02);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 622240
+**** 0
+0001 500819
+LUPT 34LU00819NILBUISGLP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(BUISGL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500820
+LUPT 34LU00820NILBUISGLP00006OSIMPLIFIED
+ATTC 24FUNCTN33CONVIS1OBJNAM
+INST 51SY(POSGEN03);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500821
+LUPT 34LU00821NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500822
+LUPT 34LU00822NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500823
+LUPT 34LU00823NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN22CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500824
+LUPT 34LU00824NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN23CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500825
+LUPT 34LU00825NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN24CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500826
+LUPT 34LU00826NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN25CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500827
+LUPT 34LU00827NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN26CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500828
+LUPT 34LU00828NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN27CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500829
+LUPT 34LU00829NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN33CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500830
+LUPT 34LU00830NILBUISGLP00006OSIMPLIFIED
+ATTC 17FUNCTN35CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500831
+LUPT 34LU00831NILBUISGLP00004OSIMPLIFIED
+ATTC 16FUNCTN33OBJNAM
+INST 51SY(POSGEN03);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500832
+LUPT 34LU00832NILBUISGLP00006OSIMPLIFIED
+ATTC 8CONVIS1
+INST 13SY(BUISGL11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500833
+LUPT 34LU00833NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500834
+LUPT 34LU00834NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN21
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500835
+LUPT 34LU00835NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN22
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500836
+LUPT 34LU00836NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN23
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500837
+LUPT 34LU00837NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN24
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500838
+LUPT 34LU00838NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN25
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500839
+LUPT 34LU00839NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN26
+INST 13SY(BUIREL05)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500840
+LUPT 34LU00840NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN27
+INST 13SY(BUIREL05)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500841
+LUPT 34LU00841NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN33
+INST 13SY(POSGEN03)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500842
+LUPT 34LU00842NILBUISGLP00004OSIMPLIFIED
+ATTC 9FUNCTN35
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500843
+LUPT 34LU00843NILCGUSTAP00007OSIMPLIFIED
+ATTC 1
+INST 13SY(CGUSTA02)
+DISC 6OTHER
+LUCM 638030
+**** 0
+0001 500844
+LUPT 34LU00844NILCHKPNTP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500845
+LUPT 34LU00845NILCRANESP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CRANES01)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500846
+LUPT 34LU00846NILCTNAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 500847
+LUPT 34LU00847NILCTRPNTP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(POSGEN04)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 500848
+LUPT 34LU00848NILCTSAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500849
+LUPT 34LU00849NILCURENTP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500850
+LUPT 34LU00850NILCURENTP00005OSIMPLIFIED
+ATTC 14ORIENTCURVEL
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500851
+LUPT 34LU00851NILCURENTP00005OSIMPLIFIED
+ATTC 7ORIENT
+INST 20SY(CURENT01,ORIENT)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 500852
+LUPT 34LU00852NILDAMCONP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500853
+LUPT 34LU00853NILDAMCONP00004OSIMPLIFIED
+ATTC 8CATDAM3
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500854
+LUPT 34LU00854NILDAYMARP00007OSIMPLIFIED
+ATTC 1
+INST 63SY(DAYSQR01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500855
+LUPT 34LU00855NILDAYMARP00007OSIMPLIFIED
+ATTC 9TOPSHP19
+INST 63SY(DAYSQR01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500856
+LUPT 34LU00856NILDAYMARP00007OSIMPLIFIED
+ATTC 9TOPSHP20
+INST 63SY(DAYSQR01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500857
+LUPT 34LU00857NILDAYMARP00007OSIMPLIFIED
+ATTC 9TOPSHP21
+INST 63SY(DAYSQR01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500858
+LUPT 34LU00858NILDAYMARP00007OSIMPLIFIED
+ATTC 9TOPSHP24
+INST 63SY(DAYTRI01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500859
+LUPT 34LU00859NILDAYMARP00007OSIMPLIFIED
+ATTC 9TOPSHP25
+INST 63SY(DAYTRI05);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 500860
+LUPT 34LU00860NILDISMARP00007OSIMPLIFIED
+ATTC 1
+INST 51SY(DISMAR03);TX(INFORM,2,1,2,'15110',2,0,CHBLK,21)
+DISC 6OTHER
+LUCM 632430
+**** 0
+0001 500861
+LUPT 34LU00861NILDISMARP00007OSIMPLIFIED
+ATTC 8CATDIS1
+INST 51SY(DISMAR04);TX(INFORM,2,1,2,'15110',2,0,CHBLK,21)
+DISC 6OTHER
+LUCM 632430
+**** 0
+0001 500862
+LUPT 34LU00862NILDMPGRDP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 500863
+LUPT 34LU00863NILFOGSIGP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(FOGSIG01)
+DISC 9STANDARD
+LUCM 627080
+**** 0
+0001 500864
+LUPT 34LU00864NILFORSTCP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(FORSTC01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500865
+LUPT 34LU00865NILFORSTCP00004OSIMPLIFIED
+ATTC 8CONVIS1
+INST 13SY(FORSTC11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500866
+LUPT 34LU00866NILFSHFACP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(FSHHAV01)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500867
+LUPT 34LU00867NILFSHFACP00004OSIMPLIFIED
+ATTC 8CATFIF1
+INST 13SY(FSHFAC03)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500868
+LUPT 34LU00868NILFSHFACP00004OSIMPLIFIED
+ATTC 8CATFIF2
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500869
+LUPT 34LU00869NILFSHFACP00004OSIMPLIFIED
+ATTC 8CATFIF3
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500870
+LUPT 34LU00870NILFSHFACP00004OSIMPLIFIED
+ATTC 8CATFIF4
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 500871
+LUPT 34LU00871NILGATCONP00008OSIMPLIFIED
+ATTC 1
+INST 13SY(GATCON04)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500872
+LUPT 34LU00872NILGATCONP00008OSIMPLIFIED
+ATTC 8CATGAT2
+INST 13SY(GATCON04)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 500873
+LUPT 34LU00873NILGATCONP00008OSIMPLIFIED
+ATTC 8CATGAT3
+INST 13SY(GATCON04)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500874
+LUPT 34LU00874NILGATCONP00008OSIMPLIFIED
+ATTC 8CATGAT4
+INST 13SY(GATCON03)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500875
+LUPT 34LU00875NILGRIDRNP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500876
+LUPT 34LU00876NILHRBFACP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500877
+LUPT 34LU00877NILHRBFACP00004OSIMPLIFIED
+ATTC 8CATHAF1
+INST 13SY(ROLROL01)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500878
+LUPT 34LU00878NILHRBFACP00004OSIMPLIFIED
+ATTC 8CATHAF4
+INST 13SY(HRBFAC09)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500879
+LUPT 34LU00879NILHRBFACP00004OSIMPLIFIED
+ATTC 8CATHAF5
+INST 13SY(SMCFAC02)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 500880
+LUPT 34LU00880NILHULKESP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(HULKES01)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500881
+LUPT 34LU00881NILICNAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 500882
+LUPT 34LU00882NILLIGHTSP00008OSIMPLIFIED
+ATTC 1
+INST 13CS(LIGHTS05)
+DISC 9STANDARD
+LUCM 627070
+**** 0
+0001 500883
+LUPT 34LU00883NILLITFLTP00008OSIMPLIFIED
+ATTC 1
+INST 63SY(LITFLT02);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500884
+LUPT 34LU00884NILLITVESP00008OSIMPLIFIED
+ATTC 1
+INST 64SY(LITVES02);TE('LtV %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617011
+**** 0
+0001 500885
+LUPT 34LU00885NILLNDAREP00004OSIMPLIFIED
+ATTC 1
+INST 26SY(LNDARE01);CS(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612010
+**** 0
+0001 500886
+LUPT 34LU00886NILLNDELVP00004OSIMPLIFIED
+ATTC 1
+INST 52SY(POSGEN04);TX(ELEVAT,3,2,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500887
+LUPT 34LU00887NILLNDMRKP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(POSGEN01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500888
+LUPT 34LU00888NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK17FUNCTN33CONVIS1
+INST 52SY(TOWERS03);TX(OBJNAM,3,2,2,'15110',1,-1,CHBLK,26)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500889
+LUPT 34LU00889NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK15FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500890
+LUPT 34LU00890NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK15FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500891
+LUPT 34LU00891NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK17FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500892
+LUPT 34LU00892NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK17FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500893
+LUPT 34LU00893NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK20FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500894
+LUPT 34LU00894NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK20FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500895
+LUPT 34LU00895NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK20FUNCTN26CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500896
+LUPT 34LU00896NILLNDMRKP00006OSIMPLIFIED
+ATTC 26CATLMK20FUNCTN27CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500897
+LUPT 34LU00897NILLNDMRKP00004OSIMPLIFIED
+ATTC 18CATLMK17FUNCTN33
+INST 52SY(TOWERS01);TX(OBJNAM,3,2,2,'15110',1,-1,CHBLK,26)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500898
+LUPT 34LU00898NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK1CONVIS1
+INST 13SY(CAIRNS11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500899
+LUPT 34LU00899NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK3CONVIS1
+INST 13SY(CHIMNY11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500900
+LUPT 34LU00900NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK4CONVIS1
+INST 13SY(DSHAER11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500901
+LUPT 34LU00901NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK5CONVIS1
+INST 13SY(FLGSTF01)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500902
+LUPT 34LU00902NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK6CONVIS1
+INST 13SY(FLASTK11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500903
+LUPT 34LU00903NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK7CONVIS1
+INST 13SY(MSTCON14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500904
+LUPT 34LU00904NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK8CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500905
+LUPT 34LU00905NILLNDMRKP00006OSIMPLIFIED
+ATTC 16CATLMK9CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500906
+LUPT 34LU00906NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK10CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500907
+LUPT 34LU00907NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK12CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500908
+LUPT 34LU00908NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK13CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500909
+LUPT 34LU00909NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK15CONVIS1
+INST 13SY(DOMES011)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500910
+LUPT 34LU00910NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK16CONVIS1
+INST 13SY(RASCAN11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500911
+LUPT 34LU00911NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK17CONVIS1
+INST 13SY(TOWERS03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500912
+LUPT 34LU00912NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK18CONVIS1
+INST 13SY(WNDMIL12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500913
+LUPT 34LU00913NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK19CONVIS1
+INST 13SY(WIMCON11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500914
+LUPT 34LU00914NILLNDMRKP00006OSIMPLIFIED
+ATTC 17CATLMK20CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500915
+LUPT 34LU00915NILLNDMRKP00004OSIMPLIFIED
+ATTC 18CATLMK15FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500916
+LUPT 34LU00916NILLNDMRKP00004OSIMPLIFIED
+ATTC 18CATLMK17FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500917
+LUPT 34LU00917NILLNDMRKP00004OSIMPLIFIED
+ATTC 18CATLMK20FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500918
+LUPT 34LU00918NILLNDMRKP00004OSIMPLIFIED
+ATTC 8CATLMK3
+INST 13SY(CHIMNY01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500919
+LUPT 34LU00919NILLNDMRKP00004OSIMPLIFIED
+ATTC 8CATLMK6
+INST 13SY(FLASTK01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500920
+LUPT 34LU00920NILLNDMRKP00004OSIMPLIFIED
+ATTC 8CATLMK7
+INST 13SY(MSTCON04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500921
+LUPT 34LU00921NILLNDMRKP00004OSIMPLIFIED
+ATTC 9CATLMK15
+INST 13SY(DOMES001)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500922
+LUPT 34LU00922NILLNDMRKP00004OSIMPLIFIED
+ATTC 9CATLMK16
+INST 13SY(RASCAN01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500923
+LUPT 34LU00923NILLNDMRKP00004OSIMPLIFIED
+ATTC 9CATLMK17
+INST 13SY(TOWERS01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500924
+LUPT 34LU00924NILLNDMRKP00006OSIMPLIFIED
+ATTC 8CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500925
+LUPT 34LU00925NILLNDRGNP00004OSIMPLIFIED
+ATTC 1
+INST 52SY(POSGEN04);TX(OBJNAM,1,2,2,'15110',0,-1,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500926
+LUPT 34LU00926NILLOCMAGP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(LOCMAG01)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500927
+LUPT 34LU00927NILLOGPONP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500928
+LUPT 34LU00928NILM_NPUBP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 631020
+**** 0
+0001 500929
+LUPT 34LU00929NILMAGVARP00004OSIMPLIFIED
+ATTC 1
+INST 52SY(MAGVAR01);TX(VALMAG,3,1,2,'15110',1,-1,CHBLK,27)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 500930
+LUPT 34LU00930NILMARCULP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(MARCUL02)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 500931
+LUPT 34LU00931NILMIPAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500932
+LUPT 34LU00932NILMORFACP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(MORFAC03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500933
+LUPT 34LU00933NILMORFACP00006OSIMPLIFIED
+ATTC 8CATMOR1
+INST 13SY(MORFAC03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500934
+LUPT 34LU00934NILMORFACP00006OSIMPLIFIED
+ATTC 8CATMOR2
+INST 13SY(MORFAC04)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500935
+LUPT 34LU00935NILMORFACP00006OSIMPLIFIED
+ATTC 8CATMOR3
+INST 13SY(PILPNT02)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 500936
+LUPT 34LU00936NILMORFACP00006OSIMPLIFIED
+ATTC 8CATMOR5
+INST 13SY(PILPNT02)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500937
+LUPT 34LU00937NILMORFACP00008OSIMPLIFIED
+ATTC 8CATMOR7
+INST 13SY(BOYMOR11)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 500938
+LUPT 34LU00938NILOBSTRNP00004OSIMPLIFIED
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500939
+LUPT 34LU00939NILOBSTRNP00004OSIMPLIFIED
+ATTC 8CATOBS7
+INST 13SY(FOULGND1)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500940
+LUPT 34LU00940NILOBSTRNP00004OSIMPLIFIED
+ATTC 8CATOBS9
+INST 13SY(ACHARE02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 500941
+LUPT 34LU00941NILOFSPLFP00005OSIMPLIFIED
+ATTC 1
+INST 64SY(OFSPLF01);TE('Prod %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500942
+LUPT 34LU00942NILPILBOPP00006OSIMPLIFIED
+ATTC 1
+INST 63SY(PILBOP02);TE('Plt %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 628010
+**** 0
+0001 500943
+LUPT 34LU00943NILPILPNTP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(PILPNT02)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500944
+LUPT 34LU00944NILPIPAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 500945
+LUPT 34LU00945NILPIPSOLP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500946
+LUPT 34LU00946NILPRCAREP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(PRCARE12)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 500947
+LUPT 34LU00947NILPRDAREP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500948
+LUPT 34LU00948NILPRDAREP00004OSIMPLIFIED
+ATTC 16CATPRA5CONVIS1
+INST 13SY(FLASTK11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500949
+LUPT 34LU00949NILPRDAREP00004OSIMPLIFIED
+ATTC 16CATPRA8CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500950
+LUPT 34LU00950NILPRDAREP00004OSIMPLIFIED
+ATTC 16CATPRA9CONVIS1
+INST 13SY(WIMCON11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500951
+LUPT 34LU00951NILPRDAREP00003OSIMPLIFIED
+ATTC 8CATPRA1
+INST 13SY(PRDINS02)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500952
+LUPT 34LU00952NILPRDAREP00003OSIMPLIFIED
+ATTC 8CATPRA5
+INST 13SY(FLASTK01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500953
+LUPT 34LU00953NILPRDAREP00003OSIMPLIFIED
+ATTC 8CATPRA6
+INST 13SY(TMBYRD01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500954
+LUPT 34LU00954NILPRDAREP00003OSIMPLIFIED
+ATTC 8CATPRA8
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500955
+LUPT 34LU00955NILPRDAREP00003OSIMPLIFIED
+ATTC 8CATPRA9
+INST 13SY(WIMCON01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 500956
+LUPT 34LU00956NILPYLONSP00008OSIMPLIFIED
+ATTC 1
+INST 13SY(POSGEN03)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 500957
+LUPT 34LU00957NILRADRFLP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(RADRFL03)
+DISC 9STANDARD
+LUCM 627230
+**** 0
+0001 500958
+LUPT 34LU00958NILRADSTAP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(POSGEN01)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 500959
+LUPT 34LU00959NILRADSTAP00005OSIMPLIFIED
+ATTC 8CATRAS2
+INST 61SY(RDOSTA02);TE('ch %s','COMCHA',3,1,2,'15110',0,0,CHBLK,11)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 500960
+LUPT 34LU00960NILRAPIDSP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500961
+LUPT 34LU00961NILRCTLPTP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(RTLDEF51)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500962
+LUPT 34LU00962NILRCTLPTP00004OSIMPLIFIED
+ATTC 7ORIENT
+INST 20SY(RCTLPT52,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 500963
+LUPT 34LU00963NILRDOCALP00006OSIMPLIFIED
+ATTC 1
+INST 62SY(RCLDEF01);TE('No %s','OBJNAM',3,2,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500964
+LUPT 34LU00964NILRDOCALP00006OSIMPLIFIED
+ATTC 15TRAFIC1ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500965
+LUPT 34LU00965NILRDOCALP00006OSIMPLIFIED
+ATTC 15TRAFIC2ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500966
+LUPT 34LU00966NILRDOCALP00006OSIMPLIFIED
+ATTC 15TRAFIC3ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500967
+LUPT 34LU00967NILRDOCALP00006OSIMPLIFIED
+ATTC 15TRAFIC4ORIENT
+INST 117SY(RDOCAL03,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 500968
+LUPT 34LU00968NILRDOSTAP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(RDOSTA02)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 500969
+LUPT 34LU00969NILRETRFLP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(RETRFL02)
+DISC 9STANDARD
+LUCM 627080
+**** 0
+0001 500970
+LUPT 34LU00970NILROADWYP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500971
+LUPT 34LU00971NILRSCSTAP00007OSIMPLIFIED
+ATTC 1
+INST 13SY(RSCSTA02)
+DISC 6OTHER
+LUCM 638030
+**** 0
+0001 500972
+LUPT 34LU00972NILRTPBCNP00006OSIMPLIFIED
+ATTC 1
+INST 13SY(RTPBCN02)
+DISC 9STANDARD
+LUCM 627210
+**** 0
+0001 500973
+LUPT 34LU00973NILRUNWAYP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500974
+LUPT 34LU00974NILSBDAREP00004OSIMPLIFIED
+ATTC 1
+INST 38TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 500975
+LUPT 34LU00975NILSEAAREP00003SSIMPLIFIED
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 500976
+LUPT 34LU00976NILSILTNKP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500977
+LUPT 34LU00977NILSILTNKP00004OSIMPLIFIED
+ATTC 16CATSIL1CONVIS1
+INST 13SY(SILBUI11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500978
+LUPT 34LU00978NILSILTNKP00004OSIMPLIFIED
+ATTC 16CATSIL2CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500979
+LUPT 34LU00979NILSILTNKP00004OSIMPLIFIED
+ATTC 16CATSIL3CONVIS1
+INST 13SY(TOWERS03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500980
+LUPT 34LU00980NILSILTNKP00004OSIMPLIFIED
+ATTC 16CATSIL4CONVIS1
+INST 13SY(TOWERS12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500981
+LUPT 34LU00981NILSILTNKP00004OSIMPLIFIED
+ATTC 8CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500982
+LUPT 34LU00982NILSILTNKP00004OSIMPLIFIED
+ATTC 8CATSIL1
+INST 13SY(SILBUI01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500983
+LUPT 34LU00983NILSILTNKP00004OSIMPLIFIED
+ATTC 8CATSIL2
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500984
+LUPT 34LU00984NILSILTNKP00004OSIMPLIFIED
+ATTC 8CATSIL3
+INST 13SY(TOWERS01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500985
+LUPT 34LU00985NILSILTNKP00004OSIMPLIFIED
+ATTC 8CATSIL4
+INST 13SY(TOWERS02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 500986
+LUPT 34LU00986NILSISTATP00007OSIMPLIFIED
+ATTC 1
+INST 13SY(SISTAT02)
+DISC 9STANDARD
+LUCM 628020
+**** 0
+0001 500987
+LUPT 34LU00987NILSISTAWP00007OSIMPLIFIED
+ATTC 1
+INST 13SY(SISTAT02)
+DISC 9STANDARD
+LUCM 628020
+**** 0
+0001 500988
+LUPT 34LU00988NILSLCONSP00008OSIMPLIFIED
+ATTC 1
+INST 26SY(MORFAC03);CS(SLCONS03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 500989
+LUPT 34LU00989NILSLOGRDP00003SSIMPLIFIED
+ATTC 1
+INST 13SY(HILTOP01)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500990
+LUPT 34LU00990NILSLOTOPP00003SSIMPLIFIED
+ATTC 1
+INST 13SY(HILTOP01)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 500991
+LUPT 34LU00991NILSLOTOPP00003SSIMPLIFIED
+ATTC 8CONVIS1
+INST 13SY(HILTOP11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 500992
+LUPT 34LU00992NILSMCFACP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 500993
+LUPT 34LU00993NILSNDWAVP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(SNDWAV02)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 500994
+LUPT 34LU00994NILSOUNDGP00006OSIMPLIFIED
+ATTC 1
+INST 13CS(SOUNDG02)
+DISC 6OTHER
+LUCM 633010
+**** 0
+0001 500995
+LUPT 34LU00995NILSPLAREP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 500996
+LUPT 34LU00996NILSPRINGP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(SPRING02)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 500997
+LUPT 34LU00997NILT_HMONP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500998
+LUPT 34LU00998NILT_NHMNP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 500999
+LUPT 34LU00999NILT_TIMSP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 501000
+LUPT 34LU01000NILTS_FEBP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(CURDEF01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501001
+LUPT 34LU01001NILTS_FEBP00004OSIMPLIFIED
+ATTC 15CAT_TS1ORIENT
+INST 73SY(FLDSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501002
+LUPT 34LU01002NILTS_FEBP00004OSIMPLIFIED
+ATTC 15CAT_TS2ORIENT
+INST 73SY(EBBSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501003
+LUPT 34LU01003NILTS_FEBP00004OSIMPLIFIED
+ATTC 15CAT_TS3ORIENT
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501004
+LUPT 34LU01004NILTS_PADP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501005
+LUPT 34LU01005NILTS_PNHP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501006
+LUPT 34LU01006NILTS_PRHP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501007
+LUPT 34LU01007NILTS_TISP00004OSIMPLIFIED
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501008
+LUPT 34LU01008NILTOPMARP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501009
+LUPT 34LU01009NILTUNNELP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501010
+LUPT 34LU01010NILUWTROCP00004OSIMPLIFIED
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501011
+LUPT 34LU01011NILVEGATNP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501012
+LUPT 34LU01012NILWATFALP00000SSIMPLIFIED
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501013
+LUPT 34LU01013NILWATTURP00003OSIMPLIFIED
+ATTC 1
+INST 13SY(WATTUR02)
+DISC 6OTHER
+LUCM 633040
+**** 0
+0001 501014
+LUPT 34LU01014NILWEDKLPP00003OSIMPLIFIED
+ATTC 1
+INST 13SY(WEDKLP03)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 501015
+LUPT 34LU01015NILWRECKSP00004OSIMPLIFIED
+ATTC 1
+INST 13CS(WRECKS02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501016
+LUPT 34LU01016NILWRECKSP00004OSIMPLIFIED
+ATTC 8CATWRK3
+INST 13SY(FOULGND1)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501017
+LUPT 34LU01017NILcursorP00008OSIMPLIFIED
+ATTC 1
+INST 13SY(CURSRA01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501018
+LUPT 34LU01018NILcursorP00008OSIMPLIFIED
+ATTC 8cursty2
+INST 13SY(CURSRB01)
+DISC 15MARINERS OTHER
+LUCM 661040
+**** 0
+0001 501019
+LUPT 34LU01019NILdnghltP00008OSIMPLIFIED
+ATTC 1
+INST 13SY(DNGHILIT)
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 501020
+LUPT 34LU01020NILeventsP00008OSIMPLIFIED
+ATTC 1
+INST 51SY(EVENTS02);TX(OBJNAM,3,2,3,'15110',1,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 652410
+**** 0
+0001 501021
+LUPT 34LU01021NILmarfeaP00008OSIMPLIFIED
+ATTC 1
+INST 52SY(CHINFO09);TX(OBJNAM,3,1,3,'15110',1,-1,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653050
+**** 0
+0001 501022
+LUPT 34LU01022NILmarnotP00008OSIMPLIFIED
+ATTC 1
+INST 51SY(CHINFO09);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501023
+LUPT 34LU01023NILmarnotP00008OSIMPLIFIED
+ATTC 8catnot1
+INST 51SY(CHINFO08);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653030
+**** 0
+0001 501024
+LUPT 34LU01024NILmarnotP00008OSIMPLIFIED
+ATTC 8catnot2
+INST 51SY(CHINFO09);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501025
+LUPT 34LU01025NILmnufeaP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501026
+LUPT 34LU01026NILmnufeaP00005OSIMPLIFIED
+ATTC 8catnot1
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501027
+LUPT 34LU01027NILmnufeaP00005OSIMPLIFIED
+ATTC 8catnot2
+INST 13SY(CHINFO11)
+DISC 18MARINERS STANDARD
+LUCM 655020
+**** 0
+0001 501028
+LUPT 34LU01028NILownshpP00009OSIMPLIFIED
+ATTC 1
+INST 13CS(OWNSHP02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501029
+LUPT 34LU01029NILplnposP00005OSIMPLIFIED
+ATTC 1
+INST 72SY(PLNPOS01);SY(PLNPOS02,ORIENT);TX(plndat,1,2,2,'15110',4,3,CHBLK,50);
+DISC 18MARINERS STANDARD
+LUCM 652030
+**** 0
+0001 501030
+LUPT 34LU01030NILpositnP00005OSIMPLIFIED
+ATTC 1
+INST 52SY(POSITN02);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501031
+LUPT 34LU01031NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth1
+INST 89SY(POSITN02);TX('DR',2,3,2,'15110',-1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501032
+LUPT 34LU01032NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth2
+INST 89SY(POSITN02);TX('EP',2,3,2,'15110',-1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501033
+LUPT 34LU01033NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth3
+INST 87SY(POSITN02);TX('V',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501034
+LUPT 34LU01034NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth4
+INST 87SY(POSITN02);TX('A',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501035
+LUPT 34LU01035NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth5
+INST 87SY(POSITN02);TX('R',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501036
+LUPT 34LU01036NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth6
+INST 87SY(POSITN02);TX('D',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501037
+LUPT 34LU01037NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth7
+INST 87SY(POSITN02);TX('G',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501038
+LUPT 34LU01038NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth8
+INST 88SY(POSITN02);TX('Gl',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501039
+LUPT 34LU01039NILpositnP00005OSIMPLIFIED
+ATTC 8pfmeth9
+INST 87SY(POSITN02);TX('L',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501040
+LUPT 34LU01040NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth10
+INST 87SY(POSITN02);TX('M',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501041
+LUPT 34LU01041NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth11
+INST 87SY(POSITN02);TX('O',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501042
+LUPT 34LU01042NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth12
+INST 87SY(POSITN02);TX('T',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501043
+LUPT 34LU01043NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth13
+INST 88SY(POSITN02);TX('dG',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501044
+LUPT 34LU01044NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth14
+INST 89SY(POSITN02);TX('dGl',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501045
+LUPT 34LU01045NILpositnP00005OSIMPLIFIED
+ATTC 9pfmeth15
+INST 88SY(POSITN02);TX('dO',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501046
+LUPT 34LU01046NILrefpntP00007OSIMPLIFIED
+ATTC 1
+INST 13SY(REFPNT02)
+DISC 15MARINERS OTHER
+LUCM 661050
+**** 0
+0001 501047
+LUPT 34LU01047NILtidcurP00007OSIMPLIFIED
+ATTC 1
+INST 111SY(TIDCUR01,ORIENT);SY(TIDCUR03);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501048
+LUPT 34LU01048NILtidcurP00007OSIMPLIFIED
+ATTC 8catcur1
+INST 147SY(TIDCUR01,ORIENT);SY(TIDCUR03);TX('P',2,3,2,'15110',-4,2,CHBLK,50);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501049
+LUPT 34LU01049NILtidcurP00007OSIMPLIFIED
+ATTC 8catcur2
+INST 147SY(TIDCUR02,ORIENT);SY(TIDCUR03);TX('A',2,3,2,'15110',-4,2,CHBLK,50);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501050
+LUPT 34LU01050NILvesselP00009OSIMPLIFIED
+ATTC 1
+INST 13CS(VESSEL01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501051
+LUPT 34LU01051NILwaypntP00008OSIMPLIFIED
+ATTC 1
+INST 52SY(WAYPNT11);TX(OBJNAM,3,1,3,'15110',1,-1,APLRT,50)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501052
+LUPT 34LU01052NILwaypntP00008OSIMPLIFIED
+ATTC 8select1
+INST 52SY(WAYPNT11);TX(OBJNAM,3,1,3,'15110',1,-1,CHBLK,50)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501053
+LUPT 34LU01053NILwaypntP00008OSIMPLIFIED
+ATTC 8select2
+INST 52SY(WAYPNT03);TX(OBJNAM,3,1,3,'15110',1,-1,APLRT,50)
+DISC 18MARINERS STANDARD
+LUCM 652210
+**** 0
+0001 501054
+LUPT 34LU01054NIL$CSYMBP00005OSIMPLIFIED
+ATTC 1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 501055
+LUPT 34LU01055NIL$CSYMBP00005SSIMPLIFIED
+ATTC 15$SCODEBRIDGE01
+INST 13SY(BRIDGE01)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 501056
+LUPT 34LU01056NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODESCALEB10
+INST 13SY(SCALEB10)
+DISC 12DISPLAYBASE
+LUCM 611030
+**** 0
+0001 501057
+LUPT 34LU01057NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODESCALEB11
+INST 13SY(SCALEB11)
+DISC 12DISPLAYBASE
+LUCM 611030
+**** 0
+0001 501058
+LUPT 34LU01058NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODENORTHAR1
+INST 13SY(NORTHAR1)
+DISC 12DISPLAYBASE
+LUCM 611040
+**** 0
+0001 501059
+LUPT 34LU01059NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEUNITFTH1
+INST 13SY(UNITFTH1)
+DISC 12DISPLAYBASE
+LUCM 611000
+**** 0
+0001 501060
+LUPT 34LU01060NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEUNITMTR1
+INST 13SY(UNITMTR1)
+DISC 12DISPLAYBASE
+LUCM 611000
+**** 0
+0001 501061
+LUPT 34LU01061NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODECURSRA01
+INST 13SY(CURSRA01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501062
+LUPT 34LU01062NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODECURSRB01
+INST 13SY(CURSRB01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501063
+LUPT 34LU01063NIL$CSYMBP00007OSIMPLIFIED
+ATTC 15$SCODEREFPNT02
+INST 13SY(REFPNT02)
+DISC 15MARINERS OTHER
+LUCM 661050
+**** 0
+0001 501064
+LUPT 34LU01064NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODECHINFO09
+INST 13SY(CHINFO09)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501065
+LUPT 34LU01065NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODECHINFO08
+INST 13SY(CHINFO08)
+DISC 18MARINERS STANDARD
+LUCM 653030
+**** 0
+0001 501066
+LUPT 34LU01066NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODECHINFO11
+INST 13SY(CHINFO11)
+DISC 18MARINERS STANDARD
+LUCM 655020
+**** 0
+0001 501067
+LUPT 34LU01067NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODECHINFO10
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501068
+LUPT 34LU01068NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODELOWACC01
+INST 13SY(LOWACC01)
+DISC 9STANDARD
+LUCM 621000
+**** 0
+0001 501069
+LUPT 34LU01069NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEINFORM01
+INST 13SY(INFORM01)
+DISC 6OTHER
+LUCM 631030
+**** 0
+0001 501070
+LUPT 34LU01070NIL$CSYMBP00007OSIMPLIFIED
+ATTC 15$SCODEQUAPOS01
+INST 13SY(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501071
+LUPT 34LU01071NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODECHCRID01
+INST 13SY(CHCRID01)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501072
+LUPT 34LU01072NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODECHCRDEL1
+INST 13SY(CHCRDEL1)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501073
+LUPT 34LU01073NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODETREPNT04
+INST 13SY(TREPNT04)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 501074
+LUPT 34LU01074NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODETREPNT05
+INST 13SY(TREPNT05)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 501075
+LUPT 34LU01075NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODETOWERS15
+INST 13SY(TOWERS15)
+DISC 9STANDARD
+LUCM 622200
+**** 0
+0001 501076
+LUPT 34LU01076NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODETOWERS05
+INST 13SY(TOWERS05)
+DISC 6OTHER
+LUCM 632200
+**** 0
+0001 501077
+LUPT 34LU01077NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEOBSTRN11
+INST 13SY(OBSTRN11)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501078
+LUPT 34LU01078NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEOBSTRN01
+INST 13SY(OBSTRN01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501079
+LUPT 34LU01079NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEOBSTRN02
+INST 13SY(OBSTRN02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501080
+LUPT 34LU01080NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEOBSTRN03
+INST 13SY(OBSTRN03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501081
+LUPT 34LU01081NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEDANGER01
+INST 13SY(DANGER01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501082
+LUPT 34LU01082NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEDANGER02
+INST 13SY(DANGER02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501083
+LUPT 34LU01083NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEDANGER03
+INST 13SY(DANGER03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501084
+LUPT 34LU01084NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEQUARRY01
+INST 13SY(QUARRY01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501085
+LUPT 34LU01085NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODERFNERY01
+INST 13SY(RFNERY01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501086
+LUPT 34LU01086NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODERFNERY11
+INST 13SY(RFNERY11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501087
+LUPT 34LU01087NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODETNKFRM01
+INST 13SY(TNKFRM01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501088
+LUPT 34LU01088NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODETNKFRM11
+INST 13SY(TNKFRM11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501089
+LUPT 34LU01089NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEWNDFRM51
+INST 13SY(WNDFRM51)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501090
+LUPT 34LU01090NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEWNDFRM61
+INST 13SY(WNDFRM61)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501091
+LUPT 34LU01091NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODETMBYRD01
+INST 13SY(TMBYRD01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501092
+LUPT 34LU01092NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEISODGR01
+INST 13SY(ISODGR01)
+DISC 12DISPLAYBASE
+LUCM 614010
+**** 0
+0001 501093
+LUPT 34LU01093NIL$CSYMBP00006SSIMPLIFIED
+ATTC 15$SCODERECTRC55
+INST 13SY(RECTRC55)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501094
+LUPT 34LU01094NIL$CSYMBP00006SSIMPLIFIED
+ATTC 15$SCODERECTRC56
+INST 13SY(RECTRC56)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501095
+LUPT 34LU01095NIL$CSYMBP00006SSIMPLIFIED
+ATTC 15$SCODERECTRC57
+INST 13SY(RECTRC57)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501096
+LUPT 34LU01096NIL$CSYMBP00006SSIMPLIFIED
+ATTC 15$SCODERECTRC58
+INST 13SY(RECTRC58)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501097
+LUPT 34LU01097NIL$CSYMBP00006SSIMPLIFIED
+ATTC 15$SCODERECDEF51
+INST 13SY(RECDEF51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501098
+LUPT 34LU01098NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEDIRBOY01
+INST 13SY(DIRBOY01)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501099
+LUPT 34LU01099NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEDIRBOYA1
+INST 13SY(DIRBOYA1)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501100
+LUPT 34LU01100NIL$CSYMBP00004SSIMPLIFIED
+ATTC 15$SCODEDIRBOYB1
+INST 13SY(DIRBOYB1)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501101
+LUPT 34LU01101NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODERACNSP01
+INST 13SY(RACNSP01)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 501102
+LUPT 34LU01102NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODECHKSYM01
+INST 13SY(CHKSYM01)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501103
+LUPT 34LU01103NIL$CSYMBP00005SSIMPLIFIED
+ATTC 15$SCODEACHRES61
+INST 13SY(ACHRES61)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 501104
+LUPT 34LU01104NIL$CSYMBP00005SSIMPLIFIED
+ATTC 15$SCODEACHRES71
+INST 13SY(ACHRES71)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 501105
+LUPT 34LU01105NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEAISONE01
+INST 13SY(AISONE01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501106
+LUPT 34LU01106NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEAISSIX01
+INST 13SY(AISSIX01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501107
+LUPT 34LU01107NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEAISDEF01
+INST 13SY(AISDEF01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501108
+LUPT 34LU01108NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEAISSLP01
+INST 20SY(AISSLP01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501109
+LUPT 34LU01109NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEAISVES01
+INST 20SY(AISVES01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501110
+LUPT 34LU01110NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEARPATG01
+INST 13SY(ARPATG01)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501111
+LUPT 34LU01111NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEARPONE01
+INST 20SY(ARPONE01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501112
+LUPT 34LU01112NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEARPSIX01
+INST 20SY(ARPSIX01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501113
+LUPT 34LU01113NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEVECWTR01
+INST 13SY(VECWTR01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501114
+LUPT 34LU01114NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEVECGND01
+INST 13SY(VECGND01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501115
+LUPT 34LU01115NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEVECGND21
+INST 13SY(VECGND21)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501116
+LUPT 34LU01116NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEVECWTR21
+INST 20SY(VECWTR21,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501117
+LUPT 34LU01117NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEOWNSHP01
+INST 13SY(OWNSHP01)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501118
+LUPT 34LU01118NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEOWNSHP05
+INST 20SY(OWNSHP05,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501119
+LUPT 34LU01119NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEOSPONE02
+INST 13SY(OSPONE02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501120
+LUPT 34LU01120NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEOSPSIX02
+INST 13SY(OSPSIX02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501121
+LUPT 34LU01121NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODEPOSITN02
+INST 13SY(POSITN02)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501122
+LUPT 34LU01122NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEEVENTS02
+INST 13SY(EVENTS02)
+DISC 18MARINERS STANDARD
+LUCM 652410
+**** 0
+0001 501123
+LUPT 34LU01123NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODECLRLIN01
+INST 20SY(CLRLIN01,ORIENT)
+DISC 15MARINERS OTHER
+LUCM 653020
+**** 0
+0001 501124
+LUPT 34LU01124NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEDNGHILIT
+INST 14SY(DNGHILIT))
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 501125
+LUPT 34LU01125NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEWAYPNT03
+INST 13SY(WAYPNT03)
+DISC 18MARINERS STANDARD
+LUCM 652210
+**** 0
+0001 501126
+LUPT 34LU01126NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODEPLNPOS01
+INST 13SY(PLNPOS01)
+DISC 18MARINERS STANDARD
+LUCM 652030
+**** 0
+0001 501127
+LUPT 34LU01127NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEPLNSPD04
+INST 13SY(PLNSPD04)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501128
+LUPT 34LU01128NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEWAYPNT11
+INST 13SY(WAYPNT11)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501129
+LUPT 34LU01129NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEWAYPNT01
+INST 13SY(WAYPNT01)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501130
+LUPT 34LU01130NIL$CSYMBP00007OSIMPLIFIED
+ATTC 15$SCODETIDCUR01
+INST 20SY(TIDCUR01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501131
+LUPT 34LU01131NIL$CSYMBP00007OSIMPLIFIED
+ATTC 15$SCODETIDCUR02
+INST 20SY(TIDCUR02,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501132
+LUPT 34LU01132NIL$CSYMBP00007OSIMPLIFIED
+ATTC 15$SCODETIDCUR03
+INST 13SY(TIDCUR03)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501133
+LUPT 34LU01133NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEEBLVRM11
+INST 13SY(EBLVRM11)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 501134
+LUPT 34LU01134NIL$CSYMBP00009OSIMPLIFIED
+ATTC 15$SCODEERBLTIK1
+INST 20SY(ERBLTIK1,ORIENT)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 501135
+LUPT 34LU01135NIL$CSYMBP00008OSIMPLIFIED
+ATTC 15$SCODEPLNSPD03
+INST 13SY(PLNSPD03)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501136
+LUPT 34LU01136NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEUWTROC04
+INST 13SY(UWTROC04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501137
+LUPT 34LU01137NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEUWTROC03
+INST 13SY(UWTROC03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501138
+LUPT 34LU01138NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEWRECKS01
+INST 13SY(WRECKS01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501139
+LUPT 34LU01139NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEWRECKS04
+INST 13SY(WRECKS04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501140
+LUPT 34LU01140NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEWRECKS05
+INST 13SY(WRECKS05)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501141
+LUPT 34LU01141NIL$CSYMBP00004OSIMPLIFIED
+ATTC 15$SCODEQUESMRK1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 501142
+LUPT 34LU01142NIL$CSYMBP00005OSIMPLIFIED
+ATTC 15$SCODEBLKADJ01
+INST 13SY(BLKADJ01)
+DISC 9STANDARD
+LUCM 621000
+**** 0
+0001 501143
+LUPT 34LU01143NIL$TEXTSP00008OSIMPLIFIED
+ATTC 1
+INST 59TX($TXSTR,$JUSTH=3,$JUSTV=1,$SPACE=2,'15110',0,0,CHBLK,27)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501144
+LUPT 35LU01144NIL######P00005OPAPER_CHART
+ATTC 1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 501145
+LUPT 35LU01145NILACHAREP00006OPAPER_CHART
+ATTC 1
+INST 13SY(ACHARE02)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 501146
+LUPT 35LU01146NILACHBRTP00005OPAPER_CHART
+ATTC 1
+INST 61SY(ACHBRT07);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 9STANDARD
+LUCM 626220
+**** 0
+0001 501147
+LUPT 35LU01147NILAIRAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(AIRARE02)
+DISC 6OTHER
+LUCM 632240
+**** 0
+0001 501148
+LUPT 35LU01148NILBCNCARP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BCNGEN03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501149
+LUPT 35LU01149NILBCNCARP00008OPAPER_CHART
+ATTC 8BCNSHP1
+INST 63SY(BCNSTK02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501150
+LUPT 35LU01150NILBCNCARP00008OPAPER_CHART
+ATTC 8BCNSHP3
+INST 63SY(BCNTOW01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501151
+LUPT 35LU01151NILBCNCARP00008OPAPER_CHART
+ATTC 8BCNSHP4
+INST 63SY(BCNLTC01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501152
+LUPT 35LU01152NILBCNCARP00008OPAPER_CHART
+ATTC 8BCNSHP5
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501153
+LUPT 35LU01153NILBCNCARP00008OPAPER_CHART
+ATTC 8BCNSHP7
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501154
+LUPT 35LU01154NILBCNISDP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BCNGEN03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501155
+LUPT 35LU01155NILBCNISDP00008OPAPER_CHART
+ATTC 8BCNSHP1
+INST 63SY(BCNSTK02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501156
+LUPT 35LU01156NILBCNISDP00008OPAPER_CHART
+ATTC 8BCNSHP3
+INST 63SY(BCNTOW01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501157
+LUPT 35LU01157NILBCNISDP00008OPAPER_CHART
+ATTC 8BCNSHP4
+INST 63SY(BCNLTC01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501158
+LUPT 35LU01158NILBCNISDP00008OPAPER_CHART
+ATTC 8BCNSHP5
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501159
+LUPT 35LU01159NILBCNISDP00008OPAPER_CHART
+ATTC 8BCNSHP7
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501160
+LUPT 35LU01160NILBCNLATP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BCNGEN03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501161
+LUPT 35LU01161NILBCNLATP00008OPAPER_CHART
+ATTC 16BCNSHP2CATLAM1
+INST 63SY(PRICKE03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501162
+LUPT 35LU01162NILBCNLATP00008OPAPER_CHART
+ATTC 16BCNSHP2CATLAM2
+INST 63SY(PRICKE04);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501163
+LUPT 35LU01163NILBCNLATP00008OPAPER_CHART
+ATTC 16BCNSHP6CONVIS1
+INST 63SY(CAIRNS11);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501164
+LUPT 35LU01164NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP1
+INST 63SY(BCNSTK02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501165
+LUPT 35LU01165NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP3
+INST 63SY(BCNTOW01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501166
+LUPT 35LU01166NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP4
+INST 63SY(BCNLTC01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501167
+LUPT 35LU01167NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP5
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501168
+LUPT 35LU01168NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP6
+INST 63SY(CAIRNS01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501169
+LUPT 35LU01169NILBCNLATP00008OPAPER_CHART
+ATTC 8BCNSHP7
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501170
+LUPT 35LU01170NILBCNSAWP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BCNGEN03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501171
+LUPT 35LU01171NILBCNSAWP00008OPAPER_CHART
+ATTC 8BCNSHP1
+INST 63SY(BCNSTK02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501172
+LUPT 35LU01172NILBCNSAWP00008OPAPER_CHART
+ATTC 8BCNSHP3
+INST 63SY(BCNTOW01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501173
+LUPT 35LU01173NILBCNSAWP00008OPAPER_CHART
+ATTC 8BCNSHP4
+INST 63SY(BCNLTC01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501174
+LUPT 35LU01174NILBCNSAWP00008OPAPER_CHART
+ATTC 8BCNSHP5
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501175
+LUPT 35LU01175NILBCNSAWP00008OPAPER_CHART
+ATTC 8BCNSHP7
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501176
+LUPT 35LU01176NILBCNSPPP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BCNGEN03);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501177
+LUPT 35LU01177NILBCNSPPP00008OPAPER_CHART
+ATTC 16BCNSHP6CONVIS1
+INST 63SY(CAIRNS11);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501178
+LUPT 35LU01178NILBCNSPPP00008OPAPER_CHART
+ATTC 9CATSPM18
+INST 63SY(NOTBRD11);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501179
+LUPT 35LU01179NILBCNSPPP00008OPAPER_CHART
+ATTC 9CATSPM44
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501180
+LUPT 35LU01180NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP1
+INST 63SY(BCNSTK02);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501181
+LUPT 35LU01181NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP3
+INST 63SY(BCNTOW01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501182
+LUPT 35LU01182NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP4
+INST 63SY(BCNLTC01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501183
+LUPT 35LU01183NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP5
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501184
+LUPT 35LU01184NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP6
+INST 63SY(CAIRNS01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501185
+LUPT 35LU01185NILBCNSPPP00008OPAPER_CHART
+ATTC 8BCNSHP7
+INST 63SY(BCNGEN01);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-2,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617020
+**** 0
+0001 501186
+LUPT 35LU01186NILBERTHSP00003OPAPER_CHART
+ATTC 1
+INST 61SY(BRTHNO01);TE('No %s','OBJNAM',3,1,2,'15110',1,0,CHBLK,29)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 501187
+LUPT 35LU01187NILBOYCARP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYGEN03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501188
+LUPT 35LU01188NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP1
+INST 63SY(BOYCON01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501189
+LUPT 35LU01189NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP2
+INST 63SY(BOYCAN01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501190
+LUPT 35LU01190NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP3
+INST 63SY(BOYSPH01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501191
+LUPT 35LU01191NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP4
+INST 63SY(BOYPIL01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501192
+LUPT 35LU01192NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP5
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501193
+LUPT 35LU01193NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP6
+INST 63SY(BOYBAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501194
+LUPT 35LU01194NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501195
+LUPT 35LU01195NILBOYCARP00008OPAPER_CHART
+ATTC 8BOYSHP8
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501196
+LUPT 35LU01196NILBOYINBP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYINB01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501197
+LUPT 35LU01197NILBOYISDP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYGEN03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501198
+LUPT 35LU01198NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP1
+INST 63SY(BOYCON01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501199
+LUPT 35LU01199NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP2
+INST 63SY(BOYCAN01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501200
+LUPT 35LU01200NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP3
+INST 63SY(BOYSPH01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501201
+LUPT 35LU01201NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP4
+INST 63SY(BOYPIL01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501202
+LUPT 35LU01202NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP5
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501203
+LUPT 35LU01203NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP6
+INST 63SY(BOYBAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501204
+LUPT 35LU01204NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501205
+LUPT 35LU01205NILBOYISDP00008OPAPER_CHART
+ATTC 8BOYSHP8
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501206
+LUPT 35LU01206NILBOYLATP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYGEN03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501207
+LUPT 35LU01207NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP1
+INST 63SY(BOYCON01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501208
+LUPT 35LU01208NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP2
+INST 63SY(BOYCAN01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501209
+LUPT 35LU01209NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP3
+INST 63SY(BOYSPH01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501210
+LUPT 35LU01210NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP4
+INST 63SY(BOYPIL01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501211
+LUPT 35LU01211NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP5
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501212
+LUPT 35LU01212NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP6
+INST 63SY(BOYBAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501213
+LUPT 35LU01213NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501214
+LUPT 35LU01214NILBOYLATP00008OPAPER_CHART
+ATTC 8BOYSHP8
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501215
+LUPT 35LU01215NILBOYSAWP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYGEN03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501216
+LUPT 35LU01216NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP3
+INST 63SY(BOYSPH01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501217
+LUPT 35LU01217NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP4
+INST 63SY(BOYPIL01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501218
+LUPT 35LU01218NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP5
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501219
+LUPT 35LU01219NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP6
+INST 63SY(BOYBAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501220
+LUPT 35LU01220NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501221
+LUPT 35LU01221NILBOYSAWP00008OPAPER_CHART
+ATTC 8BOYSHP8
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501222
+LUPT 35LU01222NILBOYSPPP00008OPAPER_CHART
+ATTC 1
+INST 63SY(BOYGEN03);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501223
+LUPT 35LU01223NILBOYSPPP00008OPAPER_CHART
+ATTC 8CATSPM9
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501224
+LUPT 35LU01224NILBOYSPPP00008OPAPER_CHART
+ATTC 9CATSPM15
+INST 63SY(BOYSUP03);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501225
+LUPT 35LU01225NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP1
+INST 63SY(BOYCON01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501226
+LUPT 35LU01226NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP2
+INST 63SY(BOYCAN01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501227
+LUPT 35LU01227NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP3
+INST 63SY(BOYSPH01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501228
+LUPT 35LU01228NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP4
+INST 63SY(BOYPIL01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501229
+LUPT 35LU01229NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP5
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501230
+LUPT 35LU01230NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP6
+INST 63SY(BOYBAR01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501231
+LUPT 35LU01231NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP7
+INST 63SY(BOYSUP01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501232
+LUPT 35LU01232NILBOYSPPP00008OPAPER_CHART
+ATTC 8BOYSHP8
+INST 63SY(BOYSPR01);TE('by %s','OBJNAM',2,1,2,'15110',-2,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501233
+LUPT 35LU01233NILBRIDGEP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501234
+LUPT 35LU01234NILBUAAREP00003OPAPER_CHART
+ATTC 1
+INST 51SY(BUAARE02);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 622240
+**** 0
+0001 501235
+LUPT 35LU01235NILBUISGLP00004OPAPER_CHART
+ATTC 1
+INST 13SY(BUISGL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501236
+LUPT 35LU01236NILBUISGLP00006OPAPER_CHART
+ATTC 24FUNCTN33CONVIS1OBJNAM
+INST 51SY(POSGEN03);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501237
+LUPT 35LU01237NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501238
+LUPT 35LU01238NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501239
+LUPT 35LU01239NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN22CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501240
+LUPT 35LU01240NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN23CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501241
+LUPT 35LU01241NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN24CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501242
+LUPT 35LU01242NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN25CONVIS1
+INST 13SY(BUIREL14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501243
+LUPT 35LU01243NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN26CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501244
+LUPT 35LU01244NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN27CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501245
+LUPT 35LU01245NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN33CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501246
+LUPT 35LU01246NILBUISGLP00006OPAPER_CHART
+ATTC 17FUNCTN35CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501247
+LUPT 35LU01247NILBUISGLP00004OPAPER_CHART
+ATTC 16FUNCTN33OBJNAM
+INST 51SY(POSGEN03);TX(OBJNAM,3,2,2,'15110',1,0,CHBLK,26)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501248
+LUPT 35LU01248NILBUISGLP00006OPAPER_CHART
+ATTC 8CONVIS1
+INST 13SY(BUISGL11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501249
+LUPT 35LU01249NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501250
+LUPT 35LU01250NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN21
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501251
+LUPT 35LU01251NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN22
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501252
+LUPT 35LU01252NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN23
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501253
+LUPT 35LU01253NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN24
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501254
+LUPT 35LU01254NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN25
+INST 13SY(BUIREL04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501255
+LUPT 35LU01255NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN26
+INST 13SY(BUIREL05)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501256
+LUPT 35LU01256NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN27
+INST 13SY(BUIREL05)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501257
+LUPT 35LU01257NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN33
+INST 13SY(POSGEN03)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501258
+LUPT 35LU01258NILBUISGLP00004OPAPER_CHART
+ATTC 9FUNCTN35
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501259
+LUPT 35LU01259NILCGUSTAP00007OPAPER_CHART
+ATTC 1
+INST 13SY(CGUSTA02)
+DISC 6OTHER
+LUCM 638030
+**** 0
+0001 501260
+LUPT 35LU01260NILCHKPNTP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501261
+LUPT 35LU01261NILCRANESP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CRANES01)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 501262
+LUPT 35LU01262NILCTNAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626050
+**** 0
+0001 501263
+LUPT 35LU01263NILCTRPNTP00004OPAPER_CHART
+ATTC 1
+INST 13SY(POSGEN04)
+DISC 6OTHER
+LUCM 632250
+**** 0
+0001 501264
+LUPT 35LU01264NILCTSAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 501265
+LUPT 35LU01265NILCURENTP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501266
+LUPT 35LU01266NILCURENTP00005OPAPER_CHART
+ATTC 14ORIENTCURVEL
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501267
+LUPT 35LU01267NILCURENTP00005OPAPER_CHART
+ATTC 7ORIENT
+INST 20SY(CURENT01,ORIENT)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501268
+LUPT 35LU01268NILDAMCONP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501269
+LUPT 35LU01269NILDAMCONP00004OPAPER_CHART
+ATTC 8CATDAM3
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 501270
+LUPT 35LU01270NILDAYMARP00007OPAPER_CHART
+ATTC 1
+INST 63SY(DAYSQR21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501271
+LUPT 35LU01271NILDAYMARP00007OPAPER_CHART
+ATTC 9TOPSHP19
+INST 63SY(DAYSQR21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501272
+LUPT 35LU01272NILDAYMARP00007OPAPER_CHART
+ATTC 9TOPSHP20
+INST 63SY(DAYSQR21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501273
+LUPT 35LU01273NILDAYMARP00007OPAPER_CHART
+ATTC 9TOPSHP21
+INST 63SY(DAYSQR21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501274
+LUPT 35LU01274NILDAYMARP00007OPAPER_CHART
+ATTC 9TOPSHP24
+INST 63SY(DAYTRI21);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501275
+LUPT 35LU01275NILDAYMARP00007OPAPER_CHART
+ATTC 9TOPSHP25
+INST 63SY(DAYTRI25);TE('bn %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 627025
+**** 0
+0001 501276
+LUPT 35LU01276NILDISMARP00007OPAPER_CHART
+ATTC 1
+INST 51SY(DISMAR03);TX(INFORM,2,1,2,'15110',2,0,CHBLK,21)
+DISC 6OTHER
+LUCM 632430
+**** 0
+0001 501277
+LUPT 35LU01277NILDISMARP00007OPAPER_CHART
+ATTC 8CATDIS1
+INST 51SY(DISMAR04);TX(INFORM,2,1,2,'15110',2,0,CHBLK,21)
+DISC 6OTHER
+LUCM 632430
+**** 0
+0001 501278
+LUPT 35LU01278NILDMPGRDP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626240
+**** 0
+0001 501279
+LUPT 35LU01279NILFOGSIGP00006OPAPER_CHART
+ATTC 1
+INST 13SY(FOGSIG01)
+DISC 9STANDARD
+LUCM 627080
+**** 0
+0001 501280
+LUPT 35LU01280NILFORSTCP00004OPAPER_CHART
+ATTC 1
+INST 13SY(FORSTC01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501281
+LUPT 35LU01281NILFORSTCP00004OPAPER_CHART
+ATTC 8CONVIS1
+INST 13SY(FORSTC11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501282
+LUPT 35LU01282NILFSHFACP00004OPAPER_CHART
+ATTC 1
+INST 13SY(FSHHAV01)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 501283
+LUPT 35LU01283NILFSHFACP00004OPAPER_CHART
+ATTC 8CATFIF1
+INST 13SY(FSHFAC03)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 501284
+LUPT 35LU01284NILFSHFACP00004OPAPER_CHART
+ATTC 8CATFIF2
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 501285
+LUPT 35LU01285NILFSHFACP00004OPAPER_CHART
+ATTC 8CATFIF3
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 501286
+LUPT 35LU01286NILFSHFACP00004OPAPER_CHART
+ATTC 8CATFIF4
+INST 13SY(FSHFAC02)
+DISC 6OTHER
+LUCM 634040
+**** 0
+0001 501287
+LUPT 35LU01287NILGATCONP00008OPAPER_CHART
+ATTC 1
+INST 13SY(GATCON04)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 501288
+LUPT 35LU01288NILGATCONP00008OPAPER_CHART
+ATTC 8CATGAT2
+INST 13SY(GATCON04)
+DISC 9STANDARD
+LUCM 622010
+**** 0
+0001 501289
+LUPT 35LU01289NILGATCONP00008OPAPER_CHART
+ATTC 8CATGAT3
+INST 13SY(GATCON04)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 501290
+LUPT 35LU01290NILGATCONP00008OPAPER_CHART
+ATTC 8CATGAT4
+INST 13SY(GATCON03)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 501291
+LUPT 35LU01291NILGRIDRNP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501292
+LUPT 35LU01292NILHRBFACP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 501293
+LUPT 35LU01293NILHRBFACP00004OPAPER_CHART
+ATTC 8CATHAF1
+INST 13SY(ROLROL01)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 501294
+LUPT 35LU01294NILHRBFACP00004OPAPER_CHART
+ATTC 8CATHAF4
+INST 13SY(HRBFAC09)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 501295
+LUPT 35LU01295NILHRBFACP00004OPAPER_CHART
+ATTC 8CATHAF5
+INST 13SY(SMCFAC02)
+DISC 6OTHER
+LUCM 632410
+**** 0
+0001 501296
+LUPT 35LU01296NILHULKESP00005OPAPER_CHART
+ATTC 1
+INST 13SY(HULKES01)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501297
+LUPT 35LU01297NILICNAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626250
+**** 0
+0001 501298
+LUPT 35LU01298NILLIGHTSP00008OPAPER_CHART
+ATTC 1
+INST 13CS(LIGHTS05)
+DISC 9STANDARD
+LUCM 627070
+**** 0
+0001 501299
+LUPT 35LU01299NILLITFLTP00008OPAPER_CHART
+ATTC 1
+INST 63SY(LITFLT01);TE('by %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501300
+LUPT 35LU01300NILLITVESP00008OPAPER_CHART
+ATTC 1
+INST 64SY(LITVES01);TE('LtV %s','OBJNAM',2,1,2,'15110',-1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 617011
+**** 0
+0001 501301
+LUPT 35LU01301NILLNDAREP00004OPAPER_CHART
+ATTC 1
+INST 26SY(LNDARE01);CS(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612010
+**** 0
+0001 501302
+LUPT 35LU01302NILLNDELVP00004OPAPER_CHART
+ATTC 1
+INST 52SY(POSGEN04);TX(ELEVAT,3,2,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 501303
+LUPT 35LU01303NILLNDMRKP00004OPAPER_CHART
+ATTC 1
+INST 13SY(POSGEN01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501304
+LUPT 35LU01304NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK17FUNCTN33CONVIS1
+INST 52SY(TOWERS03);TX(OBJNAM,3,2,2,'15110',1,-1,CHBLK,26)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501305
+LUPT 35LU01305NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK15FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501306
+LUPT 35LU01306NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK15FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501307
+LUPT 35LU01307NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK17FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501308
+LUPT 35LU01308NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK17FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501309
+LUPT 35LU01309NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK20FUNCTN20CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501310
+LUPT 35LU01310NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK20FUNCTN21CONVIS1
+INST 13SY(BUIREL13)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501311
+LUPT 35LU01311NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK20FUNCTN26CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501312
+LUPT 35LU01312NILLNDMRKP00006OPAPER_CHART
+ATTC 26CATLMK20FUNCTN27CONVIS1
+INST 13SY(BUIREL15)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501313
+LUPT 35LU01313NILLNDMRKP00004OPAPER_CHART
+ATTC 18CATLMK17FUNCTN33
+INST 52SY(TOWERS01);TX(OBJNAM,3,2,2,'15110',1,-1,CHBLK,26)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501314
+LUPT 35LU01314NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK1CONVIS1
+INST 13SY(CAIRNS11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501315
+LUPT 35LU01315NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK3CONVIS1
+INST 13SY(CHIMNY11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501316
+LUPT 35LU01316NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK4CONVIS1
+INST 13SY(DSHAER11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501317
+LUPT 35LU01317NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK5CONVIS1
+INST 13SY(FLGSTF01)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501318
+LUPT 35LU01318NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK6CONVIS1
+INST 13SY(FLASTK11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501319
+LUPT 35LU01319NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK7CONVIS1
+INST 13SY(MSTCON14)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501320
+LUPT 35LU01320NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK8CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501321
+LUPT 35LU01321NILLNDMRKP00006OPAPER_CHART
+ATTC 16CATLMK9CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501322
+LUPT 35LU01322NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK10CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501323
+LUPT 35LU01323NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK12CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501324
+LUPT 35LU01324NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK13CONVIS1
+INST 13SY(MONUMT12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501325
+LUPT 35LU01325NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK15CONVIS1
+INST 13SY(DOMES011)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501326
+LUPT 35LU01326NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK16CONVIS1
+INST 13SY(RASCAN11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501327
+LUPT 35LU01327NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK17CONVIS1
+INST 13SY(TOWERS03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501328
+LUPT 35LU01328NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK18CONVIS1
+INST 13SY(WNDMIL12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501329
+LUPT 35LU01329NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK19CONVIS1
+INST 13SY(WIMCON11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501330
+LUPT 35LU01330NILLNDMRKP00006OPAPER_CHART
+ATTC 17CATLMK20CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501331
+LUPT 35LU01331NILLNDMRKP00004OPAPER_CHART
+ATTC 18CATLMK20FUNCTN20
+INST 13SY(BUIREL01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501332
+LUPT 35LU01332NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK1
+INST 13SY(CAIRNS01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501333
+LUPT 35LU01333NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK3
+INST 13SY(CHIMNY01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501334
+LUPT 35LU01334NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK4
+INST 13SY(DSHAER01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501335
+LUPT 35LU01335NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK5
+INST 13SY(FLGSTF01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501336
+LUPT 35LU01336NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK6
+INST 13SY(FLASTK01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501337
+LUPT 35LU01337NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK7
+INST 13SY(MSTCON04)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501338
+LUPT 35LU01338NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK8
+INST 13SY(POSGEN03)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501339
+LUPT 35LU01339NILLNDMRKP00004OPAPER_CHART
+ATTC 8CATLMK9
+INST 13SY(MONUMT02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501340
+LUPT 35LU01340NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK10
+INST 13SY(MONUMT02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501341
+LUPT 35LU01341NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK12
+INST 13SY(MONUMT02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501342
+LUPT 35LU01342NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK13
+INST 13SY(MONUMT02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501343
+LUPT 35LU01343NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK15
+INST 13SY(DOMES001)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501344
+LUPT 35LU01344NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK16
+INST 13SY(RASCAN01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501345
+LUPT 35LU01345NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK17
+INST 13SY(TOWERS01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501346
+LUPT 35LU01346NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK18
+INST 13SY(WNDMIL02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501347
+LUPT 35LU01347NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK19
+INST 13SY(WIMCON01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501348
+LUPT 35LU01348NILLNDMRKP00004OPAPER_CHART
+ATTC 9CATLMK20
+INST 13SY(POSGEN01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501349
+LUPT 35LU01349NILLNDMRKP00006OPAPER_CHART
+ATTC 8CONVIS1
+INST 13SY(POSGEN03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501350
+LUPT 35LU01350NILLNDRGNP00004OPAPER_CHART
+ATTC 1
+INST 52SY(POSGEN04);TX(OBJNAM,1,2,2,'15110',0,-1,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 501351
+LUPT 35LU01351NILLOCMAGP00004OPAPER_CHART
+ATTC 1
+INST 13SY(LOCMAG01)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 501352
+LUPT 35LU01352NILLOGPONP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501353
+LUPT 35LU01353NILM_NPUBP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 6OTHER
+LUCM 631020
+**** 0
+0001 501354
+LUPT 35LU01354NILMAGVARP00004OPAPER_CHART
+ATTC 1
+INST 52SY(MAGVAR01);TX(VALMAG,3,1,2,'15110',1,-1,CHBLK,27)
+DISC 6OTHER
+LUCM 631080
+**** 0
+0001 501355
+LUPT 35LU01355NILMARCULP00004OPAPER_CHART
+ATTC 1
+INST 13SY(MARCUL02)
+DISC 9STANDARD
+LUCM 626210
+**** 0
+0001 501356
+LUPT 35LU01356NILMIPAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 501357
+LUPT 35LU01357NILMORFACP00006OPAPER_CHART
+ATTC 1
+INST 13SY(MORFAC03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501358
+LUPT 35LU01358NILMORFACP00008OPAPER_CHART
+ATTC 16CATMOR7BOYSHP3
+INST 13SY(BOYMOR01)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501359
+LUPT 35LU01359NILMORFACP00008OPAPER_CHART
+ATTC 16CATMOR7BOYSHP6
+INST 13SY(BOYMOR03)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501360
+LUPT 35LU01360NILMORFACP00006OPAPER_CHART
+ATTC 8CATMOR1
+INST 13SY(MORFAC03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501361
+LUPT 35LU01361NILMORFACP00006OPAPER_CHART
+ATTC 8CATMOR2
+INST 13SY(MORFAC04)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501362
+LUPT 35LU01362NILMORFACP00006OPAPER_CHART
+ATTC 8CATMOR3
+INST 13SY(PILPNT02)
+DISC 6OTHER
+LUCM 632440
+**** 0
+0001 501363
+LUPT 35LU01363NILMORFACP00006OPAPER_CHART
+ATTC 8CATMOR5
+INST 13SY(PILPNT02)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501364
+LUPT 35LU01364NILMORFACP00008OPAPER_CHART
+ATTC 8CATMOR7
+INST 13SY(BOYMOR11)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501365
+LUPT 35LU01365NILOBSTRNP00004OPAPER_CHART
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501366
+LUPT 35LU01366NILOBSTRNP00004OPAPER_CHART
+ATTC 8CATOBS7
+INST 13SY(FOULGND1)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501367
+LUPT 35LU01367NILOBSTRNP00004OPAPER_CHART
+ATTC 8CATOBS9
+INST 13SY(ACHARE02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501368
+LUPT 35LU01368NILOFSPLFP00005OPAPER_CHART
+ATTC 1
+INST 64SY(OFSPLF01);TE('Prod %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 501369
+LUPT 35LU01369NILPILBOPP00006OPAPER_CHART
+ATTC 1
+INST 63SY(PILBOP02);TE('Plt %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21)
+DISC 9STANDARD
+LUCM 628010
+**** 0
+0001 501370
+LUPT 35LU01370NILPILPNTP00005OPAPER_CHART
+ATTC 1
+INST 13SY(PILPNT02)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501371
+LUPT 35LU01371NILPIPAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO07)
+DISC 9STANDARD
+LUCM 626230
+**** 0
+0001 501372
+LUPT 35LU01372NILPIPSOLP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501373
+LUPT 35LU01373NILPRCAREP00005OPAPER_CHART
+ATTC 1
+INST 13SY(PRCARE12)
+DISC 12DISPLAYBASE
+LUCM 615010
+**** 0
+0001 501374
+LUPT 35LU01374NILPRDAREP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501375
+LUPT 35LU01375NILPRDAREP00004OPAPER_CHART
+ATTC 16CATPRA5CONVIS1
+INST 13SY(FLASTK11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501376
+LUPT 35LU01376NILPRDAREP00004OPAPER_CHART
+ATTC 16CATPRA8CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501377
+LUPT 35LU01377NILPRDAREP00004OPAPER_CHART
+ATTC 16CATPRA9CONVIS1
+INST 13SY(WIMCON11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501378
+LUPT 35LU01378NILPRDAREP00003OPAPER_CHART
+ATTC 8CATPRA1
+INST 13SY(PRDINS02)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501379
+LUPT 35LU01379NILPRDAREP00003OPAPER_CHART
+ATTC 8CATPRA5
+INST 13SY(FLASTK01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501380
+LUPT 35LU01380NILPRDAREP00003OPAPER_CHART
+ATTC 8CATPRA6
+INST 13SY(TMBYRD01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501381
+LUPT 35LU01381NILPRDAREP00003OPAPER_CHART
+ATTC 8CATPRA8
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501382
+LUPT 35LU01382NILPRDAREP00003OPAPER_CHART
+ATTC 8CATPRA9
+INST 13SY(WIMCON01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501383
+LUPT 35LU01383NILPYLONSP00008OPAPER_CHART
+ATTC 1
+INST 13SY(POSGEN03)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 501384
+LUPT 35LU01384NILRADRFLP00006OPAPER_CHART
+ATTC 1
+INST 13SY(RADRFL03)
+DISC 9STANDARD
+LUCM 627230
+**** 0
+0001 501385
+LUPT 35LU01385NILRADSTAP00005OPAPER_CHART
+ATTC 1
+INST 13SY(POSGEN01)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 501386
+LUPT 35LU01386NILRADSTAP00005OPAPER_CHART
+ATTC 8CATRAS2
+INST 61SY(RDOSTA02);TE('ch %s','COMCHA',3,1,2,'15110',0,0,CHBLK,11)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 501387
+LUPT 35LU01387NILRAPIDSP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501388
+LUPT 35LU01388NILRCTLPTP00004OPAPER_CHART
+ATTC 1
+INST 13SY(RTLDEF51)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 501389
+LUPT 35LU01389NILRCTLPTP00004OPAPER_CHART
+ATTC 7ORIENT
+INST 20SY(RCTLPT52,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 615020
+**** 0
+0001 501390
+LUPT 35LU01390NILRDOCALP00006OPAPER_CHART
+ATTC 1
+INST 62SY(RCLDEF01);TE('No %s','OBJNAM',3,2,2,'15110',1,-1,CHBLK,21)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 501391
+LUPT 35LU01391NILRDOCALP00006OPAPER_CHART
+ATTC 15TRAFIC1ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 501392
+LUPT 35LU01392NILRDOCALP00006OPAPER_CHART
+ATTC 15TRAFIC2ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 501393
+LUPT 35LU01393NILRDOCALP00006OPAPER_CHART
+ATTC 15TRAFIC3ORIENT
+INST 117SY(RDOCAL02,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 501394
+LUPT 35LU01394NILRDOCALP00006OPAPER_CHART
+ATTC 15TRAFIC4ORIENT
+INST 117SY(RDOCAL03,ORIENT);TE('No %s','OBJNAM',3,1,2,'15110',1,-1,CHBLK,21);TE('ch %s','COMCHA',3,1,2,'15110',1,1,CHBLK,11)
+DISC 12DISPLAYBASE
+LUCM 615060
+**** 0
+0001 501395
+LUPT 35LU01395NILRDOSTAP00004OPAPER_CHART
+ATTC 1
+INST 13SY(RDOSTA02)
+DISC 6OTHER
+LUCM 638010
+**** 0
+0001 501396
+LUPT 35LU01396NILRETRFLP00006OPAPER_CHART
+ATTC 1
+INST 13SY(RETRFL01)
+DISC 9STANDARD
+LUCM 627080
+**** 0
+0001 501397
+LUPT 35LU01397NILROADWYP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501398
+LUPT 35LU01398NILRSCSTAP00007OPAPER_CHART
+ATTC 1
+INST 13SY(RSCSTA02)
+DISC 6OTHER
+LUCM 638030
+**** 0
+0001 501399
+LUPT 35LU01399NILRTPBCNP00006OPAPER_CHART
+ATTC 1
+INST 13SY(RTPBCN02)
+DISC 9STANDARD
+LUCM 627210
+**** 0
+0001 501400
+LUPT 35LU01400NILRUNWAYP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501401
+LUPT 35LU01401NILSBDAREP00004OPAPER_CHART
+ATTC 1
+INST 38TX(NATSUR,1,2,2,'15110',0,0,CHBLK,25)
+DISC 6OTHER
+LUCM 634010
+**** 0
+0001 501402
+LUPT 35LU01402NILSEAAREP00003SPAPER_CHART
+ATTC 1
+INST 38TX(OBJNAM,1,2,3,'15110',0,0,CHBLK,26)
+DISC 9STANDARD
+LUCM 621060
+**** 0
+0001 501403
+LUPT 35LU01403NILSILTNKP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501404
+LUPT 35LU01404NILSILTNKP00004OPAPER_CHART
+ATTC 16CATSIL1CONVIS1
+INST 13SY(SILBUI11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501405
+LUPT 35LU01405NILSILTNKP00004OPAPER_CHART
+ATTC 16CATSIL2CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501406
+LUPT 35LU01406NILSILTNKP00004OPAPER_CHART
+ATTC 16CATSIL3CONVIS1
+INST 13SY(TOWERS03)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501407
+LUPT 35LU01407NILSILTNKP00004OPAPER_CHART
+ATTC 16CATSIL4CONVIS1
+INST 13SY(TOWERS12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501408
+LUPT 35LU01408NILSILTNKP00004OPAPER_CHART
+ATTC 8CONVIS1
+INST 13SY(TNKCON12)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501409
+LUPT 35LU01409NILSILTNKP00004OPAPER_CHART
+ATTC 8CATSIL1
+INST 13SY(SILBUI01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501410
+LUPT 35LU01410NILSILTNKP00004OPAPER_CHART
+ATTC 8CATSIL2
+INST 13SY(TNKCON02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501411
+LUPT 35LU01411NILSILTNKP00004OPAPER_CHART
+ATTC 8CATSIL3
+INST 13SY(TOWERS01)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501412
+LUPT 35LU01412NILSILTNKP00004OPAPER_CHART
+ATTC 8CATSIL4
+INST 13SY(TOWERS02)
+DISC 6OTHER
+LUCM 632220
+**** 0
+0001 501413
+LUPT 35LU01413NILSISTATP00007OPAPER_CHART
+ATTC 1
+INST 13SY(SISTAT02)
+DISC 9STANDARD
+LUCM 628020
+**** 0
+0001 501414
+LUPT 35LU01414NILSISTAWP00007OPAPER_CHART
+ATTC 1
+INST 13SY(SISTAT02)
+DISC 9STANDARD
+LUCM 628020
+**** 0
+0001 501415
+LUPT 35LU01415NILSLCONSP00008OPAPER_CHART
+ATTC 1
+INST 26SY(MORFAC03);CS(SLCONS03)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501416
+LUPT 35LU01416NILSLOGRDP00003SPAPER_CHART
+ATTC 1
+INST 13SY(HILTOP01)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 501417
+LUPT 35LU01417NILSLOTOPP00003SPAPER_CHART
+ATTC 1
+INST 13SY(HILTOP01)
+DISC 6OTHER
+LUCM 632010
+**** 0
+0001 501418
+LUPT 35LU01418NILSLOTOPP00003SPAPER_CHART
+ATTC 8CONVIS1
+INST 13SY(HILTOP11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501419
+LUPT 35LU01419NILSMCFACP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501420
+LUPT 35LU01420NILSNDWAVP00004OPAPER_CHART
+ATTC 1
+INST 13SY(SNDWAV02)
+DISC 9STANDARD
+LUCM 624010
+**** 0
+0001 501421
+LUPT 35LU01421NILSOUNDGP00006OPAPER_CHART
+ATTC 1
+INST 13CS(SOUNDG02)
+DISC 6OTHER
+LUCM 633010
+**** 0
+0001 501422
+LUPT 35LU01422NILSPLAREP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO06)
+DISC 9STANDARD
+LUCM 626040
+**** 0
+0001 501423
+LUPT 35LU01423NILSPRINGP00004OPAPER_CHART
+ATTC 1
+INST 13SY(SPRING02)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 501424
+LUPT 35LU01424NILT_HMONP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 501425
+LUPT 35LU01425NILT_NHMNP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 501426
+LUPT 35LU01426NILT_TIMSP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDEHT01)
+DISC 6OTHER
+LUCM 633050
+**** 0
+0001 501427
+LUPT 35LU01427NILTS_FEBP00004OPAPER_CHART
+ATTC 1
+INST 13SY(CURDEF01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501428
+LUPT 35LU01428NILTS_FEBP00004OPAPER_CHART
+ATTC 15CAT_TS1ORIENT
+INST 73SY(FLDSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501429
+LUPT 35LU01429NILTS_FEBP00004OPAPER_CHART
+ATTC 15CAT_TS2ORIENT
+INST 73SY(EBBSTR01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501430
+LUPT 35LU01430NILTS_FEBP00004OPAPER_CHART
+ATTC 15CAT_TS3ORIENT
+INST 73SY(CURENT01,ORIENT);TE('%4.1lf kn','CURVEL',3,1,2,'15110',1,-1,CHBLK,31)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501431
+LUPT 35LU01431NILTS_PADP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501432
+LUPT 35LU01432NILTS_PNHP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501433
+LUPT 35LU01433NILTS_PRHP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501434
+LUPT 35LU01434NILTS_TISP00004OPAPER_CHART
+ATTC 1
+INST 13SY(TIDSTR01)
+DISC 6OTHER
+LUCM 633060
+**** 0
+0001 501435
+LUPT 35LU01435NILTOPMARP00006OPAPER_CHART
+ATTC 1
+INST 13CS(TOPMAR01)
+DISC 9STANDARD
+LUCM 627050
+**** 0
+0001 501436
+LUPT 35LU01436NILTUNNELP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501437
+LUPT 35LU01437NILUWTROCP00004OPAPER_CHART
+ATTC 1
+INST 13CS(OBSTRN04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501438
+LUPT 35LU01438NILVEGATNP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501439
+LUPT 35LU01439NILWATFALP00000SPAPER_CHART
+ATTC 1
+INST 1
+DISC 1
+LUCM 1
+**** 0
+0001 501440
+LUPT 35LU01440NILWATTURP00003OPAPER_CHART
+ATTC 1
+INST 13SY(WATTUR02)
+DISC 6OTHER
+LUCM 633040
+**** 0
+0001 501441
+LUPT 35LU01441NILWEDKLPP00003OPAPER_CHART
+ATTC 1
+INST 13SY(WEDKLP03)
+DISC 6OTHER
+LUCM 634020
+**** 0
+0001 501442
+LUPT 35LU01442NILWRECKSP00004OPAPER_CHART
+ATTC 1
+INST 13CS(WRECKS02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501443
+LUPT 35LU01443NILWRECKSP00004OPAPER_CHART
+ATTC 8CATWRK3
+INST 13SY(FOULGND1)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501444
+LUPT 35LU01444NILcursorP00008OPAPER_CHART
+ATTC 1
+INST 13SY(CURSRA01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501445
+LUPT 35LU01445NILcursorP00008OPAPER_CHART
+ATTC 8cursty2
+INST 13SY(CURSRB01)
+DISC 15MARINERS OTHER
+LUCM 661040
+**** 0
+0001 501446
+LUPT 35LU01446NILdnghltP00008OPAPER_CHART
+ATTC 1
+INST 13SY(DNGHILIT)
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 501447
+LUPT 35LU01447NILeventsP00008OPAPER_CHART
+ATTC 1
+INST 51SY(EVENTS02);TX(OBJNAM,3,2,3,'15110',1,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 652410
+**** 0
+0001 501448
+LUPT 35LU01448NILmarfeaP00008OPAPER_CHART
+ATTC 1
+INST 52SY(CHINFO09);TX(OBJNAM,3,1,3,'15110',1,-1,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653050
+**** 0
+0001 501449
+LUPT 35LU01449NILmarnotP00008OPAPER_CHART
+ATTC 1
+INST 51SY(CHINFO09);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501450
+LUPT 35LU01450NILmarnotP00008OPAPER_CHART
+ATTC 8catnot1
+INST 51SY(CHINFO08);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653030
+**** 0
+0001 501451
+LUPT 35LU01451NILmarnotP00008OPAPER_CHART
+ATTC 8catnot2
+INST 51SY(CHINFO09);TX(usrmrk,3,1,2,'15110',0,0,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501452
+LUPT 35LU01452NILmnufeaP00005OPAPER_CHART
+ATTC 1
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501453
+LUPT 35LU01453NILmnufeaP00005OPAPER_CHART
+ATTC 8catnot1
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501454
+LUPT 35LU01454NILmnufeaP00005OPAPER_CHART
+ATTC 8catnot2
+INST 13SY(CHINFO11)
+DISC 18MARINERS STANDARD
+LUCM 655020
+**** 0
+0001 501455
+LUPT 35LU01455NILownshpP00009OPAPER_CHART
+ATTC 1
+INST 13CS(OWNSHP02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501456
+LUPT 35LU01456NILplnposP00005OPAPER_CHART
+ATTC 1
+INST 72SY(PLNPOS01);SY(PLNPOS02,ORIENT);TX(plndat,1,2,2,'15110',4,3,CHBLK,50);
+DISC 18MARINERS STANDARD
+LUCM 652030
+**** 0
+0001 501457
+LUPT 35LU01457NILpositnP00005OPAPER_CHART
+ATTC 1
+INST 52SY(POSITN02);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501458
+LUPT 35LU01458NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth1
+INST 89SY(POSITN02);TX('DR',2,3,2,'15110',-1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501459
+LUPT 35LU01459NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth2
+INST 89SY(POSITN02);TX('EP',2,3,2,'15110',-1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501460
+LUPT 35LU01460NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth3
+INST 87SY(POSITN02);TX('V',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501461
+LUPT 35LU01461NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth4
+INST 87SY(POSITN02);TX('A',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501462
+LUPT 35LU01462NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth5
+INST 87SY(POSITN02);TX('R',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501463
+LUPT 35LU01463NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth6
+INST 87SY(POSITN02);TX('D',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501464
+LUPT 35LU01464NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth7
+INST 87SY(POSITN02);TX('G',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501465
+LUPT 35LU01465NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth8
+INST 88SY(POSITN02);TX('Gl',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501466
+LUPT 35LU01466NILpositnP00005OPAPER_CHART
+ATTC 8pfmeth9
+INST 87SY(POSITN02);TX('L',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501467
+LUPT 35LU01467NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth10
+INST 87SY(POSITN02);TX('M',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501468
+LUPT 35LU01468NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth11
+INST 87SY(POSITN02);TX('O',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501469
+LUPT 35LU01469NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth12
+INST 87SY(POSITN02);TX('T',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501470
+LUPT 35LU01470NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth13
+INST 88SY(POSITN02);TX('dG',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501471
+LUPT 35LU01471NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth14
+INST 89SY(POSITN02);TX('dGl',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501472
+LUPT 35LU01472NILpositnP00005OPAPER_CHART
+ATTC 9pfmeth15
+INST 88SY(POSITN02);TX('dO',3,3,2,'15110',1,1,CHBLK,50);TX(loctim,1,1,2,'15110',0,-1,CHBLK,50)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501473
+LUPT 35LU01473NILrefpntP00007OPAPER_CHART
+ATTC 1
+INST 13SY(REFPNT02)
+DISC 15MARINERS OTHER
+LUCM 661050
+**** 0
+0001 501474
+LUPT 35LU01474NILtidcurP00007OPAPER_CHART
+ATTC 1
+INST 111SY(TIDCUR01,ORIENT);SY(TIDCUR03);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501475
+LUPT 35LU01475NILtidcurP00007OPAPER_CHART
+ATTC 8catcur1
+INST 147SY(TIDCUR01,ORIENT);SY(TIDCUR03);TX('P',2,3,2,'15110',-4,2,CHBLK,50);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501476
+LUPT 35LU01476NILtidcurP00007OPAPER_CHART
+ATTC 8catcur2
+INST 147SY(TIDCUR02,ORIENT);SY(TIDCUR03);TX('A',2,3,2,'15110',-4,2,CHBLK,50);TX(curstr,2,3,2,'15110',-1,2,CHBLK,50);TX(loctim,3,1,2,'15110',1,-2,CHBLK,50)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501477
+LUPT 35LU01477NILvesselP00009OPAPER_CHART
+ATTC 1
+INST 13CS(VESSEL01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501478
+LUPT 35LU01478NILwaypntP00008OPAPER_CHART
+ATTC 1
+INST 52SY(WAYPNT11);TX(OBJNAM,3,1,3,'15110',1,-1,APLRT,50)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501479
+LUPT 35LU01479NILwaypntP00008OPAPER_CHART
+ATTC 8select1
+INST 52SY(WAYPNT11);TX(OBJNAM,3,1,3,'15110',1,-1,CHBLK,50)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501480
+LUPT 35LU01480NILwaypntP00008OPAPER_CHART
+ATTC 8select2
+INST 52SY(WAYPNT03);TX(OBJNAM,3,1,3,'15110',1,-1,APLRT,50)
+DISC 18MARINERS STANDARD
+LUCM 652210
+**** 0
+0001 501481
+LUPT 35LU01481NIL$CSYMBP00005OPAPER_CHART
+ATTC 1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 501482
+LUPT 35LU01482NIL$CSYMBP00005SPAPER_CHART
+ATTC 15$SCODEBRIDGE01
+INST 13SY(BRIDGE01)
+DISC 12DISPLAYBASE
+LUCM 612210
+**** 0
+0001 501483
+LUPT 35LU01483NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODESCALEB10
+INST 13SY(SCALEB10)
+DISC 12DISPLAYBASE
+LUCM 611030
+**** 0
+0001 501484
+LUPT 35LU01484NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODESCALEB11
+INST 13SY(SCALEB11)
+DISC 12DISPLAYBASE
+LUCM 611030
+**** 0
+0001 501485
+LUPT 35LU01485NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODENORTHAR1
+INST 13SY(NORTHAR1)
+DISC 12DISPLAYBASE
+LUCM 611040
+**** 0
+0001 501486
+LUPT 35LU01486NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEUNITFTH1
+INST 13SY(UNITFTH1)
+DISC 12DISPLAYBASE
+LUCM 611000
+**** 0
+0001 501487
+LUPT 35LU01487NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEUNITMTR1
+INST 13SY(UNITMTR1)
+DISC 12DISPLAYBASE
+LUCM 611000
+**** 0
+0001 501488
+LUPT 35LU01488NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODECURSRA01
+INST 13SY(CURSRA01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501489
+LUPT 35LU01489NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODECURSRB01
+INST 13SY(CURSRB01)
+DISC 12DISPLAYBASE
+LUCM 611010
+**** 0
+0001 501490
+LUPT 35LU01490NIL$CSYMBP00007OPAPER_CHART
+ATTC 15$SCODEREFPNT02
+INST 13SY(REFPNT02)
+DISC 15MARINERS OTHER
+LUCM 661050
+**** 0
+0001 501491
+LUPT 35LU01491NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODECHINFO09
+INST 13SY(CHINFO09)
+DISC 18MARINERS STANDARD
+LUCM 653040
+**** 0
+0001 501492
+LUPT 35LU01492NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODECHINFO08
+INST 13SY(CHINFO08)
+DISC 18MARINERS STANDARD
+LUCM 653030
+**** 0
+0001 501493
+LUPT 35LU01493NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODECHINFO11
+INST 13SY(CHINFO11)
+DISC 18MARINERS STANDARD
+LUCM 655020
+**** 0
+0001 501494
+LUPT 35LU01494NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODECHINFO10
+INST 13SY(CHINFO10)
+DISC 18MARINERS STANDARD
+LUCM 655010
+**** 0
+0001 501495
+LUPT 35LU01495NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODELOWACC01
+INST 13SY(LOWACC01)
+DISC 9STANDARD
+LUCM 621000
+**** 0
+0001 501496
+LUPT 35LU01496NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEINFORM01
+INST 13SY(INFORM01)
+DISC 6OTHER
+LUCM 631030
+**** 0
+0001 501497
+LUPT 35LU01497NIL$CSYMBP00007OPAPER_CHART
+ATTC 15$SCODEQUAPOS01
+INST 13SY(QUAPOS01)
+DISC 12DISPLAYBASE
+LUCM 612410
+**** 0
+0001 501498
+LUPT 35LU01498NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODECHCRID01
+INST 13SY(CHCRID01)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501499
+LUPT 35LU01499NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODECHCRDEL1
+INST 13SY(CHCRDEL1)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501500
+LUPT 35LU01500NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODETREPNT04
+INST 13SY(TREPNT04)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 501501
+LUPT 35LU01501NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODETREPNT05
+INST 13SY(TREPNT05)
+DISC 6OTHER
+LUCM 632030
+**** 0
+0001 501502
+LUPT 35LU01502NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODETOWERS15
+INST 13SY(TOWERS15)
+DISC 9STANDARD
+LUCM 622200
+**** 0
+0001 501503
+LUPT 35LU01503NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODETOWERS05
+INST 13SY(TOWERS05)
+DISC 6OTHER
+LUCM 632200
+**** 0
+0001 501504
+LUPT 35LU01504NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEOBSTRN11
+INST 13SY(OBSTRN11)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501505
+LUPT 35LU01505NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEOBSTRN01
+INST 13SY(OBSTRN01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501506
+LUPT 35LU01506NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEOBSTRN02
+INST 13SY(OBSTRN02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501507
+LUPT 35LU01507NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEOBSTRN03
+INST 13SY(OBSTRN03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501508
+LUPT 35LU01508NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEDANGER01
+INST 13SY(DANGER01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501509
+LUPT 35LU01509NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEDANGER02
+INST 13SY(DANGER02)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501510
+LUPT 35LU01510NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEDANGER03
+INST 13SY(DANGER03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501511
+LUPT 35LU01511NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEQUARRY01
+INST 13SY(QUARRY01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501512
+LUPT 35LU01512NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODERFNERY01
+INST 13SY(RFNERY01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501513
+LUPT 35LU01513NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODERFNERY11
+INST 13SY(RFNERY11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501514
+LUPT 35LU01514NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODETNKFRM01
+INST 13SY(TNKFRM01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501515
+LUPT 35LU01515NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODETNKFRM11
+INST 13SY(TNKFRM11)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501516
+LUPT 35LU01516NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEWNDFRM51
+INST 13SY(WNDFRM51)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501517
+LUPT 35LU01517NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEWNDFRM61
+INST 13SY(WNDFRM61)
+DISC 9STANDARD
+LUCM 622220
+**** 0
+0001 501518
+LUPT 35LU01518NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODETMBYRD01
+INST 13SY(TMBYRD01)
+DISC 6OTHER
+LUCM 632270
+**** 0
+0001 501519
+LUPT 35LU01519NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEISODGR01
+INST 13SY(ISODGR01)
+DISC 12DISPLAYBASE
+LUCM 614010
+**** 0
+0001 501520
+LUPT 35LU01520NIL$CSYMBP00006SPAPER_CHART
+ATTC 15$SCODERECTRC55
+INST 13SY(RECTRC55)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501521
+LUPT 35LU01521NIL$CSYMBP00006SPAPER_CHART
+ATTC 15$SCODERECTRC56
+INST 13SY(RECTRC56)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501522
+LUPT 35LU01522NIL$CSYMBP00006SPAPER_CHART
+ATTC 15$SCODERECTRC57
+INST 13SY(RECTRC57)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501523
+LUPT 35LU01523NIL$CSYMBP00006SPAPER_CHART
+ATTC 15$SCODERECTRC58
+INST 13SY(RECTRC58)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501524
+LUPT 35LU01524NIL$CSYMBP00006SPAPER_CHART
+ATTC 15$SCODERECDEF51
+INST 13SY(RECDEF51)
+DISC 9STANDARD
+LUCM 625020
+**** 0
+0001 501525
+LUPT 35LU01525NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEDIRBOY01
+INST 13SY(DIRBOY01)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501526
+LUPT 35LU01526NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEDIRBOYA1
+INST 13SY(DIRBOYA1)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501527
+LUPT 35LU01527NIL$CSYMBP00004SPAPER_CHART
+ATTC 15$SCODEDIRBOYB1
+INST 13SY(DIRBOYB1)
+DISC 9STANDARD
+LUCM 627040
+**** 0
+0001 501528
+LUPT 35LU01528NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODERACNSP01
+INST 13SY(RACNSP01)
+DISC 9STANDARD
+LUCM 622210
+**** 0
+0001 501529
+LUPT 35LU01529NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODECHKSYM01
+INST 13SY(CHKSYM01)
+DISC 12DISPLAYBASE
+LUCM 617010
+**** 0
+0001 501530
+LUPT 35LU01530NIL$CSYMBP00005SPAPER_CHART
+ATTC 15$SCODEACHRES61
+INST 13SY(ACHRES61)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 501531
+LUPT 35LU01531NIL$CSYMBP00005SPAPER_CHART
+ATTC 15$SCODEACHRES71
+INST 13SY(ACHRES71)
+DISC 9STANDARD
+LUCM 626010
+**** 0
+0001 501532
+LUPT 35LU01532NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEAISONE01
+INST 13SY(AISONE01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501533
+LUPT 35LU01533NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEAISSIX01
+INST 13SY(AISSIX01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501534
+LUPT 35LU01534NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEAISDEF01
+INST 13SY(AISDEF01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501535
+LUPT 35LU01535NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEAISSLP01
+INST 20SY(AISSLP01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501536
+LUPT 35LU01536NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEAISVES01
+INST 20SY(AISVES01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501537
+LUPT 35LU01537NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEARPATG01
+INST 13SY(ARPATG01)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501538
+LUPT 35LU01538NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEARPONE01
+INST 20SY(ARPONE01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501539
+LUPT 35LU01539NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEARPSIX01
+INST 20SY(ARPSIX01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654010
+**** 0
+0001 501540
+LUPT 35LU01540NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEVECWTR01
+INST 13SY(VECWTR01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501541
+LUPT 35LU01541NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEVECGND01
+INST 13SY(VECGND01)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501542
+LUPT 35LU01542NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEVECGND21
+INST 13SY(VECGND21)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501543
+LUPT 35LU01543NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEVECWTR21
+INST 20SY(VECWTR21,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 654030
+**** 0
+0001 501544
+LUPT 35LU01544NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEOWNSHP01
+INST 13SY(OWNSHP01)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501545
+LUPT 35LU01545NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEOWNSHP05
+INST 20SY(OWNSHP05,ORIENT)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501546
+LUPT 35LU01546NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEOSPONE02
+INST 13SY(OSPONE02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501547
+LUPT 35LU01547NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEOSPSIX02
+INST 13SY(OSPSIX02)
+DISC 12DISPLAYBASE
+LUCM 642010
+**** 0
+0001 501548
+LUPT 35LU01548NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODEPOSITN02
+INST 13SY(POSITN02)
+DISC 15MARINERS OTHER
+LUCM 662010
+**** 0
+0001 501549
+LUPT 35LU01549NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEEVENTS02
+INST 13SY(EVENTS02)
+DISC 18MARINERS STANDARD
+LUCM 652410
+**** 0
+0001 501550
+LUPT 35LU01550NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODECLRLIN01
+INST 20SY(CLRLIN01,ORIENT)
+DISC 15MARINERS OTHER
+LUCM 653020
+**** 0
+0001 501551
+LUPT 35LU01551NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEDNGHILIT
+INST 14SY(DNGHILIT))
+DISC 18MARINERS STANDARD
+LUCM 653010
+**** 0
+0001 501552
+LUPT 35LU01552NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEWAYPNT03
+INST 13SY(WAYPNT03)
+DISC 18MARINERS STANDARD
+LUCM 652210
+**** 0
+0001 501553
+LUPT 35LU01553NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODEPLNPOS01
+INST 13SY(PLNPOS01)
+DISC 18MARINERS STANDARD
+LUCM 652030
+**** 0
+0001 501554
+LUPT 35LU01554NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEPLNSPD04
+INST 13SY(PLNSPD04)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501555
+LUPT 35LU01555NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEWAYPNT11
+INST 13SY(WAYPNT11)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501556
+LUPT 35LU01556NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEWAYPNT01
+INST 13SY(WAYPNT01)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501557
+LUPT 35LU01557NIL$CSYMBP00007OPAPER_CHART
+ATTC 15$SCODETIDCUR01
+INST 20SY(TIDCUR01,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501558
+LUPT 35LU01558NIL$CSYMBP00007OPAPER_CHART
+ATTC 15$SCODETIDCUR02
+INST 20SY(TIDCUR02,ORIENT)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501559
+LUPT 35LU01559NIL$CSYMBP00007OPAPER_CHART
+ATTC 15$SCODETIDCUR03
+INST 13SY(TIDCUR03)
+DISC 18MARINERS STANDARD
+LUCM 653080
+**** 0
+0001 501560
+LUPT 35LU01560NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEEBLVRM11
+INST 13SY(EBLVRM11)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 501561
+LUPT 35LU01561NIL$CSYMBP00009OPAPER_CHART
+ATTC 15$SCODEERBLTIK1
+INST 20SY(ERBLTIK1,ORIENT)
+DISC 15MARINERS OTHER
+LUCM 661010
+**** 0
+0001 501562
+LUPT 35LU01562NIL$CSYMBP00008OPAPER_CHART
+ATTC 15$SCODEPLNSPD03
+INST 13SY(PLNSPD03)
+DISC 12DISPLAYBASE
+LUCM 642210
+**** 0
+0001 501563
+LUPT 35LU01563NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEUWTROC04
+INST 13SY(UWTROC04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501564
+LUPT 35LU01564NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEUWTROC03
+INST 13SY(UWTROC03)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501565
+LUPT 35LU01565NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEWRECKS01
+INST 13SY(WRECKS01)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501566
+LUPT 35LU01566NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEWRECKS04
+INST 13SY(WRECKS04)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501567
+LUPT 35LU01567NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEWRECKS05
+INST 13SY(WRECKS05)
+DISC 6OTHER
+LUCM 634050
+**** 0
+0001 501568
+LUPT 35LU01568NIL$CSYMBP00004OPAPER_CHART
+ATTC 15$SCODEQUESMRK1
+INST 13SY(QUESMRK1)
+DISC 9STANDARD
+LUCM 621010
+**** 0
+0001 501569
+LUPT 35LU01569NIL$CSYMBP00005OPAPER_CHART
+ATTC 15$SCODEBLKADJ01
+INST 13SY(BLKADJ01)
+DISC 9STANDARD
+LUCM 621000
+**** 0
+0001 501570
+LUPT 35LU01570NIL$TEXTSP00008OPAPER_CHART
+ATTC 1
+INST 59TX($TXSTR,$JUSTH=3,$JUSTV=1,$SPACE=2,'15110',0,0,CHBLK,27)
+DISC 12DISPLAYBASE
+LUCM 610000
+**** 0
+0001 501571
+LNST 10LS03346NIL
+LIND 38ACHARE51001080082003030005030030600568
+LXPO 30boundary of an anchorage area
+LCRF 6ACHMGD
+LVCT 32SPA;SW1;PU1429,568;PD1429,1070;
+LVCT 31SPA;SW1;PU1273,717;PD1577,717;
+LVCT 55SPA;SW1;PU1226,967;PD1332,1071;PD1530,1071;PD1628,970;
+LVCT 29SPA;SW1;PU306,815;PD906,815;
+LVCT 31SPA;SW1;PU2732,815;PD3336,815;
+LVCT 42SPA;SW1;PU2868,813;PD3030,975;PD3199,807;
+LVCT 31SPA;SW1;PU1928,814;PD2528,814;
+LVCT 42SPA;SW1;PU2068,812;PD2233,976;PD2397,812;
+LVCT 39SPA;SW1;PU390,812;PD546,974;PD713,813;
+**** 0
+0001 501572
+LNST 10LS03354NIL
+LIND 38ACHRES51001080082002729005030044600572
+LXPO 64boundary of an area where anchoring is prohibited or restricted
+LCRF 6ACHMGD
+LVCT 32SPA;SW1;PU1208,572;PD1208,1074;
+LVCT 31SPA;SW1;PU1052,721;PD1356,721;
+LVCT 55SPA;SW1;PU1005,971;PD1111,1075;PD1309,1075;PD1407,974;
+LVCT 31SPA;SW1;PU1418,640;PD987,1071;
+LVCT 31SPA;SW1;PU2248,809;PD2552,809;
+LVCT 31SPA;SW1;PU2404,809;PD2404,959;
+LVCT 29SPA;SW1;PU446,810;PD747,810;
+LVCT 31SPA;SW1;PU2874,810;PD3175,810;
+LVCT 31SPA;SW1;PU3030,810;PD3030,971;
+LVCT 31SPA;SW1;PU1655,812;PD1957,812;
+LVCT 31SPA;SW1;PU1808,812;PD1808,979;
+LVCT 29SPA;SW1;PU595,812;PD595,970;
+**** 0
+0001 501573
+LNST 10LS03194NIL
+LIND 38ADMARE01019040146800304001500210501470
+LXPO 22jurisdiction boundary
+LCRF 6ACHGRD
+LVCT 33SPA;SW2;PU2105,1470;PD2409,1470;
+LVCT 33SPA;SW2;PU2261,1470;PD2261,1620;
+**** 0
+0001 501574
+LNST 10LS03347NIL
+LIND 38CBLARE51000940083402739005000029500637
+LXPO 35boundary of a submarine cable area
+LCRF 6ACHMGD
+LVCT 29SPA;SW1;PU295,840;PD895,840;
+LVCT 31SPA;SW1;PU2430,840;PD3034,840;
+LVCT 43SPA;SW1;PU2566,843;PD2727,1004;PD2897,836;
+LVCT 31SPA;SW1;PU1631,844;PD2231,844;
+LVCT 43SPA;SW1;PU1767,843;PD1933,1008;PD2097,843;
+LVCT 39SPA;SW1;PU436,842;PD592,997;PD757,835;
+LVCT 54SPA;SW1;PU1280,637;PD1130,837;PD1330,937;PD1180,1137;
+**** 0
+0001 501575
+LNST 10LS02012NIL
+LIND 38CBLSUB06004480127402293005000069201050
+LXPO 16submarine cable
+LCRF 6ACHMGD
+LVCT 57SPA;SW1;PU2935,1050;PD2785,1250;PD2985,1350;PD2835,1550;
+LVCT 57SPA;SW1;PU1390,1263;PD1541,1161;PD1839,1365;PD1994,1263;
+LVCT 55SPA;SW1;PU692,1264;PD847,1164;PD1148,1371;PD1292,1264;
+LVCT 57SPA;SW1;PU2076,1249;PD2228,1149;PD2527,1352;PD2686,1249;
+**** 0
+0001 501576
+LNST 10LS03432NIL
+LIND 38CHCRDEL1046360265000799008040517902251
+LXPO 46this line has been deleted by a manual update
+LCRF 6ACHCOR
+LVCT 33SPA;SW1;PU5179,3055;PD5978,2251;
+**** 0
+0001 501577
+LNST 10LS03359NIL
+LIND 38CHCRID01044830265000300003000542402498
+LXPO 36this line has been manually updated
+LCRF 6ACHCOR
+LVCT 27SPA;SW1;PU5574,2648;CI150;
+**** 0
+0001 501578
+LNST 10LS03418NIL
+LIND 38CTNARE51001040083003030005180029800640
+LXPO 41boundary of area with a specific caution
+LCRF 6ACHMGD
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2724,822;PD3328,822;
+LVCT 42SPA;SW1;PU2890,826;PD3051,987;PD3221,819;
+LVCT 31SPA;SW1;PU1920,829;PD2520,829;
+LVCT 42SPA;SW1;PU2056,828;PD2222,993;PD2386,828;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+LVCT 26SPA;SW1;PU1415,899;CI259;
+LVCT 31SPA;SW1;PU1411,725;PD1411,950;
+LVCT 33SPA;SW1;PU1395,1043;PD1450,1043;
+**** 0
+0001 501579
+LNST 10LS03417NIL
+LIND 38CTYARE51012980081200600001640150700812
+LXPO 46boundary of area to be navigated with caution
+LCRF 6ACHMGD
+LVCT 31SPA;SW1;PU1507,814;PD2107,814;
+LVCT 42SPA;SW1;PU1647,812;PD1812,976;PD1976,812;
+**** 0
+0001 501580
+LNST 10LS03208NIL
+LIND 38DWLDEF01014490141502550005260159601192
+LXPO 63deep water route centreline, direction not defined in the data
+LCRF 6ATRFCD
+LVCT 93SPA;SW1;PU3522,1270;PD3522,1574;PD3626,1574;PD3726,1529;PD3726,1313;PD3623,1270;PD3522,1270;
+LVCT 69SPA;SW1;PU3847,1266;PD3923,1575;PD3994,1266;PD4080,1571;PD4146,1266;
+LVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+LVCT 33SPA;SW1;PU3002,1415;PD3327,1415;
+LVCT 45SPA;SW1;PU2269,1570;PD2064,1415;PD2269,1260;
+LVCT 33SPA;SW1;PU3618,1718;PD4022,1718;
+LVCT 309SPA;SW1;PU2353,1288;PD2366,1260;PD2379,1235;PD2396,1218;PD2413,1201;PD2439,1192;PD2462,1194;PD2492,1203;PD2520,1209;PD2543,1243;PD2561,1262;PD2573,1284;PD2573,1309;PD2561,1333;PD2548,1354;PD2528,1378;PD2505,1403;PD2484,1429;PD2471,1448;PD2460,1465;PD2458,1487;PD2458,1510;PD2458,1527;PD2460,1549;PD2460,1551;
+LVCT 33SPA;SW2;PU2439,1635;PD2492,1635;
+LVCT 45SPA;SW1;PU2653,1565;PD2858,1410;PD2653,1255;
+**** 0
+0001 501581
+LNST 10LS02015NIL
+LIND 38DWRTCL05014490141502550004580159601260
+LXPO 62two-way deep water route centreline, not based on fixed marks
+LCRF 6ATRFCD
+LVCT 93SPA;SW1;PU3522,1270;PD3522,1574;PD3626,1574;PD3726,1529;PD3726,1313;PD3623,1270;PD3522,1270;
+LVCT 69SPA;SW1;PU3847,1266;PD3923,1575;PD3994,1266;PD4080,1571;PD4146,1266;
+LVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+LVCT 33SPA;SW1;PU2299,1415;PD2624,1415;
+LVCT 33SPA;SW1;PU3002,1415;PD3327,1415;
+LVCT 45SPA;SW1;PU2299,1570;PD2094,1415;PD2299,1260;
+LVCT 33SPA;SW1;PU3618,1718;PD4022,1718;
+LVCT 45SPA;SW1;PU2624,1570;PD2829,1415;PD2624,1260;
+**** 0
+0001 501582
+LNST 10LS02016NIL
+LIND 38DWRTCL06014490141502550004580159601260
+LXPO 58two-way deep water route centreline, based on fixed marks
+LCRF 6ATRFCD
+LVCT 93SPA;SW1;PU3522,1270;PD3522,1574;PD3626,1574;PD3726,1529;PD3726,1313;PD3623,1270;PD3522,1270;
+LVCT 69SPA;SW1;PU3847,1266;PD3923,1575;PD3994,1266;PD4080,1571;PD4146,1266;
+LVCT 33SPA;SW1;PU3618,1718;PD4022,1718;
+LVCT 33SPA;SW1;PU1596,1415;PD3327,1415;
+LVCT 45SPA;SW1;PU2299,1570;PD2094,1415;PD2299,1260;
+LVCT 45SPA;SW1;PU2624,1570;PD2829,1415;PD2624,1260;
+**** 0
+0001 501583
+LNST 10LS02017NIL
+LIND 38DWRTCL07014490141501860004580159601269
+LXPO 62one-way deep water route centreline, not based on fixed marks
+LCRF 6ATRFCD
+LVCT 69SPA;SW1;PU3157,1275;PD3233,1584;PD3304,1275;PD3390,1584;PD3456,1275;
+LVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+LVCT 33SPA;SW1;PU2312,1415;PD2637,1415;
+LVCT 33SPA;SW1;PU2928,1727;PD3332,1727;
+LVCT 45SPA;SW1;PU1934,1579;PD2139,1424;PD1934,1269;
+LVCT 93SPA;SW1;PU2832,1279;PD2832,1583;PD2936,1583;PD3036,1538;PD3036,1322;PD2933,1279;PD2832,1279;
+**** 0
+0001 501584
+LNST 10LS02018NIL
+LIND 38DWRTCL08014490141501860004580159601269
+LXPO 58one-way deep water route centreline, based on fixed-marks
+LCRF 6ATRFCD
+LVCT 69SPA;SW1;PU3157,1275;PD3233,1584;PD3304,1275;PD3390,1580;PD3456,1275;
+LVCT 33SPA;SW1;PU1596,1415;PD2637,1415;
+LVCT 33SPA;SW1;PU2928,1727;PD3332,1727;
+LVCT 45SPA;SW1;PU1934,1579;PD2139,1424;PD1934,1269;
+LVCT 93SPA;SW1;PU2832,1279;PD2832,1583;PD2936,1583;PD3036,1538;PD3036,1322;PD2933,1279;PD2832,1279;
+**** 0
+0001 501585
+LNST 10LS03352NIL
+LIND 38DWRUTE51001040083003030003090029800743
+LXPO 31boundary of a deep water route
+LCRF 6ATRFCD
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2724,822;PD3328,822;
+LVCT 42SPA;SW1;PU2890,826;PD3051,987;PD3221,819;
+LVCT 31SPA;SW1;PU1920,818;PD2520,818;
+LVCT 42SPA;SW1;PU2056,828;PD2222,993;PD2386,828;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+LVCT 89SPA;SW1;PU1101,747;PD1101,1051;PD1205,1051;PD1305,1006;PD1305,790;PD1202,747;PD1101,747;
+LVCT 66SPA;SW1;PU1426,743;PD1502,1052;PD1573,743;PD1659,1048;PD1725,743;
+**** 0
+0001 501586
+LNST 10LS03381NIL
+LIND 38ENTRES51001380080702729005780044600522
+LXPO 60boundary of an area where entry is prohibited or restricted
+LCRF 6ACHMGD
+LVCT 31SPA;SW1;PU2248,809;PD2552,809;
+LVCT 31SPA;SW1;PU2404,809;PD2404,959;
+LVCT 29SPA;SW1;PU446,810;PD747,810;
+LVCT 31SPA;SW1;PU2874,810;PD3175,810;
+LVCT 31SPA;SW1;PU3030,810;PD3030,971;
+LVCT 31SPA;SW1;PU1655,812;PD1957,812;
+LVCT 31SPA;SW1;PU1808,812;PD1808,979;
+LVCT 29SPA;SW1;PU595,812;PD595,970;
+LVCT 26SPA;SW1;PU1237,811;CI289;
+LVCT 31SPA;SW1;PU1085,818;PD1396,818;
+**** 0
+0001 501587
+LNST 10LS03414NIL
+LIND 38ERBLNA01012440155002204000000145901555
+LXPO 30electronic bearing line, dash
+LCRF 6ANINFO
+LVCT 33SPA;SW2;PU1459,1555;PD2463,1555;
+LVCT 33SPA;SW2;PU2664,1555;PD3663,1555;
+**** 0
+0001 501588
+LNST 10LS03415NIL
+LIND 38ERBLNB01012490155201407000030145901552
+LXPO 34electronic bearing line, dash dot
+LCRF 6ANINFO
+LVCT 33SPA;SW2;PU1459,1555;PD2463,1555;
+LVCT 33SPA;SW2;PU2668,1552;PD2866,1552;
+**** 0
+0001 501589
+LNST 10LS02019NIL
+LIND 38FERYRT01001870085301999001600038700774
+LXPO 12ferry route
+LCRF 6ACHMGD
+LVCT 84SPA;SW1;PU1374,890;PD1275,934;PD869,933;PD869,774;PD1275,774;PD1374,819;PD1374,890;
+LVCT 31SPA;SW1;PU1602,853;PD1894,853;
+LVCT 29SPA;SW1;PU697,853;PD387,853;
+LVCT 31SPA;SW1;PU2094,853;PD2386,853;
+**** 0
+0001 501590
+LNST 10LS02020NIL
+LIND 38FERYRT02001870085301999001600038700774
+LXPO 18cable ferry route
+LCRF 6ACHBLK
+LVCT 84SPA;SW1;PU1374,890;PD1275,934;PD869,933;PD869,774;PD1275,774;PD1374,819;PD1374,890;
+LVCT 31SPA;SW1;PU1602,853;PD1894,853;
+LVCT 29SPA;SW1;PU697,853;PD387,853;
+LVCT 31SPA;SW1;PU2094,853;PD2386,853;
+**** 0
+0001 501591
+LNST 10LS02021NIL
+LIND 38FSHFAC02006870077400202001530068700621
+LXPO 15fishing stakes
+LCRF 6ACHGRD
+LVCT 39SPA;SW1;PU889,621;PD889,774;PD687,774;
+**** 0
+0001 501592
+LNST 10LS03355NIL
+LIND 38FSHRES51001080082002691003930044600689
+LXPO 74boundary of an area where trawling or fishing is prohibited or restricted
+LCRF 6ACHMGD
+LVCT 31SPA;SW1;PU2248,809;PD2552,809;
+LVCT 31SPA;SW1;PU2404,809;PD2404,959;
+LVCT 29SPA;SW1;PU446,810;PD747,810;
+LVCT 31SPA;SW1;PU2836,810;PD3137,810;
+LVCT 31SPA;SW1;PU2992,810;PD2992,971;
+LVCT 31SPA;SW1;PU1655,812;PD1957,812;
+LVCT 31SPA;SW1;PU1808,812;PD1808,979;
+LVCT 29SPA;SW1;PU595,812;PD595,970;
+LVCT 252SPA;SW1;PU895,973;PD1013,874;PD1063,819;PD1121,781;PD1182,758;PD1239,741;PD1302,741;PD1355,747;PD1419,769;PD1477,795;PD1529,834;PD1560,874;PD1521,910;PD1484,943;PD1438,966;PD1377,989;PD1316,1001;PD1247,1001;PD1182,989;PD1118,966;PD1063,929;PD1025,898;
+LVCT 29SPA;SW1;PU997,863;PD914,755;
+LVCT 30SPA;SW1;PU1023,897;PD996,867;
+LVCT 32SPA;SW1;PU1499,689;PD1106,1082;
+**** 0
+0001 501593
+LNST 10LS03345NIL
+LIND 38HODATA01007870063400601003000078800635
+LXPO 32boundary marking end of HO data
+LCRF 6ACHGRD
+LVCT 30SPA;SW1;PU788,935;PD1088,635;
+LVCT 30SPA;SW1;PU789,636;PD1389,636;
+**** 0
+0001 501594
+LNST 10LS03424NIL
+LIND 38LOWACC01053050265000130000790547602607
+LXPO 43safety contour of low accuracy in position
+LCRF 6ADEPSC
+LVCT 69SPA;SW1;PU5476,2607;PD5476,2686;PD5606,2686;PD5606,2607;PD5476,2607;
+**** 0
+0001 501595
+LNST 10LS03425NIL
+LIND 38LOWACC11053050265000130000790547602607
+LXPO 36contour of low accuracy in position
+LCRF 6ADEPCN
+LVCT 69SPA;SW1;PU5476,2607;PD5476,2686;PD5606,2686;PD5606,2607;PD5476,2607;
+**** 0
+0001 501596
+LNST 10LS03426NIL
+LIND 38LOWACC21053050265000130000790547602607
+LXPO 64coastline or shoreline construction of low accuracy in position
+LCRF 6ACSTLN
+LVCT 69SPA;SW1;PU5476,2607;PD5476,2686;PD5606,2686;PD5606,2607;PD5476,2607;
+**** 0
+0001 501597
+LNST 10LS03427NIL
+LIND 38LOWACC31053050265000130000790547602607
+LXPO 47area of wrecks or obstructions of low accuracy
+LCRF 6ACHGRD
+LVCT 69SPA;SW1;PU5476,2607;PD5476,2686;PD5606,2686;PD5606,2607;PD5476,2607;
+**** 0
+0001 501598
+LNST 10LS03428NIL
+LIND 38LOWACC41053050265000130000790547602607
+LXPO 52danger line of low accuracy surrounding a foul area
+LCRF 6ACHBLK
+LVCT 69SPA;SW1;PU5476,2607;PD5476,2686;PD5606,2686;PD5606,2607;PD5476,2607;
+**** 0
+0001 501599
+LNST 10LS03379NIL
+LIND 38MARSYS51001120084302558003200010900681
+LXPO 72boundary between IALA-A and IALA-B systems of lateral buoys and beacons
+LCRF 6ACHGRD
+LVCT 31SPA;SW1;PU1633,846;PD1925,846;
+LVCT 31SPA;SW1;PU2375,846;PD2667,846;
+LVCT 31SPA;SW1;PU1415,846;PD1109,846;
+LVCT 39SPA;SW1;PU743,982;PD843,681;PD945,982;
+LVCT 29SPA;SW1;PU783,863;PD909,863;
+LVCT 55SPA;SW1;PU2181,700;PD2082,700;PD2082,1001;PD2181,1001;
+LVCT 31SPA;SW1;PU2082,852;PD2181,852;
+LVCT 31SPA;SW1;PU2224,730;PD2224,829;
+LVCT 31SPA;SW1;PU2223,879;PD2223,978;
+LVCT 31SPA;SW1;PU2181,700;PD2224,730;
+LVCT 32SPA;SW1;PU2181,1001;PD2224,968;
+LVCT 42SPA;SW1;PU2224,826;PD2178,856;PD2221,882;
+LVCT 29SPA;SW1;PU618,846;PD314,846;
+LVCT 29SPA;SW1;PU109,849;PD120,843;
+**** 0
+0001 501600
+LNST 10LS03380NIL
+LIND 38NAVARE51012980081200600001640150700812
+LXPO 75boundary of a navigation feature such as a fairway, magnetic anomaly, etc.
+LCRF 6ACHGRD
+LVCT 31SPA;SW1;PU1507,814;PD2107,814;
+LVCT 42SPA;SW1;PU1647,812;PD1812,976;PD1976,812;
+**** 0
+0001 501601
+LNST 10LS03348NIL
+LIND 38PIPARE51000930080503030002210029800772
+LXPO 74boundary of a submarine pipeline area with potentially dangerous contents
+LCRF 6ACHMGD
+LVCT 25SPA;SW1;PU1619,867;CI95;
+LVCT 31SPA;SW1;PU1125,867;PD1522,867;
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2724,822;PD3328,822;
+LVCT 42SPA;SW1;PU2890,826;PD3051,987;PD3221,819;
+LVCT 31SPA;SW1;PU1920,829;PD2520,829;
+LVCT 42SPA;SW1;PU2056,828;PD2222,993;PD2386,828;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+**** 0
+0001 501602
+LNST 10LS03419NIL
+LIND 38PIPARE61000930080503030002210029800772
+LXPO 76boundary of a submarine pipeline area with generally non-dangerous contents
+LCRF 6ACHGRD
+LVCT 25SPA;SW1;PU1619,867;CI95;
+LVCT 31SPA;SW1;PU1125,867;PD1522,867;
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2724,822;PD3328,822;
+LVCT 42SPA;SW1;PU2890,826;PD3051,987;PD3221,819;
+LVCT 31SPA;SW1;PU1920,829;PD2520,829;
+LVCT 42SPA;SW1;PU2056,828;PD2222,993;PD2386,828;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+**** 0
+0001 501603
+LNST 10LS02025NIL
+LIND 38PIPSOL05017290219900589001900208702104
+LXPO 40oil, gas pipeline, submerged or on land
+LCRF 6ACHMGD
+LVCT 26SPA;SW1;PU2581,2199;CI95;
+LVCT 33SPA;SW1;PU2087,2199;PD2484,2199;
+**** 0
+0001 501604
+LNST 10LS02026NIL
+LIND 38PIPSOL06017310219700512001140208702140
+LXPO 28water pipeline, sewer, etc.
+LCRF 6ACHGRD
+LVCT 33SPA;SW1;PU2087,2197;PD2485,2197;
+LVCT 26SPA;SW1;PU2542,2197;CI57;
+**** 0
+0001 501605
+LNST 10LS03651NIL
+LIND 38PLNRTE03016030143400172001720173801343
+LXPO 27planned route for own ship
+LCRF 6APLRTE
+LVCT 41SPA;SW1;ST0;PU1824,1429;PM0;CI86;PM2;FP;
+**** 0
+0001 501606
+LNST 10LS03353NIL
+LIND 38PRCARE51001040083002869005030029800595
+LXPO 33boundary of a precautionary area
+LCRF 6ACHMGD
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2563,817;PD3167,817;
+LVCT 42SPA;SW1;PU2729,821;PD2890,982;PD3060,814;
+LVCT 31SPA;SW1;PU1759,824;PD2359,824;
+LVCT 42SPA;SW1;PU1895,823;PD2061,988;PD2225,823;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+LVCT 56SPA;SW1;PU1138,1098;PD1504,1098;PD1313,595;PD1141,1098;
+LVCT 33SPA;SW1;PU1291,1027;PD1346,1027;
+LVCT 31SPA;SW1;PU1315,971;PD1315,773;
+**** 0
+0001 501607
+LNST 10LS02028NIL
+LIND 38QUESMRK1005000149801456004430070001227
+LXPO 113object which is not sufficiently described to be symbolized, or for which no symbol exists in the symbol library
+LCRF 6ACHMGD
+LVCT 309SPA;SW1;PU1568,1323;PD1581,1295;PD1594,1270;PD1611,1253;PD1628,1236;PD1654,1227;PD1677,1229;PD1707,1238;PD1735,1244;PD1758,1278;PD1776,1297;PD1788,1319;PD1788,1344;PD1776,1368;PD1763,1389;PD1743,1413;PD1720,1438;PD1699,1464;PD1686,1483;PD1675,1500;PD1673,1522;PD1673,1545;PD1673,1562;PD1675,1584;PD1675,1586;
+LVCT 33SPA;SW2;PU1654,1670;PD1707,1670;
+LVCT 32SPA;SW2;PU700,1498;PD1000,1498;
+LVCT 33SPA;SW2;PU1200,1498;PD1500,1498;
+LVCT 33SPA;SW2;PU1856,1498;PD2156,1498;
+**** 0
+0001 501608
+LNST 10LS03195NIL
+LIND 38RCRDEF01016070147002323005370160101204
+LXPO 60regulated recommended route centreline, details not defined
+LCRF 6ATRFCD
+LVCT 33SPA;SW1;PU2105,1470;PD2409,1470;
+LVCT 33SPA;SW1;PU3110,1470;PD3422,1470;
+LVCT 33SPA;SW1;PU3608,1470;PD3912,1470;
+LVCT 33SPA;SW1;PU1607,1470;PD1907,1470;
+LVCT 45SPA;SW1;PU1753,1573;PD1601,1657;PD1768,1741;
+LVCT 45SPA;SW1;PU3771,1204;PD3924,1288;PD3782,1375;
+LVCT 33SPA;SW1;PU3106,1294;PD3316,1294;
+LVCT 33SPA;SW1;PU3408,1294;PD3610,1294;
+LVCT 33SPA;SW1;PU3709,1290;PD3915,1290;
+LVCT 33SPA;SW1;PU1608,1655;PD1807,1655;
+LVCT 33SPA;SW1;PU1902,1655;PD2108,1655;
+LVCT 33SPA;SW1;PU2207,1655;PD2410,1655;
+LVCT 309SPA;SW1;PU2609,1310;PD2622,1282;PD2635,1257;PD2652,1240;PD2669,1223;PD2695,1214;PD2718,1216;PD2748,1225;PD2776,1231;PD2799,1265;PD2817,1284;PD2829,1306;PD2829,1331;PD2817,1355;PD2804,1376;PD2784,1400;PD2761,1425;PD2740,1451;PD2727,1470;PD2716,1487;PD2714,1509;PD2714,1532;PD2714,1549;PD2716,1571;PD2716,1573;
+LVCT 33SPA;SW1;PU2695,1656;PD2745,1656;
+**** 0
+0001 501609
+LNST 10LS02239NIL
+LIND 38RCRTCL01016070147002305005230160701209
+LXPO 73regulated two-way recommended route centreline, not based on fixed marks
+LCRF 6ATRFCD
+LVCT 33SPA;SW1;PU2608,1470;PD2912,1470;
+LVCT 33SPA;SW1;PU2105,1470;PD2409,1470;
+LVCT 33SPA;SW1;PU3110,1470;PD3422,1470;
+LVCT 33SPA;SW1;PU3608,1470;PD3912,1470;
+LVCT 33SPA;SW1;PU1607,1470;PD1907,1470;
+LVCT 45SPA;SW1;PU2152,1564;PD2000,1648;PD2167,1732;
+LVCT 45SPA;SW1;PU3355,1209;PD3508,1293;PD3366,1380;
+LVCT 33SPA;SW1;PU2690,1299;PD2900,1299;
+LVCT 33SPA;SW1;PU2992,1299;PD3194,1299;
+LVCT 33SPA;SW1;PU3293,1295;PD3499,1295;
+LVCT 33SPA;SW1;PU2007,1646;PD2206,1646;
+LVCT 33SPA;SW1;PU2301,1646;PD2507,1646;
+LVCT 33SPA;SW1;PU2606,1646;PD2809,1646;
+**** 0
+0001 501610
+LNST 10LS03211NIL
+LIND 38RCRTCL02016070147002305002610160701209
+LXPO 73regulated one-way recommended route centreline, not based on fixed marks
+LCRF 6ATRFCD
+LVCT 33SPA;SW1;PU2608,1470;PD2912,1470;
+LVCT 33SPA;SW1;PU2105,1470;PD2409,1470;
+LVCT 33SPA;SW1;PU3110,1470;PD3422,1470;
+LVCT 33SPA;SW1;PU3608,1470;PD3912,1470;
+LVCT 33SPA;SW1;PU1607,1470;PD1907,1470;
+LVCT 45SPA;SW1;PU3355,1209;PD3508,1293;PD3366,1380;
+LVCT 33SPA;SW1;PU2690,1299;PD2900,1299;
+LVCT 33SPA;SW1;PU2992,1299;PD3194,1299;
+LVCT 33SPA;SW1;PU3293,1295;PD3499,1295;
+**** 0
+0001 501611
+LNST 10LS02239NIL
+LIND 38RCRTCL03016070147002305005230160701209
+LXPO 69regulated two-way recommended route centreline, based on fixed-marks
+LCRF 6ATRFCD
+LVCT 33SPA;SW1;PU1607,1470;PD3912,1470;
+LVCT 45SPA;SW1;PU2152,1564;PD2000,1648;PD2167,1732;
+LVCT 45SPA;SW1;PU3355,1209;PD3508,1293;PD3366,1380;
+LVCT 33SPA;SW1;PU2690,1299;PD2900,1299;
+LVCT 33SPA;SW1;PU2992,1299;PD3194,1299;
+LVCT 33SPA;SW1;PU3293,1295;PD3499,1295;
+LVCT 33SPA;SW1;PU2007,1646;PD2206,1646;
+LVCT 33SPA;SW1;PU2301,1646;PD2507,1646;
+LVCT 33SPA;SW1;PU2606,1646;PD2809,1646;
+**** 0
+0001 501612
+LNST 10LS03212NIL
+LIND 38RCRTCL04016070147002305002610160701209
+LXPO 69regulated one-way recommended route centreline, based on fixed marks
+LCRF 6ATRFCD
+LVCT 33SPA;SW1;PU1607,1470;PD3912,1470;
+LVCT 45SPA;SW1;PU3355,1209;PD3508,1293;PD3366,1380;
+LVCT 33SPA;SW1;PU2690,1299;PD2900,1299;
+LVCT 33SPA;SW1;PU2992,1299;PD3194,1299;
+LVCT 33SPA;SW1;PU3293,1295;PD3499,1295;
+**** 0
+0001 501613
+LNST 10LS03335NIL
+LIND 38RECDEF02009320141502220004430110701179
+LXPO 63non-regulated recommended track, direction not defined in data
+LCRF 6ACHGRD
+LVCT 33SPA;SW1;PU1107,1415;PD1423,1415;
+LVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+LVCT 33SPA;SW1;PU3002,1415;PD3327,1415;
+LVCT 309SPA;SW1;PU2358,1275;PD2371,1247;PD2384,1222;PD2401,1205;PD2418,1188;PD2444,1179;PD2467,1181;PD2497,1190;PD2525,1196;PD2548,1230;PD2566,1249;PD2578,1271;PD2578,1296;PD2566,1320;PD2553,1341;PD2533,1365;PD2510,1390;PD2489,1416;PD2476,1435;PD2465,1452;PD2463,1474;PD2463,1497;PD2463,1514;PD2465,1536;PD2465,1538;
+LVCT 33SPA;SW2;PU2444,1622;PD2497,1622;
+LVCT 45SPA;SW1;PU2254,1570;PD2049,1415;PD2254,1260;
+LVCT 45SPA;SW1;PU2660,1566;PD2865,1411;PD2660,1256;
+**** 0
+0001 501614
+LNST 10LS03336NIL
+LIND 38RECTRC09009320141502220003100110701260
+LXPO 66non-regulated recommended two-way track, not based on fixed marks
+LCRF 6ACHGRD
+LVCT 33SPA;SW1;PU1107,1415;PD1423,1415;
+LVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+LVCT 33SPA;SW1;PU2299,1415;PD2624,1415;
+LVCT 33SPA;SW1;PU3002,1415;PD3327,1415;
+LVCT 45SPA;SW1;PU2299,1570;PD2094,1415;PD2299,1260;
+LVCT 45SPA;SW1;PU2624,1570;PD2829,1415;PD2624,1260;
+**** 0
+0001 501615
+LNST 10LS03337NIL
+LIND 38RECTRC10011130141402013003100111301259
+LXPO 62non-regulated recommended two-way track, based on fixed-marks
+LCRF 6ACHGRD
+LVCT 45SPA;SW1;PU2217,1569;PD2012,1414;PD2217,1259;
+LVCT 33SPA;SW1;PU1113,1414;PD3126,1414;
+LVCT 45SPA;SW1;PU2542,1569;PD2747,1414;PD2542,1259;
+**** 0
+0001 501616
+LNST 10LS03338NIL
+LIND 38RECTRC11009320141501526003100110701260
+LXPO 66non-regulated recommended one-way track, not based on fixed marks
+LCRF 6ACHGRD
+LVCT 33SPA;SW1;PU1107,1415;PD1432,1415;
+LVCT 33SPA;SW1;PU1605,1415;PD1930,1415;
+LVCT 33SPA;SW1;PU2308,1415;PD2633,1415;
+LVCT 45SPA;SW1;PU1930,1570;PD2135,1415;PD1930,1260;
+**** 0
+0001 501617
+LNST 10LS03339NIL
+LIND 38RECTRC12011070141501526003100110701260
+LXPO 62non-regulated recommended one-way track, based on fixed marks
+LCRF 6ACHGRD
+LVCT 33SPA;SW1;PU1107,1415;PD2633,1415;
+LVCT 45SPA;SW1;PU1930,1570;PD2135,1415;PD1930,1260;
+**** 0
+0001 501618
+LNST 10LS03161NIL
+LIND 38RESARE51019040146800304001500210501470
+LXPO 30boundary of a restricted area
+LCRF 6ACHMGD
+LVCT 33SPA;SW2;PU2105,1470;PD2409,1470;
+LVCT 33SPA;SW2;PU2261,1470;PD2261,1620;
+**** 0
+0001 501619
+LNST 10LS03420NIL
+LIND 38SCLBDY51002630059800610002440026400597
+LXPO 65chart scale boundary, the double line indicates the larger scale
+LCRF 6ACHGRF
+LVCT 29SPA;SW3;PU264,597;PD874,597;
+LVCT 29SPA;SW1;PU264,772;PD865,772;
+LVCT 29SPA;SW1;PU264,841;PD865,841;
+**** 0
+0001 501620
+LNST 10LS03421NIL
+LIND 38TIDINF51001040083003276003360029800656
+LXPO 57boundary of an area for which there is tidal information
+LCRF 6ACHGRD
+LVCT 29SPA;SW1;PU298,822;PD898,822;
+LVCT 31SPA;SW1;PU2970,816;PD3574,816;
+LVCT 42SPA;SW1;PU3136,820;PD3297,981;PD3467,813;
+LVCT 31SPA;SW1;PU2166,823;PD2766,823;
+LVCT 42SPA;SW1;PU2302,822;PD2468,987;PD2632,822;
+LVCT 39SPA;SW1;PU432,831;PD588,986;PD753,824;
+LVCT 31SPA;SW1;PU1083,824;PD1967,824;
+LVCT 394SPA;SW1;PU1155,823;PD1155,799;PD1162,768;PD1177,735;PD1199,707;PD1228,685;PD1262,669;PD1295,658;PD1326,656;PD1359,663;PD1389,673;PD1417,690;PD1440,709;PD1462,741;PD1479,779;PD1479,808;PD1479,823;PD1479,849;PD1484,878;PD1491,901;PD1506,930;PD1536,955;PD1548,965;PD1565,975;PD1585,984;PD1616,990;PD1651,992;PD1690,984;PD1719,971;PD1752,950;PD1776,926;PD1795,892;PD1806,860;PD1811,843;PD1811,823;
+**** 0
+0001 501621
+LNST 10LS02033NIL
+LIND 38UNITFTH1002760064401109004320027600644
+LXPO 50change of depth unit line, bounds 'fathom depths'
+LCRF 6ACHGRD
+LVCT 30SPA;SW1;PU276,644;PD1385,644;
+LVCT 41SPA;SW1;PU915,770;PD915,1076;PD714,1076;
+LVCT 29SPA;SW1;PU915,921;PD705,921;
+**** 0
+0001 501622
+LNST 10LS02034NIL
+LIND 38UNITMTR1002760064401109004470027600644
+LXPO 49change of depth unit line, bounds 'metre depths'
+LCRF 6ACHGRD
+LVCT 30SPA;SW1;PU276,644;PD1385,644;
+LVCT 61SPA;SW1;PU701,782;PD701,1089;PD804,786;PD908,1091;PD908,786;
+**** 0
+0001 501623
+PATT 10PT02000NIL
+PATD 55AIRARE02VSTGCON0200010000022590225600618005280043500452
+PXPO 39pattern of symbols for an airport area
+PCRF 6ALANDF
+PVCT 150SPA;SW1;PU623,980;PD859,980;PD790,901;PD790,801;PD1053,801;PD810,638;PD810,516;PD751,452;PD680,516;PD680,638;PD435,795;PD684,797;PD684,907;PD623,980;
+**** 0
+0001 501624
+PATT 10PT01206NIL
+PATD 55DIAMOND1VLINCON0000000000022500225002250043130112500093
+PXPO 43area of depth less than the safety contour
+PCRF 6\DEPCN
+PVCT 53SP\;SW1;PU1125,93;PD3375,4406;PU1125,4406;PD3375,93;
+**** 0
+0001 501625
+PATT 10PT03373NIL
+PATD 55DQUALA11VSTGCON0140010000024230141701697011840157000856
+PXPO 74pattern of symbols for a chart of 5m accuracy with full seafloor coverage
+PCRF 6ACHGRD
+PVCT 33SPA;SW1;PU2779,1066;PD3080,1066;
+PVCT 32SPA;SW1;PU3021,947;PD2840,1187;
+PVCT 32SPA;SW1;PU2841,947;PD3021,1186;
+PVCT 33SPA;SW1;PU2257,1066;PD2558,1066;
+PVCT 32SPA;SW1;PU2499,947;PD2318,1187;
+PVCT 32SPA;SW1;PU2319,947;PD2499,1186;
+PVCT 33SPA;SW1;PU1728,1071;PD2029,1071;
+PVCT 32SPA;SW1;PU1970,952;PD1789,1192;
+PVCT 32SPA;SW1;PU1790,952;PD1970,1191;
+PVCT 33SPA;SW1;PU2009,1420;PD2310,1420;
+PVCT 33SPA;SW1;PU2251,1301;PD2070,1541;
+PVCT 33SPA;SW1;PU2071,1301;PD2251,1540;
+PVCT 33SPA;SW1;PU2537,1415;PD2838,1415;
+PVCT 33SPA;SW1;PU2779,1296;PD2598,1536;
+PVCT 33SPA;SW1;PU2599,1296;PD2779,1535;
+PVCT 33SPA;SW1;PU2287,1756;PD2588,1756;
+PVCT 33SPA;SW1;PU2529,1637;PD2348,1877;
+PVCT 33SPA;SW1;PU2349,1637;PD2529,1876;
+PVCT 322SPA;SW1;PU1600,1052;PD1570,971;PD1581,917;PD1600,879;PD1647,859;PD1678,856;PD3105,856;PD3186,863;PD3236,886;PD3256,914;PD3267,944;PD3267,968;PD3267,1006;PD3248,1037;PD2561,1951;PD2534,1982;PD2507,2013;PD2480,2029;PD2461,2032;PD2442,2040;PD2407,2036;PD2388,2032;PD2349,2021;PD2330,2005;PD2310,1982;PD2287,1955;PD1600,1052;
+**** 0
+0001 501626
+PATT 10PT03374NIL
+PATD 55DQUALA21VSTGCON0140010000024010124701697011840157000856
+PXPO 77pattern of symbols for a chart with 20m accuracy with full seafloor coverage
+PCRF 6ACHGRD
+PVCT 33SPA;SW1;PU2779,1066;PD3080,1066;
+PVCT 32SPA;SW1;PU3021,947;PD2840,1187;
+PVCT 32SPA;SW1;PU2841,947;PD3021,1186;
+PVCT 33SPA;SW1;PU2257,1066;PD2558,1066;
+PVCT 32SPA;SW1;PU2499,947;PD2318,1187;
+PVCT 32SPA;SW1;PU2319,947;PD2499,1186;
+PVCT 33SPA;SW1;PU1728,1071;PD2029,1071;
+PVCT 32SPA;SW1;PU1970,952;PD1789,1192;
+PVCT 32SPA;SW1;PU1790,952;PD1970,1191;
+PVCT 33SPA;SW1;PU2009,1420;PD2310,1420;
+PVCT 33SPA;SW1;PU2251,1301;PD2070,1541;
+PVCT 33SPA;SW1;PU2071,1301;PD2251,1540;
+PVCT 33SPA;SW1;PU2537,1415;PD2838,1415;
+PVCT 33SPA;SW1;PU2779,1296;PD2598,1536;
+PVCT 33SPA;SW1;PU2599,1296;PD2779,1535;
+PVCT 322SPA;SW1;PU1600,1052;PD1570,971;PD1581,917;PD1600,879;PD1647,859;PD1678,856;PD3105,856;PD3186,863;PD3236,886;PD3256,914;PD3267,944;PD3267,968;PD3267,1006;PD3248,1037;PD2561,1951;PD2534,1982;PD2507,2013;PD2480,2029;PD2461,2032;PD2442,2040;PD2407,2036;PD2388,2032;PD2349,2021;PD2330,2005;PD2310,1982;PD2287,1955;PD1600,1052;
+**** 0
+0001 501627
+PATT 10PT03375NIL
+PATD 55DQUALB01VSTGCON0140010000024010124701697011840157000856
+PXPO 109pattern of symbols for a chart with 50m accuracy from standard survey based on lines of continuous soundings
+PCRF 6ACHGRD
+PVCT 33SPA;SW1;PU2779,1066;PD3080,1066;
+PVCT 32SPA;SW1;PU3021,947;PD2840,1187;
+PVCT 32SPA;SW1;PU2841,947;PD3021,1186;
+PVCT 33SPA;SW1;PU2257,1066;PD2558,1066;
+PVCT 32SPA;SW1;PU2499,947;PD2318,1187;
+PVCT 32SPA;SW1;PU2319,947;PD2499,1186;
+PVCT 33SPA;SW1;PU1728,1071;PD2029,1071;
+PVCT 32SPA;SW1;PU1970,952;PD1789,1192;
+PVCT 32SPA;SW1;PU1790,952;PD1970,1191;
+PVCT 33SPA;SW1;PU2253,1459;PD2554,1459;
+PVCT 33SPA;SW1;PU2495,1340;PD2314,1580;
+PVCT 33SPA;SW1;PU2315,1340;PD2495,1579;
+PVCT 322SPA;SW1;PU1600,1052;PD1570,971;PD1581,917;PD1600,879;PD1647,859;PD1678,856;PD3105,856;PD3186,863;PD3236,886;PD3256,914;PD3267,944;PD3267,968;PD3267,1006;PD3248,1037;PD2561,1951;PD2534,1982;PD2507,2013;PD2480,2029;PD2461,2032;PD2442,2040;PD2407,2036;PD2388,2032;PD2349,2021;PD2330,2005;PD2310,1982;PD2287,1955;PD1600,1052;
+**** 0
+0001 501628
+PATT 10PT03376NIL
+PATD 55DQUALC01VSTGCON0160010000024070106201604004300159100837
+PXPO 58pattern of symbols for a low accuracy or incomplete chart
+PCRF 6ACHGRD
+PVCT 32SPA;SW1;PU3021,947;PD2840,1187;
+PVCT 32SPA;SW1;PU2841,947;PD3021,1186;
+PVCT 32SPA;SW1;PU2499,947;PD2318,1187;
+PVCT 32SPA;SW1;PU2319,947;PD2499,1186;
+PVCT 32SPA;SW1;PU1970,952;PD1789,1192;
+PVCT 32SPA;SW1;PU1790,952;PD1970,1191;
+PVCT 171SPA;SW1;PU1783,837;PD1738,851;PD1703,865;PD1668,890;PD1640,925;PD1615,967;PD1601,1005;PD1591,1054;PD1598,1106;PD1608,1148;PD1626,1194;PD1671,1232;PD1727,1257;PD1776,1267;
+PVCT 218SPA;SW1;PU1769,841;PD3024,841;PD3066,855;PD3118,883;PD3150,914;PD3178,953;PD3185,981;PD3192,1019;PD3195,1054;PD3192,1099;PD3185,1141;PD3167,1183;PD3150,1208;PD3111,1243;PD3083,1260;PD3059,1267;PD3024,1264;PD1773,1264;
+PVCT 33SPA;SW1;PU1731,1069;PD2031,1069;
+PVCT 33SPA;SW1;PU2780,1066;PD3080,1066;
+PVCT 33SPA;SW1;PU2249,1064;PD2549,1064;
+**** 0
+0001 501629
+PATT 10PT03377NIL
+PATD 55DQUALD01VSTGCON0160010000022680107801604004300146600843
+PXPO 43pattern of symbols for an unreliable chart
+PCRF 6ACHGRD
+PVCT 32SPA;SW1;PU2739,942;PD2558,1182;
+PVCT 32SPA;SW1;PU2559,942;PD2739,1181;
+PVCT 32SPA;SW1;PU1970,952;PD1789,1192;
+PVCT 32SPA;SW1;PU1790,952;PD1970,1191;
+PVCT 171SPA;SW1;PU1658,843;PD1613,857;PD1578,871;PD1543,896;PD1515,931;PD1490,973;PD1476,1011;PD1466,1060;PD1473,1112;PD1483,1154;PD1501,1200;PD1546,1238;PD1602,1263;PD1651,1273;
+PVCT 218SPA;SW1;PU1644,847;PD2899,847;PD2941,861;PD2993,889;PD3025,920;PD3053,959;PD3060,987;PD3067,1025;PD3070,1060;PD3067,1105;PD3060,1147;PD3042,1189;PD3025,1214;PD2986,1249;PD2958,1266;PD2934,1273;PD2899,1270;PD1648,1270;
+PVCT 33SPA;SW1;PU1734,1069;PD2034,1067;
+PVCT 33SPA;SW1;PU2493,1064;PD2815,1064;
+**** 0
+0001 501630
+PATT 10PT03378NIL
+PATD 55DQUALU01VSTGCON0160010000029270105901604004300212400841
+PXPO 57pattern of symbols for a chart with quality not assessed
+PCRF 6ACHGRD
+PVCT 171SPA;SW1;PU2316,841;PD2271,855;PD2236,869;PD2201,894;PD2173,929;PD2148,971;PD2134,1009;PD2124,1058;PD2131,1110;PD2141,1152;PD2159,1198;PD2204,1236;PD2260,1261;PD2309,1271;
+PVCT 218SPA;SW1;PU2302,845;PD3557,845;PD3599,859;PD3651,887;PD3683,918;PD3711,957;PD3718,985;PD3725,1023;PD3728,1058;PD3725,1103;PD3718,1145;PD3700,1187;PD3683,1212;PD3644,1247;PD3616,1264;PD3592,1271;PD3557,1268;PD2306,1268;
+PVCT 139SPA;SW1;PU2841,946;PD2842,1137;PD2852,1166;PD2873,1186;PD2904,1201;PD2938,1203;PD2961,1193;PD2990,1175;PD3008,1158;PD3018,1134;PD3018,946;
+**** 0
+0001 501631
+PATT 10PT01207NIL
+PATD 55DRGARE01VLINCON0015000000015000150000200002000150001300
+PXPO 13dredged area
+PCRF 6DCHGRD
+PVCT 39SPD;SW1;PU1500,1300;PD;PU1700,1500;PD;
+**** 0
+0001 501632
+PATT 10PT03416NIL
+PATD 55FOULAR01VLINCON0015010000008370072800570006840102000850
+PXPO 35foul area, not safe for navigation
+PCRF 6ACHGRD
+PVCT 33SPA;SW1;PU1590,1294;PD1409,1534;
+PVCT 33SPA;SW1;PU1410,1294;PD1590,1533;
+PVCT 32SPA;SW1;PU1022,850;PD1200,1090;
+PVCT 32SPA;SW1;PU1196,853;PD1020,1093;
+**** 0
+0001 501633
+PATT 10PT02001NIL
+PATD 55FSHFAC03VSTGCON0200010000046430216800604001510313502173
+PXPO 51pattern of symbols for an area with fishing stakes
+PCRF 6ACHGRD
+PVCT 57SPA;SW1;PU3135,2173;PD3135,2323;PD3739,2323;PD3739,2180;
+PVCT 33SPA;SW1;PU3290,2176;PD3290,2324;
+PVCT 33SPA;SW1;PU3438,2179;PD3438,2321;
+PVCT 33SPA;SW1;PU3590,2179;PD3590,2321;
+**** 0
+0001 501634
+PATT 10PT01211NIL
+PATD 55FSHFAC04VSTGCON0200010000017530018900511004380049200416
+PXPO 71pattern of symbols for an area with fish traps, fish weirs, tunny nets
+PCRF 6ACHGRD
+PVCT 61SPA;SW1;PU492,854;PD1003,854;PD1003,632;PD494,632;PD494,853;
+PVCT 29SPA;SW1;PU558,416;PD776,634;
+**** 0
+0001 501635
+PATT 10PT01212NIL
+PATD 55FSHHAV02VSTGCON0200010000022000147000790003200071001335
+PXPO 36pattern of symbols for a fish haven
+PCRF 6ECHGRD
+PVCT 122SPE;SW1;PU835,1490;PD725,1355;PU835,1500;PD710,1625;PU835,1500;PD890,1440;PD960,1390;PD1050,1350;PD1150,1335;PD1240,1340;
+PVCT 119PD1340,1360;PD1425,1400;PD1485,1445;PD1500,1475;PU840,1495;PD925,1565;PD1030,1625;PD1140,1650;PD1220,1655;PD1305,1640;
+PVCT 85PD1385,1610;PD1450,1550;PD1500,1480;PU1365,1380;PD1340,1445;PD1340,1535;PD1385,1600;
+**** 0
+0001 501636
+PATT 10PT01213NIL
+PATD 55ICEARE04VLINCON0000000000022500225001434013310238100815
+PXPO 51continuous pattern for an ice area (glacier, etc.)
+PCRF 6ECHGRD
+PVCT 116SPE;SW1;PU2559,2146;PD2775,1978;PU2381,1153;PD2596,1396;PU2981,1537;PD3253,1603;PU2953,1059;PD3028,815;PU3131,2043;
+PVCT 61PD3412,1959;PU3665,1593;PD3731,1865;PU3553,1125;PD3815,1106;
+**** 0
+0001 501637
+PATT 10PT02003NIL
+PATD 55MARCUL02VSTGCON0200010000024090036900705004030041600568
+PXPO 37pattern of symbols for a marine farm
+PCRF 6ACHGRD
+PVCT 202SPA;SW1;PU505,847;PD641,725;PD714,684;PD771,668;PD822,662;PD882,673;PD944,693;PD984,717;PD1018,744;PD1039,774;PD1004,803;PD968,831;PD914,855;PD871,869;PD819,871;PD763,869;PD709,857;PD670,835;PD505,698;
+PVCT 51SPA;SW1;PU416,669;PD416,570;PD1117,570;PD1117,666;
+PVCT 51SPA;SW1;PU416,871;PD416,971;PD1120,971;PD1121,871;
+PVCT 29SPA;SW1;PU564,871;PD564,971;
+PVCT 29SPA;SW1;PU965,871;PD965,971;
+PVCT 29SPA;SW1;PU765,870;PD765,968;
+PVCT 29SPA;SW1;PU564,571;PD564,672;
+PVCT 29SPA;SW1;PU965,569;PD965,670;
+PVCT 29SPA;SW1;PU764,568;PD764,668;
+**** 0
+0001 501638
+PATT 10PT03143NIL
+PATD 55MARSHES1VSTGCON0150015000007500101600400003930055000499
+PXPO 31pattern of symbols for a marsh
+PCRF 6ACHBRN
+PVCT 29SPA;SW2;PU751,765;PD751,499;
+PVCT 29SPA;SW2;PU626,892;PD876,892;
+PVCT 29SPA;SW2;PU550,810;PD950,810;
+PVCT 29SPA;SW2;PU664,799;PD592,634;
+PVCT 29SPA;SW2;PU830,799;PD901,637;
+**** 0
+0001 501639
+PATT 10PT03113NIL
+PATD 55NODATA03VSTGCON0010010000029420104000602003960234200645
+PXPO 22area of no chart data
+PCRF 6ACHGRD
+PVCT 33SPA;SW2;PU2342,1041;PD2542,1040;
+**** 0
+0001 501640
+PATT 10PT03372NIL
+PATD 55OVERSC01VLINCON0000010000042430122700000004000344300827
+PXPO 82overscale part of a display containing data from more than one navigation purpose
+PCRF 6ACHGRD
+PVCT 32SPA;SW1;PU3443,827;PD3443,1227;
+**** 0
+0001 501641
+PATT 10PT03371NIL
+PATD 55PRTSUR01VSTGCON0100010000023470064000201000000244800741
+PXPO 27incompletely surveyed area
+PCRF 6ACHGRD
+PVCT 31SPA;SW2;PU2448,741;PD2650,741;
+**** 0
+0001 501642
+PATT 10PT02007NIL
+PATD 55QUESMRK1VSTGCON0200010000016760150100220004430156801227
+PXPO 137pattern of symbols for an area which is not sufficiently described to be symbolized, or for which no symbol exists in the symbol library
+PCRF 6ACHMGD
+PVCT 309SPA;SW1;PU1568,1323;PD1581,1295;PD1594,1270;PD1611,1253;PD1628,1236;PD1654,1227;PD1677,1229;PD1707,1238;PD1735,1244;PD1758,1278;PD1776,1297;PD1788,1319;PD1788,1344;PD1776,1368;PD1763,1389;PD1743,1413;PD1720,1438;PD1699,1464;PD1686,1483;PD1675,1500;PD1673,1522;PD1673,1545;PD1673,1562;PD1675,1584;PD1675,1586;
+PVCT 33SPA;SW2;PU1654,1670;PD1707,1670;
+**** 0
+0001 501643
+PATT 10PT03180NIL
+PATD 55RCKLDG01VLINCON0000000000023190215201541013320232500814
+PXPO 28rock or coral drying ledges
+PCRF 6ALANDF
+PVCT 33SPA;SW1;PU2559,2146;PD2775,1978;
+PVCT 33SPA;SW1;PU2490,1030;PD2593,1337;
+PVCT 33SPA;SW1;PU3102,1412;PD2942,1642;
+PVCT 32SPA;SW1;PU2953,1059;PD3028,815;
+PVCT 33SPA;SW1;PU3194,1797;PD3244,2086;
+PVCT 33SPA;SW1;PU3751,1761;PD3866,1506;
+PVCT 33SPA;SW1;PU3768,1160;PD3518,1079;
+PVCT 33SPA;SW1;PU2593,1331;PD2325,1193;
+PVCT 33SPA;SW1;PU2951,1640;PD2924,1374;
+PVCT 33SPA;SW1;PU2554,2146;PD2583,1889;
+PVCT 33SPA;SW1;PU3197,1797;PD3409,1967;
+PVCT 33SPA;SW1;PU3859,1507;PD3595,1618;
+PVCT 32SPA;SW1;PU3522,1083;PD3727,948;
+PVCT 32SPA;SW1;PU3028,814;PD3138,1049;
+**** 0
+0001 501644
+PATT 10PT02238NIL
+PATD 55SNDWAV01VSTGCON0200010000000290049901179001790003700316
+PXPO 34pattern of symbols for sand waves
+PCRF 6ACHGRD
+PVCT 222SPA;SW1;PU37,495;PD121,495;PD163,473;PD228,328;PD263,328;PD320,473;PD347,495;PD523,495;PD554,468;PD600,331;PD626,331;PD677,468;PD710,495;PD856,495;PD906,495;PD937,476;PD998,316;PD1036,316;PD1093,473;PD1132,495;PD1216,495;
+**** 0
+0001 501645
+PATT 10PT01224NIL
+PATD 55TSSJCT02VLINCON0000000000007500075000500005000075000250
+PXPO 73precautionary area or a traffic separation scheme crossing or roundabout
+PCRF 6UTRFCF
+PVCT 30SPU;SW1;PU750,750;PD1250,250;
+**** 0
+0001 501646
+PATT 10PT02008NIL
+PATD 55VEGATN03VSTGCON0100010000007490074600362003990057400348
+PXPO 36pattern of symbols for wooded areas
+PCRF 6ALANDF
+PVCT 29SPA;SW1;PU750,747;PD750,350;
+PVCT 29SPA;SW1;PU574,447;PD936,447;
+PVCT 29SPA;SW1;PU641,545;PD858,545;
+PVCT 29SPA;SW1;PU684,348;PD814,348;
+PVCT 29SPA;SW1;PU695,747;PD815,747;
+PVCT 29SPA;SW1;PU638,396;PD858,396;
+PVCT 29SPA;SW1;PU621,494;PD883,494;
+**** 0
+0001 501647
+PATT 10PT03001NIL
+PATD 55VEGATN04VSTGCON0100010000007500075000400003000055000450
+PXPO 33pattern of symbols for mangroves
+PCRF 6ALANDF
+PVCT 25SPA;SW1;PU750,600;CI150;
+PVCT 29SPA;SW1;PU550,750;PD950,750;
+PVCT 29SPA;SW1;PU750,748;PD750,587;
+**** 0
+0001 501648
+SYMB 10SY02035NIL
+SYMD 39ACHARE02V012670105200402005030106100789
+SXPO 90anchorage area as a point at small scale, or anchor points of mooring trot at large scale
+SCRF 6ACHMGD
+SVCT 32SPA;SW1;PU1264,789;PD1264,1291;
+SVCT 31SPA;SW1;PU1108,938;PD1412,938;
+SVCT 57SPA;SW1;PU1061,1188;PD1167,1292;PD1365,1292;PD1463,1191;
+**** 0
+0001 501649
+SYMB 10SY01228NIL
+SYMD 39ACHARE51V022500225001229013040162101471
+SXPO 15anchorage area
+SCRF 6JCHMGF
+SVCT 117SPJ;SW1;PU2193,1471;PD2193,1800;PD1875,1800;PD1875,1912;PD2193,1912;PD2193,2596;PD1987,2550;PD1800,2409;PD1621,2409;
+SVCT 121PD1875,2596;PD2250,2775;PD2596,2596;PD2850,2409;PD2700,2409;PD2475,2550;PD2268,2596;PD2268,1912;PD2596,1912;PD2596,1800;
+SVCT 37PD2268,1800;PD2268,1471;PD2193,1471;
+**** 0
+0001 501650
+SYMB 10SY03003NIL
+SYMD 39ACHBRT07V012640106200506005060101000783
+SXPO 44designated anchor berth for a single vessel
+SCRF 6ACHMGD
+SVCT 32SPA;SW1;PU1262,783;PD1262,1004;
+SVCT 33SPA;SW1;PU1262,1289;PD1262,1207;
+SVCT 57SPA;SW1;PU1516,1135;PD1364,1287;PD1167,1287;PD1010,1132;
+SVCT 27SPA;SW1;PU1261,1101;CI101;
+SVCT 31SPA;SW1;PU1107,937;PD1424,937;
+**** 0
+0001 501651
+SYMB 10SY03399NIL
+SYMD 39ACHRES51V009810095801229013040162101471
+SXPO 49area where anchoring is prohibited or restricted
+SCRF 6ACHMGF
+SVCT 273SPA;SW1;PU2193,1471;PD2193,1800;PD1875,1800;PD1875,1912;PD2193,1912;PD2193,2596;PD1987,2550;PD1800,2409;PD1621,2409;PD1875,2596;PD2250,2775;PD2596,2596;PD2850,2409;PD2700,2409;PD2475,2550;PD2268,2596;PD2268,1912;PD2596,1912;PD2596,1800;PD2268,1800;PD2268,1471;PD2193,1471;
+SVCT 33SPA;SW3;PU2703,1671;PD1701,2679;
+**** 0
+0001 501652
+SYMB 10SY03401NIL
+SYMD 39ACHRES61V009810095801435013040162101471
+SXPO 70area where anchoring is prohibited or restricted, with other cautions
+SCRF 12ACHMGFCCHMGD
+SVCT 273SPA;SW1;PU2193,1471;PD2193,1800;PD1875,1800;PD1875,1912;PD2193,1912;PD2193,2596;PD1987,2550;PD1800,2409;PD1621,2409;PD1875,2596;PD2250,2775;PD2596,2596;PD2850,2409;PD2700,2409;PD2475,2550;PD2268,2596;PD2268,1912;PD2596,1912;PD2596,1800;PD2268,1800;PD2268,1471;PD2193,1471;
+SVCT 33SPA;SW3;PU2703,1671;PD1701,2679;
+SVCT 33SPC;SW3;PU3001,2775;PD3056,2775;
+SVCT 33SPC;SW1;PU3019,2325;PD3019,2671;
+**** 0
+0001 501653
+SYMB 10SY03403NIL
+SYMD 39ACHRES71V009810095801447013040140301471
+SXPO 73area where anchoring is prohibited or restricted, with other information
+SCRF 12ACHMGFCCHMGD
+SVCT 273SPA;SW1;PU2193,1471;PD2193,1800;PD1875,1800;PD1875,1912;PD2193,1912;PD2193,2596;PD1987,2550;PD1800,2409;PD1621,2409;PD1875,2596;PD2250,2775;PD2596,2596;PD2850,2409;PD2700,2409;PD2475,2550;PD2268,2596;PD2268,1912;PD2596,1912;PD2596,1800;PD2268,1800;PD2268,1471;PD2193,1471;
+SVCT 33SPA;SW3;PU2703,1671;PD1701,2679;
+SVCT 45SPC;SW1;PU1495,2761;PD1495,2527;PD1403,2526;
+SVCT 33SPC;SW1;PU1404,2762;PD1591,2762;
+SVCT 33SPC;SW1;PU1449,2408;PD1452,2448;
+**** 0
+0001 501654
+SYMB 10SY02075NIL
+SYMD 39AIRARE02V007490075000796007960035100352
+SXPO 30symbol for airport as a point
+SCRF 6ALANDF
+SVCT 25SPA;SW1;PU749,750;CI398;
+SVCT 150SPA;SW1;PU623,980;PD859,980;PD790,901;PD790,801;PD1053,801;PD810,638;PD810,516;PD751,452;PD680,516;PD680,638;PD435,795;PD684,797;PD684,907;PD623,980;
+**** 0
+0001 501655
+SYMB 10SY03500NIL
+SYMD 39AISDEF01V004720105000562007510034500391
+SXPO 53AIS target whose heading and course are both unknown
+SCRF 12AARPATCCHMGD
+SVCT 40SPA;SW1;ST0;PU472,1052;PM0;CI31;PM2;FP;
+SVCT 52SPA;SW2;PU350,1142;PD598,1142;PD469,391;PD345,1140;
+SVCT 259SPC;SW1;PU687,638;PD700,610;PD713,585;PD730,568;PD747,551;PD773,542;PD796,544;PD826,553;PD854,559;PD877,593;PD895,612;PD907,634;PD907,659;PD895,683;PD882,704;PD862,728;PD839,753;PD818,779;PD805,798;PD794,815;PD792,837;PD792,860;PD792,877;PD794,899;PD794,901;
+SVCT 29SPC;SW1;PU775,929;PD811,929;
+**** 0
+0001 501656
+SYMB 10SY03216NIL
+SYMD 39AISONE01V073710161500405001710717401445
+SXPO 31one minute mark for AIS vector
+SCRF 6AARPAT
+SVCT 57SPA;SW1;PU7174,1616;PD7579,1616;PD7372,1445;PD7174,1616;
+**** 0
+0001 501657
+SYMB 10SY03215NIL
+SYMD 39AISSIX01V073710165700405002140717301445
+SXPO 31six minute mark for AIS vector
+SCRF 6AARPAT
+SVCT 57SPA;SW1;PU7173,1617;PD7578,1616;PD7371,1445;PD7173,1617;
+SVCT 33SPA;SW3;PU7173,1659;PD7578,1659;
+**** 0
+0001 501658
+SYMB 10SY03210NIL
+SYMD 39AISSLP01V004720105000253007510034500391
+SXPO 20sleeping AIS target
+SCRF 6AARPAT
+SVCT 40SPA;SW1;ST0;PU472,1052;PM0;CI31;PM2;FP;
+SVCT 52SPA;SW2;PU350,1142;PD598,1142;PD469,391;PD345,1140;
+**** 0
+0001 501659
+SYMB 10SY03209NIL
+SYMD 39AISVES01V004950105000499012480024500051
+SXPO 48active AIS target showing vector and/or heading
+SCRF 6AARPAT
+SVCT 51SPA;SW2;PU245,1299;PD744,1299;PD495,51;PD245,1299;
+SVCT 40SPA;SW1;ST0;PU495,1050;PM0;CI31;PM2;FP;
+**** 0
+0001 501660
+SYMB 10SY03221NIL
+SYMD 39ARPATG01V015000150000500005000125001250
+SXPO 12ARPA target
+SCRF 6eARPAT
+SVCT 59SPe;PU1500,1500;SW2;CI250;PU1500,1500;ST0;PM0;CI62;PM2;FP;
+**** 0
+0001 501661
+SYMB 10SY03219NIL
+SYMD 39ARPONE01V050330216700394000000482802167
+SXPO 31one minute mark on ARPA vector
+SCRF 6AARPAT
+SVCT 33SPA;SW2;PU4828,2167;PD5222,2167;
+**** 0
+0001 501662
+SYMB 10SY03220NIL
+SYMD 39ARPSIX01V053840214500397000000518902146
+SXPO 31six minute mark on ARPA vector
+SCRF 6AARPAT
+SVCT 33SPA;SW5;PU5189,2146;PD5586,2146;
+**** 0
+0001 501663
+SYMB 10SY01232NIL
+SYMD 39BCNCAR01V007500075000402006120055000445
+SXPO 35cardinal beacon, north, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 113SPH;ST0;PU750,780;PM0;PD552,1052,950,1057,750,780;PM2;FP;PU750,445;PM0;PD952,720,555,720,750,445;PM2;FP;SPm;SW1;
+SVCT 84PU750,445;PD550,720;PD950,720;PD750,445;PU550,1055;PD950,1055;PD750,780;PD550,1055;
+**** 0
+0001 501664
+SYMB 10SY01233NIL
+SYMD 39BCNCAR02V007500075000400006600055000420
+SXPO 34cardinal beacon, east, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 112SPH;ST0;PU750,420;PM0;PD947,695,552,692,750,420;PM2;FP;PU585,805;PM0;PD947,805,750,1080,552,805;PM2;FP;SPm;SW1;
+SVCT 82PU750,420;PD550,695;PD950,695;PD750,420;PU550,805;PD950,805;PD750,1080;PD550,805;
+**** 0
+0001 501665
+SYMB 10SY01234NIL
+SYMD 39BCNCAR03V007500075000400006100055000445
+SXPO 35cardinal beacon, south, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 112SPH;ST0;PU585,445;PM0;PD947,447,750,720,555,445;PM2;FP;PU585,780;PM0;PD947,780,750,1055,552,780;PM2;FP;SPm;SW1;
+SVCT 82PU750,720;PD550,445;PD950,445;PD750,720;PU550,780;PD950,780;PD750,1055;PD550,780;
+**** 0
+0001 501666
+SYMB 10SY01235NIL
+SYMD 39BCNCAR04V007500075000400006100055000445
+SXPO 34cardinal beacon, west, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 113SPH;ST0;PU750,780;PM0;PD552,1055,947,1055,750,780;PM2;FP;PU585,445;PM0;PD947,445,750,720,550,445;PM2;FP;SPm;SW1;
+SVCT 84PU550,1055;PD950,1055;PD750,780;PD550,1055;PU750,720;PD550,445;PD950,445;PD750,720;
+**** 0
+0001 501667
+SYMB 10SY02039NIL
+SYMD 39BCNDEF13V012380145200527004460113501234
+SXPO 40default symbol for a beacon, simplified
+SCRF 18ACHMGDCCHGRDDOUTLW
+SVCT 309SPA;SW1;PU1442,1329;PD1455,1301;PD1468,1276;PD1486,1260;PD1503,1243;PD1529,1234;PD1552,1237;PD1582,1246;PD1610,1253;PD1632,1287;PD1650,1306;PD1662,1329;PD1661,1354;PD1649,1377;PD1635,1398;PD1615,1422;PD1591,1446;PD1570,1472;PD1557,1491;PD1546,1508;PD1543,1529;PD1542,1552;PD1542,1568;PD1543,1590;PD1543,1591;
+SVCT 33SPA;SW2;PU1518,1680;PD1570,1680;
+SVCT 84SPC;SW1;ST0;PU1135,1250;PM0;PD1135,1649;PD1335,1649;PD1335,1251;PD1135,1250;PM2;FP;
+SVCT 69SPD;SW1;PU1135,1250;PD1135,1649;PD1335,1649;PD1335,1251;PD1135,1250;
+SVCT 41SPD;SW1;ST0;PU1238,1452;PM0;CI15;PM2;FP;
+**** 0
+0001 501668
+SYMB 10SY01238NIL
+SYMD 39BCNGEN01V007500075000300005150060000300
+SXPO 31beacon in general, paper-chart
+SCRF 6CCHBLK
+SVCT 121SPC;ST0;PU675,743;PM0;PD675,300,818,300,818,750,809,725,806,706,800,700,778,690,759,684,753,681,734,684,725,684,712,690;
+SVCT 109PD703,703,693,718,681,725,675,740,675,750;PM2;FP;PU750,750;SW2;CI65;PU600,750;PD684,750;PU815,750;PD900,750;
+**** 0
+0001 501669
+SYMB 10SY02040NIL
+SYMD 39BCNGEN03V012310163400593005000108101188
+SXPO 39default symbol for beacon, paper-chart
+SCRF 12ACHMGDCCHBLK
+SVCT 309SPA;SW1;PU1454,1302;PD1467,1274;PD1480,1249;PD1497,1232;PD1514,1215;PD1540,1206;PD1563,1208;PD1593,1217;PD1621,1223;PD1644,1257;PD1662,1276;PD1674,1298;PD1674,1323;PD1662,1347;PD1649,1368;PD1629,1392;PD1606,1417;PD1585,1443;PD1572,1462;PD1561,1479;PD1559,1501;PD1559,1524;PD1559,1541;PD1561,1563;PD1561,1565;
+SVCT 33SPA;SW2;PU1540,1652;PD1593,1652;
+SVCT 33SPC;SW2;PU1081,1577;PD1399,1576;
+SVCT 26SPC;SW2;PU1231,1634;CI54;
+SVCT 33SPC;SW4;PU1230,1575;PD1227,1188;
+**** 0
+0001 501670
+SYMB 10SY02041NIL
+SYMD 39BCNISD21V014930062300222005440138100354
+SXPO 35isolated danger beacon, simplified
+SCRF 12AOUTLWCCHRED
+SVCT 41SPC;SW1;ST0;PU1493,464;PM0;CI110;PM2;FP;
+SVCT 41SPC;SW1;ST0;PU1491,788;PM0;CI110;PM2;FP;
+SVCT 26SPA;SW1;PU1493,464;CI110;
+SVCT 26SPA;SW1;PU1491,788;CI110;
+**** 0
+0001 501671
+SYMB 10SY01253NIL
+SYMD 39BCNLAT15V006000085000200004000050000650
+SXPO 38major lateral beacon, red, simplified
+SCRF 12FCHREDmOUTLW
+SVCT 117SPF;ST0;PU500,1050;PM0;PD700,1050,700,650,500,650,500,1050;PM2;FP;SPm;SW1;PU500,1050;PD700,1050;PD700,650;PD500,650;
+SVCT 12PD500,1050;
+SVCT 39SPm;SW1;ST0;PU600,850;PM0;CI15;PM2;FP;
+**** 0
+0001 501672
+SYMB 10SY01254NIL
+SYMD 39BCNLAT16V007500075000200004000065000550
+SXPO 40major lateral beacon, green, simplified
+SCRF 12GCHGRNmOUTLW
+SVCT 112SPG;ST0;PU650,950;PM0;PD850,950,850,550,650,550,650,950;PM2;FP;SPm;SW1;PU650,950;PD850,950;PD850,550;PD650,550;
+SVCT 11PD650,950;
+SVCT 39SPm;SW1;ST0;PU750,750;PM0;CI15;PM2;FP;
+**** 0
+0001 501673
+SYMB 10SY02042NIL
+SYMD 39BCNLAT21V004130075600133005000034700505
+SXPO 38minor lateral beacon, red, simplified
+SCRF 12aOUTLWbCHRED
+SVCT 77SPb;SW1;ST0;PU347,1005;PM0;PD347,505;PD480,505;PD480,1005;PD347,1005;PM2;FP;
+SVCT 62SPa;SW1;PU347,1005;PD347,505;PD480,505;PD480,1005;PD347,1005;
+SVCT 39SPa;SW1;ST0;PU413,756;PM0;CI15;PM2;FP;
+**** 0
+0001 501674
+SYMB 10SY02043NIL
+SYMD 39BCNLAT22V004130075600133005000034700505
+SXPO 40minor lateral beacon, green, simplified
+SCRF 12aOUTLWbCHGRN
+SVCT 77SPb;SW1;ST0;PU347,1005;PM0;PD347,505;PD480,505;PD480,1005;PD347,1005;PM2;FP;
+SVCT 62SPa;SW1;PU347,1005;PD347,505;PD480,505;PD480,1005;PD347,1005;
+SVCT 39SPa;SW1;ST0;PU413,756;PM0;CI15;PM2;FP;
+**** 0
+0001 501675
+SYMB 10SY01255NIL
+SYMD 39BCNLTC01V007500075000500005180050000300
+SXPO 28lattice beacon, paper-chart
+SCRF 6CCHBLK
+SVCT 113SPC;PU750,750;SW2;CI68;PU500,750;PD678,750;PU812,750;PD1000,750;SW2;PU550,750;PD650,300;PD850,300;PD950,750;SW2;
+SVCT 81PU562,675;PD903,543;PU596,543;PD931,671;PU640,343;PD884,465;PU850,350;PD609,468;
+**** 0
+0001 501676
+SYMB 10SY01260NIL
+SYMD 39BCNSAW13V007500075000200004000065000550
+SXPO 36major safe water beacon, simplified
+SCRF 18CCHBLKmOUTLWBDEPVS
+SVCT 112SPC;ST0;PU650,950;PM0;PD850,950,850,550,650,550,650,950;PM2;FP;SPm;SW1;PU650,950;PD850,950;PD850,550;PD650,550;
+SVCT 11PD650,950;
+SVCT 39SPB;SW1;ST0;PU750,750;PM0;CI15;PM2;FP;
+**** 0
+0001 501677
+SYMB 10SY02044NIL
+SYMD 39BCNSAW21V004130075600133005000034700505
+SXPO 36minor safe water beacon, simplified
+SCRF 18aOUTLWbCHBLKBDEPVS
+SVCT 77SPb;SW1;ST0;PU347,1005;PM0;PD347,505;PD480,505;PD480,1005;PD347,1005;PM2;FP;
+SVCT 62SPa;SW1;PU347,1005;PD347,505;PD480,505;PD480,1005;PD347,1005;
+SVCT 39SPB;SW1;ST0;PU413,756;PM0;CI15;PM2;FP;
+**** 0
+0001 501678
+SYMB 10SY01265NIL
+SYMD 39BCNSPP13V007500075000200004000065000550
+SXPO 41major special purpose beacon, simplified
+SCRF 12HCHYLWmOUTLW
+SVCT 112SPH;ST0;PU650,950;PM0;PD850,950,850,550,650,550,650,950;PM2;FP;SPm;SW1;PU650,950;PD850,950;PD850,550;PD650,550;
+SVCT 11PD650,950;
+SVCT 39SPm;SW1;ST0;PU750,750;PM0;CI15;PM2;FP;
+**** 0
+0001 501679
+SYMB 10SY02045NIL
+SYMD 39BCNSPP21V004130075600133005000034700505
+SXPO 41minor special purpose beacon, simplified
+SCRF 12aOUTLWbCHYLW
+SVCT 77SPb;SW1;ST0;PU347,1005;PM0;PD347,505;PD480,505;PD480,1005;PD347,1005;PM2;FP;
+SVCT 62SPa;SW1;PU347,1005;PD347,505;PD480,505;PD480,1005;PD347,1005;
+SVCT 39SPa;SW1;ST0;PU413,756;PM0;CI15;PM2;FP;
+**** 0
+0001 501680
+SYMB 10SY02046NIL
+SYMD 39BCNSTK02V007500075000250004510062500299
+SXPO 41minor, stake or pole beacon, paper-chart
+SCRF 6ACHBLK
+SVCT 29SPA;SW2;PU625,750;PD875,750;
+SVCT 29SPA;SW2;PU754,299;PD755,749;
+**** 0
+0001 501681
+SYMB 10SY01267NIL
+SYMD 39BCNTOW01V007500075000500005200050000300
+SXPO 26beacon tower, paper-chart
+SCRF 6CCHBLK
+SVCT 109SPC;PU750,750;SW2;CI70;PU500,750;PD680,750;PU815,750;PD1000,750;SW2;PU550,750;PD650,300;PD850,300;PD950,750;
+**** 0
+0001 501682
+SYMB 10SY03650NIL
+SYMD 41BLKADJ01V01070020250200002000000370098239
+SXPO 82symbol to be used for checking and adjusting the brightness and contrast controls
+SCRF 12ABKAJ1BBKAJ2
+SVCT 75SPA;SW1;ST0;PU37,982;PM0;PD2037,982;PD2037,2982;PD37,2982;PD37,982;PM2;FP;
+SVCT 81SPB;SW1;ST0;PU448,1377;PM0;PD1648,1377;PD1648,2577;PD448,2577;PD448,1377;PM2;FP;
+**** 0
+0001 501683
+SYMB 10SY01268NIL
+SYMD 39BOYBAR01V015000150000615004400114501110
+SXPO 25barrel buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 122SPC;PU1500,1500;SW2;CI50;PU1200,1500;PD1200,1345;PD1210,1280;PD1245,1210;PU1290,1165;PD1335,1140;PD1390,1120;PD1435,1110;
+SVCT 121PD1480,1110;PD1530,1120;PD1590,1155;PD1635,1185;PD1660,1215;PD1685,1265;PD1700,1310;PD1705,1345;PD1705,1500;PU1275,1175;
+SVCT 121PD1310,1230;PD1345,1280;PD1365,1335;PD1380,1410;PD1390,1455;PD1390,1500;PU1545,1500;PD1760,1500;PU1245,1210;PD1290,1165;
+SVCT 25PU1445,1500;PD1145,1500;
+**** 0
+0001 501684
+SYMB 10SY01269NIL
+SYMD 39BOYCAN01V007500075000616003940046200415
+SXPO 22can buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 110SPC;PU750,750;SW2;CI59;PU462,750;PD690,750;PU803,750;PD1031,750;SW2;PU509,750;PD603,415;PD1078,415;PD984,750;
+**** 0
+0001 501685
+SYMB 10SY01270NIL
+SYMD 39BOYCAR01V007500075000416006160048400437
+SXPO 33cardinal buoy, north, simplified
+SCRF 12HCHYLWmOUTLW
+SVCT 113SPH;ST0;PU778,790;PM0;PD778,1050,484,1053,778,790;PM2;FP;PU593,718;PM0;PD900,718,900,437,593,718;PM2;FP;SPm;SW1;
+SVCT 83PU593,718;PD900,718;PD900,440;PD593,718;PU778,787;PD778,1053;PD484,1053;PD778,787;
+**** 0
+0001 501686
+SYMB 10SY01271NIL
+SYMD 39BOYCAR02V007650075000365006600058500420
+SXPO 32cardinal buoy, east, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 112SPH;ST0;PU640,695;PM0;PD950,692,947,420,640,695;PM2;FP;PU585,805;PM0;PD890,805,585,1080,585,805;PM2;FP;SPm;SW1;
+SVCT 82PU585,805;PD892,805;PD585,1080;PD585,805;PU640,695;PD950,695;PD950,420;PD640,695;
+**** 0
+0001 501687
+SYMB 10SY01272NIL
+SYMD 39BOYCAR03V007150075000415006100059500445
+SXPO 33cardinal buoy, south, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 113SPH;ST0;PU735,445;PM0;PD1010,445,700,715,700,445;PM2;FP;PU625,780;PM0;PD900,780,595,1052,595,780;PM2;FP;SPm;SW1;
+SVCT 93PU595,780;PD900,780;PD595,1055;PD595,780;PU700,445;PD1010,445;PD700,715;PU700,445;PD700,715;
+**** 0
+0001 501688
+SYMB 10SY01273NIL
+SYMD 39BOYCAR04V007500075000607006100044500445
+SXPO 32cardinal buoy, west, simplified
+SCRF 12mOUTLWHCHYLW
+SVCT 114SPH;ST0;PU750,720;PM0;PD750,445,1050,445,750,720;PM2;FP;PU750,780;PM0;PD750,1055,452,1055,750,780;PM2;FP;SPm;SW1;
+SVCT 84PU750,780;PD750,1055;PD445,1055;PD750,780;PU750,445;PD750,720;PD1052,445;PD750,445;
+**** 0
+0001 501689
+SYMB 10SY01274NIL
+SYMD 39BOYCON01V007500075000575004940046200312
+SXPO 26conical buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI56;PU525,750;PD537,659;PD556,584;PD584,528;PD625,468;PD659,425;PD709,381;PD775,343;PD825,312;
+SVCT 112PD843,343;PD884,415;PD925,509;PD940,575;PU462,750;PD696,750;PU940,575;PD953,659;PD959,750;PU800,750;PD1037,750;
+**** 0
+0001 501690
+SYMB 10SY03356NIL
+SYMD 39BOYDEF03V012360142900721004430103301203
+SXPO 36default symbol for buoy, simplified
+SCRF 18ACHMGDCCHGRDDOUTLW
+SVCT 309SPA;SW1;PU1534,1299;PD1547,1271;PD1560,1246;PD1577,1229;PD1594,1212;PD1620,1203;PD1643,1205;PD1673,1214;PD1701,1220;PD1724,1254;PD1742,1273;PD1754,1295;PD1754,1320;PD1742,1344;PD1729,1365;PD1709,1389;PD1686,1414;PD1665,1440;PD1652,1459;PD1641,1476;PD1639,1498;PD1639,1521;PD1639,1538;PD1641,1560;PD1641,1562;
+SVCT 33SPA;SW2;PU1620,1646;PD1673,1646;
+SVCT 42SPC;SW1;ST0;PU1236,1429;PM0;CI203;PM2;FP;
+SVCT 27SPD;SW1;PU1236,1429;CI203;
+SVCT 41SPD;SW1;ST0;PU1236,1429;PM0;CI15;PM2;FP;
+**** 0
+0001 501691
+SYMB 10SY02048NIL
+SYMD 39BOYGEN03V012360168400765004740097001263
+SXPO 37default symbol for buoy, paper-chart
+SCRF 12ACHMGDCCHBLK
+SVCT 309SPA;SW1;PU1515,1359;PD1528,1331;PD1541,1306;PD1558,1289;PD1575,1272;PD1601,1263;PD1624,1265;PD1654,1274;PD1682,1280;PD1705,1314;PD1723,1333;PD1735,1355;PD1735,1380;PD1723,1404;PD1710,1425;PD1690,1449;PD1667,1474;PD1646,1500;PD1633,1519;PD1622,1536;PD1620,1558;PD1620,1581;PD1620,1598;PD1622,1620;PD1622,1622;
+SVCT 33SPA;SW2;PU1601,1706;PD1654,1706;
+SVCT 27SPC;SW2;PU1231,1453;CI173;
+SVCT 26SPC;SW2;PU1233,1682;CI55;
+SVCT 33SPC;SW2;PU1288,1682;PD1495,1682;
+SVCT 32SPC;SW2;PU970,1682;PD1176,1682;
+**** 0
+0001 501692
+SYMB 10SY01279NIL
+SYMD 39BOYINB01V007500075000857004990032100316
+SXPO 31installation buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 122SPC;PU750,750;SW2;CI65;PU750,387;CI71;PU321,750;PD681,750;PU809,750;PD1178,750;PU368,750;PD465,465;PD1034,465;PD1131,750;
+**** 0
+0001 501693
+SYMB 10SY02049NIL
+SYMD 39BOYISD12V015540062400384005440136600353
+SXPO 33isolated danger buoy, simplified
+SCRF 12AOUTLWCCHRED
+SVCT 41SPC;SW1;ST0;PU1640,463;PM0;CI110;PM2;FP;
+SVCT 41SPC;SW1;ST0;PU1476,787;PM0;CI110;PM2;FP;
+SVCT 26SPA;SW1;PU1640,463;CI110;
+SVCT 26SPA;SW1;PU1476,787;CI110;
+**** 0
+0001 501694
+SYMB 10SY02050NIL
+SYMD 39BOYLAT13V010330096000433004390072400663
+SXPO 40conical lateral buoy, green, simplified
+SCRF 12ACHGRNBOUTLW
+SVCT 70SPA;SW1;ST0;PU1157,1102;PM0;PD1157,663;PD724,1102;PD1157,1102;PM2;FP;
+SVCT 55SPB;SW1;PU1157,1102;PD1157,663;PD724,1102;PD1157,1102;
+SVCT 40SPB;SW1;ST0;PU1033,960;PM0;CI15;PM2;FP;
+**** 0
+0001 501695
+SYMB 10SY02051NIL
+SYMD 39BOYLAT14V010330096000433004390072400663
+SXPO 38conical lateral buoy, red, simplified
+SCRF 12ACHREDbOUTLW
+SVCT 70SPA;SW1;ST0;PU1157,1102;PM0;PD1157,663;PD724,1102;PD1157,1102;PM2;FP;
+SVCT 55SPb;SW1;PU1157,1102;PD1157,663;PD724,1102;PD1157,1102;
+SVCT 40SPb;SW1;ST0;PU1033,960;PM0;CI15;PM2;FP;
+**** 0
+0001 501696
+SYMB 10SY02052NIL
+SYMD 39BOYLAT23V007740069000528003990049900499
+SXPO 42can shape lateral buoy, green, simplified
+SCRF 12ACHGRNBOUTLW
+SVCT 75SPA;SW1;ST0;PU499,898;PM0;PD651,500;PD1027,500;PD901,898;PD499,898;PM2;FP;
+SVCT 60SPB;SW1;PU499,898;PD651,500;PD1027,499;PD901,898;PD499,898;
+SVCT 39SPB;SW1;ST0;PU774,690;PM0;CI15;PM2;FP;
+**** 0
+0001 501697
+SYMB 10SY02053NIL
+SYMD 39BOYLAT24V007740069000528004000049900499
+SXPO 40can shape lateral buoy, red, simplified
+SCRF 12ACHREDbOUTLW
+SVCT 75SPA;SW1;ST0;PU499,899;PM0;PD651,500;PD1027,499;PD901,898;PD499,899;PM2;FP;
+SVCT 60SPb;SW1;PU499,899;PD651,500;PD1027,499;PD901,898;PD499,899;
+SVCT 39SPb;SW1;ST0;PU774,690;PM0;CI15;PM2;FP;
+**** 0
+0001 501698
+SYMB 10SY01290NIL
+SYMD 39BOYMOR01V007500075000610005800040500230
+SXPO 40mooring buoy, barrel shape, paper-chart
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI60;PU705,295;CI65;PU800,750;PD1015,750;PU685,750;PD405,750;SW2;PU960,750;PD960,620;PU450,750;
+SVCT 121PD450,620;PD455,570;PD475,510;PD505,460;PD530,435;PD567,402;PD610,382;PD652,370;PD705,362;PD752,367;PD805,385;PD857,412;
+SVCT 121PD895,447;PD930,497;PD950,547;PD960,595;PD960,620;PU530,435;PD567,490;PU612,580;PD632,662;PD637,712;PD640,750;PU567,490;
+SVCT 11PD612,580;
+**** 0
+0001 501699
+SYMB 10SY01291NIL
+SYMD 39BOYMOR03V007500075000616005560046500259
+SXPO 37mooring buoy, can shape, paper-chart
+SCRF 6CCHBLK
+SVCT 115SPC;PU750,750;SW2;CI65;PU843,334;CI75;PU465,750;PD681,750;PU809,750;PD1034,750;SW2;PU512,750;PD606,418;PD1081,418;
+SVCT 11PD990,750;
+**** 0
+0001 501700
+SYMB 10SY02054NIL
+SYMD 39BOYMOR11V007480057000759003500036800395
+SXPO 47installation buoy and mooring buoy, simplified
+SCRF 6ACHBLK
+SVCT 39SPA;SW2;ST0;PU755,466;PM0;CI71;PM2;FP;
+SVCT 76SPA;SW1;ST0;PU368,745;PM0;PD433,548;PD1060,548;PD1127,745;PD368,745;PM2;FP;
+**** 0
+0001 501701
+SYMB 10SY01292NIL
+SYMD 39BOYPIL01V007500075000597004910044300318
+SXPO 25pillar buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 119SPC;PU750,750;SW2;CI59;PU443,750;PD693,750;PU803,750;PD1040,750;SW2;PU509,750;PD728,515;PD793,318;PD890,318;PD890,556;
+SVCT 11PD984,750;
+**** 0
+0001 501702
+SYMB 10SY01294NIL
+SYMD 39BOYSAW12V007500075000406004060054700547
+SXPO 28safe water buoy, simplified
+SCRF 12CCHREDmOUTLW
+SVCT 60SPC;PU750,750;ST0;PM0;CI200;PM2;FP;SPm;PU750,750;SW1;CI203;
+SVCT 39SPm;SW1;ST0;PU750,750;PM0;CI15;PM2;FP;
+**** 0
+0001 501703
+SYMB 10SY01295NIL
+SYMD 39BOYSPH01V007340075000565004910045600312
+SXPO 28spherical buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 115SPC;PU734,750;SW2;CI53;PU790,750;PD1021,750;PU515,750;PD487,681;PD478,625;PD471,565;PD484,500;PD503,453;PD537,409;
+SVCT 112PD575,371;PD621,340;PD665,325;PD718,312;PD775,312;PD831,325;PD893,353;PD934,384;PD962,425;PD996,478;PD1015,531;
+SVCT 63PD1018,590;PD1012,662;PD990,712;PD971,750;PU456,750;PD681,750;
+**** 0
+0001 501704
+SYMB 10SY01297NIL
+SYMD 39BOYSPP11V007500075000400004000055000550
+SXPO 33special purpose buoy, simplified
+SCRF 12HCHYLWmOUTLW
+SVCT 60SPH;PU750,750;ST0;PM0;CI200;PM2;FP;SPm;PU750,750;SW1;CI200;
+SVCT 39SPm;SW1;ST0;PU750,750;PM0;CI15;PM2;FP;
+**** 0
+0001 501705
+SYMB 10SY03121NIL
+SYMD 39BOYSPP15V010130096200433004390072400663
+SXPO 84special purpose TSS buoy marking the starboard side of the traffic lane, simplified
+SCRF 12ACHYLWBOUTLW
+SVCT 70SPA;SW1;ST0;PU1157,1102;PM0;PD1157,663;PD724,1102;PD1157,1102;PM2;FP;
+SVCT 55SPB;SW1;PU1157,1102;PD1157,663;PD724,1102;PD1157,1102;
+SVCT 40SPB;SW1;ST0;PU1013,960;PM0;CI15;PM2;FP;
+**** 0
+0001 501706
+SYMB 10SY03122NIL
+SYMD 39BOYSPP25V007740069000528004000049900499
+SXPO 79special purpose TSS buoy marking the port side of the traffic lane, simplified
+SCRF 12ACHYLWBOUTLW
+SVCT 75SPA;SW1;ST0;PU499,899;PM0;PD651,500;PD1027,499;PD901,898;PD499,899;PM2;FP;
+SVCT 60SPB;SW1;PU499,899;PD651,500;PD1027,499;PD901,898;PD499,899;
+SVCT 39SPB;SW1;ST0;PU774,690;PM0;CI15;PM2;FP;
+**** 0
+0001 501707
+SYMB 10SY01299NIL
+SYMD 39BOYSPR01V007500075000287004910060300318
+SXPO 23spar buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 120SPC;ST0;PU690,750;PM0;PD793,318,890,318,800,709,781,703,771,696,753,693,731,700,687,750,715,706,706,712,690,750;PM2;FP;
+SVCT 60PU750,750;SW2;CI59;PU603,750;PD690,750;PU803,750;PD890,750;
+**** 0
+0001 501708
+SYMB 10SY01300NIL
+SYMD 39BOYSUP01V007500075000857005400032100275
+SXPO 24super-buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 121SPC;PU750,750;SW2;CI65;PU321,750;PD681,750;PU809,750;PD1178,750;PU368,750;PD465,465;PD1034,465;PD1131,750;SW2;PU750,465;
+SVCT 11PD750,275;
+**** 0
+0001 501709
+SYMB 10SY02055NIL
+SYMD 39BOYSUP02V007490051300767004750036500275
+SXPO 36super-buoy ODAS & LANBY, simplified
+SCRF 6ACHBLK
+SVCT 51SPA;SW2;PU368,750;PD465,465;PD1034,465;PD1131,750;
+SVCT 29SPA;SW2;PU750,465;PD750,275;
+SVCT 76SPA;SW1;ST0;PU365,747;PM0;PD464,462;PD1036,465;PD1132,747;PD365,747;PM2;FP;
+**** 0
+0001 501710
+SYMB 10SY01301NIL
+SYMD 39BOYSUP03V007500075000857006310031800178
+SXPO 31LANBY, super-buoy, paper-chart
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI59;PU750,318;PD750,178;PU653,225;PD840,318;PU653,318;PD840,225;PU318,750;PD690,750;PU803,750;
+SVCT 78PD1175,750;PU365,750;PD462,462;PD1031,462;PD1128,750;SW2;PU750,462;PD750,265;
+**** 0
+0001 501711
+SYMB 10SY03127NIL
+SYMD 39BRIDGE01V005510081600400004000035100617
+SXPO 26symbol for opening bridge
+SCRF 6ACHMGD
+SVCT 25SPA;SW1;PU551,817;CI200;
+SVCT 25SPA;SW1;PU552,813;CI115;
+**** 0
+0001 501712
+SYMB 10SY01358NIL
+SYMD 39BRTHNO01V007500075000700007000040000400
+SXPO 20berth number symbol
+SCRF 6JCHMGD
+SVCT 25SPJ;PU750,750;SW1;CI350;
+**** 0
+0001 501713
+SYMB 10SY02240NIL
+SYMD 39BUAARE02V011420143600518005180088601182
+SXPO 14built-up area
+SCRF 6ALANDF
+SVCT 42SPA;SW1;ST0;PU1145,1441;PM0;CI259;PM2;FP;
+**** 0
+0001 501714
+SYMB 10SY02057NIL
+SYMD 39BUIREL01V007500075000400004000055000550
+SXPO 46non-conspicuous religious building, Christian
+SCRF 6ALANDF
+SVCT 64SPA;SW1;ST0;PU650,550;PM0;PD850,550;PD750,650;PD650,550;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU950,650;PM0;PD950,850;PD850,750;PD950,650;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU650,950;PM0;PD850,950;PD750,850;PD650,950;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU550,650;PM0;PD550,850;PD650,750;PD550,650;PM2;FP;
+SVCT 29SPA;SW1;PU650,750;PD850,750;
+SVCT 29SPA;SW1;PU750,650;PD750,850;
+SVCT 49SPA;SW1;PU650,550;PD850,550;PD750,650;PD650,550;
+SVCT 49SPA;SW1;PU950,650;PD950,850;PD850,750;PD950,650;
+SVCT 49SPA;SW1;PU850,950;PD650,950;PD750,850;PD850,950;
+SVCT 49SPA;SW1;PU550,650;PD550,850;PD650,750;PD550,650;
+**** 0
+0001 501715
+SYMB 10SY02056NIL
+SYMD 39BUIREL04V007500075000572002840046200603
+SXPO 50non-conspicuous religious building, non-Christian
+SCRF 6ALANDF
+SVCT 30SPA;SW1;PU462,603;PD1034,887;
+SVCT 30SPA;SW1;PU462,887;PD1034,603;
+SVCT 59SPA;SW1;PU534,637;PD959,637;PD959,853;PD534,853;PD534,637;
+**** 0
+0001 501716
+SYMB 10SY03118NIL
+SYMD 39BUIREL05V007460088600349004660056100518
+SXPO 18mosque or minaret
+SCRF 6ALANDF
+SVCT 149SPA;SW1;PU561,518;PD588,552;PD618,579;PD652,596;PD686,610;PD723,615;PD752,613;PD783,610;PD818,598;PD844,582;PD867,567;PD887,546;PD901,529;PD910,518;
+SVCT 24SPA;SW1;PU743,885;CI99;
+SVCT 29SPA;SW1;PU743,781;PD743,613;
+SVCT 39SPA;SW1;ST0;PU745,884;PM0;CI20;PM2;FP;
+**** 0
+0001 501717
+SYMB 10SY02057NIL
+SYMD 39BUIREL13V007500075000400004000055000550
+SXPO 42conspicuous religious building, Christian
+SCRF 6ACHBLK
+SVCT 64SPA;SW1;ST0;PU650,550;PM0;PD850,550;PD750,650;PD650,550;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU950,650;PM0;PD950,850;PD850,750;PD950,650;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU650,950;PM0;PD850,950;PD750,850;PD650,950;PM2;FP;
+SVCT 64SPA;SW1;ST0;PU550,650;PM0;PD550,850;PD650,750;PD550,650;PM2;FP;
+SVCT 29SPA;SW1;PU650,750;PD850,750;
+SVCT 29SPA;SW1;PU750,650;PD750,850;
+SVCT 49SPA;SW1;PU650,550;PD850,550;PD750,650;PD650,550;
+SVCT 49SPA;SW1;PU950,650;PD950,850;PD850,750;PD950,650;
+SVCT 49SPA;SW1;PU850,950;PD650,950;PD750,850;PD850,950;
+SVCT 49SPA;SW1;PU550,650;PD550,850;PD650,750;PD550,650;
+**** 0
+0001 501718
+SYMB 10SY02058NIL
+SYMD 39BUIREL14V007500075000572002840046200603
+SXPO 46conspicuous religious building, non-Christian
+SCRF 6ACHBLK
+SVCT 30SPA;SW1;PU462,603;PD1034,887;
+SVCT 30SPA;SW1;PU462,887;PD1034,603;
+SVCT 59SPA;SW1;PU534,637;PD959,637;PD959,853;PD534,853;PD534,637;
+**** 0
+0001 501719
+SYMB 10SY03119NIL
+SYMD 39BUIREL15V007440088300349004660056100518
+SXPO 30conspicuous mosque or minaret
+SCRF 6ACHBLK
+SVCT 149SPA;SW1;PU561,518;PD588,552;PD618,579;PD652,596;PD686,610;PD723,615;PD752,613;PD783,610;PD818,598;PD844,582;PD867,567;PD887,546;PD901,529;PD910,518;
+SVCT 24SPA;SW1;PU743,885;CI99;
+SVCT 29SPA;SW1;PU743,781;PD743,613;
+SVCT 39SPA;SW1;ST0;PU745,884;PM0;CI20;PM2;FP;
+**** 0
+0001 501720
+SYMB 10SY01307NIL
+SYMD 39BUISGL01V007500075000250002500061800618
+SXPO 16single building
+SCRF 12WLANDFKCHBRN
+SVCT 112SPK;ST0;PU618,618;PM0;PD868,618,868,868,618,868,618,618;PM2;FP;SPW;SW2;PU618,618;PD868,618;PD868,868;PD618,868;
+SVCT 11PD618,618;
+**** 0
+0001 501721
+SYMB 10SY01308NIL
+SYMD 39BUISGL11V007500075000250002500061800618
+SXPO 28conspicuous single building
+SCRF 12WLANDFCCHBLK
+SVCT 112SPW;ST0;PU618,618;PM0;PD868,618,868,868,618,868,618,618;PM2;FP;SPC;SW2;PU618,618;PD868,618;PD868,868;PD618,868;
+SVCT 11PD618,618;
+**** 0
+0001 501722
+SYMB 10SY01309NIL
+SYMD 39CAIRNS01V007500075000468004770051000310
+SXPO 6cairn
+SCRF 6WLANDF
+SVCT 121SPW;ST0;PU768,312;PM0;PD809,325,834,337,859,368,868,393,875,412,875,443,862,468,853,487,837,509,828,518,837,493,850,468;
+SVCT 114PD853,450,853,418,843,387,834,368,818,350,793,328,768,312;PM2;FP;PU675,512;PM0;PD700,534,725,553,734,568,743,593;
+SVCT 122PD750,618,750,637,737,668,728,693,712,712,684,734,700,709,712,684,725,634,725,609,712,578,703,559,684,528,675,512;PM2;FP;
+SVCT 121PU878,525;PM0;PD903,528,928,537,953,562,962,578,975,603,978,628,975,653,968,675,959,693,943,709,925,734,943,700,953,668;
+SVCT 119PD959,634,950,593,934,568,912,543,893,534,878,525;PM2;FP;PU750,750;SW2;CI37;PU628,628;CI118;PU756,425;CI115;PU868,634;
+SVCT 47CI109;PU528,750;PD709,750;PU787,750;PD962,750;
+**** 0
+0001 501723
+SYMB 10SY01310NIL
+SYMD 39CAIRNS11V007500075000468004770051000310
+SXPO 18conspicuous cairn
+SCRF 6CCHBLK
+SVCT 121SPC;ST0;PU768,312;PM0;PD809,325,834,337,859,368,868,393,875,412,875,443,862,468,853,487,837,509,828,518,837,493,850,468;
+SVCT 114PD853,450,853,418,843,387,834,368,818,350,793,328,768,312;PM2;FP;PU675,512;PM0;PD700,534,725,553,734,568,743,593;
+SVCT 122PD750,618,750,637,737,668,728,693,712,712,684,734,700,709,712,684,725,634,725,609,712,578,703,559,684,528,675,512;PM2;FP;
+SVCT 121PU878,525;PM0;PD903,528,928,537,953,562,962,578,975,603,978,628,975,653,968,675,959,693,943,709,925,734,943,700,953,668;
+SVCT 119PD959,634,950,593,934,568,912,543,893,534,878,525;PM2;FP;PU750,750;SW2;CI37;PU628,628;CI118;PU756,425;CI115;PU868,634;
+SVCT 47CI109;PU528,750;PD709,750;PU787,750;PD962,750;
+**** 0
+0001 501724
+SYMB 10SY03384NIL
+SYMD 39CBLARE51V031010185500374011120293001289
+SXPO 11cable area
+SCRF 6ACHMGF
+SVCT 57SPA;SW3;PU3246,1289;PD2930,1791;PD3304,1923;PD3005,2401;
+**** 0
+0001 501725
+SYMB 10SY02059NIL
+SYMD 39CGUSTA02V001980074800702004690016900312
+SXPO 19coastguard station
+SCRF 18ALANDFBCHWHTCCHMGF
+SVCT 39SPA;SW1;ST0;PU200,750;PM0;CI31;PM2;FP;
+SVCT 74SPB;SW2;ST0;PU271,312;PM0;PD871,312;PD871,687;PD271,687;PD271,312;PM2;FP;
+SVCT 59SPC;SW2;PU271,312;PD871,312;PD871,687;PD271,687;PD271,312;
+SVCT 49SPC;SW2;PU496,437;PD446,412;PD399,412;PD346,440;
+SVCT 49SPC;SW2;PU346,562;PD396,612;PD446,612;PD496,571;
+SVCT 109SPC;SW2;PU746,437;PD696,412;PD649,412;PD596,440;PD596,562;PD652,612;PD696,612;PD746,587;PD746,515;PD696,515;
+SVCT 29SPC;SW2;PU346,440;PD346,562;
+**** 0
+0001 501726
+SYMB 10SY03357NIL
+SYMD 39CHCRDEL1V007800054400805008050037100143
+SXPO 50this object has been manually deleted or modified
+SCRF 6ACHCOR
+SVCT 30SPA;SW1;PU371,948;PD1176,143;
+**** 0
+0001 501727
+SYMB 10SY03357NIL
+SYMD 39CHCRID01V055190185400098006020547001851
+SXPO 38this object has been manually updated
+SCRF 6ACHCOR
+SVCT 26SPA;SW1;PU5519,2404;CI49;
+SVCT 33SPA;SW1;PU5519,1851;PD5519,2353;
+**** 0
+0001 501728
+SYMB 10SY01313NIL
+SYMD 39CHIMNY01V007430075000478006720056800134
+SXPO 8chimney
+SCRF 6WLANDF
+SVCT 114SPW;PU743,750;SW2;CI56;PU806,750;PD918,750;PU656,750;PD703,290;PD775,290;PD831,750;PU568,750;PD681,750;PU703,290;
+SVCT 113PD687,237;PD690,193;PD715,168;PD753,153;PD812,153;PD840,165;PD871,146;PD925,134;PD975,137;PD1021,140;PD1043,162;
+SVCT 62PD1046,206;PD993,237;PD931,240;PD928,268;PD868,293;PD775,293;
+**** 0
+0001 501729
+SYMB 10SY01314NIL
+SYMD 39CHIMNY11V007430075000478006720056800134
+SXPO 20conspicuous chimney
+SCRF 6CCHBLK
+SVCT 114SPC;PU743,750;SW2;CI56;PU806,750;PD918,750;PU656,750;PD703,290;PD775,290;PD831,750;PU568,750;PD681,750;PU703,290;
+SVCT 113PD687,237;PD690,193;PD715,168;PD753,153;PD812,153;PD840,165;PD871,146;PD925,134;PD975,137;PD1021,140;PD1043,162;
+SVCT 62PD1046,206;PD993,237;PD931,240;PD928,268;PD868,293;PD775,293;
+**** 0
+0001 501730
+SYMB 10SY02076NIL
+SYMD 39CHINFO06V011420143600518005180088601182
+SXPO 16HO caution note
+SCRF 6ACHMGD
+SVCT 27SPA;SW1;PU1145,1441;CI259;
+SVCT 33SPA;SW1;PU1141,1267;PD1141,1492;
+SVCT 33SPA;SW1;PU1109,1585;PD1164,1585;
+**** 0
+0001 501731
+SYMB 10SY02077NIL
+SYMD 39CHINFO07V026350185900495004950240001605
+SXPO 20HO information note
+SCRF 6ACHMGD
+SVCT 69SPA;SW1;PU2400,2100;PD2895,2100;PD2895,1605;PD2400,1605;PD2400,2100;
+SVCT 33SPA;SW1;PU2631,1672;PD2631,1714;
+SVCT 45SPA;SW1;PU2635,2009;PD2635,1775;PD2543,1774;
+SVCT 33SPA;SW1;PU2544,2010;PD2711,2010;
+**** 0
+0001 501732
+SYMB 10SY02063NIL
+SYMD 39CHINFO08V026350185900495004950240001605
+SXPO 27mariner's information note
+SCRF 6ANINFO
+SVCT 69SPA;SW1;PU2400,2100;PD2895,2100;PD2895,1605;PD2400,1605;PD2400,2100;
+SVCT 33SPA;SW1;PU2631,1672;PD2631,1714;
+SVCT 45SPA;SW1;PU2635,2009;PD2635,1775;PD2543,1774;
+SVCT 33SPA;SW1;PU2544,2010;PD2711,2010;
+**** 0
+0001 501733
+SYMB 10SY02064NIL
+SYMD 39CHINFO09V011420143600518005180088601182
+SXPO 22mariners caution note
+SCRF 6ANINFO
+SVCT 27SPA;SW1;PU1145,1441;CI259;
+SVCT 33SPA;SW1;PU1141,1267;PD1141,1492;
+SVCT 33SPA;SW1;PU1109,1585;PD1164,1585;
+**** 0
+0001 501734
+SYMB 10SY02062NIL
+SYMD 39CHINFO10V026350185900495004950240001605
+SXPO 32manufacturer's information note
+SCRF 6AADINF
+SVCT 69SPA;SW1;PU2400,2100;PD2895,2100;PD2895,1605;PD2400,1605;PD2400,2100;
+SVCT 33SPA;SW1;PU2631,1672;PD2631,1714;
+SVCT 45SPA;SW1;PU2635,2009;PD2635,1775;PD2543,1774;
+SVCT 33SPA;SW1;PU2544,2010;PD2711,2010;
+**** 0
+0001 501735
+SYMB 10SY02061NIL
+SYMD 39CHINFO11V011420143600518005180088601182
+SXPO 28manufacturer's caution note
+SCRF 6AADINF
+SVCT 27SPA;SW1;PU1145,1441;CI259;
+SVCT 33SPA;SW1;PU1141,1267;PD1141,1492;
+SVCT 33SPA;SW1;PU1109,1585;PD1164,1585;
+**** 0
+0001 501736
+SYMB 10SY03204NIL
+SYMD 39CHKSYM01V006800068200501005000041900433
+SXPO 65test symbol for checking symbol sizes, should measure 5mm by 5mm
+SCRF 12ACHBLKBOUTLW
+SVCT 74SPA;SW1;ST0;PU419,433;PM0;PD419,933;PD920,933;PD920,433;PD419,433;PM2;FP;
+SVCT 59SPB;SW1;PU419,433;PD419,933;PD920,933;PD920,433;PD419,433;
+**** 0
+0001 501737
+SYMB 10SY01319NIL
+SYMD 39CLRLIN01V014990150000325006070133700893
+SXPO 39arrow head for mariner's clearing line
+SCRF 6fNINFO
+SVCT 63SPf;ST0;PU1337,1500;PM0;PD1500,893,1662,1500,1337,1500;PM2;FP;
+**** 0
+0001 501738
+SYMB 10SY01322NIL
+SYMD 39CRANES01V007500075000600005000050000300
+SXPO 7cranes
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI50;PU550,750;PD700,750;PU800,750;PD950,750;PU700,750;PD700,350;PU800,750;PD800,350;PU500,300;
+SVCT 52PD1100,300;PU500,300;PD500,450;PD600,450;PD600,350;
+**** 0
+0001 501739
+SYMB 10SY03385NIL
+SYMD 39CTNARE51V020610124600994009940027601846
+SXPO 46caution area, a specific caution note applies
+SCRF 6ATRFCF
+SVCT 31SPA;SW3;PU775,2471;PD775,2006;
+SVCT 31SPA;SW2;PU708,2651;PD851,2651;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+**** 0
+0001 501740
+SYMB 10SY03362NIL
+SYMD 39CTYARE51V020610124600994009940027601846
+SXPO 56cautionary area (e.g. ferry area) navigate with caution
+SCRF 6ATRFCF
+SVCT 31SPA;SW3;PU775,2471;PD775,2006;
+SVCT 31SPA;SW2;PU708,2651;PD851,2651;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+**** 0
+0001 501741
+SYMB 10SY03387NIL
+SYMD 39CTYARE71V020610124601235009940003501846
+SXPO 41cautionary area with further information
+SCRF 12ATRFCFDCHMGD
+SVCT 31SPA;SW3;PU775,2471;PD775,2006;
+SVCT 31SPA;SW2;PU708,2651;PD851,2651;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+SVCT 41SPD;SW1;PU127,2827;PD127,2593;PD35,2592;
+SVCT 30SPD;SW1;PU36,2828;PD223,2828;
+SVCT 29SPD;SW1;PU81,2474;PD84,2514;
+**** 0
+0001 501742
+SYMB 10SY03431NIL
+SYMD 39CURDEF01V007850081001009009080029700362
+SXPO 53current or tidal stream whose direction is not known
+SCRF 6ACHGRD
+SVCT 42SPA;SW1;PU685,1257;PD785,1058;PD884,1257;
+SVCT 41SPA;SW1;PU685,1073;PD785,874;PD884,1073;
+SVCT 30SPA;SW1;PU785,362;PD785,1270;
+SVCT 39SPA;SW1;PU684,611;PD786,364;PD886,611;
+SVCT 259SPA;SW1;PU297,710;PD310,682;PD323,657;PD340,640;PD357,623;PD383,614;PD406,616;PD436,625;PD464,631;PD487,665;PD505,684;PD517,706;PD517,731;PD505,755;PD492,776;PD472,800;PD449,825;PD428,851;PD415,870;PD404,887;PD402,909;PD402,932;PD402,949;PD404,971;PD404,973;
+SVCT 31SPA;SW2;PU383,1057;PD436,1057;
+SVCT 284SPA;SW1;PU1086,704;PD1099,676;PD1112,651;PD1129,634;PD1146,617;PD1172,608;PD1195,610;PD1225,619;PD1253,625;PD1276,659;PD1294,678;PD1306,700;PD1306,725;PD1294,749;PD1281,770;PD1261,794;PD1238,819;PD1217,845;PD1204,864;PD1193,881;PD1191,903;PD1191,926;PD1191,943;PD1193,965;PD1193,967;
+SVCT 33SPA;SW2;PU1172,1051;PD1225,1051;
+**** 0
+0001 501743
+SYMB 10SY03128NIL
+SYMD 39CURENT01V007850081000202009080068400362
+SXPO 18non-tidal current
+SCRF 6ACHGRD
+SVCT 42SPA;SW1;PU685,1257;PD785,1058;PD884,1257;
+SVCT 41SPA;SW1;PU685,1073;PD785,874;PD884,1073;
+SVCT 30SPA;SW1;PU785,362;PD785,1270;
+SVCT 39SPA;SW1;PU684,611;PD786,364;PD886,611;
+**** 0
+0001 501744
+SYMB 10SY01328NIL
+SYMD 39CURSRA01V023840224701000010000187501755
+SXPO 16ordinary cursor
+SCRF 6BCURSR
+SVCT 57SPB;SW3;PU2379,1755;PD2379,2755;PU1875,2250;PD2875,2250;
+**** 0
+0001 501745
+SYMB 10SY03365NIL
+SYMD 39CURSRB01V021720225401001010010167301752
+SXPO 24cursor with open centre
+SCRF 6ACURSR
+SVCT 33SPA;SW3;PU1673,2252;PD2073,2252;
+SVCT 33SPA;SW3;PU2274,2252;PD2674,2252;
+SVCT 33SPA;SW3;PU2170,1752;PD2170,2152;
+SVCT 33SPA;SW3;PU2171,2353;PD2171,2753;
+**** 0
+0001 501746
+SYMB 10SY01329NIL
+SYMD 39DANGER01V006200081400800006320022500496
+SXPO 39underwater hazard with a defined depth
+SCRF 12ADEPVSBCHBLK
+SVCT 242SPA;SW1;ST0;PU234,731;PM0;PD300,637;PD387,556;PD459,525;PD553,496;PD706,496;PD806,525;PD909,584;PD975,662;PD1025,762;PD1025,881;PD959,975;PD881,1050;PD784,1100;PD681,1128;PD540,1125;PD440,1087;PD350,1028;PD275,950;PD225,850;PD234,731;PM2;FP;
+SVCT 22SPB;SW1;PU387,556;PD;
+SVCT 22SPB;SW1;PU300,637;PD;
+SVCT 22SPB;SW1;PU234,731;PD;
+SVCT 22SPB;SW1;PU225,850;PD;
+SVCT 22SPB;SW1;PU275,950;PD;
+SVCT 23SPB;SW1;PU350,1028;PD;
+SVCT 23SPB;SW1;PU440,1087;PD;
+SVCT 23SPB;SW1;PU540,1125;PD;
+SVCT 23SPB;SW1;PU681,1128;PD;
+SVCT 23SPB;SW1;PU784,1100;PD;
+SVCT 23SPB;SW1;PU881,1050;PD;
+SVCT 22SPB;SW1;PU959,975;PD;
+SVCT 23SPB;SW1;PU1025,881;PD;
+SVCT 23SPB;SW1;PU1025,762;PD;
+SVCT 22SPB;SW1;PU975,662;PD;
+SVCT 22SPB;SW1;PU906,584;PD;
+SVCT 22SPB;SW1;PU809,528;PD;
+SVCT 22SPB;SW1;PU706,500;PD;
+SVCT 22SPB;SW1;PU553,500;PD;
+SVCT 22SPB;SW1;PU459,525;PD;
+**** 0
+0001 501747
+SYMB 10SY03183NIL
+SYMD 39DANGER02V006300082800800006280022500500
+SXPO 52underwater hazard with depth greater than 20 metres
+SCRF 6ACHBLK
+SVCT 22SPA;SW1;PU387,556;PD;
+SVCT 22SPA;SW1;PU300,637;PD;
+SVCT 22SPA;SW1;PU234,731;PD;
+SVCT 22SPA;SW1;PU225,850;PD;
+SVCT 22SPA;SW1;PU275,950;PD;
+SVCT 23SPA;SW1;PU350,1028;PD;
+SVCT 23SPA;SW1;PU440,1087;PD;
+SVCT 23SPA;SW1;PU540,1125;PD;
+SVCT 23SPA;SW1;PU681,1128;PD;
+SVCT 23SPA;SW1;PU784,1100;PD;
+SVCT 23SPA;SW1;PU881,1050;PD;
+SVCT 22SPA;SW1;PU959,975;PD;
+SVCT 23SPA;SW1;PU1025,881;PD;
+SVCT 23SPA;SW1;PU1025,762;PD;
+SVCT 22SPA;SW1;PU975,662;PD;
+SVCT 22SPA;SW1;PU906,584;PD;
+SVCT 22SPA;SW1;PU809,528;PD;
+SVCT 22SPA;SW1;PU706,500;PD;
+SVCT 22SPA;SW1;PU553,500;PD;
+SVCT 22SPA;SW1;PU459,525;PD;
+**** 0
+0001 501748
+SYMB 10SY03610NIL
+SYMD 39DANGER03V006200081400800006320022500496
+SXPO 44underwater hazard which covers and uncovers
+SCRF 12ADEPITBCHBLK
+SVCT 242SPA;SW1;ST0;PU234,731;PM0;PD300,637;PD387,556;PD459,525;PD553,496;PD706,496;PD806,525;PD909,584;PD975,662;PD1025,762;PD1025,881;PD959,975;PD881,1050;PD784,1100;PD681,1128;PD540,1125;PD440,1087;PD350,1028;PD275,950;PD225,850;PD234,731;PM2;FP;
+SVCT 22SPB;SW1;PU387,556;PD;
+SVCT 22SPB;SW1;PU300,637;PD;
+SVCT 22SPB;SW1;PU234,731;PD;
+SVCT 22SPB;SW1;PU225,850;PD;
+SVCT 22SPB;SW1;PU275,950;PD;
+SVCT 23SPB;SW1;PU350,1028;PD;
+SVCT 23SPB;SW1;PU440,1087;PD;
+SVCT 23SPB;SW1;PU540,1125;PD;
+SVCT 23SPB;SW1;PU681,1128;PD;
+SVCT 23SPB;SW1;PU784,1100;PD;
+SVCT 23SPB;SW1;PU881,1050;PD;
+SVCT 22SPB;SW1;PU959,975;PD;
+SVCT 23SPB;SW1;PU1025,881;PD;
+SVCT 23SPB;SW1;PU1025,762;PD;
+SVCT 22SPB;SW1;PU975,662;PD;
+SVCT 22SPB;SW1;PU906,584;PD;
+SVCT 22SPB;SW1;PU809,528;PD;
+SVCT 22SPB;SW1;PU706,500;PD;
+SVCT 22SPB;SW1;PU553,500;PD;
+SVCT 22SPB;SW1;PU459,525;PD;
+**** 0
+0001 501749
+SYMB 10SY03224NIL
+SYMD 39DAYSQR01V007530060300401005830054900204
+SXPO 42square or rectangular daymark, simplified
+SCRF 6ACHMGD
+SVCT 59SPA;SW1;PU549,204;PD549,605;PD950,605;PD950,204;PD549,204;
+SVCT 29SPA;SW1;PU751,634;PD751,787;
+SVCT 39SPA;SW1;ST0;PU751,602;PM0;CI50;PM2;FP;
+SVCT 24SPA;SW1;PU751,602;CI50;
+**** 0
+0001 501750
+SYMB 10SY03225NIL
+SYMD 39DAYSQR21V007470082400401006830054900204
+SXPO 43square or rectangular daymark, paper chart
+SCRF 6ACHMGD
+SVCT 59SPA;SW1;PU549,204;PD549,605;PD950,605;PD950,204;PD549,204;
+SVCT 29SPA;SW1;PU750,605;PD750,758;
+SVCT 24SPA;SW1;PU751,822;CI65;
+SVCT 29SPA;SW1;PU603,822;PD687,822;
+SVCT 29SPA;SW1;PU816,822;PD901,822;
+**** 0
+0001 501751
+SYMB 10SY03226NIL
+SYMD 39DAYTRI01V007660050400500006010051700103
+SXPO 41triangular daymark, point up, simplified
+SCRF 6ACHMGD
+SVCT 50SPA;SW1;PU517,505;PD1017,505;PD768,103;PD517,505;
+SVCT 29SPA;SW1;PU766,506;PD766,704;
+SVCT 39SPA;SW1;ST0;PU766,505;PM0;CI50;PM2;FP;
+SVCT 24SPA;SW1;PU766,505;CI50;
+**** 0
+0001 501752
+SYMB 10SY03227NIL
+SYMD 39DAYTRI05V007500061900503006070050000224
+SXPO 43triangular daymark, point down, simplified
+SCRF 6ACHMGD
+SVCT 50SPA;SW1;PU500,225;PD1003,224;PD751,626;PD500,228;
+SVCT 39SPA;SW1;ST0;PU750,617;PM0;CI50;PM2;FP;
+SVCT 24SPA;SW1;PU750,617;CI50;
+SVCT 29SPA;SW1;PU751,642;PD751,831;
+**** 0
+0001 501753
+SYMB 10SY03228NIL
+SYMD 39DAYTRI21V007460075100500007270049800088
+SXPO 42triangular daymark, point up, paper chart
+SCRF 6ACHMGD
+SVCT 48SPA;SW1;PU498,490;PD998,490;PD749,88;PD498,490;
+SVCT 29SPA;SW1;PU747,491;PD747,689;
+SVCT 24SPA;SW1;PU747,750;CI65;
+SVCT 29SPA;SW1;PU599,748;PD683,748;
+SVCT 29SPA;SW1;PU812,748;PD897,748;
+**** 0
+0001 501754
+SYMB 10SY03229NIL
+SYMD 39DAYTRI25V007510081000503006490050000224
+SXPO 44triangular daymark, point down, paper chart
+SCRF 6ACHMGD
+SVCT 50SPA;SW1;PU500,225;PD1003,224;PD751,626;PD500,228;
+SVCT 29SPA;SW1;PU751,625;PD751,747;
+SVCT 24SPA;SW1;PU750,808;CI65;
+SVCT 29SPA;SW1;PU602,808;PD686,808;
+SVCT 29SPA;SW1;PU815,808;PD900,808;
+**** 0
+0001 501755
+SYMB 10SY03500NIL
+SYMD 39DIRBOY01V-23240077801312008270012800355
+SXPO 21direction of buoyage
+SCRF 6ACHMGD
+SVCT 94SPA;SW1;PU478,983;PD179,983;PD783,381;PD1381,983;PD1079,983;PD1079,1182;PD478,1182;PD478,983;
+SVCT 25SPA;SW2;PU280,507;CI152;
+SVCT 26SPA;SW2;PU1291,507;CI149;
+**** 0
+0001 501756
+SYMB 10SY03133NIL
+SYMD 39DIRBOYA1V-23240077801312008270012800355
+SXPO 86direction and color of buoyage for approaching harbour in IALA region A (red to port)
+SCRF 18ACHMGDBCHREDCCHGRN
+SVCT 94SPA;SW1;PU478,983;PD179,983;PD783,381;PD1381,983;PD1079,983;PD1079,1182;PD478,1182;PD478,983;
+SVCT 25SPB;SW2;PU280,507;CI152;
+SVCT 26SPC;SW2;PU1291,507;CI149;
+**** 0
+0001 501757
+SYMB 10SY03132NIL
+SYMD 39DIRBOYB1V-23240077801312008270012800355
+SXPO 88direction and color of buoyage for approaching harbour in IALA region B (green to port)
+SCRF 18ACHMGDBCHGRNCCHRED
+SVCT 94SPA;SW1;PU478,983;PD179,983;PD783,381;PD1381,983;PD1079,983;PD1079,1182;PD478,1182;PD478,983;
+SVCT 25SPB;SW2;PU280,507;CI152;
+SVCT 26SPC;SW2;PU1291,507;CI149;
+**** 0
+0001 501758
+SYMB 10SY02242NIL
+SYMD 39DISMAR03V008250075600865004000033500494
+SXPO 14distance mark
+SCRF 6ACHMGD
+SVCT 29SPA;SW1;PU650,494;PD650,894;
+SVCT 29SPA;SW1;PU785,644;PD650,794;
+SVCT 29SPA;SW1;PU695,744;PD800,894;
+SVCT 29SPA;SW1;PU900,644;PD900,894;
+SVCT 82SPA;SW1;PU900,684;PD935,649;PD965,639;PD985,639;PD1027,659;PD1050,689;PD1050,894;
+SVCT 86SPA;SW1;PU1050,694;PD1070,654;PD1110,636;PD1135,636;PD1177,654;PD1200,694;PD1200,894;
+SVCT 24SPA;SW1;PU419,765;CI84;
+**** 0
+0001 501759
+SYMB 10SY03386NIL
+SYMD 39DISMAR04V008250075600550004000065000494
+SXPO 28distance point with no mark
+SCRF 6ACHMGD
+SVCT 29SPA;SW1;PU650,494;PD650,894;
+SVCT 29SPA;SW1;PU785,644;PD650,794;
+SVCT 29SPA;SW1;PU695,744;PD800,894;
+SVCT 29SPA;SW1;PU900,644;PD900,894;
+SVCT 82SPA;SW1;PU900,684;PD935,649;PD965,639;PD985,639;PD1027,659;PD1050,689;PD1050,894;
+SVCT 86SPA;SW1;PU1050,694;PD1070,654;PD1110,636;PD1135,636;PD1177,654;PD1200,694;PD1200,894;
+**** 0
+0001 501760
+SYMB 10SY01331NIL
+SYMD 39DNGHILITV015000150000587005870120601206
+SXPO 47transparent danger highlight for mariner's use
+SCRF 6SDNGHL
+SVCT 114SPS;ST3;PU1206,1206;PM0;PD1793,1206,1793,1793,1206,1793,1206,1206;PM2;FP;SW3;PU1206,1793;PD1793,1793;PD1793,1206;
+SVCT 25PD1206,1206;PD1206,1793;
+**** 0
+0001 501761
+SYMB 10SY03114NIL
+SYMD 39DOMES001V007470053000503004210049800150
+SXPO 5dome
+SCRF 6ALANDF
+SVCT 24SPA;SW1;PU745,528;CI43;
+SVCT 29SPA;SW1;PU703,524;PD539,524;
+SVCT 270SPA;SW1;PU538,525;PD528,509;PD514,475;PD502,440;PD498,410;PD498,370;PD508,328;PD526,280;PD542,250;PD570,220;PD600,194;PD628,180;PD676,162;PD716,154;PD760,150;PD809,158;PD855,172;PD901,202;PD943,242;PD965,274;PD987,316;PD999,368;PD1001,430;PD991,471;PD977,505;PD963,521;
+SVCT 39SPA;SW1;PU787,524;PD961,524;PD964,516;
+**** 0
+0001 501762
+SYMB 10SY03115NIL
+SYMD 39DOMES011V007460052100503004210049800150
+SXPO 17conspicuous dome
+SCRF 6ACHBLK
+SVCT 24SPA;SW1;PU745,528;CI43;
+SVCT 29SPA;SW1;PU703,524;PD539,524;
+SVCT 270SPA;SW1;PU538,525;PD528,509;PD514,475;PD502,440;PD498,410;PD498,370;PD508,328;PD526,280;PD542,250;PD570,220;PD600,194;PD628,180;PD676,162;PD716,154;PD760,150;PD809,158;PD855,172;PD901,202;PD943,242;PD965,274;PD987,316;PD999,368;PD1001,430;PD991,471;PD977,505;PD963,521;
+SVCT 39SPA;SW1;PU787,524;PD961,524;PD964,516;
+**** 0
+0001 501763
+SYMB 10SY01332NIL
+SYMD 39DSHAER01V007500075000350005310058400259
+SXPO 12dish aerial
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI40;PU584,750;PD700,750;PU790,750;PD900,750;PU659,265;PD934,434;PU800,350;PD825,309;PU725,490;
+SVCT 121PD665,750;PU781,506;PD825,750;PU659,259;PD640,300;PD634,365;PD646,418;PD684,468;PD725,490;PD781,506;PD818,506;PD865,500;
+SVCT 21PD909,475;PD934,434;
+**** 0
+0001 501764
+SYMB 10SY01333NIL
+SYMD 39DSHAER11V007500075000350005310058400259
+SXPO 24conspicuous dish aerial
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI40;PU584,750;PD700,750;PU790,750;PD900,750;PU659,265;PD934,434;PU800,350;PD825,309;PU725,490;
+SVCT 121PD665,750;PU781,506;PD825,750;PU659,259;PD640,300;PD634,365;PD646,418;PD684,468;PD725,490;PD781,506;PD818,506;PD865,500;
+SVCT 21PD909,475;PD934,434;
+**** 0
+0001 501765
+SYMB 10SY03392NIL
+SYMD 39DWRTPT51V023130261501570009340158700881
+SXPO 25part of deep water route
+SCRF 6ATRFCF
+SVCT 113SPA;SW2;PU1587,901;PD1587,1802;PD1880,1804;PD1987,1751;PD2089,1603;PD2089,1105;PD1987,952;PD1883,901;PD1587,901;
+SVCT 66SPA;SW2;PU2353,899;PD2551,1806;PD2755,904;PD2954,1815;PD3157,881;
+**** 0
+0001 501766
+SYMB 10SY03501NIL
+SYMD 39DWRUTE51V022500225000619014990194401500
+SXPO 70reciprocal traffic directions in a two-way part of a deep-water route
+SCRF 6ATRFCD
+SVCT 152SPA;ST3;PU2096,1950;PM0;PD1944,1950;PD2245,1500;PD2553,1950;PD2401,1950;PD2401,2546;PD2563,2546;PD2252,2999;PD1947,2546;PD2096,2546;PD2096,1950;PM2;FP;
+SVCT 141SPA;SW1;PU2096,1950;PD1944,1950;PD2245,1500;PD2553,1950;PD2401,1950;PD2401,2546;PD2563,2546;PD2252,2999;PD1947,2546;PD2096,2546;PD2096,1950;
+**** 0
+0001 501767
+SYMB 10SY03361NIL
+SYMD 39EBBSTR01V007850088300202008840068400364
+SXPO 33ebb stream, rate at spring tides
+SCRF 6ACHGRD
+SVCT 39SPA;SW1;PU684,611;PD786,364;PD886,611;
+SVCT 30SPA;SW1;PU785,366;PD785,1248;
+**** 0
+0001 501768
+SYMB 10SY03391NIL
+SYMD 39EBLVRM11V007500075000200002000065000650
+SXPO 41point of origin for an offset EBL or VRM
+SCRF 6CNINFO
+SVCT 36SPC;PU750,750;ST0;PM0;CI100;PM2;FP;
+**** 0
+0001 501769
+SYMB 10SY03405NIL
+SYMD 39ENTRES51V022650272100994009940027601846
+SXPO 64area where entry is prohibited or restricted or "to be avoided"
+SCRF 6ATRFCF
+SVCT 32SPA;SW3;PU1020,2344;PD558,2344;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+**** 0
+0001 501770
+SYMB 10SY03406NIL
+SYMD 39ENTRES61V022650272101171010190027601846
+SXPO 85area where entry is prohibited or restricted or "to be avoided", with other cautions
+SCRF 12ATRFCFCCHMGD
+SVCT 32SPA;SW3;PU1020,2344;PD558,2344;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+SVCT 33SPC;SW1;PU1392,2865;PD1447,2865;
+SVCT 33SPC;SW1;PU1405,2479;PD1405,2814;
+**** 0
+0001 501771
+SYMB 10SY03407NIL
+SYMD 39ENTRES71V022650272101235009940003501846
+SXPO 88area where entry is prohibited or restricted or "to be avoided", with other information
+SCRF 12ATRFCFCCHMGD
+SVCT 32SPA;SW3;PU1020,2344;PD558,2344;
+SVCT 26SPA;SW2;PU773,2343;CI497;
+SVCT 41SPC;SW1;PU127,2827;PD127,2593;PD35,2592;
+SVCT 30SPC;SW1;PU36,2828;PD223,2828;
+SVCT 29SPC;SW1;PU81,2474;PD84,2514;
+**** 0
+0001 501772
+SYMB 10SY03393NIL
+SYMD 39ERBLTIK1V026740132001226001270207201317
+SXPO 23range mark for an ERBL
+SCRF 6ANINFO
+SVCT 33SPA;SW2;PU2601,1317;PD2750,1317;
+SVCT 33SPA;SW2;PU2322,1353;PD2468,1324;
+SVCT 33SPA;SW2;PU2893,1327;PD3039,1355;
+SVCT 33SPA;SW2;PU2072,1436;PD2211,1379;
+SVCT 33SPA;SW2;PU3157,1396;PD3298,1444;
+**** 0
+0001 501773
+SYMB 10SY01334NIL
+SYMD 39EVENTS02V007500075000400003000055000600
+SXPO 21mariner's event mark
+SCRF 6fNINFO
+SVCT 79SPf;SW2;PU550,600;PD950,600;PD950,900;PD550,900;PD550,600;PU550,900;PD950,600;
+**** 0
+0001 501774
+SYMB 10SY03184NIL
+SYMD 39FAIRWY51V022500225000600013500195001500
+SXPO 52fairway with one-way traffic in direction indicated
+SCRF 6ACHGRD
+SVCT 105SPA;SW1;PU2100,2850;PD2100,1950;PD1950,1950;PD2250,1500;PD2550,1950;PD2400,1950;PD2400,2850;PD2100,2850;
+**** 0
+0001 501775
+SYMB 10SY03185NIL
+SYMD 39FAIRWY52V022500225000601013510194801499
+SXPO 29fairway with two-way traffic
+SCRF 6ACHGRD
+SVCT 69SPA;SW1;PU2403,2397;PD2549,2397;PD2251,2850;PD1953,2397;PD2102,2397;
+SVCT 93SPA;SW1;PU2097,2396;PD2097,1949;PD1948,1949;PD2250,1499;PD2544,1949;PD2399,1949;PD2399,2396;
+**** 0
+0001 501776
+SYMB 10SY01335NIL
+SYMD 39FLASTK01V015000150000300006070135000943
+SXPO 12flare stack
+SCRF 6WLANDF
+SVCT 120SPW;ST0;PU1450,1500;PM0;PD1450,1175,1550,1175,1550,1500,1537,1462,1500,1450,1468,1462,1450,1500;PM2;FP;PU1500,1500;SW2;
+SVCT 123CI50;PU1550,1500;PD1650,1500;PU1450,1500;PD1350,1500;PU1556,943;PD1525,962;PD1493,981;PD1468,1012;PD1450,1050;PD1450,1087;
+SVCT 119PD1456,1106;PD1481,1118;PD1512,1118;PD1531,1106;PD1543,1081;PD1537,1050;PD1525,1037;PD1525,1012;PD1525,987;PD1543,968;
+SVCT 12PD1556,943;
+**** 0
+0001 501777
+SYMB 10SY01336NIL
+SYMD 39FLASTK11V015000150000300006070135000943
+SXPO 24conspicuous flare stack
+SCRF 6CCHBLK
+SVCT 120SPC;ST0;PU1450,1500;PM0;PD1450,1175,1550,1175,1550,1500,1537,1462,1500,1450,1468,1462,1450,1500;PM2;FP;PU1500,1500;SW2;
+SVCT 123CI50;PU1550,1500;PD1650,1500;PU1450,1500;PD1350,1500;PU1556,943;PD1525,962;PD1493,981;PD1468,1012;PD1450,1050;PD1450,1087;
+SVCT 119PD1456,1106;PD1481,1118;PD1512,1118;PD1531,1106;PD1543,1081;PD1537,1050;PD1525,1037;PD1525,1012;PD1525,987;PD1543,968;
+SVCT 12PD1556,943;
+**** 0
+0001 501778
+SYMB 10SY03360NIL
+SYMD 39FLDSTR01V007850081000202009150068400362
+SXPO 35flood stream, rate at spring tides
+SCRF 6ACHGRD
+SVCT 30SPA;SW1;PU785,362;PD785,1277;
+SVCT 39SPA;SW1;PU684,611;PD786,364;PD886,611;
+SVCT 30SPA;SW1;PU787,894;PD886,1099;
+SVCT 31SPA;SW1;PU787,1079;PD886,1277;
+SVCT 31SPA;SW1;PU785,1103;PD785,1161;
+**** 0
+0001 501779
+SYMB 10SY01337NIL
+SYMD 39FLGSTF01V007500075000300005000060000300
+SXPO 20flagstaff, flagpole
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI50;PU750,700;PD750,300;PD900,300;PD900,475;PD750,475;PU600,750;PD700,750;PU800,750;PD900,750;
+**** 0
+0001 501780
+SYMB 10SY01338NIL
+SYMD 39FOGSIG01V007500075000363004000026500771
+SXPO 11fog signal
+SCRF 6JCHMGF
+SVCT 113SPJ;SW2;PU265,787;PD284,890;PD328,990;PD378,1062;PD446,1125;PD512,1171;PU387,781;PD406,859;PD446,934;PD487,1000;
+SVCT 73PD537,1043;PD571,1059;PU509,771;PD525,850;PD568,912;PD609,946;PD628,962;
+**** 0
+0001 501781
+SYMB 10SY01339NIL
+SYMD 39FORSTC01V007500075000400004000055000550
+SXPO 20fortified structure
+SCRF 6WLANDF
+SVCT 59SPW;SW2;PU550,550;PD950,550;PD950,950;PD550,950;PD550,550;
+**** 0
+0001 501782
+SYMB 10SY01340NIL
+SYMD 39FORSTC11V007500075000400004000055000550
+SXPO 31conspicuous fortified structure
+SCRF 6CCHBLK
+SVCT 59SPC;SW2;PU550,550;PD950,550;PD950,950;PD550,950;PD550,550;
+**** 0
+0001 501783
+SYMB 10SY03129NIL
+SYMD 39FOULGND1V006660076700390003000046500613
+SXPO 62foul area of seabed safe for navigation but not for anchoring
+SCRF 6ACHGRD
+SVCT 29SPA;SW1;PU641,613;PD539,913;
+SVCT 29SPA;SW1;PU793,613;PD688,912;
+SVCT 29SPA;SW1;PU507,713;PD855,713;
+SVCT 29SPA;SW1;PU465,814;PD821,814;
+**** 0
+0001 501784
+SYMB 10SY03390NIL
+SYMD 39FRYARE51V016310086302560002980051300728
+SXPO 11ferry area
+SCRF 6ACHMGF
+SVCT 29SPA;SW1;PU823,863;PD513,863;
+SVCT 31SPA;SW1;PU2279,863;PD2571,863;
+SVCT 88SPA;SW1;PU1883,728;PD1086,728;PD1086,1026;PD1882,1022;PD2083,923;PD2084,823;PD1883,728;
+SVCT 31SPA;SW1;PU2778,868;PD3073,868;
+**** 0
+0001 501785
+SYMB 10SY03390NIL
+SYMD 39FRYARE52V016310086302560002980051300728
+SXPO 17cable ferry area
+SCRF 6ACHBLK
+SVCT 29SPA;SW1;PU823,863;PD513,863;
+SVCT 31SPA;SW1;PU2279,863;PD2571,863;
+SVCT 88SPA;SW1;PU1883,728;PD1086,728;PD1086,1026;PD1882,1022;PD2083,923;PD2084,823;PD1883,728;
+SVCT 31SPA;SW1;PU2778,868;PD3073,868;
+**** 0
+0001 501786
+SYMB 10SY01342NIL
+SYMD 39FSHFAC02V007720063100511004380049200416
+SXPO 32fish trap, fish weir, tunny net
+SCRF 6ACHGRD
+SVCT 61SPA;SW1;PU492,854;PD1003,854;PD1003,632;PD494,632;PD494,853;
+SVCT 29SPA;SW1;PU558,416;PD776,634;
+**** 0
+0001 501787
+SYMB 10SY02067NIL
+SYMD 39FSHFAC03V034370225400604001510313502173
+SXPO 12fish stakes
+SCRF 6ACHGRD
+SVCT 57SPA;SW1;PU3135,2173;PD3135,2323;PD3739,2323;PD3739,2180;
+SVCT 33SPA;SW1;PU3290,2176;PD3290,2324;
+SVCT 33SPA;SW1;PU3438,2179;PD3438,2321;
+SVCT 33SPA;SW1;PU3590,2179;PD3590,2321;
+**** 0
+0001 501788
+SYMB 10SY03193NIL
+SYMD 39FSHGRD01V012020154701104004490052701303
+SXPO 15fishing ground
+SCRF 6ACHGRD
+SVCT 31SPA;SW2;PU699,1532;PD546,1344;
+SVCT 31SPA;SW2;PU701,1535;PD527,1708;
+SVCT 126SPA;SW2;PU703,1532;PD780,1449;PD877,1379;PD1002,1323;PD1141,1303;PD1267,1309;PD1406,1337;PD1525,1393;PD1608,1455;PD1629,1498;
+SVCT 114SPA;SW2;PU697,1530;PD816,1628;PD962,1711;PD1115,1745;PD1226,1752;PD1345,1732;PD1456,1691;PD1546,1607;PD1616,1509;
+SVCT 57SPA;SW2;PU1333,1322;PD1287,1442;PD1287,1609;PD1370,1729;
+SVCT 33SPA;SW2;PU1631,1497;PD1614,1511;
+**** 0
+0001 501789
+SYMB 10SY01343NIL
+SYMD 39FSHHAV01V008750075000984006160025000440
+SXPO 11fish haven
+SCRF 6DCHGRD
+SVCT 122SPD;SW2;PU384,868;PD525,750;PD584,684;PD653,640;PD725,612;PD793,593;PD868,593;PD931,600;PD1006,625;PD1075,656;PD1137,703;
+SVCT 115PD1175,750;PD1128,793;PD1084,831;PD1028,859;PD956,887;PD884,900;PD803,900;PD725,887;PD650,859;PD584,815;PD540,778;
+SVCT 114PU500,731;PD400,603;PU1018,628;PD1000,662;PD987,709;PD984,740;PD984,765;PD993,809;PD1012,865;PU540,778;PD500,731;
+SVCT 123PU750,440;PD;PU750,1056;PD;PU1234,750;PD;PU250,750;PD;PU465,500;PD;PU1015,500;PD;PU1025,1000;PD;PU309,900;PD;PU309,590;PD;
+SVCT 121PU1175,590;PD;PU1175,900;PD;PU390,534;PD;PU265,650;PD;PU275,850;PD;PU1215,850;PD;PU1209,650;PD;PU1106,550;PD;PU1115,950;
+SVCT 122PD;PU365,950;PD;PU565,465;PD;PU665,450;PD;PU815,450;PD;PU915,459;PD;PU915,1031;PD;PU815,1050;PD;PU665,1050;PD;PU565,1031;
+SVCT 18PD;PU465,1000;PD;
+**** 0
+0001 501790
+SYMB 10SY03400NIL
+SYMD 39FSHRES51V008210142601021006020186900411
+SXPO 59area where fishing or trawling is prohibited or restricted
+SCRF 6ACHMGF
+SVCT 251SPA;SW2;PU1869,874;PD2051,722;PD2127,637;PD2216,580;PD2309,544;PD2397,519;PD2494,519;PD2575,528;PD2672,561;PD2761,601;PD2841,661;PD2890,722;PD2830,777;PD2773,827;PD2701,863;PD2608,899;PD2515,916;PD2410,916;PD2309,899;PD2212,863;PD2127,806;PD2070,758;
+SVCT 31SPA;SW2;PU2037,717;PD1908,551;
+SVCT 31SPA;SW3;PU2075,759;PD2035,712;
+SVCT 32SPA;SW3;PU2801,411;PD2199,1013;
+**** 0
+0001 501791
+SYMB 10SY03402NIL
+SYMD 39FSHRES61V008210142601153006070186900411
+SXPO 80area where fishing or trawling is prohibited or restricted, with other cautions
+SCRF 12ACHMGFECHMGD
+SVCT 251SPA;SW2;PU1869,874;PD2051,722;PD2127,637;PD2216,580;PD2309,544;PD2397,519;PD2494,519;PD2575,528;PD2672,561;PD2761,601;PD2841,661;PD2890,722;PD2830,777;PD2773,827;PD2701,863;PD2608,899;PD2515,916;PD2410,916;PD2309,899;PD2212,863;PD2127,806;PD2070,758;
+SVCT 31SPA;SW2;PU2037,717;PD1908,551;
+SVCT 31SPA;SW3;PU2075,759;PD2035,712;
+SVCT 32SPA;SW3;PU2801,411;PD2199,1013;
+SVCT 31SPE;SW1;PU2992,700;PD2992,925;
+SVCT 33SPE;SW1;PU2967,1018;PD3022,1018;
+**** 0
+0001 501792
+SYMB 10SY03404NIL
+SYMD 39FSHRES71V008210142601287006020160300411
+SXPO 83area where fishing or trawling is prohibited or restricted, with other information
+SCRF 12ACHMGFECHMGD
+SVCT 251SPA;SW2;PU1869,874;PD2051,722;PD2127,637;PD2216,580;PD2309,544;PD2397,519;PD2494,519;PD2575,528;PD2672,561;PD2761,601;PD2841,661;PD2890,722;PD2830,777;PD2773,827;PD2701,863;PD2608,899;PD2515,916;PD2410,916;PD2309,899;PD2212,863;PD2127,806;PD2070,758;
+SVCT 31SPA;SW2;PU2037,717;PD1908,551;
+SVCT 31SPA;SW3;PU2075,759;PD2035,712;
+SVCT 32SPA;SW3;PU2801,411;PD2199,1013;
+SVCT 43SPE;SW1;PU1695,1007;PD1695,773;PD1603,772;
+SVCT 33SPE;SW1;PU1604,1008;PD1791,1008;
+SVCT 31SPE;SW1;PU1649,654;PD1652,694;
+**** 0
+0001 501793
+SYMB 10SY01344NIL
+SYMD 39GATCON03V015000150000700007000115001150
+SXPO 20navigable lock gate
+SCRF 6JTRFCD
+SVCT 123SPJ;PU1500,1500;SW1;CI350;PU1181,1350;PD1812,1350;PU1181,1650;PD1818,1650;PU1250,1500;PD1500,1250;PU1250,1500;PD1500,1750;
+SVCT 37PU1650,1250;PD1400,1500;PD1650,1750;
+**** 0
+0001 501794
+SYMB 10SY01345NIL
+SYMD 39GATCON04V015000150000700007000115001150
+SXPO 24non-navigable lock gate
+SCRF 6JTRFCD
+SVCT 99SPJ;PU1500,1500;SW1;CI350;PU1181,1350;PD1812,1350;PU1181,1650;PD1818,1650;PU1500,1250;PD1500,1750;
+**** 0
+0001 501795
+SYMB 10SY03366NIL
+SYMD 39HILTOP01V005860107001007008360007800631
+SXPO 21hill or mountain top
+SCRF 6ALANDF
+SVCT 66SPA;SW1;ST0;PU849,993;PM0;PD873,1078;PD1085,969;PD849,993;PM2;FP;
+SVCT 69SPA;SW1;ST0;PU849,1122;PM0;PD795,1191;PD1016,1306;PD849,1122;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU389,1202;PM0;PD334,1132;PD172,1322;PD389,1202;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU558,1254;PM0;PD475,1224;PD425,1467;PD558,1254;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU722,1203;PM0;PD640,1244;PD789,1445;PD722,1203;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU726,890;PM0;PD796,946;PD912,726;PD729,891;PD726,890;PM2;FP;
+SVCT 65SPA;SW1;ST0;PU304,1071;PM0;PD328,983;PD78,959;PD304,1071;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU548,887;PM0;PD639,871;PD550,631;PD546,888;PD548,887;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU389,958;PM0;PD462,908;PD281,728;PD388,957;PD389,958;PM2;FP;
+**** 0
+0001 501796
+SYMB 10SY03367NIL
+SYMD 39HILTOP11V005860107001007008360007800631
+SXPO 33conspicuous hill or mountain top
+SCRF 6ACHBLK
+SVCT 66SPA;SW1;ST0;PU849,993;PM0;PD873,1078;PD1085,969;PD849,993;PM2;FP;
+SVCT 69SPA;SW1;ST0;PU849,1122;PM0;PD795,1191;PD1016,1306;PD849,1122;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU389,1202;PM0;PD334,1132;PD172,1322;PD389,1202;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU558,1254;PM0;PD475,1224;PD425,1467;PD558,1254;PM2;FP;
+SVCT 68SPA;SW1;ST0;PU722,1203;PM0;PD640,1244;PD789,1445;PD722,1203;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU726,890;PM0;PD796,946;PD912,726;PD729,891;PD726,890;PM2;FP;
+SVCT 65SPA;SW1;ST0;PU304,1071;PM0;PD328,983;PD78,959;PD304,1071;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU548,887;PM0;PD639,871;PD550,631;PD546,888;PD548,887;PM2;FP;
+SVCT 74SPA;SW1;ST0;PU389,958;PM0;PD462,908;PD281,728;PD388,957;PD389,958;PM2;FP;
+**** 0
+0001 501797
+SYMB 10SY02068NIL
+SYMD 39HRBFAC09V007500075000584005840045300459
+SXPO 16fishing harbour
+SCRF 6ACHMGD
+SVCT 353SPA;SW1;PU553,750;PD578,725;PD612,693;PD643,675;PD675,659;PD712,643;PD737,637;PD775,634;PD803,634;PD837,634;PD878,643;PD909,653;PD943,668;PD978,687;PD1003,709;PD1025,728;PD1037,750;PD1009,775;PD975,809;PD934,828;PD903,843;PD862,853;PD828,859;PD803,859;PD768,859;PD737,853;PD712,850;PD693,843;PD659,828;PD628,809;PD603,787;PD578,775;PD568,762;PD553,750;
+SVCT 99SPA;SW1;PU553,750;PD462,837;PD459,809;PD453,775;PD453,743;PD453,703;PD462,662;PD475,643;PD553,750;
+SVCT 130SPA;SW1;PU540,550;PD584,512;PD612,493;PD656,475;PD715,462;PD775,459;PD831,468;PD875,484;PD915,509;PD959,550;PD993,590;PD1003,603;
+SVCT 147SPA;SW1;PU534,946;PD581,990;PD631,1015;PD668,1031;PD706,1040;PD756,1043;PD787,1043;PD828,1034;PD871,1018;PD912,993;PD943,968;PD971,943;PD1006,900;
+**** 0
+0001 501798
+SYMB 10SY01348NIL
+SYMD 39HULKES01V007500075000488002660049600609
+SXPO 5hulk
+SCRF 12XCSTLNECHBRN
+SVCT 121SPE;ST0;PU500,840;PM0;PD550,856,606,865,656,875,700,875,750,859,784,856,825,840,859,825,884,809,925,790,950,775,965,756;
+SVCT 115PD984,750,965,725,940,700,909,684,881,665,850,650,815,634,790,625,753,618,715,609,681,609,656,609,625,615,600,615;
+SVCT 116PD565,625,540,631,525,640,500,650,500,840,500,840;PM2;FP;SPX;SW2;PU500,840;PD500,650;PU496,653;PD559,621;PD643,609;
+SVCT 121PD718,609;PD800,625;PD878,665;PD953,709;PD984,746;PD906,803;PD831,840;PD771,862;PD690,875;PD659,875;PD609,868;PD500,843;
+**** 0
+0001 501799
+SYMB 10SY03396NIL
+SYMD 39INFARE51V-13940242700804008050000202172
+SXPO 52area with minor restrictions or information notices
+SCRF 6ACHMGF
+SVCT 31SPA;SW2;PU231,2854;PD672,2854;
+SVCT 31SPA;SW2;PU348,2228;PD355,2323;
+SVCT 40SPA;SW2;PU2,2977;PD806,2977;PD803,2173;
+SVCT 38SPA;SW2;PU4,2972;PD4,2172;PD799,2172;
+SVCT 42SPA;SW2;PU446,2853;PD446,2440;PD267,2440;
+**** 0
+0001 501800
+SYMB 10SY03369NIL
+SYMD 39INFORM01V039910300401601015980380801599
+SXPO 65this object has additional information available by cursor query
+SCRF 6ACHMGD
+SVCT 69SPA;SW2;PU4914,2094;PD5409,2094;PD5409,1599;PD4914,1599;PD4914,2094;
+SVCT 33SPA;SW2;PU5145,1666;PD5145,1708;
+SVCT 45SPA;SW2;PU5159,2003;PD5159,1769;PD5067,1768;
+SVCT 33SPA;SW2;PU5058,2004;PD5225,2004;
+SVCT 27SPA;SW2;PU3916,3089;CI108;
+SVCT 33SPA;SW2;PU4908,2092;PD3988,3011;
+**** 0
+0001 501801
+SYMB 10SY01392NIL
+SYMD 39ISODGR01V006000070000700007000025000350
+SXPO 54isolated danger of depth less than the safety contour
+SCRF 6RISDNG
+SVCT 114SPR;ST0;PU600,350;PM0;PD850,450,950,700,850,950,600,1050,350,950,250,700,350,450,600,350,600,625,737,487,812,562;
+SVCT 112PD675,700,812,837,737,912,600,775,462,912,387,837,525,700,387,562,462,487,600,625,600,350;PM2;FP;SW1;PU250,700;
+SVCT 82PD350,450;PD600,350;PD850,450;PD950,700;PD850,950;PD600,1050;PD350,950;PD250,700;
+**** 0
+0001 501802
+SYMB 10SY03395NIL
+SYMD 39ITZARE51V021890131001149009010169300910
+SXPO 24area of inshore traffic
+SCRF 6ACHMGF
+SVCT 32SPA;SW2;PU1834,1811;PD1834,910;
+SVCT 32SPA;SW2;PU2540,913;PD2540,1811;
+SVCT 31SPA;SW2;PU1693,911;PD1986,911;
+SVCT 33SPA;SW2;PU1703,1809;PD1986,1809;
+SVCT 31SPA;SW2;PU2233,911;PD2842,911;
+**** 0
+0001 501803
+SYMB 10SY01395NIL
+SYMD 39LIGHTDEFV015000150000237007000137500800
+SXPO 12light flare
+SCRF 6ICHMGD
+SVCT 117SPI;ST2;PU1500,1500;PM0;PD1375,937,1375,912,1381,875,1400,843,1418,825,1450,800,1493,800,1531,800,1556,806,1593,831;
+SVCT 122PD1606,868,1612,900,1612,931,1500,1500;PM2;FP;SPI;SW1;PU1500,1500;PD1375,925;PD1375,887;PD1387,850;PD1406,831;PD1437,806;
+SVCT 101PD1475,800;PD1500,800;PD1531,800;PD1562,812;PD1587,837;PD1606,875;PD1612,900;PD1606,956;PD1500,1500;
+**** 0
+0001 501804
+SYMB 10SY01396NIL
+SYMD 39LIGHTS01V007500075000240007000062800050
+SXPO 17light flare, red
+SCRF 6OLITRD
+SVCT 114SPO;ST2;PU750,750;PM0;PD631,190,631,165,634,131,650,96,671,75,703,56,746,50,787,53,812,62,846,87,862,121,868,153;
+SVCT 115PD865,184,750,750;PM2;FP;SW1;PU750,750;PD628,178;PD631,140;PD643,106;PD662,84;PD693,59;PD728,50;PD756,50;PD787,53;
+SVCT 59PD818,68;PD843,93;PD859,125;PD868,156;PD859,209;PD750,750;
+**** 0
+0001 501805
+SYMB 10SY01397NIL
+SYMD 39LIGHTS02V022500222000285008100210001492
+SXPO 19light flare, green
+SCRF 12PLITGN^DEPMD
+SVCT 117SPP;ST2;PU2250,2220;PM0;PD2130,1657,2130,1635,2130,1597,2145,1560,2167,1545,2197,1522,2242,1515,2280,1522,2310,1530;
+SVCT 120PD2340,1552,2355,1590,2362,1620,2362,1650,2250,2220;PM2;FP;SP^;SW1;PU2385,1605;PD2377,1642;PD2250,2302;SPP;PU2250,2220;
+SVCT 121PD2122,1642;PD2130,1605;PD2137,1575;PD2160,1552;PD2190,1522;PD2227,1515;PD2250,1515;PD2280,1522;PD2317,1537;PD2340,1560;
+SVCT 113PD2355,1590;PD2362,1620;PD2355,1672;PD2250,2220;SP^;PU2250,2302;PD2100,1627;PD2122,1560;PD2182,1507;PD2250,1492;
+SVCT 37PD2310,1515;PD2347,1537;PD2377,1597;
+**** 0
+0001 501806
+SYMB 10SY01398NIL
+SYMD 39LIGHTS03V007500075000246007000062500050
+SXPO 29light flare, white or yellow
+SCRF 6QLITYW
+SVCT 114SPQ;ST2;PU750,750;PM0;PD628,187,628,162,631,128,650,93,668,75,700,53,743,50,784,50,809,59,843,84,871,131,871,178;
+SVCT 115PD871,178,750,750;PM2;FP;SW1;PU750,750;PD625,175;PD628,137;PD640,103;PD659,81;PD690,56;PD725,50;PD753,50;PD784,50;
+SVCT 59PD815,65;PD840,90;PD862,115;PD865,153;PD856,206;PD750,750;
+**** 0
+0001 501807
+SYMB 10SY02079NIL
+SYMD 39LIGHTS81V006420074500374002510045000624
+SXPO 12strip light
+SCRF 6ACHMGD
+SVCT 69SPA;SW1;PU450,873;PD524,624;PD598,874;PD674,624;PD749,875;PD824,624;
+**** 0
+0001 501808
+SYMB 10SY01399NIL
+SYMD 39LIGHTS82V007680212300584003020003001742
+SXPO 11floodlight
+SCRF 6ACHMGD
+SVCT 26SPA;SW1;PU146,1928;CI116;
+SVCT 31SPA;SW1;PU301,2031;PD514,2039;
+SVCT 31SPA;SW1;PU270,1817;PD555,1742;
+SVCT 31SPA;SW1;PU319,1923;PD614,1893;
+**** 0
+0001 501809
+SYMB 10SY01400NIL
+SYMD 39LITFLT01V007500075000900003220030000500
+SXPO 25light float, paper-chart
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI72;PU300,750;PD650,750;SW2;PU450,750;PD350,550;PU1050,750;PD1150,550;SW2;PU600,600;PD650,500;
+SVCT 83PD850,500;PD900,600;PU350,550;PD550,600;PD950,600;PD1150,550;PU850,750;PD1200,750;
+**** 0
+0001 501810
+SYMB 10SY02245NIL
+SYMD 39LITFLT02V007410060100613002240043400489
+SXPO 24light float, simplified
+SCRF 6ACHBLK
+SVCT 65SPA;SW1;ST0;PU435,539;PM0;PD529,713;PD963,713;PD1047,538;PM2;FP;
+SVCT 75SPA;SW1;ST0;PU434,538;PM0;PD529,713;PD963,713;PD1044,538;PD434,538;PM2;FP;
+SVCT 49SPA;SW1;PU637,537;PD637,489;PD847,489;PD847,538;
+**** 0
+0001 501811
+SYMB 10SY01402NIL
+SYMD 39LITVES01V007500075000900006700030000150
+SXPO 26light vessel, paper-chart
+SCRF 6CCHBLK
+SVCT 120SPC;PU750,750;SW2;CI70;PU300,750;PD650,750;SW2;PU450,750;PD350,500;PU1050,750;PD1150,500;PU750,575;PD750,300;PU550,575;
+SVCT 115PD550,395;PU950,575;PD950,400;SW2;PU750,300;PD750,150;PU650,200;PD850,300;PU650,300;PD850,200;PU410,650;PD575,650;
+SVCT 94PU925,650;PD1090,650;PU350,500;PD547,575;PD750,575;PD950,575;PD1150,500;PU850,750;PD1200,750;
+**** 0
+0001 501812
+SYMB 10SY02080NIL
+SYMD 39LITVES02V007470056300745003640037500381
+SXPO 25light vessel, simplified
+SCRF 6ACHBLK
+SVCT 75SPA;SW1;ST0;PU497,745;PM0;PD375,541;PD1120,541;PD987,745;PD497,745;PM2;FP;
+SVCT 29SPA;SW1;PU747,540;PD747,381;
+**** 0
+0001 501813
+SYMB 10SY01403NIL
+SYMD 39LNDARE01V022500225000206002060214702147
+SXPO 31land as a point at small scale
+SCRF 12VLANDAXCSTLN
+SVCT 63SPV;PU2250,2250;ST0;PM0;CI93;PM2;FP;SPX;PU2250,2250;SW2;CI103;
+**** 0
+0001 501814
+SYMB 10SY03197NIL
+SYMD 39LOCMAG01V014140067000181009330130000201
+SXPO 51cursor pick site for a magnetic anomaly at a point
+SCRF 6ACHMGD
+SVCT 32SPA;SW1;PU1481,869;PD1481,1134;
+SVCT 130SPA;SW1;PU1481,897;PD1481,201;PD1300,727;PD1335,738;PD1363,753;PD1386,772;PD1404,792;PD1423,811;PD1445,841;PD1462,867;PD1479,893;
+**** 0
+0001 501815
+SYMB 10SY03198NIL
+SYMD 39LOCMAG51V01430-214600374018590116000000
+SXPO 69cursor pick site for a magnetic anomaly along a line or over an area
+SCRF 6ACHMGF
+SVCT 138SPA;SW2;PU1526,1403;PD1526,0;PD1160,1060;PD1231,1082;PD1288,1112;PD1334,1150;PD1370,1191;PD1408,1229;PD1452,1289;PD1487,1341;PD1522,1395;
+SVCT 33SPA;SW2;PU1534,1395;PD1534,1859;
+**** 0
+0001 501816
+SYMB 10SY03398NIL
+SYMD 39LOWACC01V027920262101129012350156201291
+SXPO 38point feature or area of low accuracy
+SCRF 6ACHBLK
+SVCT 33SPA;SW1;PU1654,1670;PD1707,1670;
+SVCT 273SPA;SW1;PU1673,1579;PD1672,1520;PD1673,1501;PD1690,1481;PD1703,1463;PD1729,1437;PD1740,1412;PD1746,1383;PD1739,1352;PD1729,1332;PD1708,1313;PD1685,1297;PD1665,1294;PD1642,1291;PD1619,1297;PD1598,1307;PD1578,1327;PD1568,1347;PD1562,1366;PD1562,1384;PD1567,1401;PD1572,1406;
+SVCT 33SPA;SW1;PU1747,1582;PD2691,2526;
+**** 0
+0001 501817
+SYMB 10SY03199NIL
+SYMD 39MAGVAR01V014080064800181009150130000201
+SXPO 51cursor pick site for magnetic variation at a point
+SCRF 6ACHMGD
+SVCT 156SPA;SW1;ST0;PU1481,897;PM0;PD1481,201;PD1300,727;PD1335,738;PD1363,753;PD1386,772;PD1404,792;PD1423,811;PD1445,841;PD1462,867;PD1479,893;PD1481,897;PM2;FP;
+SVCT 32SPA;SW1;PU1475,202;PD1475,1116;
+**** 0
+0001 501818
+SYMB 10SY03196NIL
+SYMD 39MAGVAR51V014130367400366018540116000000
+SXPO 69cursor pick site for magnetic variation along a line or over an area
+SCRF 6ACHMGF
+SVCT 165SPA;SW2;ST0;PU1526,1403;PM0;PD1526,0;PD1160,1060;PD1231,1082;PD1288,1112;PD1334,1150;PD1370,1191;PD1408,1229;PD1452,1289;PD1487,1341;PD1522,1395;PD1526,1403;PM2;FP;
+SVCT 33SPA;SW2;PU1521,1390;PD1521,1854;
+**** 0
+0001 501819
+SYMB 10SY02081NIL
+SYMD 39MARCUL02V007690077000705004030041600568
+SXPO 10fish farm
+SCRF 6ACHGRD
+SVCT 202SPA;SW1;PU505,847;PD641,725;PD714,684;PD771,668;PD822,662;PD882,673;PD944,693;PD984,717;PD1018,744;PD1039,774;PD1004,803;PD968,831;PD914,855;PD871,869;PD819,871;PD763,869;PD709,857;PD670,835;PD505,698;
+SVCT 51SPA;SW1;PU416,669;PD416,570;PD1117,570;PD1117,666;
+SVCT 51SPA;SW1;PU416,871;PD416,971;PD1120,971;PD1121,871;
+SVCT 29SPA;SW1;PU564,871;PD564,971;
+SVCT 29SPA;SW1;PU965,871;PD965,971;
+SVCT 29SPA;SW1;PU765,870;PD765,968;
+SVCT 29SPA;SW1;PU564,571;PD564,672;
+SVCT 29SPA;SW1;PU965,569;PD965,670;
+SVCT 29SPA;SW1;PU764,568;PD764,668;
+**** 0
+0001 501820
+SYMB 10SY02082NIL
+SYMD 39MONUMT02V007470074900400004060055000394
+SXPO 9monument
+SCRF 6ALANDF
+SVCT 24SPA;SW2;PU750,750;CI50;
+SVCT 29SPA;SW2;PU550,750;PD687,750;
+SVCT 29SPA;SW2;PU800,750;PD950,750;
+SVCT 29SPA;SW1;PU809,401;PD653,564;
+SVCT 29SPA;SW1;PU825,506;PD650,700;
+SVCT 29SPA;SW1;PU837,631;PD775,700;
+SVCT 49SPA;SW1;PU628,749;PD673,394;PD811,397;PD850,747;
+**** 0
+0001 501821
+SYMB 10SY02083NIL
+SYMD 39MONUMT12V007470074900400004060055000394
+SXPO 21conspicuous monument
+SCRF 6ACHBLK
+SVCT 24SPA;SW2;PU750,750;CI50;
+SVCT 29SPA;SW2;PU550,750;PD687,750;
+SVCT 29SPA;SW2;PU800,750;PD950,750;
+SVCT 29SPA;SW1;PU809,401;PD653,564;
+SVCT 29SPA;SW1;PU825,506;PD650,700;
+SVCT 29SPA;SW1;PU837,631;PD775,700;
+SVCT 49SPA;SW1;PU628,749;PD673,394;PD811,397;PD850,747;
+**** 0
+0001 501822
+SYMB 10SY02084NIL
+SYMD 39MORFAC03V007470074600253002530060300617
+SXPO 16mooring dolphin
+SCRF 12ALANDABCHBLK
+SVCT 74SPA;SW2;ST0;PU603,617;PM0;PD856,617;PD856,870;PD605,870;PD603,617;PM2;FP;
+SVCT 59SPB;SW2;PU603,617;PD856,617;PD856,870;PD605,870;PD603,617;
+**** 0
+0001 501823
+SYMB 10SY02085NIL
+SYMD 39MORFAC04V007500075000350005030057000247
+SXPO 26deviation mooring dolphin
+SCRF 6ACHBLK
+SVCT 29SPA;SW1;PU570,750;PD920,750;
+SVCT 49SPA;SW1;PU610,750;PD655,390;PD835,390;PD875,750;
+SVCT 29SPA;SW1;PU747,749;PD747,247;
+**** 0
+0001 501824
+SYMB 10SY01412NIL
+SYMD 39MSTCON04V007500075000300006500060000150
+SXPO 5mast
+SCRF 6WLANDF
+SVCT 94SPW;PU750,750;SW2;CI50;PU600,750;PD700,750;PU800,750;PD900,750;PU700,750;PD750,150;PD800,750;
+**** 0
+0001 501825
+SYMB 10SY01414NIL
+SYMD 39MSTCON14V007500075000300006500060000150
+SXPO 17conspicuous mast
+SCRF 6CCHBLK
+SVCT 94SPC;PU750,750;SW2;CI50;PU600,750;PD700,750;PU800,750;PD900,750;PU700,750;PD750,150;PD800,750;
+**** 0
+0001 501826
+SYMB 10SY02086NIL
+SYMD 39NORTHAR1V015000082500355015000130700000
+SXPO 12north arrow
+SCRF 6ASCLBR
+SVCT 30SPA;SW2;PU1500,1500;PD1500,0;
+SVCT 53SPA;SW2;PU1325,987;PD1325,656;PD1662,987;PD1662,662;
+SVCT 66SPA;SW1;ST0;PU1307,395;PM0;PD1662,395;PD1495,3;PD1307,395;PM2;FP;
+**** 0
+0001 501827
+SYMB 10SY02087NIL
+SYMD 39NOTBRD11V007500075000300004000060000350
+SXPO 25conspicuous notice board
+SCRF 6CCHBLK
+SVCT 99SPC;SW1;PU650,750;PD850,750;PU750,750;PD750,550;PU600,550;PD900,550;PD900,350;PD600,350;PD600,550;
+**** 0
+0001 501828
+SYMB 10SY02248NIL
+SYMD 39OBSTRN01V015000150000410004100129501295
+SXPO 30obstruction, depth not stated
+SCRF 12ADEPVSBCHBLK
+SVCT 42SPA;SW1;ST0;PU1500,1500;PM0;CI205;PM2;FP;
+SVCT 24SPB;SW1;PU1500,1300;PD;
+SVCT 24SPB;SW1;PU1500,1700;PD;
+SVCT 24SPB;SW1;PU1700,1500;PD;
+SVCT 24SPB;SW1;PU1300,1500;PD;
+SVCT 24SPB;SW1;PU1580,1310;PD;
+SVCT 24SPB;SW1;PU1640,1360;PD;
+SVCT 24SPB;SW1;PU1685,1425;PD;
+SVCT 24SPB;SW1;PU1675,1585;PD;
+SVCT 24SPB;SW1;PU1640,1640;PD;
+SVCT 24SPB;SW1;PU1575,1680;PD;
+SVCT 24SPB;SW1;PU1420,1680;PD;
+SVCT 24SPB;SW1;PU1360,1635;PD;
+SVCT 24SPB;SW1;PU1315,1570;PD;
+SVCT 24SPB;SW1;PU1320,1420;PD;
+SVCT 24SPB;SW1;PU1355,1355;PD;
+SVCT 24SPB;SW1;PU1420,1315;PD;
+**** 0
+0001 501829
+SYMB 10SY03130NIL
+SYMD 39OBSTRN02V015000150000400004000130001300
+SXPO 35obstruction in the intertidal area
+SCRF 6ACHBLK
+SVCT 24SPA;SW1;PU1500,1300;PD;
+SVCT 24SPA;SW1;PU1500,1700;PD;
+SVCT 24SPA;SW1;PU1700,1500;PD;
+SVCT 24SPA;SW1;PU1300,1500;PD;
+SVCT 24SPA;SW1;PU1580,1310;PD;
+SVCT 24SPA;SW1;PU1640,1360;PD;
+SVCT 24SPA;SW1;PU1685,1425;PD;
+SVCT 24SPA;SW1;PU1675,1585;PD;
+SVCT 24SPA;SW1;PU1640,1640;PD;
+SVCT 24SPA;SW1;PU1575,1680;PD;
+SVCT 24SPA;SW1;PU1420,1680;PD;
+SVCT 24SPA;SW1;PU1360,1635;PD;
+SVCT 24SPA;SW1;PU1315,1570;PD;
+SVCT 24SPA;SW1;PU1320,1420;PD;
+SVCT 24SPA;SW1;PU1355,1355;PD;
+SVCT 24SPA;SW1;PU1420,1315;PD;
+**** 0
+0001 501830
+SYMB 10SY03611NIL
+SYMD 39OBSTRN03V015000150000410004100129501295
+SXPO 38obstruction which covers and uncovers
+SCRF 12ADEPITBCHBLK
+SVCT 42SPA;SW1;ST0;PU1500,1500;PM0;CI205;PM2;FP;
+SVCT 24SPB;SW1;PU1500,1300;PD;
+SVCT 24SPB;SW1;PU1500,1700;PD;
+SVCT 24SPB;SW1;PU1700,1500;PD;
+SVCT 24SPB;SW1;PU1300,1500;PD;
+SVCT 24SPB;SW1;PU1580,1310;PD;
+SVCT 24SPB;SW1;PU1640,1360;PD;
+SVCT 24SPB;SW1;PU1685,1425;PD;
+SVCT 24SPB;SW1;PU1675,1585;PD;
+SVCT 24SPB;SW1;PU1640,1640;PD;
+SVCT 24SPB;SW1;PU1575,1680;PD;
+SVCT 24SPB;SW1;PU1420,1680;PD;
+SVCT 24SPB;SW1;PU1360,1635;PD;
+SVCT 24SPB;SW1;PU1315,1570;PD;
+SVCT 24SPB;SW1;PU1320,1420;PD;
+SVCT 24SPB;SW1;PU1355,1355;PD;
+SVCT 24SPB;SW1;PU1420,1315;PD;
+**** 0
+0001 501831
+SYMB 10SY03131NIL
+SYMD 39OBSTRN11V006980077300200002000059800672
+SXPO 59obstruction in the water which is always above water level
+SCRF 12BCSTLNALANDA
+SVCT 74SPA;SW1;ST0;PU598,672;PM0;PD598,872;PD798,872;PD797,672;PD598,672;PM2;FP;
+SVCT 49SPB;SW2;PD598,872;PD798,872;PD797,672;PD598,672;
+**** 0
+0001 501832
+SYMB 10SY01418NIL
+SYMD 39OFSPLF01V007500075000400004000055000550
+SXPO 18offshore platform
+SCRF 6CCHBLK
+SVCT 89SPC;PU750,750;ST0;PM0;CI50;PM2;FP;SW2;PU550,550;PD950,550;PD950,950;PD550,950;PD550,550;
+**** 0
+0001 501833
+SYMB 10SY03600NIL
+SYMD 39OSPONE02V050330216700394000000482802167
+SXPO 35one minute mark for ownship vector
+SCRF 6ASHIPS
+SVCT 33SPA;SW2;PU4828,2167;PD5222,2167;
+**** 0
+0001 501834
+SYMB 10SY03601NIL
+SYMD 39OSPSIX02V053840214500397000000518902146
+SXPO 35six minute mark for ownship vector
+SCRF 6ASHIPS
+SVCT 33SPA;SW5;PU5189,2146;PD5586,2146;
+**** 0
+0001 501835
+SYMB 10SY03191NIL
+SYMD 39OWNSHP01V014900149700992009920098501009
+SXPO 31own ship symbol, constant size
+SCRF 6ASHIPS
+SVCT 27SPA;SW2;PU1481,1505;CI496;
+SVCT 27SPA;SW2;PU1481,1501;CI261;
+**** 0
+0001 501836
+SYMB 10SY02251NIL
+SYMD 39OWNSHP05V006740115400401016880047400316
+SXPO 53own ship drawn to scale with conning position marked
+SCRF 6ASHIPS
+SVCT 81SPA;SW2;PU773,316;PD873,570;PD875,2004;PD475,2004;PD474,573;PD570,321;PD773,316;
+**** 0
+0001 501837
+SYMB 10SY01422NIL
+SYMD 39PASTRK01V001980090400402000000000000905
+SXPO 24time mark on past track
+SCRF 6APSTRK
+SVCT 27SPA;SW2;PU0,905;PD402,905;
+**** 0
+0001 501838
+SYMB 10SY01422NIL
+SYMD 39PASTRK02V001980090400402000000000000905
+SXPO 34time mark on secondary past track
+SCRF 6ASYTRK
+SVCT 27SPA;SW2;PU0,905;PD402,905;
+**** 0
+0001 501839
+SYMB 10SY01423NIL
+SYMD 39PILBOP02V006000083700524005320034100568
+SXPO 21pilot boarding place
+SCRF 6JCHMGD
+SVCT 85SPJ;ST0;PU603,568;PM0;PD500,837,603,1100,712,837,603,568;PM2;FP;PU603,837;SW1;CI262;
+**** 0
+0001 501840
+SYMB 10SY01424NIL
+SYMD 39PILPNT02V007500075000200002000065000650
+SXPO 16pile or bollard
+SCRF 6CCHBLK
+SVCT 36SPC;PU750,750;ST0;PM0;CI100;PM2;FP;
+**** 0
+0001 501841
+SYMB 10SY01425NIL
+SYMD 39PLNPOS01V024370234302382009190249302343
+SXPO 66surrounding ellipse for arrival date and time at planned position
+SCRF 6kPLRTE
+SVCT 117SPk;SW1;PU2493,2793;PD2521,2671;PD2681,2521;PD2943,2418;PD3225,2371;PD3656,2343;PD4096,2371;PD4396,2418;PD4650,2521;
+SVCT 121PD4818,2671;PD4875,2793;PD4856,2962;PD4650,3093;PD4396,3187;PD4096,3262;PD3656,3262;PD3225,3262;PD2943,3196;PD2643,3093;
+SVCT 25PD2503,2971;PD2493,2793;
+**** 0
+0001 501842
+SYMB 10SY01426NIL
+SYMD 39PLNPOS02V001980090400402000000000000905
+SXPO 31crossline for planned position
+SCRF 6APLRTE
+SVCT 27SPA;SW2;PU0,905;PD402,905;
+**** 0
+0001 501843
+SYMB 10SY02090NIL
+SYMD 39PLNSPD03V009000075000840005710107400864
+SXPO 42box for speed to make good, planned route
+SCRF 6APLRTE
+SVCT 67SPA;SW1;PU1074,1431;PD1076,864;PD1914,864;PD1914,1435;PD1074,1431;
+**** 0
+0001 501844
+SYMB 10SY02091NIL
+SYMD 39PLNSPD04V009000075000840005710107400864
+SXPO 44box for speed to make good, alternate route
+SCRF 6AAPLRT
+SVCT 67SPA;SW1;PU1074,1431;PD1076,864;PD1914,864;PD1914,1435;PD1074,1431;
+**** 0
+0001 501845
+SYMB 10SY01437NIL
+SYMD 39POSGEN01V007500075000400004000055000550
+SXPO 28position of a point feature
+SCRF 6WLANDF
+SVCT 55SPW;PU750,750;SW2;CI200;PU750,750;ST0;PM0;CI50;PM2;FP;
+**** 0
+0001 501846
+SYMB 10SY03004NIL
+SYMD 39POSGEN03V007500075000400004000055000550
+SXPO 40position of a conspicuous point feature
+SCRF 6WCHBLK
+SVCT 55SPW;PU750,750;SW2;CI200;PU750,750;ST0;PM0;CI50;PM2;FP;
+**** 0
+0001 501847
+SYMB 10SY02092NIL
+SYMD 39POSGEN04V007500075000200002000065000650
+SXPO 42position of an elevation or control point
+SCRF 6WCHBLK
+SVCT 25SPW;PU750,750;SW1;CI100;
+**** 0
+0001 501848
+SYMB 10SY01439NIL
+SYMD 39POSITN02V022500225000590005900195001950
+SXPO 21ownship position fix
+SCRF 6fNINFO
+SVCT 75SPf;PU2250,2250;SW1;CI290;PU2250,1950;PD2250,2540;PU1950,2250;PD2540,2250;
+**** 0
+0001 501849
+SYMB 10SY03189NIL
+SYMD 39PRCARE12V007340207700366005030055701784
+SXPO 43point symbol for traffic precautionary area
+SCRF 6ATRFCD
+SVCT 53SPA;SW1;PU557,2287;PD923,2287;PD732,1784;PD560,2287;
+SVCT 31SPA;SW1;PU710,2216;PD765,2216;
+SVCT 31SPA;SW1;PU734,2160;PD734,1962;
+**** 0
+0001 501850
+SYMB 10SY03397NIL
+SYMD 39PRCARE51V007310037401042013010021901258
+SXPO 27traffic precautionary area
+SCRF 6ATRFCF
+SVCT 54SPA;SW2;PU219,2559;PD741,1258;PD1261,2559;PD219,2559;
+SVCT 31SPA;SW4;PU738,2219;PD738,1754;
+SVCT 31SPA;SW2;PU671,2399;PD814,2399;
+**** 0
+0001 501851
+SYMB 10SY01441NIL
+SYMD 39PRDINS02V007500075000505004200049500475
+SXPO 13mine, quarry
+SCRF 12WLANDFKCHBRN
+SVCT 114SPK;ST0;PU665,555;PM0;PD520,700,495,675,495,565,585,475,665,555;PM2;FP;PU830,560;PM0;PD910,475,1000,565,1000,670;
+SVCT 118PD970,700,830,560;PM2;FP;SPW;SW2;PU615,615;PD895,895;PU885,615;PD605,895;SW1;PU585,475;PD665,555;PD520,700;PD495,675;
+SVCT 83PD495,565;PD585,475;PU910,475;PD1000,565;PD1000,670;PD970,700;PD830,560;PD910,475;
+**** 0
+0001 501852
+SYMB 10SY01442NIL
+SYMD 39PRICKE03V007500075000293004350062500315
+SXPO 30withy, port-hand, paper-chart
+SCRF 6CCHBLK
+SVCT 119SPC;SW1;PU650,750;PD859,750;PU750,750;PD750,550;PU625,528;PD687,600;PD750,618;PD825,612;PD890,581;PD918,550;PU678,393;
+SVCT 81PD725,431;PD756,437;PD809,434;PD859,390;PU790,315;PD778,350;PD756,437;PD750,550;
+**** 0
+0001 501853
+SYMB 10SY01443NIL
+SYMD 39PRICKE04V007500075000253004440060900306
+SXPO 35withy, starboard-hand, paper-chart
+SCRF 6CCHBLK
+SVCT 119SPC;SW1;PU650,750;PD859,750;PU750,750;PD750,550;PU609,628;PD675,559;PD750,540;PD809,550;PD862,606;PU668,437;PD728,387;
+SVCT 71PD768,384;PD818,406;PD856,459;PU800,306;PD768,381;PD753,450;PD750,550;
+**** 0
+0001 501854
+SYMB 10SY03370NIL
+SYMD 39QUAPOS01V001320062900351003070000000473
+SXPO 21position approximate
+SCRF 6ACHBLK
+SVCT 25SPA;SW1;PU1,479;PD1,780;
+SVCT 27SPA;SW1;PU0,478;PD100,478;
+SVCT 27SPA;SW1;PU1,630;PD100,630;
+SVCT 29SPA;SW1;PU133,502;PD133,601;
+SVCT 29SPA;SW1;PU100,477;PD134,502;
+SVCT 29SPA;SW1;PU100,628;PD134,601;
+SVCT 39SPA;SW1;PU181,774;PD263,473;PD351,776;
+SVCT 29SPA;SW1;PU215,646;PD313,646;
+**** 0
+0001 501855
+SYMB 10SY03165NIL
+SYMD 39QUARRY01V007500075000672006720039800342
+SXPO 7quarry
+SCRF 6ALANDF
+SVCT 84SPA;SW1;ST0;PU665,555;PM0;PD520,700;PD495,675;PD495,565;PD585,475;PD665,555;PM2;FP;
+SVCT 86SPA;SW1;ST0;PU830,560;PM0;PD910,475;PD1000,565;PD1000,670;PD970,700;PD830,560;PM2;FP;
+SVCT 29SPA;SW2;PU615,615;PD895,895;
+SVCT 29SPA;SW2;PU885,615;PD605,895;
+SVCT 69SPA;SW1;PU585,475;PD665,555;PD520,700;PD495,675;PD495,565;PD585,475;
+SVCT 71SPA;SW1;PU910,475;PD1000,565;PD1000,670;PD970,700;PD830,560;PD910,475;
+SVCT 25SPA;SW1;PU734,678;CI336;
+**** 0
+0001 501856
+SYMB 10SY02094NIL
+SYMD 39QUESMRK1V016780144900220004430156801227
+SXPO 113object which is not sufficiently described to be symbolized, or for which no symbol exists in the symbol library
+SCRF 6ACHMGD
+SVCT 309SPA;SW1;PU1568,1323;PD1581,1295;PD1594,1270;PD1611,1253;PD1628,1236;PD1654,1227;PD1677,1229;PD1707,1238;PD1735,1244;PD1758,1278;PD1776,1297;PD1788,1319;PD1788,1344;PD1776,1368;PD1763,1389;PD1743,1413;PD1720,1438;PD1699,1464;PD1686,1483;PD1675,1500;PD1673,1522;PD1673,1545;PD1673,1562;PD1675,1584;PD1675,1586;
+SVCT 33SPA;SW2;PU1654,1670;PD1720,1670;
+**** 0
+0001 501857
+SYMB 10SY03132NIL
+SYMD 39RACNSP01V011080104900606006100080400744
+SXPO 51symbol indicating this object is radar conspicuous
+SCRF 6ACHMGD
+SVCT 27SPA;SW1;PU1110,1051;CI149;
+SVCT 31SPA;SW1;PU1111,902;PD1111,744;
+SVCT 33SPA;SW1;PU1110,1201;PD1110,1354;
+SVCT 33SPA;SW1;PU1260,1048;PD1410,1048;
+SVCT 31SPA;SW1;PU960,1049;PD804,1049;
+SVCT 33SPA;SW1;PU1214,1155;PD1324,1265;
+SVCT 31SPA;SW1;PU1322,840;PD1213,950;
+SVCT 32SPA;SW1;PU1002,1156;PD892,1266;
+SVCT 30SPA;SW1;PU896,839;PD1005,949;
+**** 0
+0001 501858
+SYMB 10SY03133NIL
+SYMD 39RADRFL03V011080104900606006100080400744
+SXPO 16radar reflector
+SCRF 6ACHMGD
+SVCT 27SPA;SW1;PU1110,1051;CI149;
+SVCT 31SPA;SW1;PU1111,902;PD1111,744;
+SVCT 33SPA;SW1;PU1110,1201;PD1110,1354;
+SVCT 33SPA;SW1;PU1260,1048;PD1410,1048;
+SVCT 31SPA;SW1;PU960,1049;PD804,1049;
+SVCT 33SPA;SW1;PU1214,1155;PD1324,1265;
+SVCT 31SPA;SW1;PU1322,840;PD1213,950;
+SVCT 32SPA;SW1;PU1002,1156;PD892,1266;
+SVCT 30SPA;SW1;PU896,839;PD1005,949;
+**** 0
+0001 501859
+SYMB 10SY03116NIL
+SYMD 39RASCAN01V007480075000398005440054600256
+SXPO 14radar scanner
+SCRF 6ALANDF
+SVCT 24SPA;SW1;PU750,750;CI50;
+SVCT 29SPA;SW1;PU635,747;PD635,395;
+SVCT 39SPA;SW1;PU851,745;PD851,395;PD678,395;
+SVCT 29SPA;SW1;PU703,748;PD568,748;
+SVCT 29SPA;SW1;PU800,746;PD936,746;
+SVCT 29SPA;SW1;PU681,395;PD635,395;
+SVCT 29SPA;SW1;PU742,391;PD742,257;
+SVCT 29SPA;SW2;PU546,256;PD944,256;
+**** 0
+0001 501860
+SYMB 10SY03124NIL
+SYMD 39RASCAN11V007530074800398005440054600256
+SXPO 26conspicuous radar scanner
+SCRF 6ACHBLK
+SVCT 24SPA;SW1;PU750,750;CI50;
+SVCT 29SPA;SW1;PU635,747;PD635,395;
+SVCT 39SPA;SW1;PU851,745;PD851,395;PD678,395;
+SVCT 29SPA;SW1;PU703,748;PD568,748;
+SVCT 29SPA;SW1;PU800,746;PD936,746;
+SVCT 29SPA;SW1;PU681,395;PD635,395;
+SVCT 29SPA;SW1;PU742,391;PD742,257;
+SVCT 29SPA;SW2;PU546,256;PD944,256;
+**** 0
+0001 501861
+SYMB 10SY03430NIL
+SYMD 39RCLDEF01V007510074801209010370014400231
+SXPO 52radio calling-in point whose direction is not known
+SCRF 6ACHMGD
+SVCT 259SPA;SW1;PU144,651;PD157,623;PD170,598;PD187,581;PD204,564;PD230,555;PD253,557;PD283,566;PD311,572;PD334,606;PD352,625;PD364,647;PD364,672;PD352,696;PD339,717;PD319,741;PD296,766;PD275,792;PD262,811;PD251,828;PD249,850;PD249,873;PD249,890;PD251,912;PD251,914;
+SVCT 29SPA;SW2;PU230,998;PD283,998;
+SVCT 284SPA;SW1;PU1133,651;PD1146,623;PD1159,598;PD1176,581;PD1193,564;PD1219,555;PD1242,557;PD1272,566;PD1300,572;PD1323,606;PD1341,625;PD1353,647;PD1353,672;PD1341,696;PD1328,717;PD1308,741;PD1285,766;PD1264,792;PD1251,811;PD1240,828;PD1238,850;PD1238,873;PD1238,890;PD1240,912;PD1240,914;
+SVCT 31SPA;SW2;PU1219,998;PD1272,998;
+SVCT 25SPA;SW1;PU750,750;CI218;
+SVCT 39SPA;SW1;PU580,589;PD752,231;PD923,589;
+SVCT 40SPA;SW1;PU920,914;PD742,1268;PD580,911;
+**** 0
+0001 501862
+SYMB 10SY02098NIL
+SYMD 39RCTLPT52V022570207700597013900196001383
+SXPO 120recommended traffic direction between parts of a traffic separation scheme, or for ships not needing a deep water route
+SCRF 6ATRFCD
+SVCT 45SPA;SW3;PU2134,1545;PD2257,1383;PD2380,1545;
+SVCT 45SPA;SW3;PU2043,1661;PD1960,1777;PD2108,1777;
+SVCT 45SPA;SW3;PU2394,1773;PD2557,1773;PD2463,1650;
+SVCT 57SPA;SW3;PU2104,2585;PD2104,2773;PD2408,2773;PD2408,2588;
+SVCT 33SPA;SW3;PU2104,2435;PD2104,2278;
+SVCT 33SPA;SW3;PU2104,1937;PD2104,2087;
+SVCT 33SPA;SW3;PU2423,1929;PD2423,2075;
+SVCT 33SPA;SW3;PU2419,2270;PD2419,2422;
+**** 0
+0001 501863
+SYMB 10SY02099NIL
+SYMD 39RDOCAL02V007500075000436007370053200231
+SXPO 57radio calling-in point for traffic in one direction only
+SCRF 6ATRFCD
+SVCT 25SPA;SW1;PU750,750;CI218;
+SVCT 39SPA;SW1;PU580,589;PD752,231;PD923,589;
+**** 0
+0001 501864
+SYMB 10SY03099NIL
+SYMD 39RDOCAL03V007500075000436010370053200231
+SXPO 54radio calling-in point for traffic in both directions
+SCRF 6ATRFCD
+SVCT 25SPA;SW1;PU750,750;CI218;
+SVCT 39SPA;SW1;PU580,589;PD752,231;PD923,589;
+SVCT 40SPA;SW1;PU920,914;PD742,1268;PD580,911;
+**** 0
+0001 501865
+SYMB 10SY02100NIL
+SYMD 39RDOSTA02V007500075000590005900045300455
+SXPO 14radio station
+SCRF 6ACHMGD
+SVCT 25SPA;SW1;PU748,750;CI295;
+**** 0
+0001 501866
+SYMB 10SY03340NIL
+SYMD 39RECDEF51V024700141301731004430159601179
+SXPO 60recommended track as an area, direction not defined in data
+SCRF 6ACHGRD
+SVCT 33SPA;SW1;PU1596,1415;PD1921,1415;
+SVCT 33SPA;SW1;PU3002,1415;PD3327,1415;
+SVCT 309SPA;SW1;PU2358,1275;PD2371,1247;PD2384,1222;PD2401,1205;PD2418,1188;PD2444,1179;PD2467,1181;PD2497,1190;PD2525,1196;PD2548,1230;PD2566,1249;PD2578,1271;PD2578,1296;PD2566,1320;PD2553,1341;PD2533,1365;PD2510,1390;PD2489,1416;PD2476,1435;PD2465,1452;PD2463,1474;PD2463,1497;PD2463,1514;PD2465,1536;PD2465,1538;
+SVCT 33SPA;SW2;PU2444,1622;PD2497,1622;
+SVCT 45SPA;SW1;PU2254,1570;PD2049,1415;PD2254,1260;
+SVCT 45SPA;SW1;PU2660,1566;PD2865,1411;PD2660,1256;
+**** 0
+0001 501867
+SYMB 10SY03341NIL
+SYMD 39RECTRC55V024610141300310017280230800551
+SXPO 63recommended two-way track as an area, not based on fixed marks
+SCRF 6ACHGRD
+SVCT 33SPA;SW1;PU2461,2279;PD2461,1954;
+SVCT 33SPA;SW1;PU2463,1577;PD2463,1253;
+SVCT 31SPA;SW1;PU2462,876;PD2461,551;
+SVCT 45SPA;SW1;PU2615,1576;PD2462,1781;PD2308,1578;
+SVCT 45SPA;SW1;PU2618,1253;PD2462,1048;PD2308,1253;
+**** 0
+0001 501868
+SYMB 10SY03342NIL
+SYMD 39RECTRC56V023770141000310014860222500665
+SXPO 59recommended two-way track as an area, based on fixed marks
+SCRF 6ACHGRD
+SVCT 45SPA;SW1;PU2534,1570;PD2379,1774;PD2225,1570;
+SVCT 45SPA;SW1;PU2535,1246;PD2380,1041;PD2225,1246;
+SVCT 32SPA;SW1;PU2378,665;PD2378,2151;
+**** 0
+0001 501869
+SYMB 10SY03343NIL
+SYMD 39RECTRC57V021370141500308010250198100920
+SXPO 63recommended one-way track as an area, not based on fixed marks
+SCRF 6ACHGRD
+SVCT 33SPA;SW1;PU2135,1945;PD2136,1621;
+SVCT 32SPA;SW1;PU2135,1245;PD2135,920;
+SVCT 45SPA;SW1;PU2289,1621;PD2135,1418;PD1981,1621;
+**** 0
+0001 501870
+SYMB 10SY03344NIL
+SYMD 39RECTRC58V020110141600309012060185400795
+SXPO 59recommended one-way track as an area, based on fixed marks
+SCRF 6ACHGRD
+SVCT 45SPA;SW1;PU2163,1499;PD2008,1294;PD1854,1499;
+SVCT 32SPA;SW1;PU2007,795;PD2007,2001;
+**** 0
+0001 501871
+SYMB 10SY01451NIL
+SYMD 39REFPNT02V015500165001000010000105001150
+SXPO 49reference point, 'ghost cursor' (user interface)
+SCRF 6fNINFO
+SVCT 117SPf;SW1;PU1050,1550;PD1450,1550;PD1450,1150;PU1050,1750;PD1450,1750;PD1450,2150;PU1650,1150;PD1650,1550;PD2050,1550;
+SVCT 37PU2050,1750;PD1650,1750;PD1650,2150;
+**** 0
+0001 501872
+SYMB 10SY03125NIL
+SYMD 39RETRFL01V007500075000203003470105200405
+SXPO 29retro reflector, paper chart
+SCRF 6ACHMGD
+SVCT 31SPA;SW1;PU1053,465;PD1255,465;
+SVCT 31SPA;SW1;PU1052,688;PD1254,688;
+SVCT 31SPA;SW1;PU1053,574;PD1255,574;
+SVCT 31SPA;SW1;PU1052,405;PD1052,752;
+**** 0
+0001 501873
+SYMB 10SY03126NIL
+SYMD 39RETRFL02V007000070000204003470097900534
+SXPO 28retro reflector, simplified
+SCRF 6ACHMGD
+SVCT 30SPA;SW1;PU979,594;PD1181,594;
+SVCT 30SPA;SW1;PU981,821;PD1183,821;
+SVCT 30SPA;SW1;PU981,709;PD1183,709;
+SVCT 29SPA;SW1;PU980,534;PD980,881;
+**** 0
+0001 501874
+SYMB 10SY03166NIL
+SYMD 39RFNERY01V015100126500680006800116900912
+SXPO 9refinery
+SCRF 6ALANDF
+SVCT 120SPA;SW1;ST0;PU1450,1500;PM0;PD1450,1175;PD1550,1175;PD1550,1500;PD1537,1462;PD1500,1450;PD1468,1462;PD1450,1500;PM2;FP;
+SVCT 207SPA;SW2;PU1556,943;PD1525,962;PD1493,981;PD1468,1012;PD1450,1050;PD1450,1087;PD1456,1106;PD1481,1118;PD1512,1118;PD1531,1106;PD1543,1081;PD1537,1050;PD1525,1037;PD1525,1012;PD1525,987;PD1543,968;PD1556,943;
+SVCT 27SPA;SW1;PU1509,1252;CI340;
+SVCT 33SPA;SW2;PU1349,1496;PD1644,1496;
+**** 0
+0001 501875
+SYMB 10SY03167NIL
+SYMD 39RFNERY11V015010127000680006800116900912
+SXPO 21conspicuous refinery
+SCRF 6ACHBLK
+SVCT 120SPA;SW1;ST0;PU1450,1500;PM0;PD1450,1175;PD1550,1175;PD1550,1500;PD1537,1462;PD1500,1450;PD1468,1462;PD1450,1500;PM2;FP;
+SVCT 207SPA;SW2;PU1556,943;PD1525,962;PD1493,981;PD1468,1012;PD1450,1050;PD1450,1087;PD1456,1106;PD1481,1118;PD1512,1118;PD1531,1106;PD1543,1081;PD1537,1050;PD1525,1037;PD1525,1012;PD1525,987;PD1543,968;PD1556,943;
+SVCT 27SPA;SW1;PU1509,1252;CI340;
+SVCT 33SPA;SW2;PU1349,1496;PD1644,1496;
+**** 0
+0001 501876
+SYMB 10SY03368NIL
+SYMD 39ROLROL01V003670061900720003040000000477
+SXPO 14RoRo terminal
+SCRF 6ACHBLK
+SVCT 25SPA;SW1;PU1,479;PD1,780;
+SVCT 29SPA;SW1;PU398,481;PD398,781;
+SVCT 27SPA;SW1;PU0,478;PD100,478;
+SVCT 27SPA;SW1;PU1,630;PD100,630;
+SVCT 29SPA;SW1;PU398,481;PD497,481;
+SVCT 29SPA;SW1;PU398,632;PD497,632;
+SVCT 29SPA;SW1;PU100,628;PD137,778;
+SVCT 29SPA;SW1;PU497,630;PD533,781;
+SVCT 29SPA;SW1;PU532,603;PD532,503;
+SVCT 29SPA;SW1;PU135,601;PD135,501;
+SVCT 29SPA;SW1;PU100,477;PD134,502;
+SVCT 29SPA;SW1;PU100,628;PD134,601;
+SVCT 29SPA;SW1;PU497,630;PD532,604;
+SVCT 29SPA;SW1;PU496,480;PD532,505;
+SVCT 24SPA;SW1;PU261,702;CI74;
+SVCT 24SPA;SW1;PU647,702;CI73;
+**** 0
+0001 501877
+SYMB 10SY01452NIL
+SYMD 39RSCSTA02V003010075000500004000005000550
+SXPO 15rescue station
+SCRF 6ACHBLK
+SVCT 74SPA;SW1;ST0;PU300,550;PM0;PD200,750;PD300,950;PD400,750;PD300,550;PM2;FP;
+SVCT 87SPA;SW1;PU50,750;PD50,750;PD200,750;PD300,750;PD350,750;PD500,750;PD550,750;PD550,750;
+**** 0
+0001 501878
+SYMB 10SY03408NIL
+SYMD 39RSRDEF51V022650272101319009940028601837
+SXPO 43area in which undefined restrictions exist
+SCRF 12ATRFCFDCHMGD
+SVCT 31SPA;SW3;PU785,2462;PD785,1997;
+SVCT 31SPA;SW2;PU718,2642;PD861,2642;
+SVCT 26SPA;SW2;PU783,2334;CI497;
+SVCT 309SPD;SW1;PU1385,2484;PD1398,2456;PD1411,2431;PD1428,2414;PD1445,2397;PD1471,2388;PD1494,2390;PD1524,2399;PD1552,2405;PD1575,2439;PD1593,2458;PD1605,2480;PD1605,2505;PD1593,2529;PD1580,2550;PD1560,2574;PD1537,2599;PD1516,2625;PD1503,2644;PD1492,2661;PD1490,2683;PD1490,2706;PD1490,2723;PD1492,2745;PD1492,2747;
+SVCT 33SPD;SW2;PU1471,2831;PD1524,2831;
+**** 0
+0001 501879
+SYMB 10SY03409NIL
+SYMD 39RTLDEF51V022570207701177013900163901383
+SXPO 154recommended route between parts of a traffic separation scheme, or for ships not needing a deep water route, with the direction not specified in the data
+SCRF 12ATRFCDICHMGD
+SVCT 45SPA;SW3;PU2134,1545;PD2257,1383;PD2380,1545;
+SVCT 45SPA;SW3;PU2043,1661;PD1960,1777;PD2108,1777;
+SVCT 45SPA;SW3;PU2394,1773;PD2557,1773;PD2463,1650;
+SVCT 57SPA;SW3;PU2104,2585;PD2104,2773;PD2408,2773;PD2408,2588;
+SVCT 33SPA;SW3;PU2104,2435;PD2104,2278;
+SVCT 33SPA;SW3;PU2104,1937;PD2104,2087;
+SVCT 33SPA;SW3;PU2423,1929;PD2423,2075;
+SVCT 33SPA;SW3;PU2419,2270;PD2419,2422;
+SVCT 309SPI;SW1;PU1639,2104;PD1652,2076;PD1665,2051;PD1682,2034;PD1699,2017;PD1725,2008;PD1748,2010;PD1778,2019;PD1806,2025;PD1829,2059;PD1847,2078;PD1859,2100;PD1859,2125;PD1847,2149;PD1834,2170;PD1814,2194;PD1791,2219;PD1770,2245;PD1757,2264;PD1746,2281;PD1744,2303;PD1744,2326;PD1744,2343;PD1746,2365;PD1746,2367;
+SVCT 33SPI;SW2;PU1725,2451;PD1778,2451;
+SVCT 309SPI;SW1;PU2596,2102;PD2609,2074;PD2622,2049;PD2639,2032;PD2656,2015;PD2682,2006;PD2705,2008;PD2735,2017;PD2763,2023;PD2786,2057;PD2804,2076;PD2816,2098;PD2816,2123;PD2804,2147;PD2791,2168;PD2771,2192;PD2748,2217;PD2727,2243;PD2714,2262;PD2703,2279;PD2701,2301;PD2701,2324;PD2701,2341;PD2703,2363;PD2703,2365;
+SVCT 33SPI;SW2;PU2682,2449;PD2735,2449;
+**** 0
+0001 501880
+SYMB 10SY02259NIL
+SYMD 39RTPBCN02V007200080600643006080039900502
+SXPO 25radar transponder beacon
+SCRF 6ACHMGD
+SVCT 42SPA;SW2;PU1019,705;PD1042,808;PD1021,916;
+SVCT 39SPA;SW2;PU420,707;PD399,808;PD420,913;
+SVCT 41SPA;SW2;PU657,1110;PD556,1060;PD496,990;
+SVCT 41SPA;SW2;PU802,1104;PD893,1058;PD959,988;
+SVCT 39SPA;SW2;PU657,502;PD556,554;PD492,618;
+SVCT 39SPA;SW2;PU804,506;PD899,558;PD959,622;
+**** 0
+0001 501881
+SYMB 10SY02105NIL
+SYMD 39SCALEB10V011500305500001020000115001055
+SXPO 58one mile scalebar for display scales larger than 1/80,000
+SCRF 12ASCLBRDCHGRD
+SVCT 33SPD;SW4;PU1150,1255;PD1150,1055;
+SVCT 33SPA;SW4;PU1150,1455;PD1150,1255;
+SVCT 33SPD;SW4;PU1150,1655;PD1150,1455;
+SVCT 33SPA;SW4;PU1150,1855;PD1150,1655;
+SVCT 33SPD;SW4;PU1150,2055;PD1150,1855;
+SVCT 33SPA;SW4;PU1150,2255;PD1150,2055;
+SVCT 33SPD;SW4;PU1150,2455;PD1150,2255;
+SVCT 33SPA;SW4;PU1150,2655;PD1150,2455;
+SVCT 33SPD;SW4;PU1150,2855;PD1150,2655;
+SVCT 33SPA;SW4;PU1150,3055;PD1150,2855;
+**** 0
+0001 501882
+SYMB 10SY02106NIL
+SYMD 39SCALEB11V011500305500001020000115001055
+SXPO 6410 mile latitude scale for display scales smaller than 1/80,000
+SCRF 12ASNDG2DSNDG1
+SVCT 33SPA;SW4;PU1150,1055;PD1150,1455;
+SVCT 33SPD;SW4;PU1150,1455;PD1150,1855;
+SVCT 33SPA;SW4;PU1150,1855;PD1150,2255;
+SVCT 33SPD;SW4;PU1150,2255;PD1150,2655;
+SVCT 33SPA;SW4;PU1150,2655;PD1150,3055;
+**** 0
+0001 501883
+SYMB 10SY01458NIL
+SYMD 39SILBUI01V007500075000300003000060000600
+SXPO 5silo
+SCRF 12WLANDFKCHBRN
+SVCT 60SPK;PU750,750;ST0;PM0;CI150;PM2;FP;SPW;PU750,750;SW2;CI150;
+**** 0
+0001 501884
+SYMB 10SY01459NIL
+SYMD 39SILBUI11V007500075000300003000060000600
+SXPO 17conspicuous silo
+SCRF 12WLANDFCCHBLK
+SVCT 60SPW;PU750,750;ST0;PM0;CI150;PM2;FP;SPC;PU750,750;SW2;CI150;
+**** 0
+0001 501885
+SYMB 10SY02107NIL
+SYMD 39SISTAT02V004840075800640004250046000734
+SXPO 15signal station
+SCRF 18ACHWHTBLANDFCCHMGF
+SVCT 78SPA;SW1;ST0;PU500,787;PM0;PD1100,787;PD1100,1159;PD500,1159;PD500,787;PM2;FP;
+SVCT 53SPC;SW2;PU1100,787;PD1100,1159;PD500,1159;PD500,787;
+SVCT 133SPC;SW2;PU725,875;PD700,850;PD650,850;PD625,875;PD625,925;PD650,950;PD690,950;PD725,975;PD725,1025;PD700,1059;PD634,1059;PD606,1028;
+SVCT 133SPC;SW2;PU975,875;PD950,850;PD900,850;PD875,875;PD875,925;PD903,950;PD940,950;PD975,975;PD975,1028;PD950,1053;PD884,1053;PD856,1025;
+SVCT 30SPC;SW2;PU500,787;PD1100,787;
+SVCT 39SPB;SW1;ST0;PU485,759;PM0;CI25;PM2;FP;
+**** 0
+0001 501886
+SYMB 10SY02108NIL
+SYMD 39SMCFAC02V007500075000680006850041000405
+SXPO 22yacht harbour, marina
+SCRF 6ACHMGD
+SVCT 181SPA;SW1;PU830,420;PD750,545;PD750,930;PD1050,865;PD1020,840;PD990,815;PD960,785;PD930,745;PD905,705;PD880,665;PD860,620;PD845,570;PD835,525;PD830,480;PD830,450;PD830,425;PD830,420;
+SVCT 379SPA;SW1;PU750,505;PD720,515;PD690,540;PD665,555;PD640,580;PD620,605;PD600,635;PD580,660;PD565,695;PD550,730;PD540,760;PD535,800;PD530,840;PD530,895;PD535,925;PD535,965;PD545,950;PD570,925;PD590,905;PD620,890;PD655,880;PD675,875;PD705,875;PD690,855;PD675,825;PD660,780;PD655,750;PD655,725;PD655,700;PD655,670;PD665,635;PD675,600;PD695,570;PD710,545;PD730,520;PD745,505;PD750,505;
+SVCT 25SPA;SW1;PU750,750;CI340;
+SVCT 29SPA;SW1;PU750,405;PD750,990;
+SVCT 29SPA;SW1;PU508,989;PD989,989;
+**** 0
+0001 501887
+SYMB 10SY01462NIL
+SYMD 39SNDWAV02V006170041701179001790003700316
+SXPO 11sand waves
+SCRF 6ACHGRD
+SVCT 222SPA;SW1;PU37,495;PD121,495;PD163,473;PD228,328;PD263,328;PD320,473;PD347,495;PD523,495;PD554,468;PD600,331;PD626,331;PD677,468;PD710,495;PD856,495;PD906,495;PD937,476;PD998,316;PD1036,316;PD1093,473;PD1132,495;PD1216,495;
+**** 0
+0001 501888
+SYMB 10SY01463NIL
+SYMD 39SOUNDG00V007500075000125002500080000625
+SXPO 42deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;
+**** 0
+0001 501889
+SYMB 10SY01464NIL
+SYMD 39SOUNDG01V007500075000075002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU800,700;PD875,625;PD875,875;
+**** 0
+0001 501890
+SYMB 10SY01465NIL
+SYMD 39SOUNDG02V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501891
+SYMB 10SY01466NIL
+SYMD 39SOUNDG03V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,737;PD825,737;PU900,737;PD925,762;PD925,850;PD900,875;PD825,875;PD800,850;PU831,625;PD900,625;PD925,650;
+SVCT 41PD925,712;PD900,737;PU806,650;PD831,625;
+**** 0
+0001 501892
+SYMB 10SY02109NIL
+SYMD 39SOUNDG04V007500075000155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501893
+SYMB 10SY01468NIL
+SYMD 39SOUNDG05V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU925,625;PD800,625;PD800,737;PD900,737;PD925,762;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501894
+SYMB 10SY01469NIL
+SYMD 39SOUNDG06V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,759;PD900,734;PD825,734;PD800,759;
+SVCT 21PU900,625;PD918,643;
+**** 0
+0001 501895
+SYMB 10SY01470NIL
+SYMD 39SOUNDG07V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501896
+SYMB 10SY01471NIL
+SYMD 39SOUNDG08V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501897
+SYMB 10SY01472NIL
+SYMD 39SOUNDG09V007500075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,740;PD825,765;PD900,765;
+SVCT 11PD925,740;
+**** 0
+0001 501898
+SYMB 10SY01473NIL
+SYMD 39SOUNDG10V007500075000125002500057500625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU600,625;PD575,650;PD575,850;PD600,875;PD675,875;PD700,850;PD700,650;PU675,625;PD600,625;PU700,650;PD675,625;
+**** 0
+0001 501899
+SYMB 10SY01474NIL
+SYMD 39SOUNDG11V009750075000075002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU800,700;PD875,625;PD875,875;
+**** 0
+0001 501900
+SYMB 10SY01475NIL
+SYMD 39SOUNDG12V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501901
+SYMB 10SY01476NIL
+SYMD 39SOUNDG13V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,734;PD825,734;PU900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;PU828,625;PD900,625;PD925,650;
+SVCT 41PD925,709;PD900,734;PU803,650;PD828,625;
+**** 0
+0001 501902
+SYMB 10SY02110NIL
+SYMD 39SOUNDG14V009740075000155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501903
+SYMB 10SY01478NIL
+SYMD 39SOUNDG15V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU925,625;PD800,625;PD800,734;PD900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501904
+SYMB 10SY01479NIL
+SYMD 39SOUNDG16V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,756;PD900,731;PD825,731;PD800,756;
+SVCT 21PU900,625;PD915,640;
+**** 0
+0001 501905
+SYMB 10SY01480NIL
+SYMD 39SOUNDG17V009750072500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501906
+SYMB 10SY01481NIL
+SYMD 39SOUNDG18V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501907
+SYMB 10SY01482NIL
+SYMD 39SOUNDG19V009750075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,737;PD825,762;PD900,762;
+SVCT 11PD925,737;
+**** 0
+0001 501908
+SYMB 10SY01483NIL
+SYMD 39SOUNDG20V007500075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;
+**** 0
+0001 501909
+SYMB 10SY01484NIL
+SYMD 39SOUNDG21V009750075000075002500057500625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU575,700;PD650,625;PD650,875;
+**** 0
+0001 501910
+SYMB 10SY01485NIL
+SYMD 39SOUNDG22V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501911
+SYMB 10SY01486NIL
+SYMD 39SOUNDG23V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,734;PD825,734;PU900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;PU828,625;PD900,625;PD925,650;
+SVCT 41PD925,709;PD900,734;PU803,650;PD828,625;
+**** 0
+0001 501912
+SYMB 10SY02111NIL
+SYMD 39SOUNDG24V011990075000155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501913
+SYMB 10SY01488NIL
+SYMD 39SOUNDG25V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU925,625;PD800,625;PD800,734;PD900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501914
+SYMB 10SY01489NIL
+SYMD 39SOUNDG26V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,756;PD900,731;PD825,731;PD800,756;
+SVCT 21PU900,625;PD915,640;
+**** 0
+0001 501915
+SYMB 10SY01490NIL
+SYMD 39SOUNDG27V012000072500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501916
+SYMB 10SY01491NIL
+SYMD 39SOUNDG28V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501917
+SYMB 10SY01492NIL
+SYMD 39SOUNDG29V012000075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,737;PD825,762;PD900,762;
+SVCT 11PD925,737;
+**** 0
+0001 501918
+SYMB 10SY01493NIL
+SYMD 39SOUNDG30V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;
+**** 0
+0001 501919
+SYMB 10SY01494NIL
+SYMD 39SOUNDG31V009750075000075002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU350,700;PD425,625;PD425,875;
+**** 0
+0001 501920
+SYMB 10SY01495NIL
+SYMD 39SOUNDG32V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU350,650;PD375,625;PD450,625;PD475,650;PD475,700;PD350,825;PD350,850;PD350,875;PD475,875;
+**** 0
+0001 501921
+SYMB 10SY01496NIL
+SYMD 39SOUNDG33V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU450,731;PD375,731;PU450,731;PD475,756;PD475,850;PD450,875;PD375,875;PD350,850;PU375,625;PD450,625;PD475,650;
+SVCT 41PD475,706;PD450,731;PU350,650;PD375,625;
+**** 0
+0001 501922
+SYMB 10SY02112NIL
+SYMD 39SOUNDG34V014220075000155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501923
+SYMB 10SY01498NIL
+SYMD 39SOUNDG35V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU475,625;PD350,625;PD350,731;PD450,731;PD475,756;PD475,850;PD450,875;PD375,875;PD350,850;
+**** 0
+0001 501924
+SYMB 10SY01499NIL
+SYMD 39SOUNDG36V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU450,625;PD375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,753;PD450,728;PD375,728;PD350,753;
+SVCT 21PU450,625;PD462,637;
+**** 0
+0001 501925
+SYMB 10SY01500NIL
+SYMD 39SOUNDG37V009750075000125002500035000650
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU350,650;PD475,650;PD400,800;PD400,900;
+**** 0
+0001 501926
+SYMB 10SY01501NIL
+SYMD 39SOUNDG38V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU450,625;PD375,625;PD350,650;PD350,725;PD375,750;PD450,750;PD475,725;PD475,650;PD450,625;PU375,750;PD350,775;
+SVCT 61PD350,850;PD375,875;PD450,875;PD475,850;PD475,775;PD450,750;
+**** 0
+0001 501927
+SYMB 10SY01502NIL
+SYMD 39SOUNDG39V009750075000125002500035000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;PD350,650;PD350,734;PD375,759;PD450,759;
+SVCT 11PD475,734;
+**** 0
+0001 501928
+SYMB 10SY01503NIL
+SYMD 39SOUNDG40V007500075000125002500102500625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 108SPY;SW1;PU1050,625;PD1125,625;PD1150,650;PD1150,850;PD1125,875;PD1050,875;PD1025,850;PD1025,650;PD1050,625;
+**** 0
+0001 501929
+SYMB 10SY01504NIL
+SYMD 39SOUNDG41V005250075000075002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU800,700;PD875,625;PD875,875;
+**** 0
+0001 501930
+SYMB 10SY01505NIL
+SYMD 39SOUNDG42V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501931
+SYMB 10SY01506NIL
+SYMD 39SOUNDG43V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,734;PD825,734;PU900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;PU828,625;PD900,625;PD925,650;
+SVCT 41PD925,709;PD900,734;PU803,650;PD828,625;
+**** 0
+0001 501932
+SYMB 10SY02113NIL
+SYMD 39SOUNDG44V005250075000155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501933
+SYMB 10SY01508NIL
+SYMD 39SOUNDG45V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU925,625;PD800,625;PD800,734;PD900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501934
+SYMB 10SY01509NIL
+SYMD 39SOUNDG46V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,756;PD900,731;PD825,731;PD800,756;
+SVCT 21PU900,625;PD915,640;
+**** 0
+0001 501935
+SYMB 10SY01510NIL
+SYMD 39SOUNDG47V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501936
+SYMB 10SY01511NIL
+SYMD 39SOUNDG48V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501937
+SYMB 10SY01512NIL
+SYMD 39SOUNDG49V005250075000125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,737;PD825,762;PD900,762;
+SVCT 11PD925,737;
+**** 0
+0001 501938
+SYMB 10SY01513NIL
+SYMD 39SOUNDG50V007500075000125002500080000750
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 101SPY;SW1;PU825,750;PD900,750;PD925,775;PD925,975;PD900,1000;PD825,1000;PD800,975;PD800,775;PD825,750;
+**** 0
+0001 501939
+SYMB 10SY01514NIL
+SYMD 39SOUNDG51V007500062500075002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 39SPY;SW1;PU800,700;PD875,625;PD875,875;
+**** 0
+0001 501940
+SYMB 10SY01515NIL
+SYMD 39SOUNDG52V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501941
+SYMB 10SY01516NIL
+SYMD 39SOUNDG53V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,734;PD825,734;PU900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;PU828,625;PD900,625;PD925,650;
+SVCT 41PD925,709;PD900,734;PU803,650;PD828,625;
+**** 0
+0001 501942
+SYMB 10SY02114NIL
+SYMD 39SOUNDG54V007490062500155002980079900600
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6ASNDG1
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501943
+SYMB 10SY01518NIL
+SYMD 39SOUNDG55V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 99SPY;SW1;PU925,625;PD800,625;PD800,734;PD900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501944
+SYMB 10SY01519NIL
+SYMD 39SOUNDG56V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,756;PD900,731;PD825,731;PD800,756;
+SVCT 21PU900,625;PD915,640;
+**** 0
+0001 501945
+SYMB 10SY01520NIL
+SYMD 39SOUNDG57V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 49SPY;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501946
+SYMB 10SY01521NIL
+SYMD 39SOUNDG58V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501947
+SYMB 10SY01522NIL
+SYMD 39SOUNDG59V007500062500125002500080000625
+SXPO 46for deep soundings, greater than safety depth
+SCRF 6YSNDG1
+SVCT 119SPY;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,737;PD825,762;PD900,762;
+SVCT 11PD925,737;
+**** 0
+0001 501948
+SYMB 10SY01524NIL
+SYMD 39SOUNDGB1V007500075000631001310034000928
+SXPO 77symbol for swept sounding, used for deep soundings greater than safety depth
+SCRF 6YSNDG1
+SVCT 51SPY;SW1;PU340,928;PD340,1059;PD971,1059;PD971,928;
+**** 0
+0001 501949
+SYMB 10SY03422NIL
+SYMD 39SOUNDGC2V073500154600854008540692301119
+SXPO 25sounding of low accuracy
+SCRF 6ASNDG1
+SVCT 27SPA;SW1;PU7350,1546;CI427;
+**** 0
+0001 501950
+SYMB 10SY01526NIL
+SYMD 39SOUNDS00V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;
+**** 0
+0001 501951
+SYMB 10SY01527NIL
+SYMD 39SOUNDS01V007500075000075002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 39SPZ;SW1;PU800,700;PD875,625;PD875,875;
+**** 0
+0001 501952
+SYMB 10SY01528NIL
+SYMD 39SOUNDS02V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU800,650;PD825,625;PD900,625;PD925,650;PD925,700;PD800,825;PD800,850;PD800,875;PD925,875;
+**** 0
+0001 501953
+SYMB 10SY01529NIL
+SYMD 39SOUNDS03V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU900,734;PD825,734;PU900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;PU828,625;PD900,625;PD925,650;
+SVCT 41PD925,709;PD900,734;PU803,650;PD828,625;
+**** 0
+0001 501954
+SYMB 10SY02115NIL
+SYMD 39SOUNDS04V007500075000155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501955
+SYMB 10SY01531NIL
+SYMD 39SOUNDS05V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU925,625;PD800,625;PD800,734;PD900,734;PD925,759;PD925,850;PD900,875;PD825,875;PD800,850;
+**** 0
+0001 501956
+SYMB 10SY01532NIL
+SYMD 39SOUNDS06V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU900,625;PD825,625;PD800,650;PD800,850;PD825,875;PD900,875;PD925,850;PD925,756;PD900,731;PD825,731;PD800,756;
+SVCT 21PU900,625;PD915,640;
+**** 0
+0001 501957
+SYMB 10SY01533NIL
+SYMD 39SOUNDS07V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 49SPZ;SW1;PU800,625;PD925,625;PD850,775;PD850,875;
+**** 0
+0001 501958
+SYMB 10SY01534NIL
+SYMD 39SOUNDS08V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU900,625;PD825,625;PD800,650;PD800,725;PD825,750;PD900,750;PD925,725;PD925,650;PD900,625;PU825,750;PD800,775;
+SVCT 61PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;
+**** 0
+0001 501959
+SYMB 10SY01535NIL
+SYMD 39SOUNDS09V007500075000125002500080000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU800,850;PD825,875;PD900,875;PD925,850;PD925,650;PD900,625;PD825,625;PD800,650;PD800,737;PD825,762;PD900,762;
+SVCT 11PD925,737;
+**** 0
+0001 501960
+SYMB 10SY01536NIL
+SYMD 39SOUNDS10V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU600,625;PD575,650;PD575,850;PD600,875;PD675,875;PD700,850;PD700,650;PU675,625;PD600,625;PU700,650;PD675,625;
+**** 0
+0001 501961
+SYMB 10SY01537NIL
+SYMD 39SOUNDS11V007500075000075002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 39SPZ;SW1;PU575,700;PD650,625;PD650,875;
+**** 0
+0001 501962
+SYMB 10SY01538NIL
+SYMD 39SOUNDS12V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU575,650;PD600,625;PD675,625;PD700,650;PD700,700;PD575,825;PD575,850;PD575,875;PD700,875;
+**** 0
+0001 501963
+SYMB 10SY01539NIL
+SYMD 39SOUNDS13V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU675,731;PD600,731;PU675,731;PD700,756;PD700,850;PD675,875;PD600,875;PD575,850;PU600,625;PD675,625;PD700,650;
+SVCT 41PD700,706;PD675,731;PU575,650;PD600,625;
+**** 0
+0001 501964
+SYMB 10SY02116NIL
+SYMD 39SOUNDS14V009740075000155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501965
+SYMB 10SY01541NIL
+SYMD 39SOUNDS15V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU700,625;PD575,625;PD575,731;PD675,731;PD700,756;PD700,850;PD675,875;PD600,875;PD575,850;
+**** 0
+0001 501966
+SYMB 10SY01542NIL
+SYMD 39SOUNDS16V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU675,625;PD600,625;PD575,650;PD575,850;PD600,875;PD675,875;PD700,850;PD700,753;PD675,728;PD600,728;PD575,753;
+SVCT 21PU675,625;PD687,637;
+**** 0
+0001 501967
+SYMB 10SY01543NIL
+SYMD 39SOUNDS17V007500075000125002500057500650
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 49SPZ;SW1;PU575,650;PD700,650;PD625,800;PD625,900;
+**** 0
+0001 501968
+SYMB 10SY01544NIL
+SYMD 39SOUNDS18V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU675,625;PD600,625;PD575,650;PD575,725;PD600,750;PD675,750;PD700,725;PD700,650;PD675,625;PU600,750;PD575,775;
+SVCT 61PD575,850;PD600,875;PD675,875;PD700,850;PD700,775;PD675,750;
+**** 0
+0001 501969
+SYMB 10SY01545NIL
+SYMD 39SOUNDS19V007500075000125002500057500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU575,850;PD600,875;PD675,875;PD700,850;PD700,650;PD675,625;PD600,625;PD575,650;PD575,734;PD600,759;PD675,759;
+SVCT 11PD700,734;
+**** 0
+0001 501970
+SYMB 10SY01546NIL
+SYMD 39SOUNDS20V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;
+**** 0
+0001 501971
+SYMB 10SY01547NIL
+SYMD 39SOUNDS21V007500075000075002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 39SPZ;SW1;PU350,700;PD425,625;PD425,875;
+**** 0
+0001 501972
+SYMB 10SY01548NIL
+SYMD 39SOUNDS22V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU350,650;PD375,625;PD450,625;PD475,650;PD475,700;PD350,825;PD350,850;PD350,875;PD475,875;
+**** 0
+0001 501973
+SYMB 10SY01549NIL
+SYMD 39SOUNDS23V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU450,731;PD375,731;PU450,731;PD475,756;PD475,850;PD450,875;PD375,875;PD350,850;PU375,625;PD450,625;PD475,650;
+SVCT 41PD475,706;PD450,731;PU350,650;PD375,625;
+**** 0
+0001 501974
+SYMB 10SY02117NIL
+SYMD 39SOUNDS24V011990075000155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501975
+SYMB 10SY01551NIL
+SYMD 39SOUNDS25V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU475,625;PD350,625;PD350,731;PD450,731;PD475,756;PD475,850;PD450,875;PD375,875;PD350,850;
+**** 0
+0001 501976
+SYMB 10SY01552NIL
+SYMD 39SOUNDS26V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU450,625;PD375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,753;PD450,728;PD375,728;PD350,753;
+SVCT 21PU450,625;PD462,637;
+**** 0
+0001 501977
+SYMB 10SY01553NIL
+SYMD 39SOUNDS27V007500075000125002500035000650
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 49SPZ;SW1;PU350,650;PD475,650;PD400,800;PD400,900;
+**** 0
+0001 501978
+SYMB 10SY01554NIL
+SYMD 39SOUNDS28V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU450,625;PD375,625;PD350,650;PD350,725;PD375,750;PD450,750;PD475,725;PD475,650;PD450,625;PU375,750;PD350,775;
+SVCT 61PD350,850;PD375,875;PD450,875;PD475,850;PD475,775;PD450,750;
+**** 0
+0001 501979
+SYMB 10SY01555NIL
+SYMD 39SOUNDS29V007500075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;PD350,650;PD350,734;PD375,759;PD450,759;
+SVCT 11PD475,734;
+**** 0
+0001 501980
+SYMB 10SY01556NIL
+SYMD 39SOUNDS30V009750075000125002500035000625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU375,625;PD350,650;PD350,850;PD375,875;PD450,875;PD475,850;PD475,650;PD450,625;PD375,625;
+**** 0
+0001 501981
+SYMB 10SY01557NIL
+SYMD 39SOUNDS31V007500075000075002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 39SPZ;SW1;PU125,700;PD200,625;PD200,875;
+**** 0
+0001 501982
+SYMB 10SY01558NIL
+SYMD 39SOUNDS32V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU125,650;PD150,625;PD225,625;PD250,650;PD250,700;PD125,825;PD125,850;PD125,875;PD250,875;
+**** 0
+0001 501983
+SYMB 10SY01559NIL
+SYMD 39SOUNDS33V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU225,728;PD150,728;PU225,728;PD250,753;PD250,850;PD225,875;PD150,875;PD125,850;PU150,625;PD225,625;PD250,650;
+SVCT 41PD250,703;PD225,728;PU125,650;PD150,625;
+**** 0
+0001 501984
+SYMB 10SY03006NIL
+SYMD 39SOUNDS34V014220075000155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501985
+SYMB 10SY01561NIL
+SYMD 39SOUNDS35V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 99SPZ;SW1;PU250,625;PD125,625;PD125,728;PD225,728;PD250,753;PD250,850;PD225,875;PD150,875;PD125,850;
+**** 0
+0001 501986
+SYMB 10SY01562NIL
+SYMD 39SOUNDS36V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU225,625;PD150,625;PD125,650;PD125,850;PD150,875;PD225,875;PD250,850;PD250,750;PD225,725;PD150,725;PD125,750;
+SVCT 21PU225,625;PD234,634;
+**** 0
+0001 501987
+SYMB 10SY01563NIL
+SYMD 39SOUNDS37V007500075000125002500012500650
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 49SPZ;SW1;PU125,650;PD250,650;PD175,800;PD175,900;
+**** 0
+0001 501988
+SYMB 10SY01564NIL
+SYMD 39SOUNDS38V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU225,625;PD150,625;PD125,650;PD125,725;PD150,750;PD225,750;PD250,725;PD250,650;PD225,625;PU150,750;PD125,775;
+SVCT 61PD125,850;PD150,875;PD225,875;PD250,850;PD250,775;PD225,750;
+**** 0
+0001 501989
+SYMB 10SY01565NIL
+SYMD 39SOUNDS39V007500075000125002500012500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU125,850;PD150,875;PD225,875;PD250,850;PD250,650;PD225,625;PD150,625;PD125,650;PD125,731;PD150,756;PD225,756;
+SVCT 11PD250,731;
+**** 0
+0001 501990
+SYMB 10SY01566NIL
+SYMD 39SOUNDS40V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 108SPZ;SW1;PU1050,625;PD1125,625;PD1150,650;PD1150,850;PD1125,875;PD1050,875;PD1025,850;PD1025,650;PD1050,625;
+**** 0
+0001 501991
+SYMB 10SY01567NIL
+SYMD 39SOUNDS41V007500075000075002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 42SPZ;SW1;PU1025,700;PD1100,625;PD1100,875;
+**** 0
+0001 501992
+SYMB 10SY01568NIL
+SYMD 39SOUNDS42V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 108SPZ;SW1;PU1025,650;PD1050,625;PD1125,625;PD1150,650;PD1150,700;PD1025,825;PD1025,850;PD1025,875;PD1150,875;
+**** 0
+0001 501993
+SYMB 10SY01569NIL
+SYMD 39SOUNDS43V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU1125,731;PD1050,731;PU1125,731;PD1150,756;PD1150,850;PD1125,875;PD1050,875;PD1025,850;PU1050,625;PD1125,625;
+SVCT 56PD1150,650;PD1150,706;PD1125,731;PU1025,650;PD1050,625;
+**** 0
+0001 501994
+SYMB 10SY02119NIL
+SYMD 39SOUNDS44V005250075000155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 501995
+SYMB 10SY01571NIL
+SYMD 39SOUNDS45V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 108SPZ;SW1;PU1150,625;PD1025,625;PD1025,731;PD1125,731;PD1150,756;PD1150,850;PD1125,875;PD1050,875;PD1025,850;
+**** 0
+0001 501996
+SYMB 10SY01572NIL
+SYMD 39SOUNDS46V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU1125,625;PD1050,625;PD1025,650;PD1025,850;PD1050,875;PD1125,875;PD1150,850;PD1150,753;PD1125,728;PD1050,728;
+SVCT 34PD1025,753;PU1125,625;PD1137,637;
+**** 0
+0001 501997
+SYMB 10SY02260NIL
+SYMD 39SOUNDS47V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 53SPZ;SW1;PU1025,625;PD1150,625;PD1075,775;PD1075,875;
+**** 0
+0001 501998
+SYMB 10SY01574NIL
+SYMD 39SOUNDS48V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU1125,625;PD1050,625;PD1025,650;PD1025,725;PD1050,750;PD1125,750;PD1150,725;PD1150,650;PD1125,625;PU1050,750;
+SVCT 78PD1025,775;PD1025,850;PD1050,875;PD1125,875;PD1150,850;PD1150,775;PD1125,750;
+**** 0
+0001 501999
+SYMB 10SY01575NIL
+SYMD 39SOUNDS49V007500075000125002500102500625
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU1025,850;PD1050,875;PD1125,875;PD1150,850;PD1150,650;PD1125,625;PD1050,625;PD1025,650;PD1025,734;PD1050,759;
+SVCT 23PD1125,759;PD1150,734;
+**** 0
+0001 502000
+SYMB 10SY01576NIL
+SYMD 39SOUNDS50V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 101SPZ;SW1;PU825,750;PD900,750;PD925,775;PD925,975;PD900,1000;PD825,1000;PD800,975;PD800,775;PD825,750;
+**** 0
+0001 502001
+SYMB 10SY01577NIL
+SYMD 39SOUNDS51V007500075000075002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 40SPZ;SW1;PU800,825;PD875,750;PD875,1000;
+**** 0
+0001 502002
+SYMB 10SY01578NIL
+SYMD 39SOUNDS52V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 101SPZ;SW1;PU800,775;PD825,750;PD900,750;PD925,775;PD925,825;PD800,950;PD800,975;PD800,1000;PD925,1000;
+**** 0
+0001 502003
+SYMB 10SY01579NIL
+SYMD 39SOUNDS53V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 121SPZ;SW1;PU900,856;PD825,856;PU900,856;PD925,881;PD925,975;PD900,1000;PD825,1000;PD800,975;PU825,750;PD900,750;PD925,775;
+SVCT 41PD925,831;PD900,856;PU800,775;PD825,750;
+**** 0
+0001 502004
+SYMB 10SY02120NIL
+SYMD 39SOUNDS54V007490062500155002980079900600
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ASNDG2
+SVCT 49SPA;SW1;PU925,898;PD925,600;PD799,774;PD954,774;
+**** 0
+0001 502005
+SYMB 10SY01581NIL
+SYMD 39SOUNDS55V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 101SPZ;SW1;PU925,750;PD800,750;PD800,856;PD900,856;PD925,881;PD925,975;PD900,1000;PD825,1000;PD800,975;
+**** 0
+0001 502006
+SYMB 10SY01582NIL
+SYMD 39SOUNDS56V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 121SPZ;SW1;PU900,750;PD825,750;PD800,775;PD800,975;PD825,1000;PD900,1000;PD925,975;PD925,878;PD900,853;PD825,853;PD800,878;
+SVCT 21PU900,750;PD912,762;
+**** 0
+0001 502007
+SYMB 10SY01583NIL
+SYMD 39SOUNDS57V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 50SPZ;SW1;PU800,750;PD925,750;PD850,900;PD850,1000;
+**** 0
+0001 502008
+SYMB 10SY01584NIL
+SYMD 39SOUNDS58V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 119SPZ;SW1;PU900,750;PD825,750;PD800,775;PD800,850;PD825,875;PD900,875;PD925,850;PD925,775;PD900,750;PU825,875;PD800,900;
+SVCT 63PD800,975;PD825,1000;PD900,1000;PD925,975;PD925,900;PD900,875;
+**** 0
+0001 502009
+SYMB 10SY01585NIL
+SYMD 39SOUNDS59V007500075000125002500080000750
+SXPO 58shallow soundings, less than or equal to the safety depth
+SCRF 6ZSNDG2
+SVCT 121SPZ;SW1;PU800,975;PD825,1000;PD900,1000;PD925,975;PD925,775;PD900,750;PD825,750;PD800,775;PD800,859;PD825,884;PD900,884;
+SVCT 11PD925,859;
+**** 0
+0001 502010
+SYMB 10SY01586NIL
+SYMD 39SOUNDSA1V007500075000205000010052500970
+SXPO 89symbol for drying height, used for shallow soundings, less than or equal to safety depth
+SCRF 6ZSNDG2
+SVCT 29SPZ;SW1;PU525,970;PD730,970;
+**** 0
+0001 502011
+SYMB 10SY01587NIL
+SYMD 39SOUNDSB1V007500075000631001310034000928
+SXPO 90symbol for swept sounding, used for shallow soundings, less than or equal to safety depth
+SCRF 6ZSNDG2
+SVCT 51SPZ;SW1;PU340,928;PD340,1059;PD971,1059;PD971,928;
+**** 0
+0001 502012
+SYMB 10SY03423NIL
+SYMD 39SOUNDSC2V073500154600854008540692301119
+SXPO 25sounding of low accuracy
+SCRF 6ASNDG1
+SVCT 27SPA;SW1;PU7350,1546;CI427;
+**** 0
+0001 502013
+SYMB 10SY01589NIL
+SYMD 39SPRING02V015000150000300003500135001150
+SXPO 7spring
+SCRF 6ECHGRD
+SVCT 114SPE;SW3;PU1500,1500;PD;PU1550,1500;PD;PU1600,1500;PD;PU1450,1500;PD;PU1400,1500;PD;PU1500,1450;PD;PU1500,1400;PD;
+SVCT 121PU1500,1350;PD;PU1500,1300;PD;PU1500,1250;PD;PU1500,1200;PD;PU1550,1150;PD;PU1600,1150;PD;PU1650,1200;PD;PU1650,1250;PD;
+SVCT 61PU1450,1150;PD;PU1400,1150;PD;PU1350,1200;PD;PU1350,1250;PD;
+**** 0
+0001 502014
+SYMB 10SY03410NIL
+SYMD 39SWPARE51V006510117701101003040009100869
+SXPO 11swept area
+SCRF 6ACHGRF
+SVCT 51SPA;SW3;PU91,872;PD91,1173;PD1192,1173;PD1192,869;
+**** 0
+0001 502015
+SYMB 10SY02262NIL
+SYMD 39TIDCUR01V016360228700408014850143501667
+SXPO 44predicted tidal stream or current direction
+SCRF 6ANINFO
+SVCT 45SPA;SW1;PU1442,2172;PD1638,1972;PD1840,2175;
+SVCT 45SPA;SW1;PU1438,2474;PD1638,2275;PD1840,2474;
+SVCT 33SPA;SW1;PU1638,1683;PD1638,1879;
+SVCT 33SPA;SW1;PU1638,1976;PD1638,2168;
+SVCT 33SPA;SW1;PU1638,2275;PD1638,2477;
+SVCT 45SPA;SW1;PU1435,1866;PD1638,1667;PD1843,1876;
+SVCT 33SPA;SW1;PU1637,2952;PD1638,3152;
+SVCT 33SPA;SW1;PU1637,2619;PD1638,2819;
+**** 0
+0001 502016
+SYMB 10SY01591NIL
+SYMD 39TIDCUR02V022500225000403012000204301650
+SXPO 41actual tidal stream or current direction
+SCRF 6fNINFO
+SVCT 117SPf;SW1;PU2343,1650;PD2343,1650;PU2250,1650;PD2250,2850;PU2250,1650;PD2043,1846;PU2250,1650;PD2446,1846;PU2250,2146;
+SVCT 85PD2043,2343;PU2250,2146;PD2446,2343;PU2250,1884;PD2043,2090;PU2250,1893;PD2446,2100;
+**** 0
+0001 502017
+SYMB 10SY01592NIL
+SYMD 39TIDCUR03V022500225000815004680118102803
+SXPO 25box for current strength
+SCRF 6fNINFO
+SVCT 105SPf;SW1;PU1181,2803;PD1996,2803;PU1181,3271;PD1996,3271;PU1996,2803;PD1996,3271;PU1181,2803;PD1181,3271;
+**** 0
+0001 502018
+SYMB 10SY03188NIL
+SYMD 39TIDEHT01V007070075000884003360031100581
+SXPO 53point for which tide height information is available
+SCRF 6ACHGRD
+SVCT 30SPA;SW1;PU311,749;PD1195,749;
+SVCT 364SPA;SW1;PU383,748;PD383,724;PD390,693;PD405,660;PD427,632;PD456,610;PD490,594;PD523,583;PD554,581;PD587,588;PD617,598;PD645,615;PD668,634;PD690,666;PD707,704;PD707,733;PD707,748;PD707,774;PD712,803;PD719,826;PD734,855;PD764,880;PD776,890;PD793,900;PD813,909;PD844,915;PD879,917;PD918,909;PD947,896;PD980,875;PD1004,851;PD1023,817;PD1034,785;PD1039,768;PD1039,748;
+**** 0
+0001 502019
+SYMB 10SY03136NIL
+SYMD 39TIDSTR01V007410074700566005600046100466
+SXPO 58point or area for which a tidal stream table is available
+SCRF 6ACHGRD
+SVCT 61SPA;SW1;PU461,749;PD744,466;PD1027,749;PD742,1026;PD461,749;
+**** 0
+0001 502020
+SYMB 10SY03106NIL
+SYMD 39TMARDEF1V014320159800000003470142400661
+SXPO 54topmark for beacons, flag or other shape, paper-chart
+SCRF 6ACHBLK
+SVCT 32SPA;SW2;PU1424,1008;PD1424,661;
+**** 0
+0001 502021
+SYMB 10SY03107NIL
+SYMD 39TMARDEF2V015070160300136003640157400737
+SXPO 52topmark for buoys, flag or other shape, paper-chart
+SCRF 6ACHBLK
+SVCT 32SPA;SW2;PU1574,1101;PD1710,737;
+**** 0
+0001 502022
+SYMB 10SY01347NIL
+SYMD 39TMBYRD01V007500075000400004000055000550
+SXPO 12timber yard
+SCRF 6WLANDF
+SVCT 89SPW;SW2;PU550,650;PD950,650;PU550,850;PD950,850;PU650,550;PD650,950;PU850,550;PD850,950;
+**** 0
+0001 502023
+SYMB 10SY02121NIL
+SYMD 39TNKCON02V014980149800284002840135601357
+SXPO 5tank
+SCRF 6ALANDF
+SVCT 27SPA;SW2;PU1498,1499;CI142;
+**** 0
+0001 502024
+SYMB 10SY02122NIL
+SYMD 39TNKCON12V014980149800284002840135601357
+SXPO 17conspicuous tank
+SCRF 6ACHBLK
+SVCT 27SPA;SW2;PU1498,1499;CI142;
+**** 0
+0001 502025
+SYMB 10SY03168NIL
+SYMD 39TNKFRM01V011270168500766007660073701285
+SXPO 10tank farm
+SCRF 6ALANDF
+SVCT 41SPA;SW1;ST0;PU1016,1574;PM0;CI97;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1018,1800;PM0;CI97;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1232,1794;PM0;CI90;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1237,1576;PM0;CI97;PM2;FP;
+SVCT 27SPA;SW1;PU1120,1668;CI383;
+**** 0
+0001 502026
+SYMB 10SY03170NIL
+SYMD 39TNKFRM11V011320169000766007660074001285
+SXPO 22conspicuous tank farm
+SCRF 6ACHBLK
+SVCT 41SPA;SW1;ST0;PU1019,1574;PM0;CI97;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1021,1800;PM0;CI97;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1235,1794;PM0;CI90;PM2;FP;
+SVCT 41SPA;SW1;ST0;PU1240,1576;PM0;CI97;PM2;FP;
+SVCT 27SPA;SW1;PU1123,1668;CI383;
+**** 0
+0001 502027
+SYMB 10SY01595NIL
+SYMD 39TOPMAR02V015100146000210001650152000785
+SXPO 46topmark for buoys, cone point up, paper-chart
+SCRF 6CCHBLK
+SVCT 60SPC;ST0;PU1665,785;PM0;PD1520,950,1730,950,1665,785;PM2;FP;
+**** 0
+0001 502028
+SYMB 10SY01596NIL
+SYMD 39TOPMAR04V015150147000220001550156000785
+SXPO 48topmark for buoys, cone point down, paper-chart
+SCRF 6CCHBLK
+SVCT 60SPC;ST0;PU1560,785;PM0;PD1780,785,1620,940,1560,785;PM2;FP;
+**** 0
+0001 502029
+SYMB 10SY01597NIL
+SYMD 39TOPMAR05V015050147000275004050151500545
+SXPO 53topmark for buoys, 2 cones point upward, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1665,770;PM0;PD1515,950,1750,950,1665,770;PM2;FP;PU1715,545;PM0;PD1565,730,1790,730,1715,545;PM2;FP;
+**** 0
+0001 502030
+SYMB 10SY01598NIL
+SYMD 39TOPMAR06V015100147000280003700155500565
+SXPO 55topmark for buoys, 2 cones point downward, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1555,775;PM0;PD1790,775,1615,935,1555,775;PM2;FP;PU1600,565;PM0;PD1835,565,1665,725,1600,565;PM2;FP;
+**** 0
+0001 502031
+SYMB 10SY01599NIL
+SYMD 39TOPMAR07V015050147000240003950155000555
+SXPO 53topmark for buoys, 2 cones base to base, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1550,785;PM0;PD1785,785,1615,950,1550,785;PM2;FP;PU1700,555;PM0;PD1570,730,1790,730,1700,555;PM2;FP;
+**** 0
+0001 502032
+SYMB 10SY01600NIL
+SYMD 39TOPMAR08V015050147000330003850151000565
+SXPO 55topmark for buoys, 2 cones point to point, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1665,770;PM0;PD1510,950,1750,950,1665,770;PM2;FP;PU1595,565;PM0;PD1840,565,1670,730,1595,565;PM2;FP;
+**** 0
+0001 502033
+SYMB 10SY01601NIL
+SYMD 39TOPMAR10V015150147000180001800155000775
+SXPO 39topmark for buoys, sphere, paper-chart
+SCRF 6CCHBLK
+SVCT 36SPC;PU1640,865;ST0;PM0;CI90;PM2;FP;
+**** 0
+0001 502034
+SYMB 10SY01602NIL
+SYMD 39TOPMAR12V015100147000220004000155000555
+SXPO 42topmark for buoys, 2 spheres, paper-chart
+SCRF 6CCHBLK
+SVCT 63SPC;PU1640,865;ST0;PM0;CI90;PM2;FP;PU1680,645;PM0;CI90;PM2;FP;
+**** 0
+0001 502035
+SYMB 10SY01603NIL
+SYMD 39TOPMAR13V015050147500215002200153500730
+SXPO 41topmark for buoys, cylinder, paper-chart
+SCRF 6CCHBLK
+SVCT 64SPC;SW2;PU1535,950;PD1685,950;PD1750,730;PD1590,730;PD1535,950;
+**** 0
+0001 502036
+SYMB 10SY01604NIL
+SYMD 39TOPMAR14V015000148000240001400151000810
+SXPO 38topmark for buoys, board, paper-chart
+SCRF 6CCHBLK
+SVCT 64SPC;SW2;PU1510,950;PD1720,950;PD1750,810;PD1540,810;PD1510,950;
+**** 0
+0001 502037
+SYMB 10SY01606NIL
+SYMD 39TOPMAR16V015000147000205001950153000765
+SXPO 46topmark for buoys, cube point up, paper-chart
+SCRF 6CCHBLK
+SVCT 75SPC;SW2;PU1530,840;PD1610,960;PD1735,885;PD1660,765;PU1530,840;PD1655,765;
+**** 0
+0001 502038
+SYMB 10SY03108NIL
+SYMD 39TOPMAR17V015070160300421002630142200843
+SXPO 52topmark for buoys, flag or other shape, paper-chart
+SCRF 6ACHBLK
+SVCT 31SPA;SW2;PU1422,961;PD1843,961;
+SVCT 32SPA;SW2;PU1670,843;PD1574,1106;
+**** 0
+0001 502039
+SYMB 10SY03383NIL
+SYMD 39TOPMAR18V015070160300421002630145500843
+SXPO 40topmark for buoys, T-Shape, paper-chart
+SCRF 6ACHBLK
+SVCT 31SPA;SW2;PU1455,844;PD1876,844;
+SVCT 32SPA;SW2;PU1670,843;PD1574,1106;
+**** 0
+0001 502040
+SYMB 10SY01607NIL
+SYMD 39TOPMAR22V015000147500220001750139000745
+SXPO 48topmark for beacons, cone point up, paper-chart
+SCRF 6CCHBLK
+SVCT 60SPC;ST0;PU1500,745;PM0;PD1390,920,1610,920,1500,745;PM2;FP;
+**** 0
+0001 502041
+SYMB 10SY01608NIL
+SYMD 39TOPMAR24V015000147000220001700139000750
+SXPO 50topmark for beacons, cone point down, paper-chart
+SCRF 6CCHBLK
+SVCT 60SPC;ST0;PU1390,750;PM0;PD1610,750,1500,920,1390,750;PM2;FP;
+**** 0
+0001 502042
+SYMB 10SY01609NIL
+SYMD 39TOPMAR25V015000147000220003950139000525
+SXPO 55topmark for beacons, 2 cones point upward, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1500,525;PM0;PD1390,700,1610,700,1500,525;PM2;FP;PU1500,745;PM0;PD1390,920,1610,920,1500,745;PM2;FP;
+**** 0
+0001 502043
+SYMB 10SY01610NIL
+SYMD 39TOPMAR26V015000146000220003900139000530
+SXPO 57topmark for beacons, 2 cones point downward, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1390,750;PM0;PD1610,750,1500,920,1390,750;PM2;FP;PU1390,530;PM0;PD1610,530,1500,700,1390,530;PM2;FP;
+**** 0
+0001 502044
+SYMB 10SY01611NIL
+SYMD 39TOPMAR27V015000147500220003950139000525
+SXPO 55topmark for beacons, 2 cones base to base, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1500,525;PM0;PD1390,700,1610,700,1500,525;PM2;FP;PU1390,750;PM0;PD1610,750,1500,920,1390,750;PM2;FP;
+**** 0
+0001 502045
+SYMB 10SY01612NIL
+SYMD 39TOPMAR28V015000147000220003900139000530
+SXPO 57topmark for beacons, 2 cones point to point, paper-chart
+SCRF 6CCHBLK
+SVCT 111SPC;ST0;PU1390,530;PM0;PD1610,530,1500,700,1390,530;PM2;FP;PU1500,745;PM0;PD1390,920,1610,920,1500,745;PM2;FP;
+**** 0
+0001 502046
+SYMB 10SY01613NIL
+SYMD 39TOPMAR30V015000148000220002200139000730
+SXPO 41topmark for beacons, sphere, paper-chart
+SCRF 6CCHBLK
+SVCT 37SPC;PU1500,840;ST0;PM0;CI110;PM2;FP;
+**** 0
+0001 502047
+SYMB 10SY01614NIL
+SYMD 39TOPMAR32V015000147000220004950139000455
+SXPO 44topmark for beacons, 2 spheres, paper-chart
+SCRF 6CCHBLK
+SVCT 65SPC;PU1500,565;ST0;PM0;CI110;PM2;FP;PU1500,840;PM0;CI110;PM2;FP;
+**** 0
+0001 502048
+SYMB 10SY01615NIL
+SYMD 39TOPMAR33V015000147500150002450142500675
+SXPO 43topmark for beacons, cylinder, paper-chart
+SCRF 6CCHBLK
+SVCT 64SPC;SW2;PU1425,920;PD1575,920;PD1575,675;PD1425,675;PD1425,920;
+**** 0
+0001 502049
+SYMB 10SY01616NIL
+SYMD 39TOPMAR34V015000148500240001350138000785
+SXPO 40topmark for beacons, board, paper-chart
+SCRF 6CCHBLK
+SVCT 64SPC;SW2;PU1380,920;PD1380,785;PD1620,785;PD1620,920;PD1380,920;
+**** 0
+0001 502050
+SYMB 10SY01618NIL
+SYMD 39TOPMAR36V015000147500255002550137000700
+SXPO 48topmark for beacons, cube point up, paper-chart
+SCRF 6CCHBLK
+SVCT 64SPC;SW2;PU1500,700;PD1370,830;PD1500,955;PD1625,830;PD1500,700;
+**** 0
+0001 502051
+SYMB 10SY02123NIL
+SYMD 39TOPMAR65V015150147500279002260149500757
+SXPO 40topmark for buoys, x-shape, paper-chart
+SCRF 6ACHBLK
+SVCT 31SPA;SW2;PU1533,757;PD1746,983;
+SVCT 31SPA;SW2;PU1774,793;PD1495,926;
+**** 0
+0001 502052
+SYMB 10SY02124NIL
+SYMD 39TOPMAR85V015000148000220002200139000730
+SXPO 42topmark for beacons, x-shape, paper-chart
+SCRF 6CCHBLK
+SVCT 53SPC;SW2;PU1390,730;PD1610,950;PU1610,730;PD1390,950;
+**** 0
+0001 502053
+SYMB 10SY03110NIL
+SYMD 39TOPMAR86V014360164800420003990121900680
+SXPO 48topmark for beacons, upright cross, paper-chart
+SCRF 6ACHBLK
+SVCT 32SPA;SW2;PU1429,680;PD1429,1079;
+SVCT 31SPA;SW2;PU1219,878;PD1639,878;
+**** 0
+0001 502054
+SYMB 10SY02125NIL
+SYMD 39TOPMAR87V014960154100259003010137200721
+SXPO 51topmark for beacons, besom point down, paper-chart
+SCRF 6ACHBLK
+SVCT 32SPA;SW1;PU1499,722;PD1498,1021;
+SVCT 32SPA;SW1;PU1372,1022;PD1454,721;
+SVCT 32SPA;SW1;PU1631,1021;PD1540,721;
+**** 0
+0001 502055
+SYMB 10SY02126NIL
+SYMD 39TOPMAR88V015030121600258003010137000401
+SXPO 49topmark for beacons, besom point up, paper-chart
+SCRF 6ACHBLK
+SVCT 31SPA;SW1;PU1502,701;PD1503,402;
+SVCT 31SPA;SW1;PU1628,401;PD1546,702;
+SVCT 31SPA;SW1;PU1370,402;PD1461,702;
+**** 0
+0001 502056
+SYMB 10SY03111NIL
+SYMD 39TOPMAR89V014380167200420002800122100799
+SXPO 42topmark for beacons, T-shape, paper-chart
+SCRF 6ACHBLK
+SVCT 31SPA;SW2;PU1221,799;PD1641,799;
+SVCT 32SPA;SW2;PU1429,799;PD1429,1079;
+**** 0
+0001 502057
+SYMB 10SY01621NIL
+SYMD 39TOWERS01V007500075000345006350057700172
+SXPO 6tower
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI57;PU645,750;PD692,172;PD807,172;PD855,750;PU807,750;PD922,750;PU692,750;PD577,750;PU687,282;
+SVCT 11PD807,282;
+**** 0
+0001 502058
+SYMB 10SY01622NIL
+SYMD 39TOWERS02V007500075000300005500060000250
+SXPO 12water tower
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI50;PU650,750;PD693,350;PU850,350;PD850,250;PD650,250;PD650,350;PD850,350;PU600,750;PD700,750;
+SVCT 41PU800,750;PD900,750;PU850,750;PD803,346;
+**** 0
+0001 502059
+SYMB 10SY01623NIL
+SYMD 39TOWERS03V007500075000346006350057500171
+SXPO 18conspicuous tower
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW1;CI56;PU643,750;PD690,171;PD806,171;PD853,750;PU806,750;PD921,750;PU690,750;PD575,750;PU684,281;
+SVCT 11PD806,281;
+**** 0
+0001 502060
+SYMB 10SY02127NIL
+SYMD 39TOWERS05V007000110000300007500055000400
+SXPO 24radio, television tower
+SCRF 6ALANDF
+SVCT 25SPA;SW2;PU700,1100;CI50;
+SVCT 51SPA;SW2;PU600,1100;PD650,600;PD750,600;PD784,1100;
+SVCT 29SPA;SW2;PU634,690;PD750,690;
+SVCT 31SPA;SW2;PU550,1100;PD650,1100;
+SVCT 31SPA;SW2;PU750,1100;PD850,1100;
+SVCT 39SPA;SW2;PU800,400;PD850,450;PD850,600;
+SVCT 39SPA;SW2;PU600,400;PD550,450;PD550,600;
+**** 0
+0001 502061
+SYMB 10SY01625NIL
+SYMD 39TOWERS12V007500075000300005500060000250
+SXPO 24conspicuous water tower
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW1;CI50;PU650,750;PD693,350;PU850,350;PD850,250;PD650,250;PD650,350;PD850,350;PU600,750;PD700,750;
+SVCT 41PU800,750;PD900,750;PU850,750;PD803,346;
+**** 0
+0001 502062
+SYMB 10SY02128NIL
+SYMD 39TOWERS15V007000110000300007500055000400
+SXPO 36conspicuous radio, television tower
+SCRF 6ACHBLK
+SVCT 25SPA;SW2;PU700,1100;CI50;
+SVCT 51SPA;SW2;PU600,1100;PD650,600;PD750,600;PD784,1100;
+SVCT 29SPA;SW2;PU634,690;PD750,690;
+SVCT 31SPA;SW2;PU550,1100;PD650,1100;
+SVCT 31SPA;SW2;PU750,1100;PD850,1100;
+SVCT 39SPA;SW2;PU800,400;PD850,450;PD850,600;
+SVCT 39SPA;SW2;PU600,400;PD550,450;PD550,600;
+**** 0
+0001 502063
+SYMB 10SY02129NIL
+SYMD 39TREPNT04V007500074900362003990057400348
+SXPO 26general symbol for a tree
+SCRF 6ALANDF
+SVCT 29SPA;SW1;PU750,747;PD750,350;
+SVCT 29SPA;SW1;PU574,447;PD936,447;
+SVCT 29SPA;SW1;PU641,545;PD858,545;
+SVCT 29SPA;SW1;PU684,348;PD814,348;
+SVCT 29SPA;SW1;PU695,747;PD815,747;
+SVCT 29SPA;SW1;PU638,396;PD858,396;
+SVCT 29SPA;SW1;PU621,494;PD883,494;
+**** 0
+0001 502064
+SYMB 10SY02130NIL
+SYMD 39TREPNT05V007500075000400003000055000450
+SXPO 9mangrove
+SCRF 6ALANDF
+SVCT 25SPA;SW1;PU750,600;CI150;
+SVCT 29SPA;SW1;PU550,750;PD950,750;
+SVCT 29SPA;SW1;PU750,748;PD750,587;
+**** 0
+0001 502065
+SYMB 10SY03411NIL
+SYMD 39TSLDEF51V022500225001209013500164701500
+SXPO 88one way lane of a traffic separation scheme, with the direction not defined in the data
+SCRF 12ATRFCDCCHMGD
+SVCT 120SPA;SW1;ST3;PU1950,1950;PM0;PD2250,1500;PD2550,1950;PD2400,1950;PD2400,2850;PD2100,2850;PD2100,1950;PD1950,1950;PM2;FP;
+SVCT 105SPA;SW1;PU2100,2850;PD2100,1950;PD1950,1950;PD2250,1500;PD2550,1950;PD2400,1950;PD2400,2850;PD2100,2850;
+SVCT 309SPC;SW1;PU1647,2232;PD1660,2204;PD1673,2179;PD1690,2162;PD1707,2145;PD1733,2136;PD1756,2138;PD1786,2147;PD1814,2153;PD1837,2187;PD1855,2206;PD1867,2228;PD1867,2253;PD1855,2277;PD1842,2298;PD1822,2322;PD1799,2347;PD1778,2373;PD1765,2392;PD1754,2409;PD1752,2431;PD1752,2454;PD1752,2471;PD1754,2493;PD1754,2495;
+SVCT 33SPC;SW2;PU1733,2579;PD1786,2579;
+SVCT 309SPC;SW1;PU2636,2232;PD2649,2204;PD2662,2179;PD2679,2162;PD2696,2145;PD2722,2136;PD2745,2138;PD2775,2147;PD2803,2153;PD2826,2187;PD2844,2206;PD2856,2228;PD2856,2253;PD2844,2277;PD2831,2298;PD2811,2322;PD2788,2347;PD2767,2373;PD2754,2392;PD2743,2409;PD2741,2431;PD2741,2454;PD2741,2471;PD2743,2493;PD2743,2495;
+SVCT 33SPC;SW2;PU2722,2579;PD2775,2579;
+**** 0
+0001 502066
+SYMB 10SY02131NIL
+SYMD 39TSSCRS51V020490119200994009940024801794
+SXPO 22traffic crossing area
+SCRF 6ATRFCF
+SVCT 31SPA;SW3;PU747,2419;PD747,1954;
+SVCT 31SPA;SW2;PU680,2599;PD823,2599;
+SVCT 26SPA;SW2;PU745,2291;CI497;
+**** 0
+0001 502067
+SYMB 10SY01630NIL
+SYMD 39TSSLPT51V022500225000600013500195001500
+SXPO 67traffic direction in a one way lane of a traffic separation scheme
+SCRF 6TTRFCD
+SVCT 120SPT;ST3;PU1950,1950;PM0;PD2250,1500,2550,1950,2400,1950,2400,2850,2100,2850,2100,1950,1950,1950;PM2;FP;SW1;PU2100,2850;
+SVCT 85PD2100,1950;PD1950,1950;PD2250,1500;PD2550,1950;PD2400,1950;PD2400,2850;PD2100,2850;
+**** 0
+0001 502068
+SYMB 10SY03412NIL
+SYMD 39TSSRON51V004480074100895009150000100284
+SXPO 19traffic roundabout
+SCRF 6ATRFCF
+SVCT 269SPA;SW2;PU1,793;PD27,884;PD66,980;PD123,1057;PD212,1124;PD315,1180;PD430,1199;PD522,1194;PD620,1165;PD721,1112;PD800,1031;PD862,925;PD896,812;PD896,688;PD862,560;PD798,452;PD704,373;PD591,313;PD464,294;PD320,313;PD217,364;PD128,424;PD298,594;PD1,594;PD1,284;PD133,424;
+**** 0
+0001 502069
+SYMB 10SY03413NIL
+SYMD 39TWRDEF51V022570207701361014030156801383
+SXPO 89two way route of a traffic separation scheme, with the direction not defined in the data
+SCRF 12ATRFCDICHMGD
+SVCT 45SPA;SW3;PU2134,1545;PD2257,1383;PD2380,1545;
+SVCT 45SPA;SW3;PU2043,1661;PD1960,1777;PD2108,1777;
+SVCT 45SPA;SW3;PU2394,1773;PD2557,1773;PD2463,1650;
+SVCT 33SPA;SW3;PU2105,1965;PD2105,2178;
+SVCT 33SPA;SW3;PU2398,1959;PD2398,2170;
+SVCT 45SPA;SW3;PU2137,2616;PD2260,2786;PD2383,2616;
+SVCT 45SPA;SW3;PU2105,2373;PD1946,2373;PD2040,2493;
+SVCT 45SPA;SW3;PU2401,2373;PD2550,2373;PD2466,2504;
+SVCT 309SPI;SW1;PU1568,1942;PD1581,1914;PD1594,1889;PD1611,1872;PD1628,1855;PD1654,1846;PD1677,1848;PD1707,1857;PD1735,1863;PD1758,1897;PD1776,1916;PD1788,1938;PD1788,1963;PD1776,1987;PD1763,2008;PD1743,2032;PD1720,2057;PD1699,2083;PD1686,2102;PD1675,2119;PD1673,2141;PD1673,2164;PD1673,2181;PD1675,2203;PD1675,2205;
+SVCT 33SPI;SW2;PU1654,2289;PD1707,2289;
+SVCT 309SPI;SW1;PU2709,1939;PD2722,1911;PD2735,1886;PD2752,1869;PD2769,1852;PD2795,1843;PD2818,1845;PD2848,1854;PD2876,1860;PD2899,1894;PD2917,1913;PD2929,1935;PD2929,1960;PD2917,1984;PD2904,2005;PD2884,2029;PD2861,2054;PD2840,2080;PD2827,2099;PD2816,2116;PD2814,2138;PD2814,2161;PD2814,2178;PD2816,2200;PD2816,2202;
+SVCT 33SPI;SW2;PU2795,2286;PD2848,2286;
+**** 0
+0001 502070
+SYMB 10SY02133NIL
+SYMD 39TWRTPT52V022570207700611014030194601383
+SXPO 80reciprocal traffic directions in a two-way route of a traffic separation scheme
+SCRF 6ATRFCD
+SVCT 45SPA;SW3;PU2134,1545;PD2257,1383;PD2380,1545;
+SVCT 45SPA;SW3;PU2043,1661;PD1960,1777;PD2108,1777;
+SVCT 45SPA;SW3;PU2394,1773;PD2557,1773;PD2463,1650;
+SVCT 33SPA;SW3;PU2105,1965;PD2105,2178;
+SVCT 33SPA;SW3;PU2398,1959;PD2398,2170;
+SVCT 45SPA;SW3;PU2137,2616;PD2260,2786;PD2383,2616;
+SVCT 45SPA;SW3;PU2105,2373;PD1946,2373;PD2040,2493;
+SVCT 45SPA;SW3;PU2401,2373;PD2550,2373;PD2466,2504;
+**** 0
+0001 502071
+SYMB 10SY03141NIL
+SYMD 39TWRTPT53V022570207700597013900196001383
+SXPO 80single traffic direction in a two-way route part of a traffic separation scheme
+SCRF 6ATRFCD
+SVCT 45SPA;SW3;PU2134,1545;PD2257,1383;PD2380,1545;
+SVCT 45SPA;SW3;PU2043,1661;PD1960,1777;PD2108,1777;
+SVCT 45SPA;SW3;PU2394,1773;PD2557,1773;PD2463,1650;
+SVCT 57SPA;SW3;PU2104,2585;PD2104,2773;PD2408,2773;PD2408,2588;
+SVCT 33SPA;SW3;PU2104,2435;PD2104,2278;
+SVCT 33SPA;SW3;PU2104,1937;PD2104,2087;
+SVCT 33SPA;SW3;PU2423,1929;PD2423,2075;
+SVCT 33SPA;SW3;PU2419,2270;PD2419,2422;
+**** 0
+0001 502072
+SYMB 10SY02234NIL
+SYMD 39UNITFTH1V014100079500306004660130000595
+SXPO 41depth unit at ship's position is fathoms
+SCRF 6ASCLBR
+SVCT 31SPA;SW3;PU1303,797;PD1603,797;
+SVCT 43SPA;SW3;PU1606,595;PD1303,595;PD1300,1061;
+**** 0
+0001 502073
+SYMB 10SY03002NIL
+SYMD 39UNITMTR1V014690081300404004690126200581
+SXPO 40depth unit at ship's position is metres
+SCRF 6ASCLBR
+SVCT 66SPA;SW3;PU1262,1050;PD1263,581;PD1466,960;PD1666,588;PD1666,1044;
+**** 0
+0001 502074
+SYMB 10SY02249NIL
+SYMD 39UWTROC03V015000150000402004020129901299
+SXPO 45dangerous underwater rock of uncertain depth
+SCRF 12ADEPVSBCHBLK
+SVCT 42SPA;SW1;ST0;PU1500,1500;PM0;CI201;PM2;FP;
+SVCT 24SPB;SW1;PU1500,1300;PD;
+SVCT 24SPB;SW1;PU1500,1700;PD;
+SVCT 24SPB;SW1;PU1700,1500;PD;
+SVCT 24SPB;SW1;PU1300,1500;PD;
+SVCT 24SPB;SW1;PU1580,1310;PD;
+SVCT 24SPB;SW1;PU1640,1360;PD;
+SVCT 24SPB;SW1;PU1685,1425;PD;
+SVCT 24SPB;SW1;PU1675,1585;PD;
+SVCT 24SPB;SW1;PU1640,1640;PD;
+SVCT 24SPB;SW1;PU1575,1680;PD;
+SVCT 24SPB;SW1;PU1420,1680;PD;
+SVCT 24SPB;SW1;PU1360,1635;PD;
+SVCT 24SPB;SW1;PU1315,1570;PD;
+SVCT 24SPB;SW1;PU1320,1420;PD;
+SVCT 24SPB;SW1;PU1355,1355;PD;
+SVCT 24SPB;SW1;PU1420,1315;PD;
+SVCT 33SPB;SW1;PU1502,1371;PD1502,1648;
+SVCT 33SPB;SW1;PU1364,1505;PD1637,1506;
+**** 0
+0001 502075
+SYMB 10SY03164NIL
+SYMD 39UWTROC04V015000150000400003250129701336
+SXPO 56rock which covers and uncovers or is awash at low water
+SCRF 6ACHBLK
+SVCT 33SPA;SW1;PU1697,1500;PD1297,1500;
+SVCT 33SPA;SW1;PU1614,1337;PD1379,1661;
+SVCT 33SPA;SW1;PU1614,1655;PD1374,1336;
+**** 0
+0001 502076
+SYMB 10SY03211NIL
+SYMD 39VECGND01V007580038500590004150046600384
+SXPO 66arrowhead for ownship vector for course and speed over the ground
+SCRF 6ASHIPS
+SVCT 39SPA;SW2;PU593,796;PD760,587;PD931,799;
+SVCT 40SPA;SW2;PU466,736;PD758,384;PD1056,738;
+**** 0
+0001 502077
+SYMB 10SY03213NIL
+SYMD 39VECGND21V007580038500590004150046600384
+SXPO 70arrowhead for ARPA or AIS vector for course and speed over the ground
+SCRF 6AARPAT
+SVCT 39SPA;SW2;PU593,796;PD760,587;PD931,799;
+SVCT 40SPA;SW2;PU466,736;PD758,384;PD1056,738;
+**** 0
+0001 502078
+SYMB 10SY03222NIL
+SYMD 39VECWTR01V007580038500590003540046600384
+SXPO 68arrowhead for ownship vector for course and speed through the water
+SCRF 6ASHIPS
+SVCT 40SPA;SW2;PU466,736;PD758,384;PD1056,738;
+**** 0
+0001 502079
+SYMB 10SY03214NIL
+SYMD 39VECWTR21V007580038500590003540046600384
+SXPO 72arrowhead for ARPA or AIS vector for course and speed through the water
+SCRF 6AARPAT
+SVCT 40SPA;SW2;PU466,736;PD758,384;PD1056,738;
+**** 0
+0001 502080
+SYMB 10SY03186NIL
+SYMD 39WATTUR02V018170133301518003110096701184
+SXPO 31overfalls, eddies and breakers
+SCRF 6ACHGRD
+SVCT 308SPA;SW1;PU967,1485;PD1060,1458;PD1167,1380;PD1270,1235;PD1371,1184;PD1483,1194;PD1371,1294;PD1371,1392;PD1486,1495;PD1584,1456;PD1674,1397;PD1780,1235;PD1892,1186;PD1983,1191;PD1878,1294;PD1873,1402;PD1993,1495;PD2093,1451;PD2179,1397;PD2284,1242;PD2399,1189;PD2485,1196;PD2382,1326;PD2387,1402;PD2480,1495;
+**** 0
+0001 502081
+SYMB 10SY01634NIL
+SYMD 39WAYPNT01V007500075000600006000045000450
+SXPO 26waypoint on planned route
+SCRF 6kPLRTE
+SVCT 25SPk;PU750,750;SW4;CI300;
+**** 0
+0001 502082
+SYMB 10SY01635NIL
+SYMD 39WAYPNT03V015000150000600006000120001200
+SXPO 36waypoint on alternate planned route
+SCRF 6lAPLRT
+SVCT 27SPl;PU1500,1500;SW2;CI300;
+**** 0
+0001 502083
+SYMB 10SY03179NIL
+SYMD 39WAYPNT11V007500075000600006000045000450
+SXPO 31next waypoint on planned route
+SCRF 6APLRTE
+SVCT 25SPA;SW2;PU750,750;CI300;
+SVCT 25SPA;SW2;PU748,749;CI198;
+**** 0
+0001 502084
+SYMB 10SY01636NIL
+SYMD 39WEDKLP03V007500072501000002500025000600
+SXPO 11weed, kelp
+SCRF 6ECHGRD
+SVCT 121SPE;SW1;PU250,750;PD450,700;PD650,750;PD850,700;PD1050,750;PD1250,700;PU300,600;PD450,700;PU500,850;PD650,750;PU700,600;
+SVCT 32PD850,700;PU900,850;PD1050,750;
+**** 0
+0001 502085
+SYMB 10SY01637NIL
+SYMD 39WIMCON01V007500075000368006630060000137
+SXPO 10windmotor
+SCRF 6WLANDF
+SVCT 114SPW;PU750,750;SW2;CI50;PU750,300;PD750,700;PU800,750;PD900,750;PU700,750;PD600,750;PU750,300;PD968,300;PU750,300;
+SVCT 31PD612,137;PU750,300;PD612,462;
+**** 0
+0001 502086
+SYMB 10SY01638NIL
+SYMD 39WIMCON11V007500075000368006630060000137
+SXPO 22conspicuous windmotor
+SCRF 6CCHBLK
+SVCT 114SPC;PU750,750;SW2;CI50;PU750,300;PD750,700;PU800,750;PD900,750;PU700,750;PD600,750;PU750,300;PD968,300;PU750,300;
+SVCT 31PD612,137;PU750,300;PD612,462;
+**** 0
+0001 502087
+SYMB 10SY03172NIL
+SYMD 39WNDFRM51V007490046800778007780036000078
+SXPO 20wind generator farm
+SCRF 6ALANDF
+SVCT 29SPA;SW2;PU750,300;PD968,300;
+SVCT 29SPA;SW2;PU750,300;PD612,137;
+SVCT 29SPA;SW2;PU750,300;PD612,462;
+SVCT 25SPA;SW2;PU749,467;CI389;
+SVCT 29SPA;SW2;PU596,746;PD899,746;
+SVCT 29SPA;SW2;PU749,298;PD749,745;
+**** 0
+0001 502088
+SYMB 10SY03171NIL
+SYMD 39WNDFRM61V007470047800778007780036000078
+SXPO 32conspicuous wind generator farm
+SCRF 6ACHBLK
+SVCT 29SPA;SW2;PU750,300;PD968,300;
+SVCT 29SPA;SW2;PU750,300;PD612,137;
+SVCT 29SPA;SW2;PU750,300;PD612,462;
+SVCT 25SPA;SW2;PU749,467;CI389;
+SVCT 29SPA;SW2;PU596,746;PD899,746;
+SVCT 29SPA;SW2;PU749,298;PD749,745;
+**** 0
+0001 502089
+SYMB 10SY01639NIL
+SYMD 39WNDMIL02V007500075000300004100060000450
+SXPO 9windmill
+SCRF 6WLANDF
+SVCT 65SPW;PU750,750;SW1;CI110;PU900,450;PD600,750;PU600,450;PD900,750;
+**** 0
+0001 502090
+SYMB 10SY02037NIL
+SYMD 39WNDMIL12V007500075000300004100060000450
+SXPO 21conspicuous windmill
+SCRF 6CCHBLK
+SVCT 65SPC;PU750,750;SW1;CI110;PU900,450;PD600,750;PU600,450;PD900,750;
+**** 0
+0001 502091
+SYMB 10SY01641NIL
+SYMD 39WRECKS01V007500075000650003500040000450
+SXPO 76wreck showing any portion of hull or superstructure at level of chart datum
+SCRF 6DCHGRD
+SVCT 114SPD;ST0;PU550,750;PM0;PD400,550,1050,750,800,750,800,740,795,730,790,720,780,710,770,700,760,700,745,700,735,700;
+SVCT 115PD720,705,705,720,700,735,700,740,700,750,550,750,550,750;PM2;FP;PU750,750;SW3;CI50;PU400,750;PD700,750;PU800,750;
+SVCT 32PD1050,750;PU740,650;PD800,450;
+**** 0
+0001 502092
+SYMB 10SY01642NIL
+SYMD 39WRECKS04V007500075000500003000050000600
+SXPO 35non-dangerous wreck, depth unknown
+SCRF 6ECHBLK
+SVCT 118SPE;SW1;PU750,900;PD750,900;SPE;SW1;PU600,650;PD600,850;PU900,650;PD900,850;PU500,750;PD1000,750;PU750,600;PD750,900;
+**** 0
+0001 502093
+SYMB 10SY02038NIL
+SYMD 39WRECKS05V007500075000590004100045300540
+SXPO 31dangerous wreck, depth unknown
+SCRF 12ADEPVSCCHBLK
+SVCT 196SPA;SW1;ST0;PU453,700;PM0;PD512,625;PD600,575;PD687,550;PD800,540;PD900,575;PD981,625;PD1040,700;PD1040,800;PD987,859;PD900,915;PD800,950;PD700,950;PD600,915;PD525,865;PD453,800;PD453,700;PM2;FP;
+SVCT 29SPC;SW1;PU600,650;PD600,850;
+SVCT 29SPC;SW1;PU900,650;PD900,850;
+SVCT 30SPC;SW1;PU500,750;PD1000,750;
+SVCT 29SPC;SW1;PU750,600;PD750,900;
+SVCT 22SPC;SW1;PU453,700;PD;
+SVCT 22SPC;SW1;PU512,625;PD;
+SVCT 22SPC;SW1;PU600,575;PD;
+SVCT 22SPC;SW1;PU687,550;PD;
+SVCT 22SPC;SW1;PU800,540;PD;
+SVCT 22SPC;SW1;PU900,575;PD;
+SVCT 22SPC;SW1;PU981,625;PD;
+SVCT 23SPC;SW1;PU1040,700;PD;
+SVCT 22SPC;SW1;PU453,800;PD;
+SVCT 22SPC;SW1;PU525,865;PD;
+SVCT 22SPC;SW1;PU600,915;PD;
+SVCT 22SPC;SW1;PU700,950;PD;
+SVCT 22SPC;SW1;PU800,950;PD;
+SVCT 22SPC;SW1;PU900,915;PD;
+SVCT 22SPC;SW1;PU987,859;PD;
+SVCT 23SPC;SW1;PU1043,793;PD;
+**** 0
Added: packages/openev/branches/upstream/current/contrib/S52/S52raz.s
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52raz.s (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52raz.s 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,25 @@
+# S52raz.s: make an ELF object from PLib data
+#
+#
+# This file is part of the OpENCview project, a viewer of ENC
+# Copyright (C) 2003-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+
+# definition of symbol name and location
+.align 32
+.global S52raz
+.global S52razLen
+
+ .data
+ .type S52raz, @object
+
+# fill data segment
+S52raz:
+ .incbin "S52raz-3.2.rle"
+S52razLen: .long . - S52raz
+ .type S52razLen, @object
+
+
+# this work also
+#objcopy -v -I binary -O elf32-little \
+#--rename-section .data=.rodata in_file out_file
Added: packages/openev/branches/upstream/current/contrib/S52/S52type.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52type.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52type.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,45 @@
+// S52type.h: S52 type to bridge to external geometry name
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52TYPE_H_
+#define _S52TYPE_H_
+
+// callback for each layer to add app. specific stuff
+typedef void (*_loadLayer_cb)(const char *layername, void *ogrlayer);
+typedef void (*_loadObj_cb) (const char *objname, void *ogrobj);
+
+
+// Addressed Object Type
+typedef enum S52_Obj_t {
+//typedef enum {
+ _META_T = 0 , // meta geo stuff (ex: C_AGGR)
+ GRP_1_T = 1 , // group 1 area, earth
+ POINT_T = 'P',
+ LINES_T = 'L',
+ AREAS_T = 'A',
+ N_OBJ_T = 5 // number of object type
+//};
+} S52_Obj_t;
+
+#endif //_S52TYPE_H_
Added: packages/openev/branches/upstream/current/contrib/S52/S52utils.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52utils.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52utils.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,241 @@
+// S52utils.c: utility
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#include "S52utils.h"
+#include <stdio.h> // FILE
+#include <string.h> // strncmp()
+#include <limits.h> // PATH_MAX
+#include <stdlib.h> // exit()
+//#include <ctype.h> // isblank()
+#include <glib.h>
+
+// configuration file
+#define CONF_NAME "./s52test.conf"
+
+///////////////////////////////////////////////////////////////////
+//
+// GLOBAL MARINER PARAMETER (will move out)
+//
+// NOTE: value for Chart No 1 found in README
+//
+// Soundings ON
+// Text ON
+// Depth Shades 4
+// Safety Contour 10 m
+// Safety Depth 7 m
+// Shallow 5 m
+// Deep 30 m
+
+/* A) value for Chart No 1 */
+
+double SHOW_TEXT = TRUE; // view group 23
+double TWO_SHADES = FALSE; // flag indicating selection of two depth shades (on/off) [default ON]
+double SAFETY_CONTOUR = 10.0; // selected safety contour (meters) [IMO PS 3.6]
+double SAFETY_DEPTH = 7.0; // selected safety depth (meters) [IMO PS 3.7]
+double SHALLOW_CONTOUR = 5.0; // selected shallow water contour (meters) (optional)
+double DEEP_CONTOUR = 30.0; // selected deepwatercontour (meters) (optional)
+
+
+/* B) value for testing */
+/*
+//gboolean TWO_SHADES = TRUE; // flag indicating selection of two depth shades (on/off) [default ON]
+gboolean TWO_SHADES = FALSE; // flag indicating selection of two depth shades (on/off) [default ON]
+gboolean SHOW_TEXT = TRUE; // view group 23
+//double SAFETY_DEPTH = 30.0; // selected safety depth (meters) [IMO PS 3.7]
+//double SHALLOW_CONTOUR = 2.0; // selected shallow water contour (meters) (optional)
+double SAFETY_DEPTH = 15.0; // selected safety depth (meters) [IMO PS 3.7]
+double SHALLOW_CONTOUR = 5.0; // selected shallow water contour (meters) (optional)
+//double SAFETY_CONTOUR = 30.0; // selected safety contour (meters) [IMO PS 3.6]
+//double DEEP_CONTOUR = 30.0; // selected deepwatercontour (meters) (optional)
+//double SAFETY_CONTOUR = 5.0; // selected safety contour (meters) [IMO PS 3.6]
+//double DEEP_CONTOUR = 10.0; // selected deepwatercontour (meters) (optional)
+double SAFETY_CONTOUR = 10.0; // selected safety contour (meters) [IMO PS 3.6]
+double DEEP_CONTOUR = 15.0; // selected deepwatercontour (meters) (optional)
+*/
+
+/* param needed for certain conditional symbology */
+/*
+gboolean SHALLOW_PATTERN = FALSE; // flag indicating selection of shallow water highlight (on/off)(optional) [default OFF]
+gboolean SHIPS_OUTLINE = FALSE; // flag indicating selection of ship scale symbol (on/off) [IMO PS 8.4]
+double DISTANCE_TAGS = 0.0; // selected spacing of "distance to run" tags at a route (nm)
+double TIME_TAGS = 0.0; // selected spacing of time tags at the pasttrack (min)
+gboolean FULL_SECTORS = TRUE; // show full length light sector lines
+gboolean SYMBOLIZED_BND = TRUE; // symbolized area boundaries
+*/
+
+// WARNING: must be in sync with S52_MAR_param_t
+static char *_MARparamNm[] = {
+ "S52_MAR_NONE", //= 0, // default
+ "S52_MAR_SHOW_TEXT", //= 1, // view group 23
+ "S52_MAR_TWO_SHADES", //= 2, // flag indicating selection of two depth shades (on/off) [default ON]
+ "S52_MAR_SAFETY_CONTOUR", //= 3, // selected safety contour (meters) [IMO PS 3.6]
+ "S52_MAR_SAFETY_DEPTH", //= 4, // selected safety depth (meters) [IMO PS 3.7]
+ "S52_MAR_SHALLOW_CONTOUR", //= 5, // selected shallow water contour (meters) (optional)
+ "S52_MAR_DEEP_CONTOUR", //= 6, // selected deepwatercontour (meters) (optional)
+ "S52_MAR_SHALLOW_PATTERN", //= 7, // flag indicating selection of shallow water highlight (on/off)(optional) [default OFF]
+ "S52_MAR_SHIPS_OUTLINE", //= 8, // flag indicating selection of ship scale symbol (on/off) [IMO PS 8.4]
+ "S52_MAR_DISTANCE_TAGS", //= 9, // selected spacing of "distance to run" tags at a route (nm)
+ "S52_MAR_TIME_TAGS", //= 10, // selected spacing of time tags at the pasttrack (min)
+ "S52_MAR_FULL_SECTORS", //= 11, // show full length light sector lines
+ "S52_MAR_SYMBOLIZED_BND", //= 12, // symbolized area boundaries
+ "S52_MAR_SYMPLIFIED_PNT", //= 13, // simplified point
+ "S52_MAR_DISP_CATEGORY", //= 14, // display category
+ "S52_MAR_COLOR_PALETTE", //= 15, // color palette
+
+ "S52_MAR_NUM" //= 16 // number of parameters
+};
+
+// WARNING: must be in sync with _MARparamNm
+static double _MARparamVal[] = {
+ 0.0, // NONE
+ TRUE, // SHOW_TEXT
+ FALSE, // TWO_SHADES (flase -> 4 shade)
+ //TRUE, // TWO_SHADES (SEABED01 defautl)
+
+ 15.0, // SAFETY_CONTOUR
+ //0.0, // SAFETY_CONTOUR --to test DEPCNT02 selection (GL) in CA49995A.000
+ //0.5, // SAFETY_CONTOUR --to test DEPCNT02 selection (GL) in CA49995A.000
+ //30.0, // SAFETY_CONTOUR (SEABED01 defautl)
+
+ 7.0, // SAFETY_DEPTH
+ //5.0, // SAFETY_DEPTH
+
+ 2.0, // SHALLOW_CONTOUR (SEABED01 defautl)
+ //5.0, // SHALLOW_CONTOUR
+
+ //30.0, // DEEP_CONTOUR (SEABED01 defautl)
+ 15.0, // DEEP_CONTOUR
+
+ //FALSE, // SHALLOW_PATTERN (SEABED01 defautl)
+ TRUE, // SHALLOW_PATTERN
+
+ FALSE, // SHIPS_OUTLINE
+ 0.0, // DISTANCE_TAGS
+ 0.0, // TIME_TAGS
+ TRUE, // FULL_SECTORS
+
+ //TRUE, // SYMBOLIZED_BND
+ FALSE, // SYMBOLIZED_BND
+
+ //TRUE, // SYMPLIFIED_PNT
+ FALSE, // SYMPLIFIED_PNT
+
+// 'D', // S52_MAR_DISP_CATEGORY --DISPLAYBASE
+// 'S', // S52_MAR_DISP_CATEGORY --STANDARD
+ 'O', // S52_MAR_DISP_CATEGORY --OTHER
+
+ 0, // S52_MAR_COLOR_PALETTE --DAY_BRIGHT
+// 1, // S52_MAR_COLOR_PALETTE --DAY_BLACKBACK
+// 2, // S52_MAR_COLOR_PALETTE --DAY_WHITEBACK
+// 3, // S52_MAR_COLOR_PALETTE --DUSK
+// 4, // S52_MAR_COLOR_PALETTE --NIGHT
+
+ 16.0 // NUM
+};
+
+
+int isblank(char c) {
+
+ if (c == ' ' || c == 0x09)
+ return 1;
+ return 0;
+
+
+}
+
+//////////////////////////////////////////////////////////////////
+
+int S52_getConfig(const char *label, valueBuf *vbuf)
+// return TRUE and string value in vbuf for label, FLASE if fail
+{
+ FILE *fp;
+// int ret = 0;
+ int ret = 1;
+ char lbuf[PATH_MAX] = {'#'};
+ char tmp [PATH_MAX];
+ char frmt[PATH_MAX];
+
+ fp = fopen(CONF_NAME, "r");
+ if (NULL == fp) {
+ PRINTF("ERROR opening " CONF_NAME "\n");
+ return 0;
+ }
+
+ // prevent buffer overflow
+ sprintf(frmt, "%s%i%s", "%s %", MAXL-1, "[^\n]s");
+ //printf("frmt:%s\n", frmt);
+
+ while (ret > 0) {
+ if (lbuf[0] != '#') {
+ if (0 == strncmp(lbuf, label, strlen(label))) {
+ //sscanf(tmp, "%255s", *vbuf);
+ char *c = tmp;
+ while (isblank(*c)) c++;
+ sscanf(c, "%255[^\n]", *vbuf);
+ PRINTF("label:%s value:%s \n", lbuf, *vbuf);
+ fclose(fp);
+ return 1;
+ }
+ }
+
+
+ //ret = fscanf(fp, frmt, lbuf, vbuf);
+ ret = fscanf(fp, "%s%255[^\n]\n", lbuf, tmp);
+ //printf("label:%s \n", lbuf);
+ //printf("value:%s \n", tmp);
+ //printf("ret:%i\n", ret);
+ }
+ fclose(fp);
+
+ *vbuf[0] = '\0';
+ return 0;
+
+}
+
+double S52_getMarinerParam(S52_MAR_param_t param)
+// return Mariner parameter or '0.0' if fail
+// FIXME: check mariner param against groups selection
+{
+ valueBuf vbuf;
+
+ if (S52_MAR_NONE<param && param<S52_MAR_NUM) {
+
+ if (S52_getConfig(_MARparamNm[param], &vbuf))
+ return atof(vbuf);
+ else
+ return _MARparamVal[param];
+ }
+
+ return 0.0;
+}
+
+int S52_setMarinerParam(S52_MAR_param_t param, double val)
+{
+ if (S52_MAR_NONE<param && param<S52_MAR_NUM)
+ _MARparamVal[param] = val;
+ else
+ return FALSE;
+
+ return TRUE;
+}
Added: packages/openev/branches/upstream/current/contrib/S52/S52utils.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S52utils.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S52utils.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,75 @@
+// S52utils.h: utility
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S52UTILS_H_
+#define _S52UTILS_H_
+
+#include <stdio.h> // printf()
+
+#ifdef SOLARIS
+// well should be cc
+#define PRINTF printf(__FILE__":%i: : ", __LINE__),printf
+#else
+#define PRINTF printf(__FILE__":%i: %s(): ", __LINE__, __FUNCTION__),printf
+#endif
+
+// valid label in .conf file
+#define CONF_CATALOG "CATALOG"
+#define CONF_PLIB "PLIB"
+#define CONF_CHART "CHART"
+//#define CONF_RGB "DUMMY_RGB_BRIGHT"
+
+// global parameter for mariners' selection
+typedef
+ enum S52_MAR_param_t {
+ S52_MAR_NONE = 0, // default
+ S52_MAR_SHOW_TEXT = 1, // view group 23
+ S52_MAR_TWO_SHADES = 2, // flag indicating selection of two depth shades (on/off) [default ON]
+ S52_MAR_SAFETY_CONTOUR = 3, // selected safety contour (meters) [IMO PS 3.6]
+ S52_MAR_SAFETY_DEPTH = 4, // selected safety depth (meters) [IMO PS 3.7]
+ S52_MAR_SHALLOW_CONTOUR = 5, // selected shallow water contour (meters) (optional)
+ S52_MAR_DEEP_CONTOUR = 6, // selected deepwatercontour (meters) (optional)
+ S52_MAR_SHALLOW_PATTERN = 7, // flag indicating selection of shallow water highlight (on/off)(optional) [default OFF]
+ S52_MAR_SHIPS_OUTLINE = 8, // flag indicating selection of ship scale symbol (on/off) [IMO PS 8.4]
+ S52_MAR_DISTANCE_TAGS = 9, // selected spacing of "distance to run" tags at a route (nm)
+ S52_MAR_TIME_TAGS = 10, // selected spacing of time tags at the pasttrack (min)
+ S52_MAR_FULL_SECTORS = 11, // show full length light sector lines
+ S52_MAR_SYMBOLIZED_BND = 12, // symbolized area boundaries
+
+ S52_MAR_SYMPLIFIED_PNT = 13, // simplified point
+
+ S52_MAR_DISP_CATEGORY = 14, // display category
+
+ S52_MAR_COLOR_PALETTE = 15, // color palette
+
+ S52_MAR_NUM = 16 // number of parameters
+} S52_MAR_param_t;
+
+#define MAXL 256 // MAX lenght of buffer _including_ '\0'
+typedef char valueBuf[MAXL];
+
+extern int S52_getConfig(const char *label, valueBuf *vbuf);
+extern double S52_getMarinerParam(S52_MAR_param_t param);
+extern int S52_setMarinerParam(S52_MAR_param_t param, double val);
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S57data.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57data.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57data.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,842 @@
+// S57gvgeo.c: interface to OpenEV S57 geo data
+//
+// Project: OpENCview/OpenEV
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#include "S57data.h" // S57_geo
+#include "S52utils.h" // PRINTF()
+
+#include <glib.h> // GArray
+
+#include <stdlib.h> // exit()
+#include <string.h> // strlen()
+
+
+// MAXINT-6 is how OGR tag an UNKNOWN value
+// see gdal/ogr/ogrsf_frmts/s57/s57.h:126
+// it is then turn into a string in gv_properties
+#define EMPTY_NUMBER_MARKER "2147483641" /* MAXINT-6 */
+
+//typedef gvgeocoord geocoord;
+
+static int id = 0;
+
+typedef struct _pt3{ double x,y,z; } pt3;
+
+typedef struct _rect {
+ //double x;
+ //double y;
+ //double width;
+ //double height;
+ double x1;
+ double y1;
+ double x2;
+ double y2;
+
+} _rect;
+
+// dta for glDrawArrays()
+struct _prim {
+ int mode;
+ int first;
+ int count;
+} _prim;
+
+typedef struct _S57_prim {
+ //int nbr; // total number for primitive for this object
+ GArray *list; // list of _prim in 'vertex'
+ GArray *vertex;
+} _S57_prim;
+
+// S57 object geo data
+typedef struct _S57_geo {
+ int id; // record id (debug)
+ char name[9]; // object name 6/8 + '\0'
+ S52_Obj_t obj_t; // used in CS
+
+ _rect rect; // lat/lon extend of object
+
+ geocoord pointxyz[3]; // point
+
+ guint linexyznbr; // line
+ geocoord *linexyz;
+
+ guint ringnbr; // area
+ int *ringxyznbr;
+ geocoord **ringxyz;
+
+ //GArray *XY; // line/area list of projected geocoordinate
+
+ S57_prim *prim;
+
+ GData *attribs;
+
+ S57_geo *next; // list of geo passed to CS
+
+ void *hGeom; // opaque pointer to OGR geo
+ // used for CS
+} _S57_geo;
+
+/////////////////////////////////////////////////////
+// projection (PROJ4)
+static projPJ pj = NULL;
+static projPJ pjsrc = NULL; // projection source
+static projPJ pjdst = NULL; // projection destination
+static int _setNewPROJ = TRUE; // will set new projection
+
+static void _destroy_func(gpointer data)
+{
+ g_string_free((GString*)data, TRUE);
+}
+
+int S57_doneObject(S57_geo *geoData)
+{
+ if (NULL == geoData){
+ PRINTF("ERROR: deleting NULL geoData \n");
+ return 0;
+ }
+
+ printf("Deleting geoData %d\n", geoData->id);
+
+ //if (NULL != geoData->XY)
+ // g_array_free(geoData->XY, TRUE);
+
+ if (NULL != geoData->linexyz)
+ g_free((geocoord*)geoData->linexyz);
+
+ if (NULL != geoData->ringxyz){
+ int i;
+ for(i = 0; i < geoData->ringnbr; ++i)
+ g_free((geocoord*)geoData->ringxyz[i]);
+ g_free((geocoord*)geoData->ringxyz);
+ }
+
+ if (NULL != geoData->ringxyznbr)
+ g_free(geoData->ringxyznbr);
+
+
+ if (NULL != geoData->attribs)
+ g_datalist_clear(&geoData->attribs);
+
+ g_free((gpointer*)geoData);
+
+ return 1;
+}
+
+static int _geo2prj3dv(guint npt, pt3 *data)
+// convert to XY 'in-place'
+{
+ int i = 0;
+ pt3 *pt = data;
+ int ret = 0;
+
+ if (NULL==pjsrc || NULL==pjdst)
+ return 1;
+
+ // deg to rad --latlon
+ for (i=0; i<npt; ++i, ++data)
+ data->x *= DEG_TO_RAD,
+ data->y *= DEG_TO_RAD;
+
+ // rad to cartesian --mercator
+ ret = pj_transform(pjsrc, pjdst, npt, 3, &pt->x, &pt->y, &pt->z);
+ if (0 != ret) {
+ PRINTF("ERROR in transform (%i): %s\n", ret, pj_strerrno(pj_errno));
+ exit(0);
+ }
+
+ return 1;
+}
+
+S57_geo *S57_setPOINT(geocoord x, geocoord y, geocoord z)
+{
+ _S57_geo *geoData = g_new0(_S57_geo, 1);
+
+ geoData->id = id++;
+ geoData->obj_t = POINT_T;
+ geoData->pointxyz[0] = x;
+ geoData->pointxyz[1] = y;
+ geoData->pointxyz[2] = z;
+
+ //_geo2prj3dv(1, geoData->pointxyz);
+
+ return geoData;
+}
+
+S57_geo *S57_setLINES(guint xyznbr, geocoord *xyz)
+{
+ _S57_geo *geoData = g_new0(_S57_geo, 1);
+
+ geoData->id = id++;
+ geoData->obj_t = LINES_T;
+ geoData->linexyznbr = xyznbr;
+ geoData->linexyz = xyz;
+
+ //_geo2prj3dv(geoData->linexyznbr, geoData->linexyz);
+
+ return geoData;
+}
+
+S57_geo *S57_setAREAS(guint ringnbr, int *ringxyznbr, geocoord **ringxyz)
+{
+ _S57_geo *geoData = g_new0(_S57_geo, 1);
+
+ geoData->id = id++;
+ geoData->obj_t = AREAS_T;
+ geoData->ringnbr = ringnbr;
+ geoData->ringxyznbr = ringxyznbr;
+ geoData->ringxyz = ringxyz;
+
+ //int i = 0;
+ //for (i=0; i<geoData->ringnbr; ++i)
+ // _geo2prj3dv(geoData->ringxyznbr[i], geoData->ringxyz[i]);
+
+ return geoData;
+}
+
+S57_geo *S57_set_META()
+{
+ _S57_geo *geoData = g_new0(_S57_geo, 1);
+
+ geoData->id = id++;
+ geoData->obj_t = _META_T;
+
+ return geoData;
+}
+
+int S57_setName(S57_geo *geoData, const char *name)
+{
+ //strncat(geoData->name, name, 6);
+ strcat(geoData->name, name);
+
+ return 1;
+}
+
+char *S57_getName(S57_geo *geoData)
+{
+ return geoData->name;
+}
+
+int S57_setOGRGeo(S57_geo *geoData, void *hGeom)
+{
+ geoData->hGeom = hGeom;
+
+ return 1;
+}
+
+void *S57_getOGRGeo(S57_geo *geoData)
+{
+ return geoData->hGeom;
+}
+
+guint S57_getRingNbr(S57_geo *geoData)
+{
+ if (AREAS_T != geoData->obj_t)
+ return 1;
+ else
+ return geoData->ringnbr;
+}
+
+int S57_getGeoData(S57_geo *geoData, int ringNo, guint *npt, double **ppt)
+// helper providing uniform access to geoData
+{
+ if (NULL == geoData) {
+ PRINTF("WARNING: geoData == NULL !?\n");
+ *npt = 0;
+ return 0;
+ }
+
+ if (ringNo<0 ||
+ //(LINES_T==geoData->obj_t && 1 != ringNo) ||
+ (AREAS_T==geoData->obj_t && geoData->ringnbr<ringNo)) {
+ PRINTF("ERROR: invalid ring number requested! \n");
+ *npt = 0;
+ exit(0);
+ //return 0;
+ }
+
+ switch (geoData->obj_t) {
+ case POINT_T:
+ *npt = 1;
+ *ppt = geoData->pointxyz;
+ break;
+
+ case LINES_T:
+ *npt = geoData->linexyznbr;
+ *ppt = geoData->linexyz;
+ break;
+
+ case AREAS_T:
+ if (NULL != geoData->ringxyznbr) {
+ *npt = geoData->ringxyznbr[ringNo];
+ *ppt = geoData->ringxyz[ringNo];
+ } else
+ PRINTF("ERROR: atempt to access a tessed area .. \n"
+ "(there is no geo anymore!!)\n");
+
+ // WARNING: check if begin/end vertex are the same
+ // (OpenGIS: closed and simple ring)
+ // If so shorten it to help trace tesss (in combineCB)
+ /*
+ {
+ int n = 3 * (*npt-1);
+ double *p = *ppt;
+ if (p[0] == p[n+0] &&
+ p[1] == p[n+1] &&
+ p[2] == p[n+2]) {
+ //--(*npt);
+ // *npt -= 1; // <<< shorten
+ } else {
+ PRINTF("not close/simple ring\n");
+ //PRINTF(" START: x=%f y=%f z=%f\n", p[0],p[1],p[2]);
+ //PRINTF(" END: x=%f y=%f z=%f\n", p[n+0],p[n+1],p[n+2]);
+ //exit(0);
+ }
+
+ }
+ */
+
+ //if (geodata->ringnbr > 1) {
+ // PRINTF("WARNING!!! AREA_T ringnbr:%i only exterior ring used\n", geodata->ringnbr);
+ //}
+ break;
+ default:
+ PRINTF("ERROR object type invalid!\n");
+ //return 1;
+ exit(0);
+ }
+
+ return 1;
+}
+
+//GArray *S57_getXY(S57_geo *geoData)
+//{
+// // FIXME: reset array if projection change
+// if (NULL == geoData->XY)
+// geoData->XY = g_array_new(FALSE, FALSE, sizeof(double)*3);
+//
+// return geoData->XY;
+//}
+
+S57_prim *S57_initPrim(S57_prim *prim)
+// set/reset primitive holder
+{
+ if (NULL == prim) {
+ S57_prim *p = g_new0(S57_prim, 1);
+
+ p->list = g_array_new(FALSE, FALSE, sizeof(_prim));
+ p->vertex = g_array_new(FALSE, FALSE, sizeof(double)*3);
+
+ return p;
+ } else {
+ g_array_set_size(prim->list, 0);
+ g_array_set_size(prim->vertex, 0);
+
+ return prim;
+ }
+}
+
+S57_prim *S57_donePrim(S57_prim *prim)
+{
+ if (NULL != prim->list) g_array_free(prim->list, TRUE);
+ if (NULL != prim->vertex) g_array_free(prim->vertex, TRUE);
+
+ // failsafe
+ prim->list = NULL;
+ prim->vertex = NULL;
+
+ return NULL;
+}
+
+S57_prim *S57_initPrimGeo(S57_geo *geoData)
+{
+ //if (NULL == geoData->XY)
+ // geoData->XY = g_array_new(FALSE, FALSE, sizeof(double)*3);
+
+ geoData->prim = S57_initPrim(geoData->prim);
+
+ //geoData->prim.list = g_array_new(FALSE, FALSE, sizeof(_prim));
+ //geoData->prim.vertex = g_array_new(FALSE, FALSE, sizeof(double)*3);
+
+ return geoData->prim;
+}
+
+S57_geo *S57_donePrimGeo(S57_geo *geoData)
+{
+ g_free(geoData->prim);
+
+ geoData->prim = NULL;
+
+ return NULL;
+}
+
+int S57_begPrim(S57_prim *prim, int data)
+{
+ struct _prim p;
+
+ p.mode = data;
+ p.first = prim->vertex->len;
+
+ g_array_append_val(prim->list, p);
+
+ return 1;
+
+}
+
+int S57_addPrimVertex(S57_prim *prim, double *ptr)
+{
+ //g_array_append_val(prim->vertex, *ptr);
+ g_array_append_vals(prim->vertex, ptr, 1);
+
+ return 1;
+}
+
+int S57_endPrim(S57_prim *prim)
+{
+ struct _prim *p = &g_array_index(prim->list, struct _prim, prim->list->len-1);
+
+ p->count = prim->vertex->len - p->first;
+ return 1;
+}
+
+S57_prim *S57_getPrimGeo(S57_geo *geoData)
+{
+ return geoData->prim;
+}
+
+S57_prim *S57_getPrimData(S57_prim *prim, int *primNbr, double **vertex)
+
+{
+ *primNbr = prim->list->len;
+ *vertex = (double*)prim->vertex->data;
+
+ return prim;
+}
+
+GArray *S57_getPrimVertex(S57_prim *prim)
+{
+ return prim->vertex;
+}
+
+S57_prim *S57_setPrimSize(S57_prim *prim, int sz)
+{
+ g_array_set_size(prim->list, sz);
+ g_array_set_size(prim->vertex, sz);
+
+ return prim;
+}
+
+int S57_getPrimIdx(S57_prim *prim, int i, int *mode, int *first, int *count)
+{
+ struct _prim *p = &g_array_index(prim->list, struct _prim, i);
+
+ if (NULL == p) {
+ PRINTF("ERROR: no primitive at index: %i\n", i);
+ return 0;
+ }
+
+ *mode = p->mode;
+ *first = p->first;
+ *count = p->count;
+
+ return 1;
+}
+
+int S57_setExt(S57_geo *geoData, double x1, double y1, double x2, double y2)
+{
+ geoData->rect.x1 = x1;
+ geoData->rect.y1 = y1;
+ geoData->rect.x2 = x2;
+ geoData->rect.y2 = y2;
+
+ return 1;
+}
+
+int S57_getExt(S57_geo *geoData, double *x1, double *y1, double *x2, double *y2)
+{
+ *x1 = geoData->rect.x1;
+ *y1 = geoData->rect.y1;
+ *x2 = geoData->rect.x2;
+ *y2 = geoData->rect.y2;
+
+ return 1;
+}
+
+S52_Obj_t S57_getObjtype(S57_geo *geoData)
+{
+ if (NULL == geoData)
+ return _META_T;
+
+ return geoData->obj_t;
+}
+
+int S57_samePtPos(S57_geo *geoA, S57_geo *geoB)
+// return TRUE if 2 point are at the same position else FALSE
+{
+ // check if its the same object
+ if (geoA == geoB)
+ return FALSE;
+
+ if (geoA->pointxyz[0] == geoB->pointxyz[0] &&
+ geoA->pointxyz[1] == geoB->pointxyz[1] &&
+ geoA->pointxyz[2] == geoB->pointxyz[2])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+// return the number of attributes.
+
+static void _countItems(GQuark key_id, gpointer data, gpointer user_data)
+{
+ char *attName = g_quark_to_string(key_id);
+ if (6 == strlen(attName)){
+ int *cnt = (int*)user_data;
+ *cnt = *cnt + 1;
+ }
+}
+
+int S57_getNumAtt(S57_geo *geoData)
+{
+ int cnt = 0;
+ g_datalist_foreach(&geoData->attribs, _countItems, &cnt);
+ return cnt;
+}
+
+
+struct _qwerty {
+ int currentIdx;
+ char featureName[20];
+ char **name;
+ char **value;
+};
+
+static void getAttValues(GQuark key_id, gpointer data, gpointer user_data){
+
+ struct _qwerty *attData = (struct _qwerty*)user_data;
+
+ GString *attValue = (GString*) data;
+ char *attName = g_quark_to_string(key_id);
+
+ if (6 == strlen(attName)){
+ strcpy(attData->value[attData->currentIdx], attValue->str);
+ strcpy(attData->name [attData->currentIdx], attName );
+ printf("inserting %s %s %d", attName, attValue->str, attData->currentIdx);
+ attData->currentIdx += 1;
+ } else {
+ ;// printf("sjov Att: %s = %s \n",attName, attValue->str);
+
+ }
+}
+
+// recommend you count number of attributes in advance, to allocate the
+// propper amount of **. each char *name should be allocated 7 and the char
+// *val 20 ????
+int S57_getAttributes(S57_geo *geoData, char **name, char **val){
+ struct _qwerty tmp;
+
+ tmp.currentIdx = 0;
+ tmp.name = name;
+ tmp.value = val;
+
+ g_datalist_foreach(&geoData->attribs, getAttValues, &tmp);
+ // strcpy(name[tmp.currentIdx], "x");
+ // strcpy(val[tmp.currentIdx], "y");
+ return tmp.currentIdx;
+
+
+
+}
+
+
+GString *S57_getAttVal(S57_geo *geoData, char *att_name)
+// return attribute string value or NULL if:
+// 1- attribute name abscent
+// 2- its a mandatory attribute but its value is not define (EMPTY_NUMBER_MARKER)
+{
+ GString *att = (GString*) g_datalist_get_data(&geoData->attribs, att_name);
+
+ // mandatory attribute with ommited value
+ if (NULL!=att && (0==strncmp(att->str, EMPTY_NUMBER_MARKER, 10)))
+ return NULL;
+
+ // undefined value
+ if (NULL!=att && 0==att->len)
+ return NULL;
+
+ return att;
+}
+
+GData *S57_setAtt(S57_geo *geoData, const char *name, const char *val)
+{
+ GQuark qname = g_quark_from_string(name);
+ GString *value = g_string_new(val);
+
+ if (NULL == geoData)
+ return NULL;
+
+ if (NULL == geoData->attribs)
+ g_datalist_init(&geoData->attribs);
+
+ g_datalist_id_set_data_full(&geoData->attribs, qname, value, _destroy_func);
+
+ return NULL;
+}
+
+S57_geo *S57_linkObj(S57_geo *geoData, S57_geo *geoNew)
+// add geo to list of object, return geo
+{
+ // geo should not be linked to anyone
+ g_assert(NULL == geoNew->next);
+
+ // or linked to them self --degenerated case
+ g_assert(geoData != geoNew);
+
+ geoNew->next = geoData->next;
+ geoData->next= geoNew;
+
+ return geoData;
+}
+
+S57_geo *S57_unlinkObj(S57_geo *geoData)
+// remove the link between objects in list
+{
+ while (NULL != geoData) {
+ S57_geo *tmp = geoData->next;
+
+ geoData->next = NULL;
+ geoData = tmp;
+ }
+
+ return geoData; // NULL
+}
+
+static void _printAtt(GQuark key_id, gpointer data, gpointer user_data)
+{
+ char *attName = g_quark_to_string(key_id);
+ GString *attValue = (GString*) data;
+
+ if (6 == strlen(attName))
+ printf("\t%s : %s\n", attName, (char*)attValue->str);
+}
+
+S57_geo *S57_nextObj(S57_geo *geoData)
+// get next geo object in list --pop top node if TRUE
+{
+ if (NULL == geoData)
+ return NULL;
+
+ return geoData->next;
+}
+
+int S57_dumpData(S57_geo *geoData)
+// debug
+{
+ guint npt = 0;
+ geocoord *ppt;
+
+ switch (geoData->obj_t) {
+ case POINT_T:
+ npt = 1;
+ ppt = geoData->pointxyz;
+ //printf("POINT_T");
+ break;
+
+ case LINES_T:
+ npt = geoData->linexyznbr;
+ ppt = geoData->linexyz;
+ //printf("LINES_T");
+ break;
+
+ case AREAS_T:
+ if (NULL != geoData->ringxyznbr) {
+ npt = geoData->ringxyznbr[0];
+ ppt = geoData->ringxyz[0];
+ } else
+ PRINTF("ERROR: atempt to access a tessed area .. \n"
+ "(there is no geo anymore!!)\n");
+
+ //if (geoData->ringnbr > 1) {
+ // PRINTF("WARNING!!! AREA_T ringnbr:%i only exterior ring drawn", geoData->ringnbr);
+ //}
+ //printf("AREAS_T");
+ break;
+ default:
+ //PRINTF("WARNING: invalid object type; %i\n", geoData->obj_t);
+ ;
+ }
+
+
+ /*
+ {
+ int i = 0;
+ switch (geoData->obj_t) {
+ case POINT_T: printf("POINT_T"); break;
+ case LINES_T: printf("LINES_T"); break;
+ case AREAS_T: printf("AREAS_T"); break;
+ default:
+ PRINTF("WARNING: invalid object type; %i\n", geoData->obj_t);
+ }
+ printf("(%i): ", npt);
+
+ for (i=0; i<npt; ++i) {
+ printf("(%f,%f),", ppt[0], ppt[1]);
+ ppt += 3;
+ }
+ printf("\n");
+ }
+ */
+
+ printf("\tS57_ID : %i\n", geoData->id);
+ g_datalist_foreach(&geoData->attribs, _printAtt, NULL);
+
+ return 1;
+}
+
+int S57_initPROJ()
+{
+ if (FALSE == _setNewPROJ)
+ return 1;
+
+ { // setup source projection
+ char *argssrc[] = { "proj=latlong", "ellps=WGS84"};
+ if (!(pjsrc = pj_init(2, argssrc))){
+ PRINTF("error init src PROJ4\n");
+ exit(1);
+ }
+ }
+
+ { // setup destination projection
+ char *argsdst[] = { "proj=merc", "ellps=WGS84","unit=meter" };
+ if (!(pjdst = pj_init(3, argsdst))){
+// char *argsdst[] = { "proj=tmerc", "lon_0=11.8825", "lat_0=55.7290" , "a=6378137", "b=6356752","k=0.99997" };
+// if (!(pjdst = pj_init(6, argsdst))){
+
+ PRINTF("error init dst PROJ4\n");
+ exit(1);
+ }
+ }
+
+ { // GL matrix setup
+ char *args[] = { "proj=merc", "ellps=WGS84" };
+ if (!(pj = pj_init(2, args))){
+// char *args[] = { "proj=tmerc", "lon_0=11.8825", "lat_0=55.7290" , "a=6378137", "b=6356752","k=0.99997" };
+// if (!(pj = pj_init(6, args))){
+ PRINTF("error init src PROJ4\n");
+ exit(1);
+ }
+ }
+
+ // FIXME: will need resetting for different projection
+ _setNewPROJ = FALSE;
+
+ return 1;
+}
+
+int S57_donePROJ()
+{
+ if (NULL != pj) pj_free(pj);
+ if (NULL != pjsrc) pj_free(pjsrc);
+ if (NULL != pjdst) pj_free(pjdst);
+
+ pj = NULL;
+ pjsrc = NULL;
+ pjdst = NULL;
+
+ _setNewPROJ = TRUE;
+
+ return 1;
+}
+
+projXY S57_prj2geo(projUV pixel_xy)
+// convert PROJ to geographic (LL)
+{
+ if (NULL != pj) {
+
+ pixel_xy = pj_inv(pixel_xy, pj);
+ if (0 != pj_errno) {
+ PRINTF("x=%f y=%f %s\n", pixel_xy.u, pixel_xy.v, pj_strerrno(pj_errno));
+ }
+ pixel_xy.u /= DEG_TO_RAD;
+ pixel_xy.v /= DEG_TO_RAD;
+ }
+
+ return pixel_xy;
+}
+
+projXY S57_geo2prj(projUV pixel_xy)
+// convert geographic (LL) to PROJ
+{
+ if (NULL != pj) {
+ pixel_xy.u *= DEG_TO_RAD;
+ pixel_xy.v *= DEG_TO_RAD;
+
+ pixel_xy = pj_fwd(pixel_xy, pj);
+ if (0 != pj_errno) {
+ PRINTF("x=%f y=%f %s\n", pixel_xy.u, pixel_xy.v, pj_strerrno(pj_errno));
+ }
+ }
+
+ return pixel_xy;
+}
+
+
+void S57_getGeoWindowBoundary(double lat, double lng, double scale, int width, int height, double *latMin, double *latMax, double *lngMin, double *lngMax){
+
+ S57_initPROJ();
+
+ {
+ projUV pc1, pc2; // pixel center
+
+ pc1.v = lat;
+ pc1.u = lng;
+
+ pc1 = S57_geo2prj(pc1); // mercator center in meters
+
+ // lower right
+ pc2.u = (width/2. +0.5)*scale + pc1.u;
+ pc2.v = (height/2. +0.5)*scale + pc1.v;
+ pc2 = S57_prj2geo(pc2);
+ *lngMax = pc2.u;
+ *latMax = pc2.v;
+ // upper left
+ pc2.u = -((width/2.)*scale +0.5) + pc1.u;
+ pc2.v = -((height/2.)*scale +0.5) + pc1.v;
+ pc2 = S57_prj2geo(pc2);
+ *lngMin = pc2.u;
+ *latMin = pc2.v;
+ }
+
+ printf("lat/lng: %lf/%lf scale: %lf, w/h: %d/%d lat: %lf/%lf lng: %lf/%lf\n", lat, lng, scale, width, height, *latMin, *latMax, *lngMin, *lngMax);
+
+ //S57_donePROJ();
+
+}
+
+
+#if 0
+int main(int argc, char** argv)
+{
+
+ return 1;
+}
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S57data.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57data.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57data.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,110 @@
+// S57data.h: interface to S57 geo data
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2002-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S57DATA_H_
+#define _S57DATA_H_
+
+#include "S52type.h" // S52_Obj_t
+
+#include <glib.h> // guint, GArray, GData, GString
+#include <proj_api.h> // projXY
+
+typedef double geocoord;
+typedef struct _S57_geo S57_geo;
+typedef struct _S57_prim S57_prim;
+
+
+// FIXME: not called yet
+extern int S57_doneObject(S57_geo *geoData);
+
+extern S57_geo *S57_setPOINT(geocoord x, geocoord y, geocoord z);
+extern S57_geo *S57_setLINES(guint xyznbr, geocoord *xyz);
+extern S57_geo *S57_setAREAS(guint ringnbr, int *ringxyznbr, geocoord **ringxyz);
+extern S57_geo *S57_set_META();
+extern int S57_setName(S57_geo *geoData, const char *name);
+extern char *S57_getName(S57_geo *geoData);
+extern int S57_setOGRGeo(S57_geo *geoData, void *hGeom);
+extern void *S57_getOGRGeo(S57_geo *geoData);
+
+
+// get the number of rings
+extern guint S57_getRingNbr(S57_geo *geoData);
+// get data
+extern int S57_getGeoData(S57_geo *geoData, int ringNo, guint *npt, double **ppt);
+// get cartesian coords
+//extern GArray *S57_getXY(S57_geo *geoData);
+
+// handling of S52/S57 object rendering primitive
+extern S57_prim *S57_initPrim(S57_prim *prim);
+extern S57_prim *S57_donePrim(S57_prim *prim);
+extern S57_prim *S57_initPrimGeo(S57_geo *geoData);
+extern S57_geo *S57_donePrimGeo(S57_geo *geoData);
+extern int S57_begPrim(S57_prim *prim, int data);
+extern int S57_addPrimVertex(S57_prim *prim, double *ptr);
+extern int S57_endPrim(S57_prim *prim);
+extern S57_prim *S57_getPrimGeo(S57_geo *geoData);
+extern S57_prim *S57_getPrimData(S57_prim *prim, int *primNbr, double **vertex);
+extern GArray *S57_getPrimVertex(S57_prim *prim);
+extern int S57_getPrimIdx(S57_prim *prim, int i, int *mode, int *first, int *count);
+extern S57_prim *S57_setPrimSize(S57_prim *prim, int sz);
+
+// get/set extend
+extern int S57_setExt(S57_geo *geoData, double x1, double y1, double x2, double y2);
+extern int S57_getExt(S57_geo *geoData, double *x1, double *y1, double *x2, double *y2);
+// get type (primitive) of object
+extern S52_Obj_t S57_getObjtype(S57_geo *geoData);
+// return TRUE if same point
+extern int S57_samePtPos(S57_geo *geoA, S57_geo *geoB);
+// return S57 attribute value of the attribute name
+extern GString *S57_getAttVal(S57_geo *geoData, char *name);
+// set attribute name and value
+extern GData *S57_setAtt(S57_geo *geoData, const char *name, const char *val);
+// link list of object --return current object in list
+extern S57_geo *S57_linkObj(S57_geo *crnt, S57_geo *geoData);
+// remove the link between objects in list
+extern S57_geo *S57_unlinkObj(S57_geo *geoData);
+// get next geo in list
+extern S57_geo *S57_nextObj(S57_geo *geoData);
+
+// count the number of 'real (6length)' attributes
+extern int S57_getNumAtt(S57_geo *geoData);
+ // return the 'real' attributes of the geodata. name and val must be preallocated, and be sufficient large. (use S57_getNumAtt for counting)
+extern int S57_getAttributes(S57_geo *geoData, char **name, char **val);
+
+
+extern int S57_dumpData(S57_geo *geoData);
+
+extern int S57_initPROJ();
+extern int S57_donePROJ();
+
+
+extern projXY S57_geo2prj(projUV pixel_xy);
+extern projXY S57_prj2geo(projUV pixel_xy);
+
+// returns the window boundary with the current projection. After the geo2prj and initproj have been public, this function may be moved to application layer.
+extern void S57_getGeoWindowBoundary(double lat, double lng, double scale, int width, int height, double *latMin, double *latMax, double *lngMin, double *lngMax);
+
+// PROJ
+
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S57gv.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57gv.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57gv.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,147 @@
+// S57gvgeo.c: interface to OpenEV S57 geo data
+//
+// Project: OpENCview/OpenEV
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#include "S57gv.h"
+#include "S57data.h" // S57_geo
+#include "S52utils.h" // PRINTF()
+#include "gvshapes.h" // GvShape
+#include "gvshapeslayer.h" // GvShapes
+
+//#include "ogr_api.h" // GEOS
+
+//tatic GPtrArray *depareL = g_ptr_array_new();
+
+typedef struct GvShape _srcData;
+
+static int _loadAtt(S57_geo *geoData, GvShape *shape)
+{
+ GvProperties *props = gv_shape_get_properties(shape);
+ int nProp = gv_properties_count(props);
+ int index = 0;
+
+ //printf("SHAPE NO:%i\n", i);
+
+ //g_datalist_init(&geoData->attribs);
+
+ for (index = 0; index<nProp; ++index) {
+ const char *propName = gv_properties_get_name_by_index (props, index);
+ const char *propValue = gv_properties_get_value_by_index(props, index);
+
+ if (NULL == propValue) {
+ PRINTF("gv_properties_value = null \n");
+ exit(0);
+ }
+
+ S57_setAtt(geoData, propName, propValue);
+ }
+
+ return 1;
+}
+
+//S57_geo *S57_gvLoadObject(const char *name, srcData *shape)
+S57_geo *S57_gvLoadObject(const char *name, void *shape)
+// get object geo data from openev GvShape
+// NOTE: caller responsible to free mem for the moment
+{
+ //_S57_geo *geoData = g_new0(_S57_geo, 1);
+ S57_geo *geoData = NULL;
+ int shapetype = 0;
+ GvRect rect;
+
+ S57_initPROJ();
+
+
+ // return empty shape --for pick & Mariners' object
+ if (NULL==shape) {
+ geoData = S57_set_META();
+
+ if (NULL != name)
+ S57_setName(geoData, name);
+
+ return geoData;
+ }
+
+ // mariners' object
+ shapetype = gv_shape_type((GvShape*)shape);
+
+ // check that geometric data type are in sync with OpenGL
+ g_assert(sizeof(geocoord) == sizeof(double));
+
+ // get geo data
+ switch (shapetype) {
+
+ case GVSHAPE_POINT: {
+ GvPointShape *point = (GvPointShape *) shape;
+
+ geoData = S57_setPOINT(point->x, point->y, point->z);
+
+ break;
+ }
+
+ case GVSHAPE_LINE: {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ geoData = S57_setLINES(line->num_nodes, line->xyz_nodes);
+
+ break;
+ }
+
+ case GVSHAPE_AREA: {
+ GvAreaShape *area = (GvAreaShape *) shape;
+
+ geoData = S57_setAREAS(area->num_rings, area->num_ring_nodes, area->xyz_ring_nodes);
+
+ break;
+ // NOTE: check if winding is OK (at load time)
+ }
+
+ case GVSHAPE_COLLECTION: {
+ // ogr SPLIT_MULTIPOINT prob !!
+ //GvCollectionShape *collection = (GvCollectionShape *) shape;
+ //int nCollection = gv_shape_collection_get_count(shape);
+
+ //PRINTF("nCollection = %i\n", nCollection);
+ geoData = S57_set_META();
+
+ break;
+ }
+
+ default: {
+ // FIXME: find a decent default (see openev/gvshapes.h)!!!
+ PRINTF("ERROR: invalid object type GVSHAPE_??? = %i\n", shapetype);
+ }
+ }
+
+ gv_shape_get_extents((GvShape*)shape, &rect);
+ S57_setExt(geoData, rect.x, rect.y, rect.x+rect.width, rect.y+rect.height);
+ S57_setName(geoData, name);
+
+ _loadAtt(geoData, (GvShape*)shape);
+
+ //_dumpData(geoData);
+ if (0 == strcmp(name, "DEPARE")) {
+
+ }
+
+ return geoData;
+}
Added: packages/openev/branches/upstream/current/contrib/S52/S57gv.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57gv.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57gv.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,34 @@
+// S57gv.h: interface to get S57 data from openev (GV)
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2002-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S57GV_H_
+#define _S57GV_H_
+
+#include "S57data.h" // S57_geo
+
+//typedef struct _srcData srcData;
+
+extern S57_geo *S57_gvObjectClone(const char *name, void *shape);
+
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S57ogr.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57ogr.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57ogr.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,342 @@
+// S57ogr.c: interface to OGR S57 object data
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#include "S57ogr.h" // S57_geo
+
+#include "S52utils.h" // PRINTF()
+
+#include "ogr_api.h" // GEOS, OGR
+
+#include <glib.h> // GPtrArray
+
+typedef OGRFeatureH _srcData;
+//typedef struct _srcData OGRFeatureH;
+
+static GPtrArray *_depareL = NULL;
+//static GPtrArray *depcntL = NULL;
+
+// FIXME: *HACK* *HACK* *HACK*
+static int _keepGeom = FALSE; // keep OGR feature im memory to resolve CS
+
+static void _getExtent(OGRGeometryH geometry, S57_geo *geoData)
+{
+ OGREnvelope envelope;
+
+ if (NULL == geometry)
+ return;
+
+ OGR_G_GetEnvelope( geometry, &envelope );
+
+ S57_setExt(geoData, envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);
+
+ return;
+}
+
+
+static int _getGeoPtCount(OGRGeometryH hGeom, int iGeo, OGRGeometryH *hGeomRef )
+{
+ int vert_count = 0;
+
+ *hGeomRef = OGR_G_GetGeometryRef( hGeom, iGeo );
+ if( NULL != *hGeomRef )
+ {
+ vert_count = OGR_G_GetPointCount( *hGeomRef );
+ }
+ else
+ {
+ /* FIXME: something is wrong in OGR if we get here
+ * ie the geometry handle doesn't refer to a geometry!
+ */
+ PRINTF("WARNING: got null geometry\n" );
+ }
+
+ return vert_count;
+}
+
+static int _loadAtt(OGRFeatureH hFeature, S57_geo *geoData)
+{
+ int field_index = 0;
+ int field_count = OGR_F_GetFieldCount(hFeature);
+
+ for (field_index=0; field_index<field_count; ++field_index) {
+ if (OGR_F_IsFieldSet(hFeature, field_index)) {
+ const char *propName = OGR_Fld_GetNameRef(OGR_F_GetFieldDefnRef(hFeature,field_index));
+ const char *propValue = OGR_F_GetFieldAsString(hFeature, field_index);
+
+ S57_setAtt(geoData, propName, propValue);
+ }
+ }
+
+ return 1;
+}
+
+static GPtrArray *_addGeom(GPtrArray *list, S57_geo *geoData)
+{
+ if (NULL == list)
+ list = g_ptr_array_new();
+
+ g_ptr_array_add(list, geoData);
+
+ return list;
+}
+
+static int _keepOGRgeom(const char *layername)
+{
+ // FIXME: could we build this list when loading the PLib !?!
+ if ((0==strncmp(layername, "OBSTRN", 6)) ||
+ (0==strncmp(layername, "DEPARE", 6)) ||
+ (0==strncmp(layername, "DRGARE", 6)) ||
+ (0==strncmp(layername, "UWTROC", 6))
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static int _loadObj(const char *objname, OGRFeatureH hFeature)
+{
+ S57_geo *geoData = S57_ogrLoadObject(objname, hFeature);
+ OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeature);
+
+ _depareL = _addGeom(_depareL, geoData);
+ S57_setOGRGeo(geoData, hGeom);
+
+ return 1;
+}
+
+static int _loadAux(OGRDataSourceH hDS)
+// load auxilary data used to resolve CS
+{
+ { // line and area
+ OGRLayerH depare = OGR_DS_GetLayerByName(hDS, "DEPARE");
+ if (NULL != depare) {
+ S57_ogrLoadLayer("DEPARE", depare, _loadObj);
+ OGR_L_ResetReading(depare);
+ }
+ }
+
+ { // area
+ OGRLayerH drgare = OGR_DS_GetLayerByName(hDS, "DRGARE");
+ if (NULL != drgare) {
+ S57_ogrLoadLayer("DRGARE", drgare, _loadObj);
+ OGR_L_ResetReading(drgare);
+ }
+ }
+
+ return 1;
+}
+
+int S57_ogrLoadCell(const char *filename, _loadLayer_cb cb)
+{
+ int iLayer = 0;
+ OGRDataSourceH hDS;
+ OGRSFDriverH hDriver;
+ OGRLayerH m_covrLayer;
+ const char *drvName = NULL;
+
+ OGRRegisterAll();
+ hDS = OGROpen(filename, FALSE, &hDriver);
+
+ drvName = OGR_Dr_GetName(hDriver);
+
+ _loadAux(hDS);
+
+ for (iLayer=0; iLayer<OGR_DS_GetLayerCount(hDS); ++iLayer) {
+ OGRLayerH ogrlayer = OGR_DS_GetLayer(hDS, iLayer);
+ OGRFeatureDefnH defn = OGR_L_GetLayerDefn(ogrlayer);
+ const char *layername = OGR_FD_GetName(defn);
+
+ cb(layername, ogrlayer);
+ }
+
+ OGR_DS_Destroy (hDS);
+
+ return 1;
+}
+
+int S57_ogrLoadLayer(const char *layername, void *ogrlayer,
+ _loadObj_cb cb)
+{
+ OGRFeatureH hFeature = NULL;
+
+ _keepGeom = _keepOGRgeom(layername);
+
+ while ( NULL != (hFeature = OGR_L_GetNextFeature((OGRLayerH)ogrlayer))) {
+ cb(layername, hFeature);
+
+ if (FALSE == _keepGeom)
+ OGR_F_Destroy(hFeature);
+ }
+
+ return 1;
+}
+
+
+S57_geo *S57_ogrLoadObject(const char *objname, void *feature)
+{
+ S57_geo *geoData = NULL;
+ OGRGeometryH hGeom = OGR_F_GetGeometryRef((srcData*)feature);
+ OGRwkbGeometryType eType = wkbNone;
+
+ // check that geometric data type are in sync with OpenGL
+ //g_assert(sizeof(geocoord) == sizeof(double));
+
+ S57_initPROJ();
+
+ if (NULL != hGeom)
+ eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
+ else
+ geoData = S57_set_META();
+
+ switch (eType) {
+ // POINT
+ case wkbPoint25D:
+ case wkbPoint:
+ geoData = S57_setPOINT(OGR_G_GetX(hGeom, 0),
+ OGR_G_GetY(hGeom, 0),
+ OGR_G_GetZ(hGeom, 0));
+ break;
+
+ // LINE
+ case wkbLineString25D:
+ case wkbLineString: {
+ int idx, node, count = OGR_G_GetPointCount(hGeom);
+ geocoord *linexyz;
+
+ linexyz = g_new(geocoord, 3*count);
+
+ for (idx=0, node=count-1; node>=0; --node) {
+ linexyz[node*3+0] = OGR_G_GetX(hGeom, node);
+ linexyz[node*3+1] = OGR_G_GetY(hGeom, node);
+ linexyz[node*3+2] = OGR_G_GetZ(hGeom, node);
+ }
+
+ geoData = S57_setLINES(count, linexyz);
+
+ break;
+ }
+
+ // AREA
+ case wkbPolygon25D:
+ case wkbPolygon: {
+ OGRGeometryH hRing;
+ int iRing = 0;
+ int nRingCount = OGR_G_GetGeometryCount(hGeom);
+ int *ringxyznbr;
+ geocoord **ringxyz;
+
+ ringxyznbr = g_new(int, nRingCount);
+ ringxyz = g_new(geocoord *, nRingCount);
+
+ for (iRing=0; iRing<nRingCount; ++iRing) {
+ int node;
+ int vert_count = _getGeoPtCount(hGeom, iRing, &hRing);
+
+ ringxyznbr[iRing] = vert_count;
+ ringxyz[iRing] = g_new(geocoord, (vert_count+1)*3*sizeof(geocoord));
+
+ for (node=vert_count-1; node>=0; --node) {
+ ringxyz[iRing][node*3+0] = OGR_G_GetX(hRing, node);
+ ringxyz[iRing][node*3+1] = OGR_G_GetY(hRing, node);
+ ringxyz[iRing][node*3+2] = OGR_G_GetZ(hRing, node);
+ }
+ }
+
+ geoData = S57_setAREAS(nRingCount, ringxyznbr, ringxyz);
+
+ break;
+ }
+
+ case wkbGeometryCollection:
+ case wkbMultiLineString:
+ case wkbMultiPoint:
+ // ogr SPLIT_MULTIPOINT prob !!
+ //GvCollectionShape *collection = (GvCollectionShape *) shape;
+ //int nCollection = gv_shape_collection_get_count(shape);
+
+ //PRINTF("nCollection = %i\n", nCollection);
+
+ //geoData = S57_set_META();
+ //geoData->obj_t = _META_T;
+
+ //break;
+
+ case wkbNone: break; // META_T
+
+ default:
+ // FIXME: find a decent default (see openev/gvshapes.h)!!!
+ PRINTF("invalid object type GVSHAPE_??? = %i %0x\n", eType, eType);
+
+ }
+
+ _getExtent(hGeom, geoData);
+ _loadAtt(feature, geoData);
+ S57_setName(geoData, objname);
+
+ if (TRUE == _keepGeom)
+ S57_setOGRGeo(geoData, hGeom);
+
+ //_dumpData(geoData);
+
+ return geoData;
+}
+
+int S57_ogrTouche(S57_geo *geoData, S52_Obj_t obj_t)
+{
+ int i = 0;
+ OGRGeometryH geom = S57_getOGRGeo(geoData);
+
+ // FIXME: pull geometry at run-time, since we can't tell before hand
+ // if a LUP will call this from CS (via OBSTRN04 for exemple).
+ // Other wise it mean to keep all OGR geometry in memory !!!
+ // Or keep a list of who call this as we build the new lookup table !?
+ // (how about unloading lookup then!) .. need to think this out !
+ if (NULL == geom) {
+ PRINTF("FATAL ERROR: null geometry .. exiting\n");
+ exit(0);
+ }
+
+ for (i=0; i<_depareL->len; ++i) {
+ S57_geo *geo = g_ptr_array_index(_depareL, i);
+ OGRGeometryH area = S57_getOGRGeo(geo);
+
+ // special case (_DEPVAL01) only group 1 is needed
+ // weed out DEPARE of type line
+ if (GRP_1_T==obj_t && AREAS_T!=S57_getObjtype(geo))
+ continue;
+
+ if (TRUE == OGR_G_Touches(area, geom)) {
+ S57_linkObj(geoData, geo);
+ }
+ }
+
+ return 1;
+}
+
+#if 0
+int main(int argc, char** argv)
+{
+
+ return 1;
+}
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/S57ogr.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/S57ogr.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/S57ogr.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,43 @@
+// S57ogr.h: interface to load S57 from OGR
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2002-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#ifndef _S57OGR_H_
+#define _S57OGR_H_
+
+#include "S57data.h" // S57_geo
+#include "S52type.h" // _loadLayer_cb(), _loadObj_cb(), S52_obj_t
+
+typedef struct _srcData srcData;
+
+// callback for each layer to add app. specific stuff
+//typedef void (*_loadLayer_cb)(void *userData);
+
+
+
+extern int S57_ogrLoadCell(const char *filename, _loadLayer_cb cb);
+extern int S57_ogrLoadLayer(const char *layername, void *ogrlayer,
+ _loadObj_cb cb);
+extern S57_geo *S57_ogrLoadObject(const char *objname, void *shape);
+extern int S57_ogrTouche(S57_geo *geoData, S52_Obj_t obj_t);
+#endif
Added: packages/openev/branches/upstream/current/contrib/S52/TODO
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/TODO (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/TODO 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,61 @@
+TODO: jot pad for libS52.so missing stuff, bug, snag, ...
+
+Last update: AUG2004
+
+
+Curent focus (top priority *):
+
+ GEO:
+** -BUG: remove lower priority lines from line/area object
+
+ GL:
+* -use GEOS instead of stencil for CS
+ -add symbol scale factor in config
+ -move centroid inside concave poly for centered symbol
+ -handle overlaping symbol at the center of the window
+ -SCAMIN scale filter (CS: SCANMIN set to INFINITE)
+ -draw text at 'display priority' 8
+ -patern scale spacing (PASP field) not implemented.
+ -compute scale to display sector radius in Nautical Miles
+ -optimise tesselation to triangle fan/strip
+ -handle GLU_TESS_MAX_COORD
+ -glPushAttrib() to save GL state of the caller
+
+
+ PL:
+* -fix breaker color problem in CA49995A.000
+ -signal object that land in layer 0 (ex TOPMAR/CA49995A.000/geo.id:123)
+ -check/validate QUAPOS of spatial (not attribute) object
+ -dump vector (save display list!)
+ -WRECK03
+ -handle update: reparse CS (ex: new value for TX cmd)
+
+ Coding:
+* -jitter/mismatch "Line Style" or "Line Color" with "Area Color"
+ -handle signal (async) from openev (interrupt drawing, ...)
+ -handle multiple cells
+ -test for proper configure of openev when loading libS52.so
+ -thread-safe
+ -check user root
+
+
+In a day:
+ -GL: save display list (somehow!)
+ -PL: Mariner's object
+ -BUG: S-52 specs 3.2 for TOPMAR01 (init 'floating' inside loop)
+ -BUG: chart no 1 PLib put $LINE in layer 0
+ -gv: commit tess combinecallback
+ -gv: commit bizard float->int type cast (warning triggered by tcc)
+ -gv: jitter (probably linker to the defect above)
+ -OGR: validate CRC (the source code is at IHO)
+ -OGR: IHOOCDD.XXX
+ -GL: magnifying glass a la ghostview (debug)
+ -GL: curves
+ -GL: display dipping distance of light
+ -GL: bearing snap to light
+ -connect to postGIS/SQLite!
+ -GPS!
+ -SVG!
+ -WWW!
+ -implement some vector instruction command that are not used now
+ -installation on windows
Added: packages/openev/branches/upstream/current/contrib/S52/doc/C1.lup_collision.txt
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/doc/C1.lup_collision.txt (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/doc/C1.lup_collision.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1412 @@
+Object Class has different display priority
+NEW LUP RecID:44 ObjNm:DAMCON prio:6 rad:S
+TOP LUP RecID:43 ObjNm:DAMCON prio:3 rad:S
+Object Class has different display priority
+NEW LUP RecID:169 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:168 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:170 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:168 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:171 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:168 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:172 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:168 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:173 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:168 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:179 ObjNm:SLOGRD prio:3 rad:S
+TOP LUP RecID:178 ObjNm:SLOGRD prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:189 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:188 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:190 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:188 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:191 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:188 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:212 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:213 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:214 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:215 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:216 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:217 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:218 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:219 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:220 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:221 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:222 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:223 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:224 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:225 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:226 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:211 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:237 ObjNm:$AREAS prio:3 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:239 ObjNm:$AREAS prio:3 rad:S
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:240 ObjNm:$AREAS prio:2 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:241 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:242 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:243 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:244 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:245 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:246 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:247 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:248 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:249 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:250 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:251 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:252 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:253 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:254 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:255 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:256 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:257 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:258 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:259 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:260 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:234 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:299 ObjNm:DAMCON prio:6 rad:S
+TOP LUP RecID:298 ObjNm:DAMCON prio:3 rad:S
+Object Class has different display priority
+NEW LUP RecID:424 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:423 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:425 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:423 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:426 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:423 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:427 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:423 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:428 ObjNm:SBDARE prio:3 rad:S
+TOP LUP RecID:423 ObjNm:SBDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:434 ObjNm:SLOGRD prio:3 rad:S
+TOP LUP RecID:433 ObjNm:SLOGRD prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:444 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:443 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:445 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:443 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:446 ObjNm:TS_FEB prio:4 rad:S
+TOP LUP RecID:443 ObjNm:TS_FEB prio:2 rad:S
+Object Class has different display priority
+NEW LUP RecID:467 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:468 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:469 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:470 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:471 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:472 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:473 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:474 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:475 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:476 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:477 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:478 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:479 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:480 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:481 ObjNm:VEGATN prio:3 rad:S
+TOP LUP RecID:466 ObjNm:VEGATN prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:492 ObjNm:$AREAS prio:3 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:494 ObjNm:$AREAS prio:3 rad:S
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:495 ObjNm:$AREAS prio:2 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:496 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:497 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:498 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:499 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:500 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:501 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:502 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:503 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:504 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:505 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:506 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:507 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:508 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:509 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:510 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:511 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:512 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:513 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:514 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:515 ObjNm:$AREAS prio:5 rad:O
+TOP LUP RecID:489 ObjNm:$AREAS prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:539 ObjNm:CBLSUB prio:6 rad:O
+TOP LUP RecID:538 ObjNm:CBLSUB prio:3 rad:O
+Object Class has different display priority
+NEW LUP RecID:680 ObjNm:$LINES prio:3 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:682 ObjNm:$LINES prio:6 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:683 ObjNm:$LINES prio:6 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:684 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:685 ObjNm:$LINES prio:3 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:686 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:687 ObjNm:$LINES prio:2 rad:S
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:688 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:689 ObjNm:$LINES prio:0 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:690 ObjNm:$LINES prio:0 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:691 ObjNm:$LINES prio:4 rad:S
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:692 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:693 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:694 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:695 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:696 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:697 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:698 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:699 ObjNm:$LINES prio:3 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:700 ObjNm:$LINES prio:3 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:701 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:702 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:703 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:704 ObjNm:$LINES prio:9 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:705 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:706 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:707 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:708 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:709 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:710 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:711 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:712 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:713 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:714 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:715 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:716 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:717 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:718 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:719 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:720 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:721 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:722 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:723 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:724 ObjNm:$LINES prio:5 rad:O
+TOP LUP RecID:679 ObjNm:$LINES prio:5 rad:S
+Object Class has different display priority
+NEW LUP RecID:820 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:821 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:822 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:823 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:824 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:825 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:826 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:827 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:828 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:829 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:830 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:832 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:819 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:850 ObjNm:CURENT prio:5 rad:O
+TOP LUP RecID:849 ObjNm:CURENT prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:851 ObjNm:CURENT prio:5 rad:O
+TOP LUP RecID:849 ObjNm:CURENT prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:853 ObjNm:DAMCON prio:4 rad:O
+TOP LUP RecID:852 ObjNm:DAMCON prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:888 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:889 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:890 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:891 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:892 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:893 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:894 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:895 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:896 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:898 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:899 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:900 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:901 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:902 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:903 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:904 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:905 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:906 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:907 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:908 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:909 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:910 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:911 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:912 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:913 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:914 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:924 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:887 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:937 ObjNm:MORFAC prio:8 rad:O
+TOP LUP RecID:932 ObjNm:MORFAC prio:6 rad:O
+Object Class has different display priority
+NEW LUP RecID:948 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:949 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:950 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:951 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:952 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:953 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:954 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:955 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:947 ObjNm:PRDARE prio:0 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:1055 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1056 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1057 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1058 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1059 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1060 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1061 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1062 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1063 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1064 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1065 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1068 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1069 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1070 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1071 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1072 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1077 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1078 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1079 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1080 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1081 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1082 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1083 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1084 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1085 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1086 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1087 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1088 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1089 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1090 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1091 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1092 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1093 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1094 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1095 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1096 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1097 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1098 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1099 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1100 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1101 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1102 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different RADAR priority
+NEW LUP RecID:1103 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different RADAR priority
+NEW LUP RecID:1104 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1105 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1106 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1107 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1108 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1109 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1110 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1111 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1112 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1113 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1114 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1115 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1116 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1117 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1118 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1119 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1120 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1122 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1123 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1124 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1125 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1127 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1128 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1129 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1130 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1131 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1132 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1133 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1134 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1135 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1136 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1137 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1138 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1139 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1140 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1141 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1054 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1236 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1237 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1238 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1239 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1240 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1241 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1242 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1243 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1244 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1245 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1246 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1248 ObjNm:BUISGL prio:6 rad:O
+TOP LUP RecID:1235 ObjNm:BUISGL prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1266 ObjNm:CURENT prio:5 rad:O
+TOP LUP RecID:1265 ObjNm:CURENT prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1267 ObjNm:CURENT prio:5 rad:O
+TOP LUP RecID:1265 ObjNm:CURENT prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1269 ObjNm:DAMCON prio:4 rad:O
+TOP LUP RecID:1268 ObjNm:DAMCON prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1304 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1305 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1306 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1307 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1308 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1309 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1310 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1311 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1312 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1314 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1315 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1316 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1317 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1318 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1319 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1320 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1321 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1322 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1323 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1324 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1325 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1326 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1327 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1328 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1329 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1330 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1349 ObjNm:LNDMRK prio:6 rad:O
+TOP LUP RecID:1303 ObjNm:LNDMRK prio:4 rad:O
+Object Class has different display priority
+NEW LUP RecID:1358 ObjNm:MORFAC prio:8 rad:O
+TOP LUP RecID:1357 ObjNm:MORFAC prio:6 rad:O
+Object Class has different display priority
+NEW LUP RecID:1359 ObjNm:MORFAC prio:8 rad:O
+TOP LUP RecID:1357 ObjNm:MORFAC prio:6 rad:O
+Object Class has different display priority
+NEW LUP RecID:1364 ObjNm:MORFAC prio:8 rad:O
+TOP LUP RecID:1357 ObjNm:MORFAC prio:6 rad:O
+Object Class has different display priority
+NEW LUP RecID:1375 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1376 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1377 ObjNm:PRDARE prio:4 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1378 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1379 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1380 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1381 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different display priority
+NEW LUP RecID:1382 ObjNm:PRDARE prio:3 rad:O
+TOP LUP RecID:1374 ObjNm:PRDARE prio:0 rad:S
+Object Class has different RADAR priority
+NEW LUP RecID:1482 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1483 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1484 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1485 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1486 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1487 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1488 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1489 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1490 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1491 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1492 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1495 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1496 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1497 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1498 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1499 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1504 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1505 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1506 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1507 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1508 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1509 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1510 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1511 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1512 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1513 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1514 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1515 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1516 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1517 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1518 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1519 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1520 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1521 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1522 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1523 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1524 ObjNm:$CSYMB prio:6 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1525 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1526 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1527 ObjNm:$CSYMB prio:4 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1528 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1529 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different RADAR priority
+NEW LUP RecID:1530 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different RADAR priority
+NEW LUP RecID:1531 ObjNm:$CSYMB prio:5 rad:S
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1532 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1533 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1534 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1535 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1536 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1537 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1538 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1539 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1540 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1541 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1542 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1543 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1544 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1545 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1546 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1547 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1549 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1550 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1551 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1552 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1554 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1555 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1556 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1557 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1558 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1559 ObjNm:$CSYMB prio:7 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1560 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1561 ObjNm:$CSYMB prio:9 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1562 ObjNm:$CSYMB prio:8 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1563 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1564 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1565 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1566 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1567 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+Object Class has different display priority
+NEW LUP RecID:1568 ObjNm:$CSYMB prio:4 rad:O
+TOP LUP RecID:1481 ObjNm:$CSYMB prio:5 rad:O
+;S52_dummy.BRIGHT.txt: dummy RBG value for S52 color table DAY_BRIGHT
+;
+;
+NODTA 171 192 177
+CURSR 230 121 56
+CHBLK 0 0 0
+CHGRD 136 152 139
+CHGRF 171 192 177
+CHRED 238 90 108
+CHGRN 124 240 91
+CHYLW 243 229 77
+CHMGD 198 77 187
+CHMGF 212 177 221
+CHBRN 182 157 64
+CHWHT 216 244 225
+SCLBR 230 121 56
+CHCOR 230 121 56
+LITRD 238 90 108
+LITGN 124 240 91
+LITYW 243 229 77
+ISDNG 198 77 187
+DNGHL 238 90 108
+TRFCD 198 77 187
+TRFCF 212 177 221
+LANDA 204 197 123
+LANDF 147 116 39
+CSTLN 95 106 96
+SNDG1 136 152 139
+SNDG2 0 0 0
+DEPSC 95 106 96
+DEPCN 136 152 139
+DEPDW 216 244 225
+DEPMD 192 225 214
+DEPMS 162 210 229
+DEPVS 129 195 226
+DEPIT 143 191 147
+RADHI 82 153 60
+RADLO 124 240 91
+ARPAT 82 153 60
+NINFO 230 121 56
+RESBL 76 135 227
+ADINF 184 172 60
+RESGR 136 152 139
+SHIPS 0 0 0
+PSTRK 0 0 0
+SYTRK 136 152 139
+PLRTE 218 70 45
+APLRT 230 121 56
+UINFD 0 0 3
+UINFF 240 240 240
+UIBCK 150 150 150
+UIAFD 220 220 220
+UINFR 251 95 99
+UINFG 75 210 86
+UINFO 255 240 70
+UINFB 54 130 244
+UINFM 200 72 201
+UIBDR 125 125 125
+UIAFF 185 185 185
+OUTLW 0 0 0
+OUTLL 204 197 123
+RES01 171 192 177
+RES02 171 192 177
+RES03 171 192 177
+BKAJ1 0 0 0
+BKAJ2 0 0 0
+Line LUP :67
+Area Plain LUP :119
+Area Symbolized LUP :119
+Point Simplified LUP :116
+Point Paper Chart LUP:116
+Line Symbology :52
+Pattern Symbology :25
+Symbol Symbology :446
+Conditional Symbology:26
+gv_S57_layer_class_init
+NAME: ACHARE
+LAYER NAME: ACHARE (2)
+NAME: BCNSPP
+LAYER NAME: BCNSPP (1)
+perfect match: break here with debugger line 363
+NAME: BUISGL
+LAYER NAME: BUISGL (2)
+NAME: BOYCAR
+LAYER NAME: BOYCAR (1)
+perfect match: break here with debugger line 363
+NAME: BOYSPP
+LAYER NAME: BOYSPP (2)
+NAME: COALNE
+LAYER NAME: COALNE (4)
+NAME: CRANES
+LAYER NAME: CRANES (1)
+NAME: DAMCON
+LAYER NAME: DAMCON (1)
+NAME: DEPARE
+LAYER NAME: DEPARE (12)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: DEPCNT
+LAYER NAME: DEPCNT (6)
+NAME: DRGARE
+LAYER NAME: DRGARE (1)
+NAME: DMPGRD
+LAYER NAME: DMPGRD (1)
+perfect match: break here with debugger line 363
+NAME: HULKES
+LAYER NAME: HULKES (1)
+NAME: LNDARE
+LAYER NAME: LNDARE (3)
+NAME: LNDMRK
+LAYER NAME: LNDMRK (7)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: LIGHTS
+LAYER NAME: LIGHTS (3)
+NAME: NAVLNE
+LAYER NAME: NAVLNE (2)
+NAME: OBSTRN
+LAYER NAME: OBSTRN (2)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: PIPOHD
+LAYER NAME: PIPOHD (1)
+perfect match: break here with debugger line 363
+NAME: PIPSOL
+LAYER NAME: PIPSOL (1)
+NAME: RECTRC
+LAYER NAME: RECTRC (2)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: RESARE
+LAYER NAME: RESARE (1)
+NAME: SBDARE
+LAYER NAME: SBDARE (13)
+NAME: SLCONS
+LAYER NAME: SLCONS (18)
+NAME: SILTNK
+LAYER NAME: SILTNK (1)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: SLOTOP
+LAYER NAME: SLOTOP (4)
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+perfect match: break here with debugger line 363
+NAME: SLOGRD
+LAYER NAME: SLOGRD (1)
+NAME: SOUNDG
+LAYER NAME: SOUNDG (0)
+NAME: SWPARE
+LAYER NAME: SWPARE (1)
+NAME: TOPMAR
+LAYER NAME: TOPMAR (1)
+NAME: UWTROC
+LAYER NAME: UWTROC (3)
+NAME: M_ACCY
+LAYER NAME: M_ACCY (1)
+NAME: M_COVR
+LAYER NAME: M_COVR (1)
+NAME: M_NSYS
+LAYER NAME: M_NSYS (1)
+NAME: M_QUAL
+LAYER NAME: M_QUAL (1)
+perfect match: break here with debugger line 363
+NAME: C_AGGR
+LAYER NAME: C_AGGR (0)
+NAME: C_ASSO
+LAYER NAME: C_ASSO (0)
Added: packages/openev/branches/upstream/current/contrib/S52/doc/att.txt
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/doc/att.txt (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/doc/att.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8812 @@
+ S-57 Appendix A Chapter 2 - Attributes Edition 3.0
+ CONTENTS
+
+Acronym Code
+
+ 2.1 Introduction 2.1
+
+
+
+ 2.2 Feature Object Attributes
+ 2.3
+ Agency responsible for production AGENCY 1 2.4
+ Beacon shape BCNSHP 2 2.5
+ Building shape BUISHP 3 2.6
+ Buoy shape BOYSHP 4 2.7
+ Buried depth BURDEP 5 2.8
+ Call sign CALSGN 6 2.9
+ Category of airport/airfield CATAIR 7 2.10
+ Category of anchorage CATACH 8 2.11
+ Category of bridge CATBRG 9 2.12
+ Category of building, single CATBUI 2.14
+ Category of built-up area CATBUA 10 2.15
+ Category of cable CATCBL 11 2.16
+ Category of canal CATCAN 12 2.17
+ Category of cardinal mark CATCAM 13 2.18
+ Category of checkpoint CATCHP 14 2.19
+ Category of coastline CATCOA 15 2.20
+ Category of control point CATCTR 16 2.22
+ Category of conveyor CATCON 17 2.23
+ Category of coverage CATCOV 18 2.24
+ Category of crane CATCRN 19 2.25
+ Category of dam CATDAM 20 2.26
+ Category of distance mark CATDIS 21 2.27
+ Category of dock CATDOC 22 2.28
+ Category of dumping ground CATDPG 23 2.29
+ Category of dyke CATDYK 2.30
+ Category of fence/wall CATFNC 24 2.31
+ Category of ferry CATFRY 25 2.32
+ Category of fishing facility CATFIF 26 2.33
+ Category of fog signal CATFOG 27 2.34
+ Category of fortified structure CATFOR 28 2.36
+ Category of gate CATGAT 29 2.37
+ Category of harbour facility CATHAF 30 2.38
+ Category of hulk CATHLK 31 2.39
+ Category of ice CATICE 32 2.40
+ Category of installation buoy CATINB 33 2.41
+ Category of land region CATLND 34 2.42
+ Category of landmark CATLMK 35 2.44
+ Category of lateral mark CATLAM 36 2.46
+ Category of light CATLIT 37 2.47
+ Category of marine farm/culture CATMFA 38 2.49
+ Category of mast CATMST 2.50
+ Category of military practice area CATMPA 39 2.51
+ Category of monument CATMNT 2.52
+ Category of mooring/warping facility CATMOR 40 2.53
+ Category of navigation line CATNAV 41 2.54
+ Category of obstruction CATOBS 42 2.55
+ Category of offshore platform CATOFP 43 2.57
+ Category of oil barrier CATOLB 44 2.59
+ Category of pile CATPLE 45 2.60
+ Category of pilot boarding place CATPIL 46 2.61
+ Category of pipeline/pipe CATPIP 47 2.62
+ Category of production area CATPRA 48 2.63
+ Category of production installation CATPRI 2.64
+ Category of pylon CATPYL 49 2.65
+ Category of quality of data CATQUA 50 2.66
+ Category of radar station CATRAS 51 2.67
+ Category of radar transponder beacon CATRTB 52 2.68
+ Category of radio station CATROS 53 2.69
+ Category of recommended track CATTRK 54 2.71
+ Category of religious building CATREB 2.72
+ Category of rescue station CATRSC 55 2.73
+ Category of restricted area CATREA 56 2.74
+ Category of road CATROD 57 2.76
+ Category of runway CATRUN 58 2.77
+ Category of sea area CATSEA 59 2.78
+ Category of shoreline construction CATSLC 60 2.83
+ Category of signal station, traffic CATSIT 61 2.85
+ Category of signal station, warning CATSIW 62 2.86
+ Category of silo/tank CATSIL 63 2.88
+ Category of slope CATSLO 64 2.89
+ Category of small craft facility CATSCF 65 2.90
+ Category of special purpose mark CATSPM 66 2.92
+ Category of Tidal Stream CAT_TS 188 2.96
+ Category of tower CATTOW 2.97
+ Category of Traffic Separation Scheme CATTSS 67 2.98
+ Category of tree CATTRE 2.99
+ Category of vegetation CATVEG 68 2.100
+ Category of water turbulence CATWAT 69 2.102
+ Category of weed/kelp CATWED 70 2.103
+ Category of wreck CATWRK 71 2.104
+ Category of zone of confidence in data CATZOC 72 2.105
+ Character spacing $SPACE 73 2.108
+ Character specification $CHARS 74 2.109
+ Colour COLOUR 75 2.110
+ Colour of navigational mark COLMAR 2.111
+ Colour pattern COLPAT 76 2.112
+ Communication channel COMCHA 77 2.113
+ Compass size $CSIZE 78 2.114
+ Compilation date CPDATE 79 2.115
+ Compilation scale CSCALE 80 2.116
+ Condition CONDTN 81 2.117
+ Conspicuous, radar CONRAD 82 2.118
+ Conspicuous, visually CONVIS 83 2.119
+ Current velocity CURVEL 84 2.120
+ Date end DATEND 85 2.121
+ Date start DATSTA 86 2.122
+ Depth range value 1 DRVAL1 87 2.123
+ Depth range value 2 DRVAL2 88 2.124
+ Depth units DUNITS 89 2.125
+ Elevation ELEVAT 90 2.126
+ Estimated range of transmission ESTRNG 91 2.127
+ Exhibition condition of light EXCLIT 92 2.128
+ Exposition of sounding EXPSOU 93 2.129
+ Function FUNCTN 94 2.130
+ Height HEIGHT 95 2.133
+ Height/length units HUNITS 96 2.134
+ Horizontal accuracy HORACC 97 2.135
+ Horizontal clearance HORCLR 98 2.136
+ Horizontal length HORLEN 99 2.137
+ Horizontal width HORWID 100 2.138
+ Ice factor ICEFAC 101 2.139
+ Information INFORM 102 2.140
+ Jurisdiction JRSDTN 103 2.141
+ Justification - horizontal $JUSTH 104 2.142
+ Justification - vertical $JUSTV 105 2.143
+ Lifting capacity LIFCAP 106 2.144
+ Light characteristic LITCHR 107 2.145
+ Light visibility LITVIS 108 2.147
+ Marks navigational - System of MARSYS 109 2.148
+ Multiplicity of lights MLTYLT 110 2.149
+ Nationality NATION 111 2.150
+ Nature of construction NATCON 112 2.151
+ Nature of surface NATSUR 113 2.152
+ Nature of surface - qualifying terms NATQUA 114 2.154
+ Notice to Mariners date NMDATE 115 2.156
+ Object name OBJNAM 116 2.157
+ Orientation ORIENT 117 2.158
+ Periodic date end PEREND 118 2.159
+ Periodic date start PERSTA 119 2.160
+ Pictorial representation PICREP 120 2.161
+ Pilot district PILDST 121 2.162
+ Positional accuracy units PUNITS 189 2.163
+ Producing country PRCTRY 122 2.164
+ Product PRODCT 123 2.165
+ Publication reference PUBREF 124 2.167
+ Quality of sounding measurement QUASOU 125 2.168
+ Quality of vertical measurement QUAVEM 2.170
+ Radar wave length RADWAL 126 2.171
+ Radius RADIUS 127 2.172
+ Recording date RECDAT 128 2.173
+ Recording indication RECIND 129 2.174
+ Reference year for magnetic variation RYRMGV 130 2.175
+ Restriction RESTRN 131 2.176
+ Scale maximum SCAMAX 132 2.178
+ Scale minimum SCAMIN 133 2.179
+ Scale value one SCVAL1 134 2.180
+ Scale value two SCVAL2 135 2.181
+ Sector limit one SECTR1 136 2.182
+ Sector limit two SECTR2 137 2.183
+ Shift parameters SHIPAM 138 2.184
+ Signal frequency SIGFRQ 139 2.186
+ Signal generation SIGGEN 140 2.187
+ Signal group SIGGRP 141 2.188
+ Signal period SIGPER 142 2.189
+ Signal sequence SIGSEQ 143 2.190
+ Sounding accuracy SOUACC 144 2.191
+ Sounding distance - maximum SDISMX 145 2.192
+ Sounding distance - minimum SDISMN 146 2.193
+ Source date SORDAT 147 2.194
+ Source indication SORIND 148 2.195
+ Status STATUS 149 2.196
+ Supervision of light SUPLIT 2.198
+ Survey authority SURATH 150 2.199
+ Survey date - end SUREND 151 2.200
+ Survey date - start SURSTA 152 2.201
+ Survey type SURTYP 153 2.202
+ Symbol scaling factor $SCALE 154 2.203
+ Symbolization code $SCODE 155 2.204
+ Technique of sounding measurement TECSOU 156 2.205
+ Text string $TXSTR 157 2.207
+ Textual description TXTDSC 158 2.208
+ Tidal stream - panel values TS_TSP 159 2.209
+ Tidal stream, current -time series values TS_TSV 160 2.210
+ Tide - accuracy of water level T_ACWL 161 2.211
+ Tide - high and low water values T_HWLW 162 2.212
+ Tide - method of tidal prediction T_MTOD 163 2.213
+ Tide - time and height differences T_THDF 164 2.214
+ Tide - time series values T_TSVL 166 2.215
+ Tide - value of harmonic constituents T_VAHC 167 2.216
+ Tide, current - time interval of values T_TINT 165 2.217
+ Time end TIMEND 168 2.218
+ Time start TIMSTA 169 2.219
+ Tint $TINTS 170 2.220
+ Topmark/daymark shape TOPSHP 171 2.221
+ Traffic flow TRAFIC 172 2.224
+ Value of annual change in magnetic variation VALACM 173 2.225
+ Value of depth contour VALDCO 174 2.226
+ Value of local magnetic anomaly VALLMA 175 2.227
+ Value of magnetic variation VALMAG 176 2.228
+ Value of maximum range VALMXR 177 2.229
+ Value of nominal range VALNMR 178 2.230
+ Value of sounding VALSOU 179 2.231
+ Vertical accuracy VERACC 180 2.232
+ Vertical clearance VERCLR 181 2.233
+ Vertical clearance, closed VERCCL 182 2.234
+ Vertical clearance, open VERCOP 183 2.235
+ Vertical clearance, safe VERCSA 184 2.236
+ Vertical datum VERDAT 185 2.237
+ Vertical length VERLEN 186 2.241
+ Water level effect WATLEV 187 2.242
+
+ 2.3 National Language Attributes 2.243
+ Information in national language NINFOM 300 2.244
+ Object name in national language NOBJNM 301 2.245
+ Pilot district in national language NPLDST 302 2.246
+ Text string in national language $NTXST 303 2.247
+ Textual description in national language NTXTDS 304 2.248
+
+ 2.4 Spatial and Meta Object Attributes 2.249
+ Horizontal datum HORDAT 400 2.250
+ Positional Accuracy POSACC 401 2.253
+ Quality of position QUAPOS 402 2.254
+
+
+2.1 Introduction
+
+Each attribute is specified in a standardized way, under the following headings:
+
+ Attribute: Attribute name.
+
+ Acronym: six character code for the Attribute.
+
+ Code: integer code to be used in the coding of data.
+
+ Attribute type: one character code for the Attribute type (see below)
+
+ Each Attribute is assigned to one of six types:
+
+ * enumerated (E'): The expected input is a number selected from a list of pre- defined attribute values. Exactly one value must be chosen. The abbreviation for this type is E'.
+
+ * list (L'): The expected input is a list of one or more numbers selected from a list of pre-defined attribute values. Where more than one value is used, they must normally be separated by commas but in special cases slashes ("/") may be used. The abbreviation for this type is L'.
+
+ Note: In some cases, dependency exists between different attributes of a given object e.g. a bridge (BRIDGE) may have the values concreted' and iron/steel' for the attribute NATCON (Nature of Construction) and the values red' and green' for the attribute COLOUR. Even if it is known that the concreted part of the bridge is red and the iron/steel part is green, the Object Catalogue provides no means of indicating this relationship. However, such relationships may be formalized for a given application in which case the relationship must be described in the appropriate Product Specification (see S-57 Appendix B).
+
+ * float (F'): The expected input is a floating point numeric value with defined range, resolution, units and format. The abbreviation for this type is F'.
+
+ * integer (I'): The expected input is an integer numeric value with defined range, units and format. The abbreviation for this type is I'.
+
+ * coded string (A'): The expected input is a string of ASCII characters in a predefined format. The information is encoded according to defined coding systems e.g.: the nationality will be encoded by a two character field specified by ISO 3166 Codes for the Representation of Names of Countries', e.g. Canada => CA' (refer to S-57 Appendix A Annex A). The abbreviation for this type is A'.
+
+ * free text (S'): The expected input is a free-format alphanumeric string. It may be a file name which points to a text or graphic file. The abbreviation for this type is S'.
+
+ Expected input:
+
+ Depending on the attribute type, the expected input is defined in the following ways:
+
+ For E' and L' type attributes a list of ID-numbers with associated, defined, meanings is given. Where an attribute value which appeared in a previous edition of the Standard is no longer used, it is retained in the list but is struck-through.
+
+ For A', F', I' and S'-type attributes the expected input is indicated in accordance with the type (see above).
+
+ In certain circumstances, it may be necessary to indicate to the recipient of a data set that the value of a certain attribute for an instance of an object class is unknown. This fact is encoded by a zero length attribute value sub-field, e.g. COLOUR (where is the subfield delimiter). This applies to all attribute types (see S-57 Part 3 clause 2.1).
+
+ Definitions: a definition of the Attribute, or in the case of E' or L' type Attributes, a definition of each value of an Attribute.
+
+ References:
+
+ * INT 1: Reference to the system of numbering for the paper chart feature as used in the International Chart Series INT 1 - Symbols, Abbreviations, Terms used on Charts'. INT 1 was one of the major guidelines for the definition of attributes.
+
+ * M-4: Reference to the paragraph number in the Chart Specifications of the IHO', M-4. This was another guideline for the definition and description of the attributes.
+
+ Minimum Value: The minimum value for the expected input is indicated for floating point and integer attributes.
+
+ Maximum Value: The maximum value for the expected input is indicated for floating point and integer attributes.
+
+ Remarks: Under Remarks', further comments and notes may be given.
+
+Depending on the type of attribute, the following information is provided:
+
+ Indication: For coded string type attributes (S) it indicates the construction of the string.
+
+ For integer (I) and floating point (F) type attributes it indicates the units and resolution of the input.
+
+ Format: The Format' statement indicates the recommended standard input template. Attributes that are identified as requiring a mandatory format, are indicated by the term (mandatory). For other attributes, the format can be either implied by the domain of valid attribute values or will be variable in length depending on the attribute and its data type.
+
+ Example: an example of coded input.
+
+There are five National Language Attributes which are defined in Section 2.3. These are all string type attributes intended to hold text in a national language.
+
+There are three Attributes that are defined as attributes of spatial objects. For further information see Section 2.4. 2.2 Feature Object Attributes
+
+FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: AGENCY Code: 1
+Agency responsible for production AGENCY 1
+Attribute type: A
+
+
+Definition:
+
+ This attribute identifies the agency which produced the data.
+
+References:
+
+ INT 1: not specified;
+
+ M-4: not specified;
+
+Indication:
+
+ The agency is encoded by a two character code derived from ISO3166 (refer to S-57 Appendix A Annex A).
+
+Format:
+
+ c2 (mandatory)
+
+Remarks:
+
+ No remarks.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: BCNSHP Code: 2
+Beacon shape BCNSHP 2
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : stake, pole, perch, post IQ 90; 456.1;
+ 2 : withy IQ 92; 456.1;
+ 3 : beacon tower IQ 110; 456.4;
+ 4 : lattice beacon IQ 111; 456.4;
+ 5 : pile beacon
+ 6 : cairn IQ 100; 456.2;
+ 7 : buoyant beacon 459.1;
+
+Definitions:
+
+stake, pole, perch, post:
+ an elongated wood or metal pole, embedded in the bottom to serve as a navigational aid or a support for a navigational aid. (adapted from IHO Dictionary S-32, 5th Edition, 4960)
+
+withy : a tree without roots stuck or spoiled into the bottom of the sea to serve as a navigational aid.
+
+beacon tower: a solid structure of the order of 10 metres in height used as a navigational aid.
+
+lattice beacon: a structure consisting of strips of metal or wood crossed or interlaced to form a structure to serve as an aid to navigation or as a support for an aid to navigation.
+
+pile beacon: a long heavy timber(s) or section(s) of steel, wood, concrete, etc., forced into the seabed to serve as an aid to navigation or as a support for an aid to navigation.(Adapted from IHO Dictionary, S-32, 5th Edition, 3840 and Navigation Dictionary, US National Oceanic and Atmospheric Administration - NOAA, 1969)
+
+cairn: a mound of stones, usually conical or pyramidal, raised specifically for maritime navigation. (adapted from IHO Dictionary, S-32, 5th Edition, 601).
+
+buoyant beacon: a tall spar-like beacon fitted with a permanently submerged buoyancy chamber, the lower end of the body is secured to seabed sinker either by a flexible joint or by a cable under tension. (IHO Specifications, M-4, 459.1)
+
+Remarks:
+
+ The beacon shape describes the characteristic geometric form of the beacon. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: BUISHP Code: 3
+Building shape BUISHP 3
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : no specific shape
+ 2 : tower
+ 3 : spire
+ 4 : cupola (dome)
+ 5 : high-rise building
+ 6 : pyramid
+ 7 : cylindrical
+ 8 : spherical
+ 9 : cubic
+
+Definitions:
+
+high-rise building: a building having many storeys. (The New Shorter Oxford English Dictionary, 1993)
+
+pyramid: a polyhedron of which one face is a polygon of any number of sides, and the other faces are triangles with a common vertex. (The New Shorter Oxford English Dictionary, 1993)
+
+cylindrical: shaped like a cylinder, which is a solid geometrical figure generated by straight lines fixed in direction and describing with one of its points a closed curve, especially a circle. (The New Shorter Oxford English Dictionary, 1993)
+
+spherical: shaped like a sphere, which is a body the surface of which is at all points equidistant from the centre. (The New Shorter Oxford English Dictionary, 1993)
+
+cubic: a shape the sides of which are six equal squares; a regular hexahedron. (The New Shorter Oxford English Dictionary, 1993)
+
+Remarks:
+
+ The attribute `building shape` encodes some specific shapes of buildings.
+
+Values 2, 3 and 4 (tower, spire, and cupola/dome) have been transferred to the attribute category of landmark (CATLMK). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: BOYSHP Code: 4
+Buoy shape BOYSHP 4
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : conical (nun, ogival) IQ 20; 462.2
+ 2 : can (cylindrical) IQ 21; 462.3
+ 3 : spherical IQ 22; 462.4
+ 4 : pillar IQ 23; 462.5
+ 5 : spar (spindle) IQ 24; 462.6
+ 6 : barrel (tun) IQ 25; 462.7
+ 7 : super-buoy IQ 26; 462.9
+ 8 : ice buoy
+
+Definitions:
+
+conical/nun/ogival: the upper part of the body above the water-line, or the greater part of the superstructure, has approximately the shape or the appearance of a pointed cone with the point upwards.
+
+can/cylindrical: the upper part of the body above the water-line, or the greater part of the superstructure, has the shape of a cylinder, or a truncated cone that approximates to a cylinder, with a flat end uppermost.
+
+spherical: the upper part of the body above the water-line, or the greater part of the superstructure, has the shape of a part of a sphere.
+
+pillar: the upper part of the body above the water-line, or the greater part of the superstructure is a narrow vertical structure, pillar or lattice tower.
+
+spar/spindle: the upper part of the body above the water-line, or the greater part of the superstructure, has the form of a pole, or of a very long cylinder, floating upright.
+
+barrel: the upper part of the body above the water-line, or the greater part of the superstructure, has the form of a barrel or cylinder floating horizontally.
+
+super-buoy: a very large buoy, generally more than 5m in diameter.
+
+ice buoy: a specially constructed shuttle shaped buoy which is used in ice conditions.
+
+Remarks:
+
+ The principal shapes are those recommended in the International Association of Lighthouse Authorities - IALA System. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: BURDEP Code: 5
+Buried depth BURDEP 5
+Attribute type: F
+
+
+Definition:
+
+ The depth below the sea bed to which an object is buried.
+
+
+References:
+
+ INT 1: IL 42;
+
+ M-4: 444.5:
+
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 2.5 for a depth of 2.5 metres.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CALSGN Code: 6
+Call sign CALSGN
+Attribute type: S
+
+
+Definition:
+
+ The designated call-sign of a radio station.
+
+References:
+
+ INT 1: not specified;
+
+ M-4: not specified;
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATAIR Code: 7
+Category of airport/airfield CATAIR 7
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : military aeroplane airport
+ 2 : civil aeroplane airport
+ 3 : military heliport
+ 4 : civil heliport
+ 5 : glider airfield
+ 6 : small planes airfield
+ 7 : helicopter platform
+ 8 : emergency airfield
+
+Definitions:
+
+military aeroplane airport:
+ a large military airfield usually equipped with a control tower, hangars and accommodation for the receiving and discharging of passengers or cargo. (adapted from The Macquarie Dictionary, 1988)
+
+civil aeroplane airport: a large airfield usually equipped with a control tower, hangars and accommodation for the receiving and discharging of passengers or cargo. (The Macquarie Dictionary, 1988)
+
+military heliport: a landing place for helicopters controlled by the military.
+
+civil heliport: a landing place for helicopters, often the roof of a building. (The Macquarie Dictionary, 1988)
+
+glider airfield: an area of land set aside for the take-off and landing of gliders.
+
+small planes airfield: an area of land set aside for the take-off and landing of small aeroplanes.
+
+emergency airfield: an area of land set aside for the take-off and landing of aeroplanes or helicopters in times of emergency.
+
+Remarks:
+
+ No remarks.
+
+Value number 7 (helicopter platform) has been transferred to the attribute category of runway (CATRUN). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATACH Code: 8
+Category of anchorage CATACH 8
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : unrestricted anchorage
+ 2 : deep water anchorage IN 12.4; 431.3;
+ 3 : tanker anchorage IN 12.5; 431.3;
+ 4 : explosives anchorage IN 12.7; 431.3;
+ 5 : quarantine anchorage IN 12.8; 431.3;
+ 6 : sea-plane anchorage IN 14; 449.6;
+ 7 : small craft anchorage
+ 8 : small craft mooring area IQ 44; 431.7;
+ 9 : anchorage for periods up to 24 hours IN 12.6; 431.3;
+
+Definitions:
+
+unrestricted anchorage: an area in which vessels anchor or may anchor. (IHO Dictionary, S-32, 5th Edition, 130)
+
+deep water anchorage: an area in which vessels of deep draught anchor or may anchor.
+
+tanker anchorage: an area in which tankers anchor or may anchor.
+
+explosives anchorage: an area set apart for anchored ships discharging or receiving explosives. (IHO Dictionary, S-32, 5th Edition, 1732)
+
+quarantine anchorage: an area where a vessel anchors when satisfying quarantine regulations. (IHO Dictionary, S-32, 5th Edition, 4117)
+
+sea-plane anchorage: an area in which sea-planes anchor or may anchor.
+
+small craft anchorage: an area in which yachts and small boats anchor or may anchor.
+
+small craft mooring area:
+ an area in which yachts and small boats moor.
+
+anchorage for periods up to 24 hours:
+ an area in which vessels anchor or may anchor for periods of up to 24 hours.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATBRG Code: 9
+Category of bridge CATBRG 9
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fixed bridge ID 22; 381.1;
+ 2 : opening bridge ID 23.1; 381.3;
+ 3 : swing bridge ID 23.2; 381.3;
+ 4 : lifting bridge ID 23.3; 381.3;
+ 5 : bascule bridge ID 23.4; 381.3;
+ 6 : pontoon bridge ID 23.5; 381.3;
+ 7 : draw bridge ID 23.6; 381.3;
+ 8 : transporter bridge ID 24; 381.2;
+ 9 : footbridge
+ 10 : viaduct
+ 11 : aqueduct
+ 12 : suspension bridge
+
+Definitions:
+
+fixed bridge: a bridge having permanent horizontal and vertical alignment. (McGraw-Hill Dictionary of Scientific and Technical Terms, 3rd Edition, 1984)
+
+opening bridge: a bridge that is closed when set for carrying road traffic and open when set to permit marine traffic to pass through the waterway it crosses. Modern opening (movable) bridges are either bascule, vertical lift or swing. (adapted from McGraw-Hill Encyclopaedia of Science and Technology, 7th Edition, 1992)
+
+swing bridge: a movable bridge (or span thereof) which rotates in a horizontal plane about a vertical pivot to allow the passage of vessels. (adapted from McGraw-Hill Encyclopaedia of Science and Technology, 7th Edition, 1992)
+
+lifting bridge: a movable bridge (or span thereof) which is capable of being lifted vertically to allow vessels to pass beneath. (adapted from IHO Dictionary, S-32, 5th Edition, 547)
+
+bascule bridge: a counterpoise bridge rotated in a vertical plane about an axis at one or both ends. Also called a balance. (IHO Dictionary, S-32, 5th Edition, 545)
+
+pontoon bridge: a fixed floating bridge supported by pontoons. (McGraw-Hill Dictionary of Scientific and Technical Terms, 3rd Edition, 1984)
+
+draw bridge: a general name for bridges of which part or the entire span of the bridge may be raised or drawn aside to allow ships to pass through. (IHO Dictionary, S-32, 5th Edition, 546)
+
+transporter bridge: a bridge that has towers on each side of the waterway connected by a girder system on which a carriage runs. (IHO Chart Specifications, M-4, 381.2)
+
+foot bridge: a bridge structure used only for pedestrian traffic. (McGraw-Hill Dictionary of Scientific and Technical Terms, 3rd Edition, 1984)
+
+viaduct: a long bridge consisting of a series of beams, spans or girders (of steel, timber or concrete) supported on towers or piers and used to carry a road, railroad, etc. (adapted from McGraw-Hill Encyclopaedia of Science and Technology, 7th Edition, 1992)
+
+aqueduct: a bridge supporting an artificially elevated channel, for the conveyance of water. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+suspension bridge: a fixed bridge consisting of either a roadway or a truss suspended from two or more cables which pass over towers and are anchored by backstays to a firm foundation. (McGraw-Hill Encyclopaedia of Science and Technology, 7th Edition, 1992)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATBUI
+Category of building, single CATBUI
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : building without function/service of major interest ID 5-6; 370.3,5;
+ 2 : harbour-master`s office IF 60; 325.1;
+ 3 : custom office IF 61; 325.2;
+ 4 : health office IF 62.1; 325.3;
+ 5 : hospital IF 62.2; 325.3;
+ 6 : post office IF 63; 372.1;
+ 7 : hotel
+ 8 : railway station ID 13; 362.2;
+ 9 : police station
+ 10 : water-police station
+ 11 : pilot office IT 3; 491.4;
+ 12 : pilot lookout IT 2; 491.3;
+ 13 : power station
+ 14 : bank office
+ 15 : headquarters for district control
+ 16 : transit shed/warehouse IF 51; 328.1;
+ 17 : factory
+ 18 : administrative
+ 19 : educational facility
+ 20 : inhabited building/house
+ 21 : uninhabited building/house
+ 22 : church IE 10; 373.2;
+ 23 : chapel
+ 24 : temple IE 13,16; 373.2;
+ 25 : pagoda IE 14; 373.3;
+ 26 : shinto-shrine IE 15; 373.3;
+ 27 : buddhist temple IE 16; 373.3;
+ 28 : mosque IE 17; 373.4;
+ 29 : marabout IE 18; 373.5;
+ 30 : coastguard building IT 10; 492.1-2;
+ 31 : stadium
+
+Remarks:
+
+ The attribute `category of single building` encodes the various types of single building.
+
+This attribute is obsolete. It is only included here for reasons of backward compatibility. Categories of building may now be encoded using the attribute function (FUNCTN).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATBUA Code: 10
+Category of built-up area CATBUA 10
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : urban area ID 1; 370.3-4;
+ 2 : settlement ID 2,3; 370.5,7;
+ 3 : village ID 4; 370.6;
+ 4 : town
+ 5 : city
+ 6 : holiday village
+
+Definitions:
+
+urban area: an area predominantly occupied by man-made structures used for residential, commercial, and industrial purposes. (Nautical Chart Manual, US Department of Commerce, 1992)
+
+settlement: a small collection of dwellings in a remote area.
+
+village: a collection of houses in a rural district, usually smaller than a town.
+
+town: any considerable collection of dwellings and other buildings larger than a village, but not incorporated as a city.
+
+city: a major town inhabited by a large permanent community with all essential services.
+
+holiday village: a collection of smaller houses (cottages, mobile homes etc.) which is mainly populated on a seasonal basis.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCBL Code: 11
+Category of cable CATCBL 11
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : power line ID 26; IL 31.1; 382.1;
+ 2 : telephone/telegraph
+ 3 : transmission line
+ 4 : telephone ID 27; 382.2;
+ 5 : telegraph ID 27; 382.2;
+ 6 : mooring cable/chain
+
+Definitions:
+
+power line: a cable used for the supply of electricity.
+
+transmission line: multiple un-insulated cables usually supported by steel lattice towers. Such features are generally more prominent than normal power lines.
+
+telephone: a cable used for the transmission of telephone signals.
+
+telegraph: a cable used for the transmission of telegraph signals.
+
+mooring cable/chain: a cable or chain used to secure a mooring buoy or other floating structure.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCAN Code: 12
+Category of canal CATCAN 12
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : transportation
+ 2 : drainage
+ 3 : irrigation
+
+Definitions:
+
+transportation: a canal used for navigation as part of a transport system.
+
+drainage: a canal used to drain excess water from surrounding land.
+
+irrigation: a canal used to supply water for the purpose of irrigation.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCAM Code: 13
+Category of cardinal mark CATCAM 13
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1
+
+ 1 : north cardinal mark IQ 130.3;
+ 2 : east cardinal mark IQ 130.3;
+ 3 : south cardinal mark IQ 130.3;
+ 4 : west cardinal mark IQ 130.3;
+
+Definitions:
+
+ The four quadrants (north, east, south and west) are bounded by the true bearings NW-NE, NE-SE, SE-SW and SW-NW taken from the point of interest.
+
+ A cardinal mark is named after the quadrant in which it is placed.
+
+ The name of the cardinal mark indicates that it should be passed to the named side of the mark.
+
+Remarks:
+
+ Cardinal marks do not have a distinctive shape but are normally pillar or spar. They are always painted in yellow and black horizontal bands and their distinctive double cone top-marks are always black. (Note that such top-marks are encoded as separate TOPMAR objects). Cardinal marks may also have a special system of flashing white lights and if such lights are fitted they are encoded as separate LIGHTS objects. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCHP Code: 14
+Category of checkpoint CATCHP 14
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : custom
+
+Definitions:
+
+custom: an office, especially in ports, at which customs dues are collected or administrated. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCOA Code: 15
+Category of coastline CATCOA 15
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : steep coast IC 3; 312.1;
+ 2 : flat coast IC 5; 312.2;
+ 3 : sandy shore IC 6; 312.2;
+ 4 : stony shore IC 7; 312.2;
+ 5 : shingly shore IC 7; 312.2;
+ 6 : glacier (seaward end) IC 25; 353.8;
+ 7 : mangrove IC 32; 312.4;
+ 8 : marshy shore IC 33; 312.2;
+ 9 : coral reef
+ 10 : ice coast
+
+Definitions:
+
+steep coast: a coast backed by rock or earth cliffs, gives a good radar return and is useful for visual identification from a considerable distance off, where cliffs alternate with low lying coast along the shoreline. (IHO Chart Specifications, M-4)
+
+flat coast: a level coast with no obvious topographic features.
+
+sandy shore: a shoreline area made up of sand, i.e. loose material consisting of small but easily distinguishable, separate grains, between 0.0625 and 2.000 millimetres in diameter. (adapted from IHO Dictionary, S-32, 5th Edition, 4497)
+
+stony shore: a shoreline area made up of rock and rock fragments ranging in size from pebbles and gravel to boulders or large rock masses. (adapted from IHO Dictionary, S-32, 5th Edition, 5059)
+
+shingly shore: a shoreline area made up of rounded, often flat waterworn rock fragments larger than approximately 16 millimetres. (adapted from IHO Dictionary, S-32, 5th Edition, 4683)
+
+glacier, seaward end: projecting seaward extension of glacier, usually afloat. Also called glacier tongue. (IHO Hydrographic Dictionary, S-32, 5th Edition, 2043)
+
+mangrove: one of several genera of tropical trees or shrubs which produce many prop roots and grow along low lying coasts into shallow water. (IHO Hydrographic Dictionary, S-32, 5th Edition, 3064)
+
+marshy shore: a shoreline area made up of spongy land saturated with water. It may have a shallow covering of water, usually with a considerable amount of vegetation appearing above the surface. (adapted from IHO Dictionary, S-32, 5th Edition, 5240)
+
+coral reef: a reef, often of large extent, composed chiefly of coral and its derivatives. (IHO Dictionary, S-32, 5th Edition, 1063)
+
+ice coast: a vertical cliff forming the seaward edge of an ice shelf, ranging in height from 2m to 50m or more above sea level.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCTR Code: 16
+Category of control point CATCTR 16
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : triangulation point IB 20; 304.1
+ 2 : observation spot IB 21; 304.2
+ 3 : fixed point IB 22; 305.1
+ 4 : bench-mark IB 23; 304.3
+ 5 : boundary mark IB 24; 306
+ 6 : horizontal control, main station
+ 7 : horizontal control, secondary station
+
+Definitions:
+
+triangulation point: a recoverable point on the earth, whose geographic coordinates have been determined by angular methods with geodetic instruments. A triangulation point is a selected point, which has been marked with a station mark, or it is a conspicuous natural or artificial object. Also called trigonometric station or triangulation station. (IHO Dictionary, S-32, 5th Edition, 5646)
+
+observation spot: a point used by surveyors for determining precise position by astronomical means. (IHO Chart Specifications, M-4)
+
+fixed point: a point whose position has been accurately determined and plotted. (IHO Chart Specifications, M-4)
+
+bench-mark: a permanent, stable object containing a marked point of known elevation with respect to a datum used as a reference level for tidal observations or as a control point for levelling. (IHO Dictionary, S-32, 5th Edition, 462)
+
+boundary mark: a marker identifying the location of a surveyed boundary line (Digital Geographic Information Standard - DIGEST, Oct.87)
+
+horizontal control, main station:
+ a station in a network of permanently marked control points having their geographic positions established to form third order accuracy or better. (Canadian Hydrographic Service, Survey Standing Order, 3.1-85)
+
+horizontal control, secondary station:
+ a station in a network of control points of a localized nature utilized for shoreline plots, sounding marks, stadia work, etc., whose geographic position may be established to a slightly lower order than main control points. (Canadian Hydrographic Service, Survey Standing Order, 3.1-85)
+
+Remarks:
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCON Code: 17
+Category of conveyor CATCON 17
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : aerial cableway (telepheric) ID 25; 382.3;
+ 2 : belt conveyor
+
+Definitions:
+
+aerial cableway (telepheric):
+ a conveyor along which material or people are transported by means of overhead cables supporting buckets, cable cars, etc.
+
+belt conveyor: a conveyor along which material or people are transported by means of a moving belt.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCOV Code: 18
+Category of coverage CATCOV
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : coverage available
+ 2 : no coverage available
+
+Definitions:
+
+coverage available: continuous coverage of spatial objects is available within this area.
+
+no coverage available: an area containing no spatial objects.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATCRN Code: 19
+Category of crane CATCRN 19
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : crane without specific construction
+ 2 : container crane/gantry IF 53.2; 328.3;
+ 3 : sheerlegs IF 53.3; 328.3;
+ 4 : travelling crane IF 53.1; 328.3;
+ 5 : A-frame
+
+Definitions:
+
+container crane/gantry: a high speed, shore-based crane used in the lift-on/lift-off operation of specially constructed containers. (adapted from Nautical Chart Manual, US Department of Commerce, Coast and Geodetic Survey, 7th Edition)
+
+sheerlegs: a tripodal structure used in dockyards and harbours for stepping masts or lifting loads in to and out of vessels.
+
+travelling crane: a crane mounted on rails (track) that can move (usually parallel to the wharf face) in order to load and unload cargo vessels. (Canadian Hydrographic Service)
+
+A-frame: a type of crane shaped like the letter A'. They are often positioned on river banks or the coastline and are used for lifting logs from logging trucks and depositing them in the water. (Canadian Hydrographic Service)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATDAM Code: 20
+Category of dam CATDAM 20
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : weir
+ 2 : dam IF 44; 364.2;
+ 3 : flood barrage IF 43; 326.7;
+
+Definitions:
+
+weir: a dam erected across a river to raise the level of the water. A fence of stakes set in a river or along the shore as a trap for fish.
+ The word is now restricted to smaller works, the larger are called dams. (IHO Dictionary, S-32, 5th Edition, 5967)
+
+dam: a barrier to check or confine anything in motion; particularly one constructed to hold back water and raise its level to form a reservoir, or to prevent flooding. (IHO Dictionary, S-32, 5th Edition, 1196)
+
+flood barrage: an opening dam across a channel which, when required, is closed to control flood waters. (IHO Chart Specifications, M-4 326.7)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATDIS Code: 21
+Category of distance mark CATDIS 21
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : distance mark not physically installed IF 40;
+ 2 : visible mark, pole IF 40;
+ 3 : visible mark, board IF 40;
+ 4 : visible mark, unknown shape IF 40;
+
+Definitions:
+
+distance mark not physically installed:
+ a point at which a distance from an origin along a feature is given for information, but at which no specific marker exists.
+
+visible mark, pole: a point at which a distance from an origin along a feature is given for information and which is marked by a pole.
+
+visible mark, board: a point at which a distance from an origin along a feature is given for information and which is marked by a board.
+
+visible mark, unknown shape:
+ a point at which a distance from an origin along a feature is given for information and which is physically marked, but the shape of the mark is not known or not given.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATDOC Code: 22
+Category of dock CATDOC 22
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : tidal IF 28; 326.4;
+ 2 : non-tidal (wet dock) IF 27; 326.3;
+
+Definitions:
+
+tidal: a dock which is open to the sea and in which the water level is affected by tides.
+
+non-tidal (wet dock): a dock in which water can be maintained at any level by closing a gate when the water is at the desired level. (IHO Dictionary, S-32, 5th Edition, 1429)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATDPG Code: 23
+Category of dumping ground CATDPG 23
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : general dumping ground
+ 2 : chemical waste dumping ground IN 24; 442.1-3;
+ 3 : nuclear waste dumping ground
+ 4 : explosives dumping ground IN 23.1-2; 442.1-3;
+ 5 : spoil ground IN 62.1-2; 446.1-2;
+ 6 : vessel dumping ground
+
+Definitions:
+
+chemical waste dumping ground:
+ an area at sea where chemical waste is dumped.
+
+nuclear waste dumping ground:
+ an area at sea where nuclear waste is dumped.
+
+explosives dumping ground:
+ an area at sea where explosives are dumped.
+
+spoil ground: an area at sea where dredged material is deposited. Also called dumping ground. (IHO Dictionary, S-32, 5th Edition, 4930)
+
+vessel dumping ground:
+ an area at sea where disused vessels are scuttled.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+DELETED - DO NOT USE
+
+
+Acronym: CATDYK
+Category of dyke CATDYK
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : summer dyke IF 1; 313.1;
+ 2 : winter dyke IF 1; 313.1;
+
+Remarks:
+
+ The attribute `category of dyke` encodes the various types of dyke.
+
+This attribute is obsolete. It is only included here for reasons of backward compatibility.
+
+
+DELETED - DO NOT USE
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATFNC Code: 24
+Category of fenceline CATFNC 24
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : fence
+ 2 : muir
+ 3 : hedge
+ 4 : wall
+
+Definitions:
+
+fence: a man made barrier used as an enclosure or boundary or for protection. (Digital Geographic Information Working Group -DGIWG, Oct. 1987)
+
+hedge: a continuous growth of shrubbery planted as a fence, a boundary or a wind break. (Digital Geographic Information Standard - DIGEST)
+
+wall: a fence constructed from masonry or stone.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATFRY Code: 25
+Category of ferry CATFRY 25
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : free-moving' ferry IM 50; 438.1;
+ 2 : cable ferry IM 51; 438.2;
+ 3 : ice ferry
+
+Definitions:
+
+free-moving' ferry: a ferry which may have routes that vary with weather, tide and traffic. (adapted from M-4)
+
+cable ferry: a ferry that follows a fixed route guided by a cable. (adapted from IHO Specifications, M-4)
+
+ice ferry: a winter-time ferry which crosses a lead. (Finnish Maritime Administration)
+
+Remarks:
+
+ The attribute `category of ferry` does not encode the various types of ferry vessel, but the manoeuvrability of the ferry. The value `cable ferry` indicates a ferry that follows a fixed route guided by a cable. A cable ferry may hinder the flow of other traffic. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATFIF Code: 26
+Category of fishing facility CATFIF 26
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fishing stake IK 44.1; 447.1;
+ 2 : fish trap IK 44.2, 45; 447.2-3;
+ 3 : fish weir IK 44.2; 447.2;
+ 4 : tunny net IK 44.2, 45; 447.2;
+
+Definitions:
+
+fishing stake: a pole or stake placed in shallow water to outline a fishing ground or to catch fish (IHO Dictionary, S-32, 5th Edition, 1818).
+
+fish trap: a structure (usually portable) for catching fish (IHO Dictionary, S-32, 5th Edition, 1819).
+
+fish weir: a fence of stakes or stones set in a river or along the shore to trap fish (IHO Dictionary, S-32, 5th Edition, 5967).
+
+tunny net: a net built at sea for catching tunny (IHO Dictionary, S-32, 5th Edition, 5700).
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATFOG Code: 27
+Category of fog signal CATFOG 27
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : explosive IR 10; 452.1;
+ 2 : diaphone IR 11; 452.2;
+ 3 : siren IR 12; 452.3;
+ 4 : nautophone IR 13; 452.4;
+ 5 : reed IR 13; 452.4;
+ 6 : tyfon IR 13; 452.4;
+ 7 : bell IR 14; 452.5;
+ 8 : whistle IR 15; 452.6;
+ 9 : gong IR 16; 452.7;
+ 10 : horn IR 13; 452.4;
+
+Definitions:
+
+explosive: a signal produced by the firing of explosive charges. (Admiralty List of Lights and Fog Signals)
+
+diaphone: a diaphone uses compressed air and generally emits a powerful low-pitched sound, which often concludes with a brief sound of suddenly lowered pitch, termed the grunt'. (Admiralty List of Lights and Fog Signals)
+
+siren: a siren uses compressed air and exists in a variety of types which differ considerably in their sound and power. (Admiralty List of Lights and Fog Signals)
+
+nautophone: a horn having a diaphragm oscillated by electricity (IHO Dictionary, S-32, 5th Edition, 3371).
+
+reed: a reed uses compressed air and emits a weak, high pitched sound. (Admiralty List of Lights and Fog Signals)
+
+tyfon: a diaphragm horn which operates under the influence of compressed air or steam (IHO Dictionary, S-32, 5th Edition, 5717).
+
+bell: a ringing sound with a short range. The apparatus may be operated automatically, by hand or by wave action. (IHO Chart Specifications, M-4, 452.5)
+
+whistle: a distinctive sound made by a jet of air passing through an orifice. The apparatus may be operated automatically, by hand or by air being forced up a tube by waves acting on a buoy. (IHO Chart Specifications, M-4, 452.6)
+
+gong: a sound produced by vibration of a disc when struck. The apparatus may be operated automatically, by hand or by wave action. (IHO Chart Specifications, M-4, 452.7)
+
+horn: a horn uses compressed air or electricity to vibrate a diaphragm and exists in a variety of types which differ greatly in their sound and power. (Admiralty List of Lights and Fog Signals)
+
+Remarks:
+
+ The attribute `category of fog signal` encodes the various means of generating the signal.
+
+ The classification `horn` is the generic term for fog signals `nautophone`, `reed` and `tyfon`. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATFOR Code: 28
+Category of fortified structure CATFOR 28
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : castle IE 34.2; 379.1-2;
+ 2 : fort IE 34.1; 379.1-2;
+ 3 : battery IE 34.3; 379.2;
+ 4 : blockhouse IE 34.2; 379.1-2;
+ 5 : Martello tower
+
+Definitions:
+
+castle: a large fortified building or structure (adapted from The Collins Dictionary).
+
+fort: a fortified enclosure, building, or position able to be defended against an enemy (The Collins Dictionary).
+
+battery: a fortified structure on which artillery is mounted (The Collins Dictionary).
+
+blockhouse: a concrete structure strengthened to give protection against enemy fire, with apertures to allow defensive gunfire (The Collins Dictionary).
+
+Martello tower: a round fort for coastal defence.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATGAT Code: 29
+Category of gate CATGAT 29
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : gate in general
+ 2 : flood barrage gate IF 43; 326.7;
+ 3 : caisson IF 42; 326.5;
+ 4 : lock gate IF 41.1-2; 326.6;
+ 5 : dyke gate
+
+Definitions:
+
+flood barrage gate: an opening gate used to control flood water.
+
+caisson: a steel structure used for closing the entrance of locks, wet and dry docks. (IHO Dictionary, S-32, 5th Edition, 602)
+
+lock gate: lock gates are the massive hinged doors at each end of a lock. (adapted from IHO Dictionary, S-32, 5th Edition, 2882)
+
+dyke gate: an opening gate in a dyke.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+acronym: CATHAF Code: 30
+Category of harbour facility CATHAF 30
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : RoRo-terminal IF 50; 321.5;
+ 2 : timber yard
+ 3 : ferry terminal
+ 4 : fishing harbour IF 10; 320.1;
+ 5 : yacht harbour/marina IU 1.1; 320.2;
+ 6 : naval base
+ 7 : tanker terminal
+ 8 : passenger terminal
+ 9 : shipyard
+ 10 : container terminal
+ 11 : bulk terminal
+
+Definitions:
+
+ A terminal provides facilities for handling particular forms of cargo (IHO Dictionary, S-32, 5th Edition, 5343).
+
+RoRo-terminal: a terminal for roll-on roll-off ferries.
+
+ferry terminal: a terminal for passenger and vehicle ferries.
+
+fishing harbour: a harbour with facilities for fishing boats.
+
+yacht harbour/marina: a harbour with facilities for small boats and yachts (IHO Dictionary, S-32, 5th Edition, 3095).
+
+naval base: a centre of operations for naval vessels (adapted from The Collins Dictionary).
+
+tanker terminal: a terminal for the bulk handling of liquid cargoes.
+
+passenger terminal: a terminal for the loading and unloading of passengers.
+
+shipyard: a place where ships are built or repaired (IHO Dictionary, S-32, 5th Edition, 4686).
+
+container terminal: a terminal for container ships.
+
+bulk terminal: a terminal for the handling of bulk materials such as iron ore, coal, etc.
+
+.Remark:
+
+ Value number 2 (timber yard) has been transferred to the attribute category of production area (CATPRA). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATHLK Code: 31
+Category of hulk CATHLK 31
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : floating restaurant
+ 2 : historic ship
+ 3 : museum
+ 4 : accommodation
+ 5 : floating breakwater
+
+Definitions:
+
+floating restaurant: a permanently moored floating structure, such as an old ship, used as a restaurant.
+
+historic ship: a ship of historical interest permanently moored as a tourist attraction.
+
+museum: a permanently moored floating structure, such as an old ship, used as a museum.
+
+accommodation: a permanently moored floating structure, such as an old ship, used for accommodation.
+
+floating breakwater: a permanently moored floating structure, often constructed from old ships, used as a breakwater.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATICE Code: 32
+Category of ice CATICE 32
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fast ice IN 60.1; 449.1;
+ 2 : sea ice IN 60.2; 449.1;
+ 3 : growler area
+ 4 : pancake ice
+ 5 : glacier IC 25; 353.8;
+ 6 : ice peak
+ 7 : pack ice
+ 8 : polar ice
+
+Definitions:
+
+fast ice: sea ice which remains fast, generally in the position where originally formed, and which may attain a considerable thickness. It is found along coasts, where it is attached to the shore, or over shoals, where it may be held in position by islands, grounded icebergs or grounded polar ice. (IHO Dictionary, S-32, 5th Edition, 1772)
+
+sea ice: any form of ice which has originated from sea water. Generally any ice in the sea. (IHO Dictionary, S-32, 5th Edition, 4566)
+
+growler: a low-lying mass of flow ice which is not easily seen by approaching vessels owing to its dark indigo colour. It is therefore a menace to shipping. It is usually caused by the capsizing and disintegration of an iceberg.
+
+pancake ice: pieces of new ice, usually approximately circular, about 30 cm to 3 m across, and with raised rims, due to the pieces striking against each other as the result of wind and swell. (IHO Dictionary, S-32, 5th Edition, 3643)
+
+glacier: a mass of snow and ice continuously moving from higher to lower ground or, if afloat, continuously spreading. (IHO Dictionary, S-32, 5th Edition, 2041)
+
+pack ice: term used in a wide sense to include any area of sea ice, other than fast ice, no matter what form it takes or how it is disposed. (IHO Dictionary, S-32, 5th Edition, 3639)
+
+polar ice: sea ice that is more than one year old (in contrast to winter ice). The WMO code defines polar ice as any sea ice more than one year old and more than 3 metres thick. (IHO Dictionary, S-32, 5th Edition, 3928)
+
+Remarks:
+
+ Ice is the topic of another group and is subject to a future extension to this document. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATINB Code: 33
+Category of installation buoy CATINB 33
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : catenary anchor leg mooring (CALM) IL 16; 445.4;
+ 2 : single buoy mooring (SBM or SPM) IL 16; 445.4;
+
+Definitions:
+
+catenary anchor leg mooring(CALM):
+ incorporates a large buoy which remains on the surface at all times and is moored by 4 or more anchors. Mooring hawsers and cargo hoses lead from a turntable on top of the buoy, so that the buoy does not turn as the ship swings to wind and stream.
+
+single buoy mooring (SBM):
+ a mooring structure used by tankers to load and unload in port approaches or in offshore oil and gas fields. The size of the structure can vary between a large mooring buoy and a manned floating structure. Also known as single point mooring (SPM) (IHO Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATLND Code: 34
+Category of land region CATLND 34
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fen
+ 2 : marsh IC 33; 312.2;
+ 3 : moor/bog
+ 4 : heathland
+ 5 : mountain range
+ 6 : lowlands
+ 7 : canyon lands
+ 8 : paddy field
+ 9 : agricultural land
+ 10 : savanna/grassland
+ 11 : parkland
+ 12 : swamp IC 33; 312.2;
+ 13 : landslide
+ 14 : lava flow IC 26; 355;
+ 15 : salt pan IC 24; 353.7;
+ 16 : moraine
+ 17 : crater
+ 18 : cave
+ 19 : rock column or pinnacle
+
+Definitions:
+
+fen: a type of bog, especially a low-lying area, wholly or partly covered with water and dominated by grasslike plants, grasses, sedges and reeds. (The New Encyclopaedia Britannica, 15th Edition 1991)
+
+marsh: an area of wet, often spongy ground that is subject to frequent flooding or tidal inundations, but not considered to be continually under water. It is characterized by the growth of non woody plants and by the lack of trees. (Nautical Chart Manual, US National Oceanic and Atmospheric Administration - NOAA, 1992).
+
+moor/bog: wet spongy ground consisting of decaying vegetation, which retains stagnant water, too soft to bear the weight of any heavy body.(IHO Dictionary, S-32, 5th Edition, 504)
+
+heathland: a tract of wasteland; peat bog, usually covered by a low scrubby growth, but may have scattered small open water holes. (Nautical Chart Manual, US National Oceanic and Atmospheric Administration - NOAA, 1992)
+
+mountain range: a series of connected and aligned mountains or mountain ridges. (US National Oceanic and Atmospheric Administration - NOAA, 1992).
+
+lowlands: low and relatively level land at a lower elevation than adjoining areas. (US National Oceanic and Atmospheric Administration - NOAA, 1992)
+
+canyon lands: a relatively narrow, deep depression with steep sides, the bottom of which generally has a continuous slope. (IHO Dictionary, S-32, 5th Edition, 638)
+
+paddy field: a piece of land set aside for crops which are periodically flooded (e.g. rice paddy).
+
+agricultural land:
+ areas used for cultivation of the soil, the breeding of livestock etc. and general farming.
+
+savanna/grassland: a large area of relatively flat natural pasture.
+
+parkland: a piece of ground kept for ornament and/or recreation or maintained in its natural state as a public property or area. (Websters New Collegiate Dictionary 1975)
+
+swamp: an area of spongy land saturated with water. It may have a shallow covering of water, usually with a considerable amount of vegetation appearing above the surface. (IHO Dictionary, S-32, 5th Edition, 5240)
+
+landslide: (or landslip). The sliding down of a mass of land on a mountain or cliff-side; land which has so fallen. (IHO Dictionary, S-32, 5th Edition, 2646)
+
+lava flow: the substance that results from the cooling of molten rock. (adapted IHO Dictionary, S-32, 5th Edition, 2680)
+
+saltpan: shallow pools of brackish water used for the natural evaporation of sea water to obtain salt. (IHO Dictionary, S-32, 5th Edition, 4494)
+
+moraine: any accumulation of loose material deposited by a glacier. (Marine Chart Manual, US National Oceanic and Atmospheric Administration - NOAA, 1992)
+
+crater: bowl-shaped cavity, at the summit or on the side of a volcano.(IHO Dictionary, S-32, 5th Edition, 1115) Also a hole formed by the impact of a meteor. (Nautical Chart Manual, US National Oceanic and Atmospheric Administration - NOAA, 1992).
+
+cave: a natural subterranean chamber or series of chambers open to the earths surface. (Digital Geographic Information Standard - DIGEST)
+
+rock column or pinnacle:
+ any high tower or spire-shaped pillar of rock, alone or cresting a summit. (IHO Dictionary, S-32, 5th Edition, 3852)
+
+Remarks:
+
+ The attribute `category of land region` encodes general terms for describing landscapes. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATLMK Code: 35
+Category of landmark CATLMK 35
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : cairn IQ 100; 456.2;
+ 2 : cemetery IE 19; 373.6;
+ 3 : chimney IE 22; 374.1;
+ 4 : dish aerial IE 31; 375.4;
+ 5 : flagstaff (flagpole) IE 27; 374.7;
+ 6 : flare stack IE 23; IL 11; 374.1; 445.6;
+ 7 : mast
+ 8 : windsock
+ 9 : monument IE 24; 374.4;
+ 10 : column (pillar)
+ 11 : memorial plaque
+ 12 : obelisk
+ 13 : statue
+ 14 : cross IE 12;
+ 15 : dome IE 30.4; 487.3;
+ 16 : radar scanner IE 30.3; 487.3;
+ 17 : tower IE 20; 374.3;
+ 18 : windmill IE 25.1-2; 374.5;
+ 19 : windmotor IE 26; 374.6;
+ 20 : spire/minaret IE 10.3, 17;
+
+Definitions:
+
+cairn: a mound of stones, usually conical or pyramidal, raised as a landmark or to designate a point of importance in surveying. (IHO Dictionary, S-32, 5th Edition, 601)
+
+cemetery: an area of land for burying the dead.
+
+chimney: a vertical structure containing a passage or flue for discharging smoke and gases. (Digital Geographic Information Standard - DIGEST)
+
+dish aerial: a parabolic aerial for the receipt and transmission of high frequency radio signals. (IHO Dictionary, S-32, 5th Edition, 1400)
+
+flagstaff(flagpole): a staff or pole on which flags are raised. (Digital Geographic Information Standard - DIGEST 1.28)
+
+flare stack: a tall structure used for burning-off waste oil or gas. (IHO Dictionary, S-32, 5th Edition, 1836). Normally showing a flame and located at refineries (IHO Chart specifications, M-4).
+
+mast: a straight vertical piece of timber or a hollow cylinder. (adapted from Digital Geographic Information Standard - DIGEST)
+
+wind sock: a tapered fabric sleeve mounted so as to catch and swing with the wind, thus indicating the wind direction. (Navigation dictionary, US National Oceanic and Atmospheric Administration - NOAA, 1969)
+
+monument: a structure erected or maintained as a memorial to a person or event. (Digital Geographic Information Standard - DIGEST)
+
+column (pillar): a cylindrical or slightly tapering body of considerably greater length than diameter erected vertically. (Oxford English Dictionary)
+
+memorial plaque: a slab of metal, usually ornamented, erected as a memorial to a person or event.
+
+obelisk: a tapering shaft usually of stone or concrete, square or rectangular in section, with a pyramidal apex. (Adapted from Oxford English Dictionary)
+
+statue: a representation of a human, animal or fantasy figure in marble, bronze, etc.
+
+cross: a monument, or other structure in form of a cross. (Funk & Wagnalls Dictionary)
+
+dome: a landmark comprising a hemispherical or spheroidal shaped structure (adapted from the Macquarie Dictionary).
+
+radar scanner: a device used for directing a radar beam through a search pattern (adapted from Navigation Dictionary, US National Oceanic and Atmospheric Administration - NOAA, 1969)
+
+tower: a relatively tall structure which may be used for observation, support, storage or communication etc. (Digital Geographic Information Working Group -DGIWG, Oct. 1987)
+
+windmill: a wind driven system of vanes attached to a tower like structure (excluding wind- generated power plants). (Digital Geographic Information Standard - DIGEST)
+
+windmotor: a modern structure for the use of windpower. (IHO Chart Specifications, M-4)
+
+spire/minaret: a tall conical or pyramid-shaped structure often built on the roof or tower of a building, especially a church or mosque. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATLAM Code: 36
+Category of lateral mark CATLAM 36
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : port-hand lateral mark IQ 91-92,130.1; 456.1;
+ 2 : starboard-hand lateral mark IQ 91-92,130.1; 456.1;
+ 3 : preferred channel to starboard lateral mark IQ 130.1;
+ 4 : preferred channel to port lateral mark IQ 130.1;
+
+Definitions:
+
+port-hand lateral mark: indicates the port boundary of a navigational channel or suggested route when proceeding in the conventional direction of buoyage'.
+
+starboard-hand lateral mark:
+ indicates the starboard boundary of a navigational channel or suggested route when proceeding in the conventional direction of buoyage'.
+
+preferred channel to starboard lateral mark:
+ at a point where a channel divides, when proceeding in the conventional direction of buoyage', the preferred channel (or primary route) is indicated by a modified port-hand lateral mark.
+
+preferred channel to port lateral mark:
+ at a point where a channel divides, when proceeding in the conventional direction of buoyage', the preferred channel (or primary route) is indicated by a modified starboard-hand lateral mark.
+
+Note: the conventional direction of buoyage' may be either the general direction taken by the mariner when approaching a harbour, river, estuary or other waterway from seaward, or the direction determined by the proper authority, which in principle follows a clockwise direction around land masses.
+
+Remarks:
+
+ There are two international buoyage regions, A and B, between which lateral marks differ. The buoyage region is encoded using the separate attribute MARSYS. When top-marks, retro reflectors and/or lights are fitted to these marks, they are encoded as separate objects. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATLIT Code: 37
+Category of light CATLIT 37
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : directional function IP 30.1-3; 475.7;
+ 2 : rear/upper light
+ 3 : front/lower light
+ 4 : leading light IP 20.1-3; 475.6;
+ 5 : aero light IP 60; 476.1;
+ 6 : air obstruction light IP 61; 476.2;
+ 7 : fog detector light IP 62; 477;
+ 8 : flood light IP 63; 478.2;
+ 9 : strip light IP 64; 478.5;
+ 10 : subsidiary light IP 42; 471.8;
+ 11 : spotlight
+ 12 : front
+ 13 : rear
+ 14 : lower
+ 15 : upper
+ 16 : moirè effect IP 31; 475.8;
+ 17 : emergency
+ 18 : bearing light 478.1;
+ 19 : horizontally disposed
+ 20 : vertically disposed
+
+Definitions:
+
+directional function: a light illuminating a sector of very narrow angle and intended to mark a direction to follow. (IHO Dictionary, S-32, 5th Edition, 2778)
+
+leading light: a light associated with other lights so as to form a leading line to be followed. (adapted from IHO Dictionary, S-32, 5th Edition, 2794)
+
+aero light: an aero light is established for aeronautical navigation and may be of higher power than marine lights and visible from well offshore. (IHO Chart Specifications, M-4, 476.1)
+
+air obstruction light: a light marking an obstacle which constitutes a danger to air navigation. (IHO Dictionary, S-32, 5th Edition, 2767)
+
+fog detector light: a light used to automatically determine conditions of visibility which warrant the turning on or off of a sound signal. (IHO Dictionary, S-32, 5th Edition, 1885)
+
+flood light: a broad beam light used to illuminate a structure or area. (adapted from The Collins Dictionary)
+
+strip light: a light whose source has a linear form generally horizontal, which can reach a length of several metres. (IHO Chart Specifications, M-4, 478.5)
+
+subsidiary light: a light placed on or near the support of a main light and having a special use in navigation. (Admiralty List of Radio Signals, UK Hydrographic Office)
+
+spotlight: a powerful light focused so as to illuminate a small area. (The Collins Dictionary)
+
+front, rear, upper, lower:
+ terms used with leading lights to describe the position of the light on the lead as viewed from seaward.
+
+moirè effect: a short range (up to 2km) type of directional light. Sodium lighting gives a yellow background to a screen on which a vertical black line will be seen by an observer on the centre line. (IHO Chart Specifications, M-4, 475.8)
+
+emergency light: a light available as a backup to a main light which will be illuminated should the main light fail.
+
+bearing light: a light which enables its approximate bearing to be obtained without the use of a compass. (IHO Chart Specifications, M-4, 478.1)
+
+horizontally disposed: a group of lights of identical character and almost identical position, that are disposed horizontally.
+
+vertically disposed: a group of lights of identical character and almost identical position, that are disposed vertically.
+
+Remarks:
+
+ Marine light (a light intended primarily for marine navigation) is not included in the above list. All lights are considered to be marine lights unless the attribute category of light' indicates otherwise. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATMFA Code: 38
+Category of marine farm/culture CATMFA 38
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : crustaceans IK 47-48.2; 447.4,6;
+ 2 : oysters/mussels IK 47-48.2; 447.4,6;
+ 3 : fish IK 47-48.2; 447.4,6;
+ 4 : seaweed
+
+Definitions:
+
+crustaceans: hard shelled animals, for example crabs or lobsters.
+
+oysters/mussels: edible bivalve molluscs.
+
+fish: vertebrate cold blooded animal with gills, living in water.
+
+seaweed: the general name for marine plants of the Algae class which grow in long narrow ribbons. (International Maritime Dictionary, 2nd Ed.)
+
+Remarks:
+
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATMST
+Category of mast CATMST
+Attribute type: E
+
+INT 1 Reference: IE 28, 30.1;
+
+Chart Specification: 375.1; 487;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : radio mast / television mast
+ 2 : mooring mast
+ 3 : radar mast
+ 4 : wind sock
+
+
+Remarks:
+
+ The attribute `category of mast` encodes the various types of mast.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute category of landmark (CATLMK).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATMPA Code: 39
+Category of military practice area CATMPA 39
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : practice area in general 441.1;
+ 2 : torpedo exercise area
+ 3 : submarine exercise area IN 33; 441.5;
+ 4 : firing danger area IN 30; 441.2-3;
+ 5 : mine-laying practice area IN 32; 441.4;
+ 6 : small arms firing range
+
+Definitions:
+
+torpedo exercise area: an area within which exercises are carried out with torpedoes.
+
+submarine exercise area:
+ an area within which submarine exercises are carried out.
+
+firing danger area: areas for bombing and missile exercises. (Adapted from IHO Chart Specifications, M-4, 441)
+
+mine laying practice area:
+ an area within which mine laying exercises are carried out.
+
+small arms firing range: an area for shooting pistols, rifles and machine guns etc. at a target.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATMNT
+Category of monument CATMNT
+Attribute type: E
+
+INT 1 Reference: IE 24;
+
+Chart Specification: 374.4;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : column
+ 2 : memorial plaque
+ 3 : obelisk
+ 4 : pillar
+ 5 : statue
+
+
+Remarks:
+
+ The attribute `category of monument` encodes the various types of monument.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute category of landmark (CATLMK).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATMOR Code: 40
+Category of mooring/warping facility CATMOR 40
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : dolphin IF 20; 327.1;
+ 2 : deviation dolphin IF 21; 327.2;
+ 3 : bollard
+ 4 : tie-up wall
+ 5 : post or pile IF 22;
+ 6 : chain/wire/cable IQ 42; 431.6;
+ 7 : mooring buoy IQ 40-43; 431.5;
+
+Definitions:
+
+dolphin: a post or group of posts, which may support a deck, used for mooring or warping a vessel. (IHO Dictionary, S-32, 5th Edition, 1433)
+
+deviation dolphin: a post or group of posts, which a vessel may swing around for compass adjustment.
+
+bollard: small shaped post, mounted on a wharf or dolphin used to secure ship's lines.
+
+tie-up wall: a tie-up wall is a section of wall designated for tying-up vessels awaiting transit. Bollards and mooring devices are available for both large and small ships.
+
+post or pile: a long heavy timber or section of steel, wood, concrete, etc., forced into the seabed to serve as a mooring facility. (IHO Dictionary, S-32, 5th Edition, 3840)
+
+chain/wire/cable: a connection between two independent objects e.g. a buoy and pile or between two buoys used as a mooring facility.
+
+mooring buoy: a buoy secured to the bottom by permanent moorings with means for mooring a vessel by use of its anchor chain or mooring lines. (IHO Dictionary, S-32, 5th Edition, 575)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATNAV Code: 41
+Category of navigation line CATNAV 41
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : clearing line IM 2; 433;
+ 2 : transit line IM 2;
+ 3 : leading line bearing a recommended track IM 1, 3; 433;
+
+Definitions:
+
+clearing line: a straight line that marks the boundary between a safe and a dangerous area or that passes clear of a navigational danger. (adapted from IHO Dictionary, S-32, 5th Edition, 826)
+
+transit line: a line passing through one or more fixed marks.
+
+leading line: a line passing through one or more clearly defined objects, along the path of which a vessel can approach safely up to a certain distance off. (Adapted from IHO Dictionary, S-32, 5th Edition, 2696)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATOBS Code: 42
+Category of obstruction CATOBS 42
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : snag/stump IK 43; 327.5;
+ 2 : wellhead IL 21, 23; 445.1;
+ 3 : diffuser IL 43;
+ 4 : crib IL 43;
+ 5 : fish haven IK 46; 447.5;
+ 6 : foul area IK 1; 420.1;
+ 7 : foul ground IK 31; 422.8;
+ 8 : ice boom
+ 9 : ground tackle IQ 42; 431.6;
+
+Definitions:
+
+snag/stump: a tree, branch or broken pile embedded in the ocean floor, river or lake bottom and not visible on the surface, forming thereby a hazard to vessels. (IHO Dictionary, S-32, 5th Edition, 4794)
+
+wellhead: a submarine structure projecting some distance above the seabed and capping a temporarily abandoned or suspended oil or gas well. (IHO Dictionary, S-32, 5th Edition, 5976)
+
+diffuser: a structure on an outfall through which liquids are discharged. The structure will usually project above the level of the outfall and can be an obstruction to navigation.
+
+crib: a permanent structure set in the water, framed with wooden beams and filled with rocks or boulders. They are used to anchor log booms or support other constructions, e.g. submerged outfalls, diffusers etc.. They may always be dry, submerged or cover and uncover.
+
+fish haven: areas established by private interests, usually sport fishermen, to simulate natural reefs and wrecks that attract fish. The reefs are constructed by dumping assorted junk in areas which may be of very small extent or may stretch a considerable distance along a depth contour. Also called fishery reefs.
+
+foul area: an area of numerous unidentified dangers to navigation. The area serves as a warning to the mariner that all dangers are not identified individually and that navigation through the area may be hazardous. Commonly used to encode areas behind danger lines on navigation charts. (adapted from IHO Dictionary, S-32, 5th Edition, 1915)
+
+foul ground: areas over which it is safe to navigate but which should be avoided for anchoring, taking the ground or ground fishing. (IHO Chart Specifications, M-4, 442.8)
+
+ice boom: floating barriers, anchored to the bottom, used to deflect the path of floating ice in order to prevent the obstruction of locks, intakes, etc., and to prevent damage to bridge piers and other structures. (Canadian Hydrographic Service, Chart specifications).
+
+ground tackle: equipment such as anchors, concrete blocks, chains and cables, etc., used to position floating structures such as trot and mooring buoys etc. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATOFP Code: 43
+Category of offshore platform CATOFP 43
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : oil derrick/rig IL 10; 445.2;
+ 2 : production platform IL 10; 445.2;
+ 3 : observation/research platform IL 13;
+ 4 : articulated loading platform (ALP)
+ 5 : single anchor leg mooring (SALM) IL 12; 445.2,4;
+ 6 : mooring tower
+ 7 : artificial island IL 15;
+ 8 : floating production, storage and off-loading vessel (FPSO) IL 17;
+ 9 : accommodation platform
+ 10 : navigation, communication and control buoy (NCCB)
+
+Definitions:
+
+oil derrick/rig: a temporary mobile structure, either fixed or floating, used in the exploration stages of oil and gas fields. (IHO Dictionary, S-32, 5th Edition,
+
+production platform: a term used to indicate a permanent offshore structure equipped to control the flow of oil or gas. It does not include entirely submarine structures. (IHO Dictionary, S-32, 5th Edition, 4037)
+
+observation/research platform:
+ a platform from which one's surroundings or events can be observed, noted or recorded such as for scientific study. (adapted from IHO Dictionary, S-32, 5th Edition, 3493/3500)
+
+articulated loading platform (ALP):
+ a metal lattice tower, buoyant at one end and attached at the other by a universal joint to a concrete filled base on the sea bed. The platform may be fitted with a helicopter platform, emergency accommodation and hawser/hose retrieval. (adapted from United Kingdom Hydrographic Office CSDO 607.2 (12), May 1994)
+
+single anchor leg mooring (SALM):
+ a rigid frame or tube with a buoyancy device at its upper end , secured at its lower end to a universal joint on a large steel or concrete base resting on the sea bed, and at its upper end to a mooring buoy by a chain or wire. (adapted from United Kingdom Hydrographic Office CSDO 607.2 (12), May 1994)
+
+mooring tower: a platform secured to the sea bed and surmounted by a turntable to which ships moor. (adapted from United Kingdom Hydrographic Office CSDO 607.2 (12), May 1994)
+
+artificial island: a man-made structure usually built for the exploration or exploitation of marine resources, marine scientific research, tidal observations, etc. (adapted from IHO Dictionary, S-32, 5th Edition, 240)
+
+floating production, storage and offloading vessel (FPSO):
+ an offshore oil/gas facility consisting of a moored tanker/barge by which the product is extracted, stored and exported. (adapted from United Kingdom Hydrographic Office CSDO 607.2 (13), May 1994)
+
+accommodation platform:
+ a platform used primarily for eating, sleeping and recreation purposes.
+
+navigation, communication and control buoy (NCCB):
+ a floating structure with control room, power and storage facilities, attached to the sea bed by a flexible pipeline and cables.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATOLB Code: 44
+Category of oil barrier CATOLB 44
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : oil retention (high pressure pipe) IF 29.2;
+ 2 : floating oil barrier IF 29.1;
+
+Definitions:
+
+oil retention (high pressure pipe):
+ a pipe with holes from which air blows. When the air bubbles reach the surface they form a barrier which prevents the spread of oil. (Kort- og Matrikelstyrelsen, Denmark)
+
+floating oil barrier: a floating tube shaped structure, with a curtain (2 metre) hanging under it, below the surface, which prevents the spread of oil. (Kort- og Matrikelstyrelsen, Denmark)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATPLE Code: 45
+Category of pile CATPLE 45
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : stake
+ 2 : snag
+ 3 : post IF 22; 327.3;
+ 4 : tripodal
+
+Definitions:
+
+stake: an elongated wood or metal pole embedded in the bottom to serve as a marker or support. (adapted from IHO Dictionary, S-32, 5th Edition, 4960)
+
+post: a vertical piece of timber, metal or concrete forced into the earth or sea bed.
+
+tripodal: a single structure comprising 3 or more piles held together (sections of heavy timber, steel or concrete), and forced into the earth or sea bed. (adapted from IHO Dictionary, S-32, 5th Edition, 3840)
+
+Remarks:
+
+ No remarks.
+
+Value number 2 (snag) has been transferred to the attribute category of obstruction (CATOBS). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATPIL Code: 46
+Category of pilot boarding place CATPIL 46
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : boarding by pilot-cruising vessel IT 1.1-3; 491.1;
+ 2 : boarding by helicopter IT 1.4; 491.2;
+ 3 : pilot comes out from shore IT 1.1-3; 491.1;
+
+Definitions:
+
+boarding by pilot-cruising vessel:
+ pilot boards from a cruising vessel.
+
+boarding by helicopter: pilot boards by helicopter which comes out from the shore.
+
+pilot comes out from shore:
+ pilot boards from a vessel which comes out from the shore on request.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATPIP Code: 47
+Category of pipeline/pipe CATPIP 47
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : pipeline in general
+ 2 : outfall pipe IL 41.1; 444.2,4;
+ 3 : intake pipe IL 41.1; 444.2,4;
+ 4 : sewer IL 41.1; 444.2,4;
+ 5 : bubbler system
+ 6 : supply pipe IL 40.1; 444;
+
+Definitions:
+
+outfall pipe: a pipe (generally a sewer or drainage pipe) discharging in to the sea or a river.
+
+intake pipe: a pipe taking water from a river or other body of water, to drive a mill or supply a canal, waterworks, etc. (IHO Dictionary, S-32, 5th Edition, 2468)
+
+sewer: a pipe in a sewage system for carrying water or sewage to a disposal area.
+
+bubbler system: a submerged pipe from which warm water bubbles, preventing the surrounding water from freezing.
+
+supply pipe: a pipe used for supplying of gas or liquid product.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATPRA Code: 48
+Category of production area CATPRA 48
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : quarry IE 35.1-2; 367.1;
+ 2 : mine IE 36; 367.2;
+ 3 : stockpile
+ 4 : power station area
+ 5 : refinery area 367;
+ 6 : timber yard IF 52; 328.2;
+ 7 : factory area
+ 8 : tank farm 376.2;
+ 9 : wind farm
+
+Definitions:
+
+quarry: an excavation in solid rock from which building stone, limestone, etc. is removed.
+
+mine: an excavation in the earth for the purpose of extracting earth materials.
+
+stockpile: a reserve stock of material, equipment or other supplies.
+
+power station area: a stationary plant containing apparatus for large-scale conversion of some form of energy (hydraulic, steam, chemical, nuclear, etc.) into electrical energy.
+
+refinery area: a system of process units used to convert crude petroleum into fuels, lubricants and other petroleum-derived products.
+
+timber yard: a storage area for wood used for building, carpentry or joinery.
+
+factory area: a group of buildings where goods are manufactured.
+
+tank farm: an area in which a number of large-capacity storage tanks are located, generally used for crude oil or petroleum products.
+
+wind farm: an area in which numerous wind motors are located.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATPRI Attribute type: E
+Category of production installation CATPRI
+INT 1 Reference: IE 35.1-2, 36; IL 20, 21.1-3;
+
+Chart Specification: 367.1-2; 445; 445.1; 445.5;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : quarry
+ 2 : mine
+ 3 : wellhead
+ 4 : production well
+
+
+Remarks:
+
+ The attribute `category of production installation` encodes the various types of production installation.
+
+ Definitions of attribute values:
+
+ Mine: An excavation in the earth for the purpose of extracting earth materials.
+
+ Quarry: An excavation in solid rock from which building stone, limestone, etc. is removed.
+
+ Submerged wellhead:
+ A submarine structure projecting some distance above the seabed and capping a temporarily abandoned, or suspended, oil or gas well. (IHO Dictionary, S-32, 4th Edition)
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attributes category of production area (CATPRA) and category of obstructions (CATOBS).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATPYL Code: 49
+Category of pylon CATPYL 49
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : power transmission pylon/pole
+ 2 : telephone/telegraph pylon/pole
+ 3 : aerial cableway/sky pylon
+ 4 : bridge pylon/tower
+ 5 : bridge pier
+
+Definitions:
+
+power transmission pylon/pole:
+ a vertical construction consisting, for example, of a steel framework or of pre-stressed concrete, to support a power transmission cable or line. (adapted from Digital Geographic Information Standard - DIGEST FACC 1.2)
+
+telephone/telegraph pylon/pole:
+ a pylon or pole used to support a telephone or telegraph line. (Digital Geographic Information Standard - DIGEST FACC 1.2)
+
+aerial cableway/sky pylon:
+ a tower or pylon supporting steel cables which convey cars, buckets, or other suspended carrier units. (adapted from Digital Geographic Information Standard - DIGEST FACC 1.2)
+
+bridge pylon/tower: a tower, abutment or pylon from which a bridge deck is suspended. (adapted from Digital Geographic Information Standard - DIGEST FACC 1.2)
+
+bridge pier: a support in the form of a pillar or pier for the spans of a bridge. (adapted from Digital Geographic Information Standard - DIGEST FACC 1.2)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATQUA Code: 50
+Category of quality of data CATQUA
+Attribute type: E
+
+Expected input:
+
+ ID Meaning
+
+ 1 : data quality A
+ 2 : data quality B
+ 3 : data quality C
+ 4 : data quality D
+ 5 : data quality E
+ 6 : quality not evaluated
+
+Definitions:
+
+CategoryPositional
+Accuracy 1Sounding
+TechniqueCoverage
+DatumA 5mecho sounder/
+sweepfull 2WGS84B 20mecho sounder/
+laser/sweepfull 2transformed to
+WGS844C 50mecho sounder/
+lead linesystematic 3transformed to
+WGS844D 500mlead linenot systematicother datumEunknownunknownnot systematicunknown datum
+Remarks:
+
+Footnote numbers quoted in the table have the following meanings:
+
+1 accuracy specified at 2 drms. Accuracy is quoted with respect to the given datum of the data. The quoted accuracy is the maximum value of the cumulative error in the production of the data. It should take account of survey errors, transformation errors, digitising errors, etc.
+
+2 full coverage is defined as 100% coverage using systematic controlled surveys providing full sea floor coverage or full coverage to a defined depth and an investigation of all contacts.
+
+3 systematic is defined as a controlled survey but full coverage may not have been achieved.
+
+4 parameters for the transformation of various datums to or from WGS84 can be found in IHO publication S-60 (User's Handbook on Datum Transformations involving WGS-84).
+
+. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATRAS Code: 51
+Category of radar station CATRAS 51
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : radar surveillance station IM 30; 487;
+ 2 : coast radar station IS 1; 485.1;
+
+Definitions:
+
+radar surveillance station:
+ a radar station established for traffic surveillance. (IHO Dictionary, S-32, 5th Edition, 4144)
+
+coast radar station: a shore-based station which the mariner can contact by radio to obtain a position. IHO Chart Specifications, M-4
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATRTB Code: 52
+Category of radar transponder beacon CATRTB 52
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : ramark, radar beacon transmitting continuously IS 2; 486.1;
+ 2 : racon, radar transponder beacon IS 3.1-6; 486.2-4;
+ 3 : leading racon/radar transponder beacon IS 3.5;
+
+Definitions:
+
+ramark: a radar marker beacon which continuously transmits a signal appearing as a radial line on a radar screen, the line indicating the direction of the beacon. Ramarks are intended primarily for marine use. The name "ramark" is derived from the words radar marker. (IHO Dictionary, S-32, 5th Edition, 4208)
+
+racon: a radar beacon which returns a coded signal which provides identification of the beacon, as well as range and bearing. The range and bearing are indicated by the location of the first character received on the radar screen. The name "racon" is derived from the words radar beacon. (IHO Dictionary, S-32, 5th Edition, 4132)
+
+leading racon/radar transponder beacon:
+ a radar beacon that may be used (in conjunction with at least one other radar beacon) to indicate a leading line.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATROS Code: 53
+Category of radio station CATROS 53
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : circular (non-directional) marine or
+ aero-marine radiobeacon IS 10; 481.1;
+ 2 : directional radiobeacon IS 11; 481.2;
+ 3 : rotating-pattern radiobeacon IS 12; 481.1;
+ 4 : Consol beacon IS 13; 481.3;
+ 5 : radio direction-finding station IS 14; 483;
+ 6 : coast radio station providing QTG service IS 15; 484;
+ 7 : aeronautical radiobeacon IS 16; 482;
+ 8 : Decca
+ 9 : Loran C
+ 10 : Differential GPS
+ 11 : Toran
+ 12 : Omega
+ 13 : Syledis
+ 14 : Chaika (Chayka)
+
+Definitions:
+
+ A radiobeacon is a radio transmitter which emits a distinctive or characteristic signal on which a bearing may be taken (IHO Dictionary, S-32, 5th Edition, 4168).
+
+circular (non-directional) marine or aero-marine radiobeacon:
+ a radio station which need not necessarily be manned, the emissions of which, radiated around the horizon, enable its bearing to be determined by means of the radio direction finder of a ship. (IHO Dictionary, S-32, 5th Edition, 802)
+
+directional radiobeacon:
+ a special type of radiobeacon station the emissions of which are intended to provide a definite track for guidance. (IHO Dictionary, S-32, 5th Edition, 1378)
+
+rotating pattern radiobeacon:
+ a special type of radiobeacon station emitting a beam of waves to which a uniform turning movement is given, the bearing of the station being determined by means of an ordinary listening receiver and a stop watch. Also referred to as a rotating loop radiobeacon. (IHO Dictionary, S-32, 5th Edition, 4444)
+
+Consol beacon: a type of long range position fixing beacon.
+
+radio direction-finding station:
+ a radio station intended to determine only the direction of other stations by means of transmission from the latter. (IHO Dictionary, S-32, 5th Edition, 4174)
+
+coast radio station providing QTG service:
+ a radio station which is prepared to provide QTG service, that is to say, to transmit upon request from a ship, a radio signal, the bearing of which can be taken by that ship. (IHO Dictionary, S-32, 5th Edition, 4108)
+
+aeronautical radiobeacon:
+ a radio beacon designed for aeronautical use.
+
+Decca: the Decca Navigator System is a high accuracy, short to medium range radio navigational aid intended for coastal and landfall navigation. (Admiralty List of Radio Signals, UK Hydrographic Office, Volume 2, 1994)
+
+Loran C: Loran-C is a low frequency electronic position fixing system using pulsed transmissions at 100 Khz. (Admiralty List of Radio Signals, UK Hydrographic Office, Volume 2, 1994)
+
+Differential GPS: a radiobeacon transmitting DGPS correction signals.
+
+Toran: Toran is an electronic position fixing system used mainly by aircraft.
+
+Omega: Omega is a long-range radio navigational aid which operates within the VLF frequency band. The system comprises eight land based stations. (Admiralty List of Radio Signals, UK Hydrographic Office, Volume 2, 1994)
+
+Syledis: Syledis is a ranging position fixing system operating at 420-450MHz over a range of up to 400Km.
+
+Chiaka (Chayka): Chiaka is a low frequency electronic position fixing system using pulsed transmissions at 100 Khz. (Admiralty List of Radio Signals, UK Hydrographic Office, Volume 2, 1995)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATTRK Code: 54
+Category of recommended track CATTRK 54
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : based on a system of fixed marks IM 3; 434.1-2;
+ 2 : not based on a system of fixed marks IM 4; 434.1-2;
+
+Definitions:
+
+based on a system of fixed marks:
+ a straight route (known as a recommended track, range or leading line), which comprises at least two structures (usually beacons or daymarks) and/or natural features, which may carry lights and/or top-marks. The structures/features are positioned so that when observed to be in line, a vessel can follow a known bearing with safety. (adapted from International Association of Lighthouse Authorities - IALA Aids to Navigation Guide, 1990)
+
+not based on a system of fixed marks:
+ a route (known as a recommended track or preferred route) which is not based on a series of structures or features in line.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATREB Attribute type: E
+Category of religious building CATREB
+INT 1 Reference: IE 10.1, 13-18;
+
+Chart Specification: 373.1-5;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : church
+ 2 : chapel
+ 3 : cross; calvary
+ 4 : temple
+ 5 : pagoda
+ 6 : shinto-shrine
+ 7 : buddhist temple
+ 8 : mosque
+ 9 : marabout
+
+
+Remarks:
+
+ The attribute `category of religious building` encodes the various types of religious building.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attributes function (FUNCTN) and category of landmark (CATLMK).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATRSC Code: 55
+Category of rescue station CATRSC 55
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : rescue station with lifeboat IT 12; 493;
+ 2 : rescue station with rocket IT 12; 493;
+ 3 : rescue station with lifeboat and rocket
+ 4 : refuge for shipwrecked mariners IT 14; IQ 124; 456.4;
+ 5 : refuge for intertidal area walkers IT 14; IQ 124; 456.4;
+ 6 : lifeboat lying at a mooring IT 13; 493.2;
+
+Definitions:
+
+rescue station with lifeboat:
+ a place where equipment for saving life at sea is maintained; the type of lifeboat may vary from fast, long distance boats to inflatable inshore boats. (IHO Chart Specifications, M-4)
+
+rescue station with rocket:
+ rocket - a pyrotechnic projectile used for signalling or for life-saving purposes. (IHO Dictionary, S-32, 5th Edition, 4418)
+
+refuge for ship-wrecked mariners:
+ shelter or protection from danger or distress at sea.
+
+refuge for intertidal area walkers:
+ shelter or protection from danger in areas exposed to extreme and sudden tides or tidal streams.
+
+lifeboat lying at a mooring:
+ a place where a lifeboat is moored ready for use.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATREA Code: 56
+Category of restricted area CATREA 56
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : offshore safety zone IL 3;
+ 2 : anchoring prohibition area
+ 3 : fishing prohibition area
+ 4 : nature reserve IN 22;
+ 5 : bird sanctuary IN 22;
+ 6 : game reserve IN 22;
+ 7 : seal sanctuary IN 22;
+ 8 : degaussing range IN 25; 448.1-3;
+ 9 : military area IN 31;
+ 10 : historic wreck area IN 26; 449.5;
+ 11 : inshore traffic zone
+ 12 : navigational aid safety zone IM 29.1; 435.7;
+ 13 : danger of stranding area
+ 14 : minefield IN 34; 441.8;
+ 15 : diving prohibition area
+ 16 : area to be avoided
+ 17 : Prohibited area
+ 18 : swimming area
+ 19 : waiting area
+ 20 : research area
+ 21 : dredging area IN 63; 446.4;
+ 22 : fish sanctuary
+ 23 : ecological reserve
+ 24 : no wake area
+ 25 : swinging area
+
+Definitions:
+
+
+offshore safety zone: the area around an offshore installation within which vessels are prohibited from entering without permission; special regulations protect installations within a safety zone and vessels of all nationalities are required to respect the zone. (IHO Dictionary, S-32, 5th Edition, 4471)
+
+nature reserve: a tract of land managed so as to preserve it's flora, fauna, physical features, etc.
+
+bird sanctuary: a place where birds are bred and protected.
+
+game reserve: a place where wild animals or birds hunted for sport or food are kept undisturbed for private use.
+
+seal sanctuary: a place where seals are protected.
+
+degaussing range: an area, usually about two cables diameter, within which ships' magnetic fields may be measured; sensing instruments and cables are installed on the sea bed in the range and there are cables leading from the range to a control position ashore. (IHO Chart Specifications, M-4)
+
+military area: an area controlled by the military in which restrictions may apply. (Hydrographic Service, Royal Australian Navy)
+
+historic wreck area: an area around certain wrecks of historical importance to protect the wrecks from unauthorized interference by diving, salvage or deposition (including anchoring). (IHO Chart Specifications, M-4)
+
+navigational aid safety zone:
+ an area around a navigational aid which vessels are prohibited from entering.
+
+minefield: an area laid and maintained with explosive mines for defence or practice purposes.
+
+swimming area: an area in which people may swim and therefore vessel movement may be restricted.
+
+waiting area: an area reserved for vessels waiting to enter a harbour.
+
+research area: an area where marine research takes place.
+
+dredging area: an area where dredging is taking place.
+
+fish sanctuary: a place where fish are protected.
+
+ecological reserve: a tract of land managed so as to preserve the relation of plants and living creatures to each other and to their surroundings.
+
+no wake area: an area in which a vessels' speed must be reduced in order to reduce the size of the wake it produces.
+
+swinging area: an area where vessels turn. (Service Hydrographique et Ocèanographique de la Marine, France)
+
+
+
+Remarks:
+
+ The official legal status of each kind of restricted area defines the kind of restriction(s), e.g. the restriction for a `game preserve' may be entering prohibited', the restriction for an anchoring prohibition area' is anchoring prohibited'.
+
+Values 2, 3, 15, 16 and 17 have been transferred to the attribute restriction (RESTRN). Value number 11 has been replaced by the object class inshore traffic zone (ISTZNE). Value 13 should be encoded using object class caution area (CTNARE). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATROD Code: 57
+Category of road CATROD 57
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : motorway ID 10; 365.1;
+ 2 : major road ID 11; 365.2;
+ 3 : minor road ID 11; 365.2;
+ 4 : track/path ID 12; 365.3;
+ 5 : major street ID 12; 365.3;
+ 6 : minor street
+ 7 : crossing
+
+Definitions:
+
+motorway: a main road with separate carriageways and limited access, specially constructed and controlled for fast motor traffic.
+
+major road: a hard surfaced (metalled) road; a main through route.
+
+minor road: a secondary road for local traffic.
+
+track/path: track - a rough path or way formed by use.
+ path - a way or track laid down for walking or made by continual treading.
+
+major street: a main road, in an urban area, for through traffic.
+
+minor street: a secondary road, in an urban area, for local traffic.
+
+crossing: a place where roads, etc. intersect.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATRUN Code: 58
+Category of runway CATRUN 58
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : aeroplane runway
+ 2 : helicopter landing pad
+
+Definitions:
+
+aeroplane runway: a level stretch of land where aeroplanes take of and land.
+
+helicopter landing pad: a site on which helicopters may land and take off. (IHO Dictionary, S-32, 5th Edition, 2232)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSEA Code: 59
+Category of sea area CATSEA 59
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : sea area in general
+ 2 : gat
+ 3 : bank
+ 4 : deep
+ 5 : bay
+ 6 : trench
+ 7 : basin
+ 8 : mud flats
+ 9 : reef
+ 10 : ledge
+ 11 : canyon
+ 12 : narrows
+ 13 : shoal
+ 14 : knoll
+ 15 : ridge
+ 16 : seamount
+ 17 : pinnacle
+ 18 : abyssal plain
+ 19 : plateau
+ 20 : spur
+ 21 : shelf
+ 22 : trough
+ 23 : saddle
+ 24 : abyssal hills
+ 25 : apron
+ 26 : archipelagic apron
+ 27 : borderland
+ 28 : continental margin
+ 29 : continental rise
+ 30 : escarpment
+ 31 : fan
+ 32 : fracture zone
+ 33 : gap
+ 34 : guyot
+ 35 : hill
+ 36 : hole
+ 37 : levee
+ 38 : median valley
+ 39 : moat
+ 40 : mountains
+ 41 : peak
+ 42 : province
+ 43 : rise
+ 44 : sea channel
+ 45 : seamount chain
+ 46 : shelf-edge
+ 47 : sill
+ 48 : slope
+ 49 : terrace
+ 50 : valley
+ 51 : canal
+ 52 : lake
+ 53 : river
+
+Definitions:
+
+gat: a natural or artificial passage or channel through shoals or steep banks, or across a line of banks lying between two channels. (IHO Hydrographic Dictionary, S-32, 5th Edition)
+
+bank: an elevation over which the depth of water is relatively shallow, but normally sufficient for safe surface navigation. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+deep: in oceanography, an obsolete term which was generally restricted to depths greater than 6,000 m. (IHO Hydrographic Dictionary, S-32, 5th Edition)
+
+bay: an indentation in the coastline.
+
+trench: a long narrow, characteristically very deep and asymmetrical depression of the sea floor, with relatively steep sides. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+basin: a depression, characteristically in the deep sea floor, more or less equidimensional in plan and of variable extent. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+flat: a level tract of land, as the bed of a dry lake or an area frequently uncovered at low tide. Usually in plural.
+
+reef: rock lying at or near the sea surface that may constitute a hazard to surface navigation. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+ledge: a rocky formation continuous with and fringing the shore. (IHO Hydrographic Dictionary, S-32, 5th Edition)
+
+canyon: a relatively narrow, deep depression with steep sides, the bottom of which generally has a continuous slope, developed characteristically on some continental slopes. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+narrows: a navigable narrow part of a bay, strait, river, etc. (IHO Hydrographic Dictionary, S-32, 5th Edition)
+
+shoal: an offshore hazard to surface navigation that is composed of unconsolidated material. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+knoll: a relatively small isolated elevation of a rounded shape. (IHO-IOC Publication B- 6, Standardization of Undersea Feature Names, 2ndEdition)
+
+ridge: (a) A long, narrow elevation with steep sides. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2nd Edition)
+ (b) A long, narrow elevation often separating ocean basins. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2nd Edition)
+ (c) The linked major mid-oceanic mountain systems of global extent. Also called mid-oceanic ridge. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+seamount: a large isolated elevation, greater than 1000m in relief above the sea floor, characteristically of conical form. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+pinnacle: any high tower or spire-shaped pillar or rock or coral, alone or cresting a summit. It may extend above the surface of the water. It may or may not be a hazard to surface navigation. (IHO Hydrographic Dictionary, S-32, 5th Edition)
+
+abyssal plain: an extensive, flat, gently sloping or nearly level region at abyssal depths. (IHO- IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+plateau: a flat or nearly flat area of considerable extent, dropping off abruptly on one or more sides. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+spur: a subordinate elevation, ridge or rise projecting outward from a larger feature. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+shelf: a zone adjacent to a continent (or around an island) and extending from the low water line to a depth at which there is usually a marked increase of slope towards oceanic depths. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+trough: a long depression of the sea floor characteristically flat bottomed and steep sided and normally shallower than a trench. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+saddle: a broad pass, resembling in shape a riding saddle, in a ridge or between contiguous seamounts. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+abyssal hills: a tract, on occasion extensive, of low (100-500m) elevations on the deep sea floor. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+apron: a gently dipping featureless surface, underlain primarily by sediment, at the base of any steeper slope. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2nd Edition)
+
+archipelagic apron: a gentle slope with a generally smooth surface on the sea floor, characteristically found around groups of islands or seamounts. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+borderland: a region adjacent to a continent, normally occupied by or bordering a shelf, that is highly irregular with depths well in excess of those typical of a shelf. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+continental margin: the zone, generally consisting of shelf, slope and rise, separating the continent from the abyssal plain or deep sea floor. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+continental rise: a gentle slope rising from the oceanic depths towards the foot of a continental slope. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+escarpment: an elongated and comparatively steep slope separating or gently sloping areas. Also called: scarp. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+fan: a relatively smooth, fan-like, depositional feature normally sloping away from the outer termination of a canyon or canyon system. Also called: cone. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+fracture zone: an extensive linear zone of irregular topography of the sea floor, characterized by steep-sided or asymmetrical ridges, troughs or escarpments. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+gap: a narrow break in a ridge or a rise. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+guyot: a seamount having a comparatively smooth flat top. Also called tablemount. (IHO Hydrographic Dictionary, S-32, 5th Edition and IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+hill: a small isolated elevation (see also abyssal hills). (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+hole: a local depression, often steep sided, of the sea floor. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+levee: a depositional embankment bordering a canyon, valley or deep-sea channel. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+median valley: the axial depression of the mid-oceanic ridge system. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+moat: an annular depression that may not be continuous, located at the base of many seamounts, islands and other isolated elevations. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+mountains: a large and complex grouping of ridges and seamounts. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+peak: a prominent elevation either pointed or of a very limited extent across the summit. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+province: a region identifiable by a group of similar physiographic features whose characteristics are markedly in contrast with surrounding areas. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+rise: (a) A broad elevation that rises gently and generally smoothly from the sea floor.
+ (b) The linked major mid-oceanic mountain systems of global extent. Also called mid-oceanic ridge. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2nd Edition)
+
+sea channel: a continuously sloping, elongated narrow depression commonly found in fans or abyssal plains and customarily bordered by levees on one or both sides. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+seamount chain: several seamounts in linear or orcuate alignment. Also called: seamounts. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+shelf-edge: a narrow zone at the seaward margin of a shelf along which is a marked increase of slope. Also called: shelf break. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEd.)
+
+sill: a sea floor barrier of relatively shallow depth restricting water movement between basins. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+slope: the slope seaward from the shelf edge to the upper edge of a continental rise or the point where there is a general reduction in slope. (adapted from IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+terrace: a relatively flat horizontal or gently inclined surface, sometimes long and narrow, which is bounded by a steeper ascending slope on one side and by a steeper descending slope on the opposite side. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2nd Edition)
+
+valley: a relatively shallow, wide depression, the bottom of which usually has a continuous gradient. This term is generally not used for features that have canyon-like characteristics for a significant portion of their extent. Also called: submarine valley; sea valley. (IHO-IOC Publication B-6, Standardization of Undersea Feature Names, 2ndEdition)
+
+canal: an artificial water course used for navigation.
+
+lake: a large body of water entirely surrounded by land. (IHO Dictionary, S-32, 5th Edition, 2629)
+
+river: a relatively large natural stream of water.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSLC Code: 60
+Category of shoreline construction CATSLC 60
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT M-4
+
+ 1 : breakwater IF 4.1-3; 322.1;
+ 2 : groyne (groin) IF 6.1-3; 313.4;
+ 3 : mole IF 12; 321.3;
+ 4 : pier (jetty) IF 14; 321.2,4;
+ 5 : promenade pier IF 15; 321.2;
+ 6 : wharf (quay) IF 13; 321.1;
+ 7 : training wall IF 5; 322.2;
+ 8 : rip rap
+ 9 : revetment
+ 10 : sea wall IF 2; 313.2;
+ 11 : landing steps IF 18;
+ 12 : ramp IF 23;
+ 13 : slipway IF 23; 324.1;
+ 14 : fender
+ 15 : solid face wharf
+ 16 : open face wharf
+
+Definitions:
+
+breakwater: a structure protecting a shore area, harbour, anchorage, or basin from waves. (IHO Dictionary, S-32, 5th Edition, 542)
+
+groyne (groin): a low artificial wall-like structure of durable material extending from the land to seaward for a particular purpose, such as to prevent coast erosion (adapted from IHO Dictionary, S-32, 5th Edition, 2525 and IHO Chart Specifications, M-4)
+
+mole: a form of breakwater alongside which vessels may lie on the sheltered side only; in some cases it may lie entirely within an artificial harbour, permitting vessels to lie along both sides. (IHO Chart Specifications, M-4)
+
+pier (jetty): a long, narrow structure extending into the water to afford a berthing place for vessels, to serve as a promenade, etc. (IHO Dictionary, S-32, 5th Edition, 3833)
+
+promenade pier: a pier built only for recreational purposes. (IHO Chart Specifications, M-4)
+
+wharf (quay): a structure serving as a berthing place for vessels. (IHO Dictionary, S-32, 5th Edition, 5985)
+
+training wall: a wall or bank, often submerged, built to direct or confine the flow of a river or tidal current, or to promote a scour action. (Adapted from IHO Dictionary, S-32, 5th Edition, 5586 and IHO Chart Specifications, M-4).
+
+rip rap: A layer of broken rock, cobbles, boulders, or fragments of sufficient size to resist the erosive forces of flowing water and wave action. (Adapted from Marine Chart Manual, US National Oceanic and Atmospheric Administration - NOAA, 1992)
+
+revetment: facing of stone or other material, either permanent or temporary, placed along the edge of a stream, river or canal to stabilize the bank and to protect it from the erosive action of the stream. (Adapted from IHO Dictionary, S-32, 5th Edition, 4379)
+
+sea wall: an embankment or wall for protection against waves or tidal action along a shore or water front. (IHO Dictionary, S-32, 5th Edition, 4584)
+
+landing steps: steps at the shoreline as the connection between land and water on different levels.
+
+ramp: a sloping structure that can either be used, as a landing place, at variable water levels, for small vessels, landing ships, or a ferry boat, or for hauling a cradle carrying a vessel, which may include rails. (Adapted from IHO Dictionary, S-32, 5th Edition, 4209)
+
+slipway: the prepared and usually reinforced inclined surface on which keel- and bilge-blocks are laid for supporting a vessel under construction. (IHO Dictionary, S-32, 5th Edition, 4775)
+
+fender: a protective structure designed to cushion the impact of a vessel and prevent damage.
+
+solid face wharf: a wharf consisting of a solid wall of concrete, masonry, wood etc., such that the water cannot circulate freely under the wharf. The type of construction affects ship-handling; for example, a solid face wharf may give shelter from tidal streams, but under certain circumstances a cusion of water may build up between such a wharf and a ship attempting to berth at it, causing difficulties in ship handling. (Capt. A. Rae, pilot, Port of Halifax & Mr. R. Morash, wharf building engineer, Transport Canada)
+
+
+open face wharf: a wharf supported on piles or other structures which allow free circulation of water under the wharf. (Capt. A. Rae, pilot, Port of Halifax & Mr. R. Morash, wharf building engineer, Transport Canada)
+
+
+Remarks:
+
+ The attribute category of shoreline construction' encodes the usage of a shoreline construction. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSIT Code: 61
+Category of signal station, traffic CATSIT 61
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : port control IT 23; 495.1;
+ 2 : port entry and departure
+ 3 : International Port Traffic IT 21; 495.5;
+ 4 : berthing
+ 5 : dock
+ 6 : lock IT 24; 495.2;
+ 7 : flood barrage
+ 8 : bridge passage IT 25.1; 495.3;
+ 9 : dredging
+
+Definitions:
+
+port control: a signal station for the control of vessels within a port.
+
+port entry and departure:
+ a signal station for the control of vessels entering or leaving a port.
+
+International Port Traffic:
+ a signal station displaying International Port Traffic signals.
+
+berthing: a signal station for the control of vessels when berthing.
+
+dock: a signal station for the control of vessels entering or leaving a dock.
+
+lock: a signal station for the control of vessels entering or leaving a lock.
+
+flood barrage: a signal station for the control of vessels wishing to pass through a flood control barrage.
+
+bridge passage: a signal station for the control of vessels wishing to pass under a bridge.
+
+dredging: a signal station indicating when dredging is in progress.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSIW Code: 62
+Category of signal station, warning CATSIW 62
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : danger IT 35; 490.1;
+ 2 : maritime obstruction
+ 3 : cable
+ 4 : military practice IT 36; 490.1;
+ 5 : distress IT 26; 497;
+ 6 : weather IT 29; 494.1;
+ 7 : storm IT 28; 494.1;
+ 8 : ice IT 30; 494.1;
+ 9 : time IT 31; 494.2;
+ 10 : tide IT 33; 496.2;
+ 11 : tidal stream IT 34; 496.3;
+ 12 : tide gauge IT 32.2; 496.1;
+ 13 : tide scale IT 32.1; 496.1;
+ 14 : diving
+
+Definitions:
+
+danger: a signal or message warning of the presence of a danger to navigation.
+
+maritime obstruction: a signal or message warning of the presence of a maritime obstruction.
+
+cable: a signal or message warning of the presence of a cable.
+
+military practice: a signal or message warning of activity in a military practice area.
+
+distress: a station that may receive or transmit distress signals.
+
+weather: a visual signal displayed to indicate a weather forecast. (IHO Dictionary, S-32, 5th Edition, 4740)
+
+storm: a signal or message conveying information about storm conditions.
+
+ice: a signal or message conveying information about ice conditions.
+
+time: an accurate signal marking a specified time or time interval. It is used primarily for determining errors of timepieces. Such signals are usually sent from an observatory by radio or telegraph, but visual signals are used at some ports. (IHO Dictionary, S-32, 5th Edition, 4735)
+
+tide: a signal or message conveying information on tidal conditions in the area in question. (IHO Dictionary, S-32, 5th Edition, 4734)
+
+tidal stream: a signal or message conveying information on condition of tidal currents in the area in question. (IHO Dictionary, S-32, 5th Edition, 4733)
+
+tide gauge: a device for measuring the height of tide. A graduated staff in a sheltered area where visual observations can be made; or it may consist of an elaborate recording instrument making a continuous graphic record of tide height against time. Such an instrument is usually actuated by a float in a pipe communicating with the sea through a small hole which filters out shorter waves. (IHO Dictionary, S-32, 5th Edition, 1984)
+
+tide scale: a visual scale which directly shows the height of the water above chart datum or a local datum. (IHO Chart Specifications, M-4, 496)
+
+diving: a signal or message warning of diving activity
+
+
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSIL Code: 63
+Category of silo/tank CATSIL 63
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : silo in general IE 33; 376.3;
+ 2 : tank in general IE 32; 376.1-2;
+ 3 : grain elevator
+ 4 : water tower
+
+Definitions:
+
+silo in general: a generally cylindrical tower used for storing fodder or grain.
+
+tank in general: a fixed structure for storing liquids. (IHO Dictionary, S-32, 5th Edition, 5290)
+
+grain elevator: a storage building for grain. Usually a tall frame, metal or concrete structure with an especially compartmented interior. (The New Encyclopaedia Britannica Micropaedia, 15th Edition).
+
+water tower: a tower with an elevated container used to hold water.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSLO Code: 64
+Category of slope CATSLO 64
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : cutting ID 14; 363.2;
+ 2 : embankment ID 15; 364.1;
+ 3 : dune IC 8; 312.3;
+ 4 : hill
+ 5 : pingo
+ 6 : cliff IC 3; 312.1;
+ 7 : scree
+
+Definitions:
+
+cutting: an excavation through high ground for a road, canal, etc.
+
+embankment: an artificial elevation constructed from earth, stone, etc. carrying a road, railway or similar or serving to dam water.
+
+dune: a mound, ridge or hill of drifted material on the sea coast or in a desert. (adapted from IHO Dictionary, S-32, 5th Edition, 1496)
+
+hill: a small isolated elevation, smaller than a mountain. (IHO Dictionary, S-32, 5th Edition, 2262)
+
+pingo: a dome-shaped hill formed in a permafrost area when the hydrostatic pressure of freezing ground water causes the upheaval of a layer of frozen ground. (Encyclopaedia Britannica Mycropaedia, 15th Edition)
+
+cliff: land rising abruptly for a considerable distance above the water or surrounding land. (IHO Dictionary, S-32, 5th Edition, 829)
+
+scree: rocky debris on the side or at the foot of a mountain forming a steep stony slope.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSCF Code: 65
+Category of small craft facility CATSCF 65
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1
+
+ 1 : visitor's berth IU 2;
+ 2 : nautical club IU 4;
+ 3 : boat hoist IU 6;
+ 4 : sailmaker IU 8;
+ 5 : boatyard IU 9;
+ 6 : public inn IU 10;
+ 7 : restaurant IU 11;
+ 8 : chandler IU 12;
+ 9 : provisions IU 13;
+ 10 : doctor IU 15;
+ 11 : pharmacy IU 16;
+ 12 : water tap IU 17;
+ 13 : fuel station IU 18;
+ 14 : electricity IU 19;
+ 15 : bottle gas IU 20;
+ 16 : showers IU 21;
+ 17 : launderette IU 22;
+ 18 : public toilets IU 23;
+ 19 : post box IU 24;
+ 20 : public telephone IU 25;
+ 21 : refuse bin IU 26;
+ 22 : car park IU 27;
+ 23 : parking for boats and trailers IU 28;
+ 24 : caravan site IU 29;
+ 25 : camping site IU 30;
+ 26 : sewerage pump-out station
+ 27 : emergency telephone
+ 28 : landing/launching place for boats IF 17; IU 7;
+ 29 : visitors mooring IU 3;
+ 30 : scrubbing berth
+ 31 : picnic area
+
+Definitions:
+
+visitor's berth: a berth set aside for the use of visiting vessels.
+
+nautical club: a club for mariners generally associated with other small craft facilities.
+
+boat hoist: a hoist for lifting boats out of the water.
+
+sailmaker: a place where sails are made or may be taken for repair.
+
+boatyard: a place on shore where boats may be built, stored and repaired.
+
+public inn: a public house providing food, drink and accommodation. (The Collins Reference English Dictionary, 1992)
+
+restaurant: a commercial establishment serving food. (The Collins Reference Dictionary, 1992)
+
+chandler: a dealer in ships' supplies. (The Collins Reference Dictionary, 1992)
+
+provisions: a place where food and other such supplies are available.
+
+doctor: a place where a doctor is available to provide medical attention.
+
+pharmacy a place where medical drugs are dispensed.
+
+water tap: a place where fresh water is available.
+
+fuel station: a place where fuel is available.
+
+electricity: a place where a connection to an electrical supply is available.
+
+bottle gas: a place where bottled gas is available.
+
+showers: a place where showers are available.
+
+launderette: a place where there are facilities for washing clothes.
+
+public toilets: a place where toilets are available for public use.
+
+post box: a place where mail may be posted.
+
+public telephone: a place where a telephone is available for public use.
+
+refuse bin: a place where refuse may be dumped.
+
+car park: a place where cars may be parked.
+
+parking for boats and trailers: a place on shore where boats and/or trailers may be parked.
+
+caravan site: a place where caravans may be parked or where caravan accommodation is provided.
+
+camping site: a place where visitors may pitch tents and camp.
+
+sewerage pump-out station: a place where sewerage may be pumped off a vessel.
+
+emergency telephone: a place where a telephone is available for emergency use only.
+
+landing/launching place for boats: a place where boats may be landed or launched.
+
+visitors mooring: a mooring set aside for the use of visiting vessels.
+
+scrubbing berth: a place where vessels may berth for the purpose of careening.
+
+picnic area: a place where people may go to eat a picnic.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATSPM Code: 66
+Category of special purpose mark CATSPM 66
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : firing danger area mark IQ 125; 441.2;
+ 2 : target mark IQ 51;
+ 3 : marker ship mark IQ 52;
+ 4 : degaussing range mark IQ 54; 448.3;
+ 5 : barge mark IQ 53;
+ 6 : cable mark IQ 55, 123; 443.6; 458;
+ 7 : spoil ground mark IQ 56; 446.3;
+ 8 : outfall mark IQ 57; 444.4;
+ 9 : ODAS (Ocean-Data-Acquisition-System) IQ 58; 462.9;
+ 10 : recording mark IQ 59;
+ 11 : seaplane anchorage mark IQ 60;
+ 12 : recreation zone mark IQ 62;
+ 13 : private mark IQ 70;
+ 14 : mooring mark 431.5;
+ 15 : LANBY (Large Automatic Navigational Buoy) IQ 26; 474.4-5;
+ 16 : leading mark IQ 120; 458;
+ 17 : measured distance mark IQ 122; 458;
+ 18 : notice mark IQ 126; 456.8;
+ 19 : TSS mark (Traffic Separation Scheme) IQ 61;
+ 20 : anchoring prohibited mark
+ 21 : berthing prohibited mark
+ 22 : overtaking prohibited mark
+ 23 : two-way traffic prohibited mark
+ 24 : reduced wake' mark
+ 25 : speed limit mark 456.2;
+ 26 : stop mark
+ 27 : general warning mark
+ 28 : sound ship's siren' mark
+ 29 : restricted vertical clearance mark
+ 30 : maximum vessel's draught mark
+ 31 : restricted horizontal clearance mark
+ 32 : strong current warning mark
+ 33 : berthing permitted mark
+ 34 : overhead power cable mark
+ 35 : channel edge gradient' mark
+ 36 : telephone mark
+ 37 : ferry crossing mark
+ 38 : marine traffic lights
+ 39 : pipeline mark
+ 40 : anchorage mark
+ 41 : clearing mark IQ 121; 458;
+ 42 : control mark
+ 43 : diving mark
+ 44 : refuge beacon IQ 124;
+ 45 : foul ground mark
+ 46 : yachting mark
+ 47 : heliport mark
+ 48 : GPS mark
+ 49 : seaplane landing mark
+ 50 : entry prohibited mark
+ 51 : work in progress mark
+ 52 : mark with unknown purpose
+
+Definitions:
+
+firing danger mark: a mark used to indicate a firing danger area, usually at sea.
+
+target mark: any object toward which something is directed.
+ the distinctive marking or instrumentation of a ground point to aid its identification on a photograph. (Adapted from IHO Dictionary, S-32, 5th Edition, 5309)
+
+marker ship mark: a mark marking the position of a ship which is used as a target during some military exercise. (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+degaussing range mark:
+ a mark used to indicate a degaussing range.
+
+barge mark: a mark of relevance to barges.
+
+cable mark: a mark used to indicate the position of submarine cables or the point at which they run on to the land.
+
+spoil ground mark: a mark used to indicate the limit of a spoil ground (adapted from IHO Dictionary, S-32, 5th Edition, 4931).
+
+outfall mark: a mark used to indicate the position of an outfall or the point at which it leaves the land.
+
+ODAS: Ocean Data Acquisition System (IHO Dictionary, S-32, 5th Edition, 5953)
+
+recording mark: a mark used to record data for scientific purposes.
+
+seaplane anchorage mark:
+ a mark used to indicate a seaplane anchorage.
+
+recreation zone mark: a mark used to indicate a recreation zone.
+
+private mark: a privately maintained mark.
+
+mooring mark: a mark indicating a mooring or moorings.
+
+LANBY: a large buoy designed to take the place of a lightship where construction of an offshore light station is not feasible. (IHO Dictionary, S-32, 5th Edition, 2656)
+
+leading mark: aids to navigation or other indicators so located as to indicate the path to be followed. Leading marks identify a leading line when they are in transit. (IHO Dictionary, S-32, 5th Edition, 2697)
+
+measured distance mark:
+ a mark forming part of a transit indicating one end of a measured distance.
+
+notice mark: a notice board or sign indicating information to the mariner.
+
+TSS mark: a mark indicating a traffic separation scheme.
+
+
+anchoring prohibited mark:
+ a mark indicating an anchoring prohibited area.
+
+berthing prohibited mark:
+ a mark indicating that berthing is prohibited.
+
+overtaking prohibited mark:
+ a mark indicating that overtaking is prohibited.
+
+two-way traffic prohibited mark:
+ a mark indicating a one-way route.
+
+reduced wake' mark: a mark indicating that vessels must not generate excessive wake.
+
+speed limit mark: a mark indicating that a speed limit applies.
+
+stop mark: a mark indicating the place where the bow of a ship must stop when traffic lights show red.
+
+general warning mark: a mark indicating that special caution must be exercised in the vicinity of the mark.
+
+sound ships siren' mark:
+ a mark indicating that a ship should sound its siren or horn.
+
+restricted vertical clearance mark:
+ a mark indicating the minimum vertical space available for passage.
+
+maximum vessel's draught mark:
+ a mark indicating the maximum draught of vessel permitted.
+
+restricted horizontal clearance mark:
+ a mark indicating the minimum horizontal space available for passage.
+
+strong current warning mark:
+ a mark warning of strong currents.
+
+berthing permitted mark:
+ a mark indicating that berthing is allowed.
+
+overhead power cable mark:
+ a mark indicating an overhead power cable.
+
+channel edge gradient' mark:
+ a mark indicating the gradient of the slope of a dredge channel edge.
+
+telephone mark: a mark indicating the presence of a telephone.
+
+ferry crossing mark: a mark indicating that a ferry route crosses the ship route; often used with a sound ship's siren' mark.
+
+pipeline mark: a mark used to indicate the position of submarine pipelines or the point at which they run on to the land.
+
+anchorage mark: a mark indicating an anchorage area.
+
+clearing mark: a mark used to indicate a clearing line.
+
+control mark: a mark indicating the location at which a restriction or requirement exists.
+
+diving mark: a mark indicating that diving may take place in the vicinity.
+
+refuge beacon: a mark providing or indicating a place of safety.
+
+foul ground mark: a mark indicating a foul ground.
+
+yachting mark: a mark installed for use by yachtsmen.
+
+heliport mark: a mark indicating an area where helicopters may land.
+
+GPS mark: a mark indicating a location at which a GPS position has been accurately determined.
+
+seaplane landing mark: a mark indicating an area where sea-planes land.
+
+entry prohibited mark: a mark indicating that entry is prohibited.
+
+work in progress mark: a mark indicating that work (generally construction) is in progress.
+
+mark with unknown purpose:
+ a mark whose detailed characteristics are unknown.
+
+
+Remarks:
+
+ A mark may be a beacon, a buoy, a signpost or may take another form.
+
+Value number 38 should be encoded using object class signal station, traffic (SISTAT). FEATURE OBJECT ATTRIBUTES
+
+
+
+Acronym: CAT_TS Code: 188
+
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : flood stream IH 40; 407.4;
+ 2 : ebb stream IH 41; 407.4;
+ 3 : Other tidal flow
+
+Definitions:
+
+flood stream: the horizontal movement of water associated with the rising tide. Flood streams generally set towards the shore, or in the direction of the tide progression. Also called flood, flood current or ingoing stream. (Adapted from IHO Dictionary, S-32, 5th Edition)
+
+ebb stream: the horizontal movement of water associated with falling tide. Ebb streams generally set seaward, or in the opposite direction to the tide progression. Also called ebb, ebb current or outgoing stream. (Adapted from IHO Dictionary, S-32, 5th Edition)
+
+Other tidal flow: any other horizontal movement of water associated with tides, eg. rotary flow.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATTOW Attribute type: E
+Category of tower CATTOW
+INT 1 Reference: IE 20, 21, 29; 30.2;
+
+Chart Specification: 374.2-3; 375.2; 487.3;
+
+Expected input:
+
+ ID Meaning
+
+ 1 : light tower
+ 2 : water tower
+ 3 : radio/television tower
+ 4 : cooling tower
+ 5 : radar tower
+ 6 : lookout tower
+ 7 : observation tower
+
+Remarks:
+
+ The attribute category of tower' encodes the various types of tower.
+
+ Definitions of attribute values:
+
+ Light tower: A tower carrying a light as a navigational aid.
+
+ Water tower: A tower with an elevated container used to hold water.
+
+ Radio/television tower:
+ A tower used for transmitting and/or receiving radio/television signals.
+
+ Cooling tower: A tower to cool liquids. (Digital Geographic Information Working Group -DGIWG, Oct.87)
+
+ Radar tower: A tower carrying radar equipment.
+
+ Lookout tower: A tower from which a watch is habitually kept.
+
+ Observation tower: A tower from which a watch is not habitually kept.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute category of landmark (CATLMK).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATTSS Code: 67
+Category of Traffic Separation Scheme CATTSS 67
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : IMO - adopted
+ 2 : not IMO - adopted
+
+Definitions:
+
+IMO - adopted: a defined Traffic Separation Scheme that has been adopted as an IMO routing measure.
+
+not IMO - adopted: a defined Traffic Separation Scheme that has not been adopted as an IMO routing measure.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: CATTRE Attribute type: E
+Category of tree CATTRE
+INT 1 Reference: IC 31.1-8;
+
+Chart Specification: 354.2;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : evergreen
+ 2 : conifer
+ 3 : palm
+ 4 : nipa palm
+ 5 : casuarina
+ 6 : filao
+ 7 : eucalypt
+ 8 : deciduous
+ 9 : mangrove
+
+
+Remarks:
+
+ The attribute category of tree' encodes the various types of tree.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute category of vegetation (CATVEG).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATVEG Code: 68
+Category of vegetation CATVEG 68
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : grass
+ 2 : paddy field
+ 3 : bush
+ 4 : deciduous wood
+ 5 : coniferous wood
+ 6 : wood in general (inc mixed wood) IC 30; 354.1;
+ 7 : mangroves IC 32; 312.4;
+ 8 : park
+ 9 : parkland
+ 10 : mixed crops
+ 11 : reed
+ 12 : moss
+ 13 : tree in general IC 31; 354.2;
+ 14 : evergreen tree IC 31.2; 354.2;
+ 15 : coniferous tree IC 31.3; 354.2;
+ 16 : palm tree IC 31.4; 354.2;
+ 17 : nipa palm tree IC 31.5; 354.2;
+ 18 : casuarina tree IC 31.6; 354.2;
+ 19 : eucalypt tree IC 31.8; 354.2;
+ 20 : deciduous tree IC 31.1; 354.2;
+ 21 : mangrove tree IC 32; 312.4;
+ 22 : filao tree IC 31.7; 354.2;
+
+Definitions:
+
+grass: vegetation belonging to a group of plants with green blades that are eaten by cattle, sheep, etc. (The Concise Oxford Dictionary)
+
+bush: a shrub or clump of shrubs with stems of moderate length. (The Concise Oxford Dictionary)
+
+deciduous wood: a wood with trees that shed their leaves annually. (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+coniferous wood: a wood with evergreen trees of a group usually bearing cones, including yews, cedars and redwoods. (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+wood in general (including mixed wood):
+ growing trees densely occupying a tract of land. (The Concise Oxford Dictionary)
+
+mangroves: one of several genera of tropical trees or shrubs which produce many prop roots and grow along low lying coasts into shallow water. (IHO Dictionary, S-32, 5th Edition, 3064)
+
+mixed crops: a mixture of arable crops.
+
+reed: any of various water or marsh plants with a firm stem. (The Concise Oxford Dictionary)
+
+moss: any small cryptogamous plant of the class Musci, growing in dense clusters on the surface of the ground in bogs, on trees, stones, etc. (The Concise Oxford Dictionary)
+
+tree in general: a woody perennial plant, having a self supporting main stem or trunk.
+
+evergreen tree: a tree which keeps its foliage all year round.
+
+coniferous tree: a cone-bearing, needle-leaved or scale-leaved evergreen tree. (adapted from The New Encyclopaedia Britannica, 15th Edition 1991)
+
+palm tree: a tropical or sub-tropical tree, shrub or vine having a tall, unbranched, columnar trunk. The trunk is crowned by a tuft or large, pleated fan or feather shaped leaves with stout sheathing and often prickly petioles (stalks), the persistent bases of which frequently clothe the trunk. (adapted from The New Encyclopaedia Britannica, 15th Edition 1991)
+
+nipa palm tree: (also called Nypa palm) a rare palm tree with regular branching involving equal or sub-equal division of the apex that results in forking. (adapted from The New Encyclopaedia Britannica, 15th Edition 1991)
+
+casuarina tree: (also called beefwood, Australian pine, ironwood, she-oak, swamp oak, whistling pine) a tree characterized by slender, green, often drooping branches that are deeply grooved and that bear, at intervals, whorls of tine leaves. (adapted from The New Encyclopaedia Britannica, 15th Edition 1991)
+
+eucalypt tree: an instance of a large genus of mostly very large trees (90 metres). (adapted from The New Encyclopaedia Britannica, 15th Edition 1991)
+
+deciduous tree: a tree which sheds its foliage for part of the year (generally in winter).
+
+mangrove tree: one of several genera of tropical trees or shrubs which produce many prop roots and grow along low lying coasts in to shallow waters. (IHO Dictionary, S-32, 5th Edition, 3064)
+
+filao tree: a variety of tropical or sub-tropical tree.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATWAT Code: 69
+Category of water turbulence CATWAT 69
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : breakers IK 17; 423.2;
+ 2 : eddies IH 45; 423.3;
+ 3 : overfalls IH 44; 423.1;
+ 4 : tide rips IH 44; 423.1;
+ 5 : bombora
+
+Definitions:
+
+breaker: a wave breaking on the shore, over a reef, etc. Breakers may be roughly classified into three kinds, although the categories may overlap: spilling breakers break gradually over a considerable distance; plunging breakers tend to curl over and break with a crash; and surging breakers peak up, but then instead of spilling or plunging they surge up on the beach face. The French word brisant' is also used for the obstacle causing the breaking of the wave. (IHO Dictionary, S-32, 5th Edition, 540)
+
+eddies: circular movements of water usually formed where currents pass obstructions, between two adjacent currents flowing counter to each other, or along the edge of a permanent current. (IHO Dictionary, S-32, 5th Edition, 1560)
+
+overfalls: short, breaking waves occurring when a strong current passes over a shoal or other submarine obstruction or meets a contrary current or wind. (IHO Dictionary, S-32, 5th Edition, 3631)
+
+tide rips: small waves formed on the surface of water by the meeting of opposing tidal currents or by a tidal current crossing an irregular bottom. (IHO Dictionary, S-32, 5th Edition, 5494)
+
+bombora: a wave that forms over a submerged offshore reef or rock, sometimes (in very calm weather or at high tide) nearly swelling but in other conditions breaking heavily and producing a dangerous stretch of broken water; the reef or rock itself. Also called bumbora or bomborah. (Australian National Dictionary)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATWED Code: 70
+Category of weed/kelp CATWED 70
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : kelp IJ 13.2; 428.2;
+ 2 : sea weed IJ 13.1; 425.5;
+ 3 : sea grass
+ 4 : saragasso
+
+Definitions:
+
+kelp: a giant plant sometimes 60 metres long with no roots, it is anchored by hold-fasts or tendrils up to 10 metres long, that cling to rock. Gas filled bubbles on fronds act as floats keeping the kelp just below the surface. (Earth Sciences References, Mary McNeil)
+
+sea weed: general name for marine plants of the algae class which grow in long narrow ribbons. Also called sea grass. (International Maritime Dictionary, 2nd Edition)
+
+sea grass: any grasslike marine alga. Eelgrass is one of the best known seagrasses. (IHO Dictionary, S-32, 5th Edition, 4565)
+
+sargasso: a certain type of sea weed, or more generally, a large floating mass of this sea weed. (IHO Dictionary, S-32, 5th Edition, 4501)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATWRK Code: 71
+Category of wreck CATWRK 71
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : non-dangerous wreck IK 29; 422.6;
+ 2 : dangerous wreck IK 28; 422.5;
+ 3 : distributed remains of wreck IK 31; 422.8;
+ 4 : wreck showing mast/masts IK 25; 422.2;
+ 5 : wreck showing any portion of hull or superstructure IK 24; 422.2;
+
+Definitions:
+
+non-dangerous wreck: a wreck which is not considered to be dangerous to surface navigation.
+
+dangerous wreck: a wreck which is considered to be dangerous to surface navigation.
+
+distributed remains of wreck:
+ (foul ground) an area over which it is safe to navigate but which should be avoided for anchoring, taking the ground or ground fishing. (IHO Chart Specifications, M-4)
+
+wreck showing mast/masts:
+ wreck of which only the mast(s) is visible at the sounding datum indicated.
+
+wreck showing any portion of hull or superstructure:
+ wreck of which any portion of the hull or superstructure is visible at the sounding datum indicated.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CATZOC Code: 72
+Category of zone of confidence in data CATZOC
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : zone of confidence A1
+ 2 : zone of confidence A2
+ 3 : zone of confidence B
+ 4 : zone of confidence C
+ 5 : zone of confidence D
+ 6 : zone of confidence U (data not assessed)
+
+Definitions:
+
+See ZOC Table on following page.
+
+ZOC Table:
+
+
+12345ZOC 1
+Position
+Accuracy
+Depth Accuracy 3
+
+Seafloor CoverageTypical Survey Characteristics 5
+
+
+
+A1
+
+
+
+
+ 5 m a = 0.5
+
+ b = 1 Full seafloor ensonification or sweep. All significant seafloor features detected 4 and depths measured.Controlled,
+systematic
+high accuracy Survey on
+WGS 84 datum; using DGPS or a minimum three lines of position (LOP) with multibeam, channel or mechanical
+sweep system.
+
+
+
+. Depth (m) Accuracy (m)10
+30
+100
+1000 0.6
+ 0.8
+ 1.5
+ 10.5
+
+
+
+A2
+
+
+
+ 20 m a = 1.0
+b = 2Full seafloor ensonification or sweep. All significant seafloor features detected 4 and depths measured.Controlled,
+systematic survey to standard accuracy; using modern survey echosounder with sonar or mechanical sweep. Depth (m) Accuracy (m)10
+30
+100
+1000 1.2
+ 1.6
+ 3.0
+ 21.0
+
+
+
+B
+
+
+
+ 50 ma = 1.0
+b = 2Full seafloor coverage not achieved; uncharted features, hazardous to surface navigation are not expected but may exist.Controlled,
+systematic survey to standard accuracy. Depth (m) Accuracy (m)10
+30
+100
+1000 1.2
+ 1.6
+ 3.0
+ 21.0
+
+
+
+C
+
+
+
+ 500 ma = 2.0
+b = 5Full seafloor coverage not achieved, depth anomalies may be expected.Low accuracy survey or data collected on an opportunity basis such as soundings on passage. Depth (m) Accuracy (m)10
+30
+100
+1000 2.5
+ 3.5
+ 7.0
+ 52.0
+D worse
+ than
+ ZOC C worse
+ than
+ ZOC CFull seafloor coverage not achieved, large depth anomalies may be expected.Poor quality data or data that cannot be quality asses-sed due to lack of information.
+Note: The CATZOC attribute definitions are currently the subject of review and the results of this review will be promulgated as soon as possible in the S-57 Corrections Document.
+Remarks:
+
+To decide on a ZOC Category, all conditions outlined in columns 2 to 4 of the table must be met.
+
+Footnote numbers quoted in the table have the following meanings:
+
+1 The allocation of a ZOC indicates that particular data meets minimum criteria for position and depth accuracy and seafloor coverage defined in this Table. Data may be further qualified by Object Class "Quality of Data" (M_QUAL) sub-attributes as follows:
+
+ a) Positional Accuracy (POSACC) and Sounding Accuracy (SOUACC) may be used to indicate that a higher position or depth accuracy has been achieved than defined in this Table (e.g. a survey where full seafloor coverage was not achieved could not be classified higher that ZOC B; however, if the position accuracy was, for instance, 15 metres, the sub-attribute POSACC could be used to indicate this).
+
+ b) Swept areas where the clearance depth is accurately known but the actual seabed depth is not accurately known may be accorded a "higher" ZOC (i.e. A1 or A2) providing positional and depth accuracies of the swept depth meets the criteria in this Table. In this instance, Depth Range Value 1 (DRVAL1) may be used to specify the swept depth. The position accuracy criteria apply to the boundaries of swept areas.
+
+ c) SURSTA, SUREND and TECSOU may be used to indicate the start and end dates of the survey and the technique of sounding measurement.
+
+2 Position Accuracy of depicted soundings at 95% CI (2.45 sigma) with respect to the given datum. It is the cumulative error and includes survey, transformation and digitizing errors etc. Position accuracy need not be rigorously computed for ZOCs B, C and D but may be estimated based on type of equipment, calibration regime, historical accuracy etc.
+
+3 Depth accuracy of depicted soundings = a + (bd)/100 at 95% CI (2.00 sigma), where d = depth in metres at the critical depth. Depth accuracy need not be rigorously computed for ZOCs B, C and D but may be estimated based on type of equipment, calibration regime, historical accuracy etc.
+
+4 Significant seafloor features are defined as those rising above depicted depths by more than:
+
+ Depth Significant Feature
+
+ a. <10 metres >0.1depth,
+ b. 10 to 30 metres >1.0 metre,
+ c. >30 metres >(0.1depth) minus 2.0 metres
+
+5 Controlled, systematic (high accuracy) survey (ZOC A1, A2 and B) - a survey comprising planned survey lines, on a geodetic datum that can be transformed to WGS 84.
+
+ Position fixing (ZOC A1) must be strong with at least three high quality Lines of Position (LOP) or Differential GPS.
+
+ Modern survey echosounder - a high precision surveying depth measuring equipment, generally including all survey echosounders designed post 1970.
+
+
+
+
+Acronym: $SPACE Code: 73
+Character spacing $SPACE 73
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : expanded/condensed
+ 2 : standard
+
+
+Definitions:
+
+expanded/condensed: string expanded or condensed to fit between the first and last positions.
+
+standard: character spacing in accordance with the typeface in use.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $CHARS Code: 74
+Character specification $CHARS 74
+Attribute type: A
+
+
+Expected input: SEWBB, where:
+
+ S style = U : Univers
+ T : Times
+ E weight = 4 : light
+ 5 : medium
+ 6 : bold
+ W width = 1 : upright
+ 2 : italic
+ BB body size = XX (body size in pica points)
+
+References:
+
+ INT 1: not specified;
+
+ M-4: not specified;
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: COLOUR Code: 75
+Colour COLOUR 75
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : white IP 11.1; 450.2-3;
+ 2 : black
+ 3 : red IP 11.2; 450.2-3;
+ 4 : green IP 11.3; 450.2-3;
+ 5 : blue IP 11.4; 450.2-3;
+ 6 : yellow IP 11.6; 450.2-3;
+ 7 : grey
+ 8 : brown
+ 9 : amber IP 11.8; 450.2-3;
+ 10 : violet IP 11.5; 450.2-3;
+ 11 : orange IP 11.7; 450.2-3;
+ 12 : magenta
+ 13 : pink
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: COLMAR Attribute type: E
+Colour of navigational mark COLMAR
+INT 1 Reference: IQ 2-5, 130.1, 130.3-6;
+
+Chart Specification: 455.4; 464; 464.1-3;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : green
+ 2 : black
+ 3 : red
+ 4 : yellow
+ 5 : white
+ 6 : orange
+ 7 : black/yellow
+ 8 : black/yellow/black
+ 9 : yellow/black
+ 10 : yellow/black/yellow
+ 11 : red/white
+ 12 : green/red/green
+ 13 : red/green/red
+ 14 : black/red/black
+ 15 : yellow/red/yellow
+ 16 : green/red
+ 17 : red/green
+ 18 : green/white
+
+Remarks:
+
+ The attribute colour of navigational mark' encodes the various colours and the combinations for navigational marks.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute colour (COLOUR).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: COLPAT Code: 76
+Colour pattern COLPAT 76
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : horizontal stripes
+ 2 : vertical stripes
+ 3 : diagonal stripes
+ 4 : squared
+ 5 : stripes (direction unknown)
+ 6 : border stripe
+
+Definitions:
+
+horizontal stripes: straight bands or stripes of differing colours painted horizontally.
+
+vertical stripes: straight bands or stripes of differing colours painted vertically.
+
+diagonal stripes: straight bands or stripes of differing colours painted diagonally (ie not horizontally or vertically).
+
+squared: often referred to as checker plate, where alternate colours are used to create squares similar to a chess or draught board. The pattern may be straight or diagonal.
+
+stripes (direction unknown):
+ straight bands or stripes of differing colours painted in an unknown direction.
+
+border stripe: a band or stripe of colour which is displayed around the outer edge of the object, which may also form a border to an inner pattern or plain colour.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: COMCHA Code: 77
+Communication channel COMCHA 77
+Attribute type: A
+
+
+Definition:
+
+ A channel number assigned to a specific radio frequency, frequencies or frequency band.
+
+Expected input:
+
+ enter specific VHF-Channel
+
+
+References:
+
+ INT 1: IM 40;
+
+ M-4: 488;
+
+ The attribute communication channel' encodes the various VHF-channels used for communication.
+
+Indication:
+
+ Each VHF-channel should be indicated by 2 digits and up to 2 characters (A-Z);
+
+ e.g. VHF-channel 7 -> 07'
+ VHF-channel 16 -> 16';
+
+ The indication of several VHF-channels is possible;
+
+Format:
+
+ [XXXX];[XXXX];...
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $CSIZE Code: 78
+Compass size $CSIZE 78
+Attribute type: F
+
+
+Expected input:
+
+ the radius of the compass.
+
+
+Definition:
+
+ specifies the display radius for a cartographic compass rose.
+
+Indication:
+
+ Unit: millimetre (mm)
+ Resolution: 0.1 mm
+
+Format:
+
+ xx.xx
+
+Example:
+
+ 68 for a compass rose radius of 68 millimetres.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CPDATE Code: 79
+Compilation date CPDATE 79
+Attribute type: A
+
+
+Definition:
+
+ The date on which the compilation of the data was completed.
+
+
+Indication:
+
+ The compilation date should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD), according to ISO 8601: 1988.
+
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+ 19871021 for 21 October 1987 as compilation date.
+
+Remarks:
+
+ No remarks.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CSCALE Code: 80
+Compilation scale CSCALE 80
+Attribute type: I
+
+
+Definition:
+
+ The scale at which the data was originally compiled.
+
+
+Minimum value: 0
+
+Indication:
+
+ The modulus of the scale is indicated, that is 1:75 000 is encoded as 75000.
+
+ Unit: none
+ Resolution: 1
+
+
+Format:
+
+ xxxxxxxx
+
+
+Example:
+
+ 75000 for a scale of 1:75 000.
+
+Remarks:
+
+ For example, the scale of the paper chart that was used for the ENC compilation. This attribute is only used in conjunction with the meta-object Compilation Scale of data' (M_CSCL) which is used to define polygons of equal compilation scale. CSCALE should therefore not be confused with the attributes SCAMIN and SCAMAX. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CONDTN Code: 81
+Condition CONDTN 81
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : under construction IF 30; 329.1;
+ 2 : ruined ID 8; IF 33.1-2; 378.1-2;
+ 3 : under reclamation IF 31; 329.2;
+ 4 : wingless IE 25.2; 374.5;
+ 5 : planned construction
+
+Definitions:
+
+under construction: a structure that is in the process of being built.
+
+ruined: a structure in a decayed or deteriorated condition resulting from neglect or disuse, or a damaged structure in need of repair. (IHO Dictionary, S-32, 5th Edition, 4456)
+
+under reclamation: an area of the sea that is being reclaimed as land, usually by the dumping of earth and other material.
+
+wingless: a windmill or windmotor from which the turbine blades are missing.
+
+planned construction: an area where a future construction is planned.
+
+Remarks:
+
+ The attribute condition' encodes the various conditions of buildings and other constructions. The default condition' should be considered to be completed, undamaged and working normally. This attribute should, therefore, only be used to indicate objects whose condition is anything other than normal'. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CONRAD Code: 82
+Conspicuous, radar CONRAD 82
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : radar conspicuous IS 5; 485.2;
+ 2 : not radar conspicuous
+ 3 : radar conspicuous (has radar reflector)
+
+Definitions:
+
+radar conspicuous: an object which returns a strong radar echo. (IHO Dictionary, S-32, 5th Edition, 4142)
+
+not radar conspicuous: an object which does not return a particularly strong radar echo.
+
+radar conspicuous (has radar reflector):
+ an object which returns a strong radar echo, having a radar reflector.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CONVIS Code: 83
+Conspicuous, visually CONVIS 83
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : visually conspicuous 340.1;
+ 2 : not visually conspicuous
+
+Definitions:
+
+visually conspicuous: term applied to an object either natural or artificial which is distinctly and notably visible from seaward. (IHO Dictionary, S-32, 5th Edition, 984)
+
+not visually conspicuous:
+ an object which is visible from seaward, but is not conspicuous.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: CURVEL Code: 84
+Current velocity CURVEL 84
+Attribute type: F
+
+
+Definition:
+
+ The rate of travel of a current.
+
+
+References:
+
+ INT 1: IH 40, 43;
+
+ M-4: 407.1; 407.4; 408.3;
+
+Indication:
+
+ Unit: knot (kt)
+ Resolution: 0.1kt
+
+Format:
+
+ xx.x
+
+Example:
+
+ 1.6 for a velocity of 1.6 knots.
+
+Remarks:
+
+ The attribute current velocity' indicates the speed of the current in knots. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: DATEND Code: 85
+Date end DATEND 85
+Attribute type: A
+
+
+Indication:
+
+ the date, end' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD), according to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+19961007 for 07 October 1996 as ending date.
+
+
+Remarks:
+
+ The attribute date end' indicates the latest date on which an object (e.g. a buoy) will be present.
+
+ This attribute is to be used to indicate the removal or cancellation of an object at a specific date in the future. See also periodic date end'
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: DATSTA Code: 86
+Date start DATSTA 86
+Attribute type: A
+
+
+Indication:
+
+ The date, start' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD), according to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+ 19960822 for 22 August 1996 as starting date.
+
+Remarks:
+
+ The attribute date, start' indicates the earliest date on which an object (e.g. a buoy) will be present.
+
+ This attribute is to be used to indicate the deployment or implementation of an object at a specific date in the future. See also periodic date start'.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: DRVAL1 Code: 87
+Depth range value 1 DRVAL1 87
+Attribute type: F
+
+
+Definition:
+
+ The minimum (shoalest) value of a depth range.
+
+References:
+
+ INT 1: II 21; IM 6;
+
+ M-4: 414; 432.4; 434.3-4;
+
+Indication:
+
+ Unit: defined in the DUNI subfield of the DSPM record or in the DUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 fm or 0.1 ft
+
+
+Format:
+
+ sxxxxx.x
+ s: sign, negative values only.
+
+Example:
+
+ 50 for a minimum depth of 50 metres.
+
+Remarks:
+
+ Where the area dries, the value is negative.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: DRVAL2 Code: 88
+Depth range value 2 DRVAL2 88
+Attribute type: F
+
+
+Definition:
+
+ The maximum (deepest) value of a depth range.
+
+References:
+
+ INT 1: II 21; IM 6;
+
+ M-4: 414; 432.4; 434.3-4;
+
+
+Indication:
+
+ Unit: defined in the DUNI subfield of the DSPM record or in the DUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 fm or 0.1 ft
+
+
+Format:
+
+ sxxxxx.x
+ s: sign, negative values only.
+
+Example:
+
+ 100 for a maximum depth of 100 metres
+
+Remarks:
+
+ Where the area dries, the value is negative. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: DUNITS Code: 89
+Depth units DUNITS 89
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : metres
+ 2 : fathoms and feet
+ 3 : feet
+ 4 : fathoms and fractions
+
+Definitions:
+
+metres: depths are specified in metres (SI units of length).
+
+fathoms and feet: depths are specified in fathoms (units of six feet of depth) and feet.
+
+feet: depths are specified in feet (imperial units of length).
+
+fathoms and fractions: depths are specified in fathoms (units of six feet of depth) and fractions of fathoms.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: ELEVAT Code: 90
+Elevation ELEVAT 90
+Attribute type: F
+
+
+Definition:
+
+ The altitude of the ground level of an object, measured from a specified vertical datum.
+
+Minimum Value: 0
+
+References:
+
+ INT 1: IC 10-13; IH 20;
+
+ M-4: 352.1-2; 302.2; 405;
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 47 for an elevation of 47 metres
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: ESTRNG Code: 91
+Estimated range of transmission ESTRNG 91
+Attribute type: F
+
+
+Definition:
+
+ The estimated range of a non-optical electromagnetic transmission.
+
+Minimum Value: 0
+
+References:
+
+ INT 1: none specified;
+
+ M-4: none specified;
+
+Indication:
+
+ Unit: nautical mile (M)
+ Resolution: 0.1M
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 45 for a range of 45 nautical miles.
+
+Remarks:
+
+ The estimated range (distance) assumes in vacuo' transmission and a standard antenna height of 5 metres. Thus it gives a hint to the mariner whether he is likely to receive transmission at a certain distance from an object carrying this attribute.
+
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: EXCLIT Code: 92
+Exhibition condition of light EXCLIT 92
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : light shown without change of character
+ 2 : daytime light IP 51; 473.4;
+ 3 : fog light IP 52; 473.5;
+ 4 : night light
+
+Definition:
+
+light shown without change of character:
+ a light shown throughout the 24 hours without change of character. IHO Chart Specifications, M-4
+
+daytime light: a light which is only exhibited by day.
+
+fog light a light which is exhibited in fog or conditions of reduced visibility.
+
+night light: a light which is only exhibited at night.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: EXPSOU Code: 93
+Exposition of sounding EXPSOU 93
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : within the range of depth of the surrounding depth area
+ 2 : shoaler than the range of depth of the surrounding depth area
+ 3 : deeper than the range of depth of the surrounding depth area
+
+Definitions:
+
+within the range of depth of the surrounding depth area:
+ the depth corresponds to the depth range of the surrounding depth area. i.e. the depth is not shoaler than the minimum depth of the surrounding depth area or deeper than the maximum depth of the surrounding depth area.
+
+shoaler than the range of depth of the surrounding depth area:
+ the depth is shoaler than the minimum depth of the surrounding depth area.
+
+deeper than the range of depth of the surrounding depth area:
+ the depth is deeper than the maximum depth of the surrounding depth area.
+
+Remarks:
+
+ This attribute indicates objects with a value of sounding' not within the range of depth of the surrounding depth area. These objects could be a potential danger for navigation.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: FUNCTN Code: 94
+Function+ FUNCTN
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : no function/service of major interest
+ 2 : harbour-master's office IF 60; 325.1;
+ 3 : custom office IF 61; 325.2;
+ 4 : health office IF 62.1; 325.3;
+ 5 : hospital IF 62.2; 325.3;
+ 6 : post office IF 63; 372.1;
+ 7 : hotel
+ 8 : railway station ID 13; 362.2;
+ 9 : police station
+ 10 : water-police station
+ 11 : pilot office IT 3; 491.4;
+ 12 : pilot lookout IT 2; 491.3;
+ 13 : bank office
+ 14 : headquarters for district control
+ 15 : transit shed/warehouse IF 51; 328.1;
+ 16 : factory
+ 17 : power station
+ 18 : administrative IG 72;
+ 19 : educational facility
+ 20 : church IE 10.1; 373.1-2;
+ 21 : chapel IE 11;
+ 22 : temple IE 13 373.2;
+ 23 : pagoda IE 14; 373.3;
+ 24 : shinto shrine IE 15; 373.3;
+ 25 : buddhist temple IE 16; 373.3;
+ 26 : mosque IE 17; 373.4;
+ 27 : marabout IE 18; 373.5;
+ 28 : lookout
+ 29 : communication
+ 30 : television
+ 31 : radio
+ 32 : radar
+ 33 : light support
+ 34 : microwave
+ 35 : cooling
+ 36 : observation
+ 37 : timeball
+ 38 : clock
+ 39 : control
+ 40 : airship mooring
+ 41 : stadium
+ 42 : bus station
+
+Definitions:
+
+harbour-master's office: the office of the local official who has charge of mooring and berthing of vessels, collecting harbour fees, etc. (adapted from IHO Dictionary, S-32, 5th Edition, 2191)
+
+customs office: an office which is charged with enforcing customs regulations.
+
+health office: the office which is charged with the administration of health laws and sanitary inspections. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+hospital: an institution or establishment providing medical or surgical treatment for the ill or wounded. (The New Shorter Oxford English Dictionary, 1993)
+
+post office: the public department, agency or organisation responsible primarily for the collection, transmission and distribution of mail. (The New Shorter Oxford English Dictionary, 1993)
+
+hotel: an establishment, especially of a comfortable or luxurious kind, where paying visitors are provided with accommodation, meals and other services. (The New Shorter Oxford English Dictionary, 1993)
+
+railway station: a building with platforms where trains arrive, load, discharge and depart. (The New Shorter Oxford English Dictionary, 1993)
+
+police station: the office of the local police force.
+
+water-police station: the headquarters of a local water-police force.
+
+pilot office: the office or headquarters of pilots; the place where the services of a pilot may be obtained. (IHO Dictionary, S-32, 5th Edition, 3845)
+
+pilot lookout: a distinctive structure on shore from which personnel keep watch upon events at sea or along the coast. (IHO Dictionary, S-32, 5th Edition, 2917)
+
+bank office: an office for custody, deposit, loan, exchange or issue of money. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+headquarters for district control:
+ the quarters of an executive officer (director, manager, etc.) with responsibility for an administrative area.
+
+transit shed/warehouse:
+ a building or part of a building for storage of wares or goods. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+factory: a building or buildings with equipment for manufacturing; a workshop. (The New Shorter Oxford English Dictionary, 1993)
+
+power station: a stationary plant containing apparatus for large scale conversion of some form of energy (such as hydraulic, steam, chemical or nuclear energy) into electrical energy. (McGraw-Hill Dictionary of Scientific and Technical Terms, 3rd Edition, 1984)
+
+administrative: a building for the management of affairs. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+educational facility: a building concerned with education (eg. school, college, university, etc.)
+
+church: a building for public Christian worship. (The New Shorter Oxford English Dictionary, 1993)
+
+chapel: a place for Christian worship other than a parish, cathedral or church, especially one attached to a private house or institution. (The New Shorter Oxford English Dictionary, 1993)
+
+temple: a building for public Jewish worship. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+pagoda: a Hindu or Buddhist temple or sacred building. (The New Shorter Oxford English Dictionary, 1993)
+
+shinto shrine: a building for public Shinto worship. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+buddhist temple: see pagoda.
+
+mosque: a Muslim place of worship. (The New Shorter Oxford English Dictionary, 1993)
+
+marabout: a shrine marking the burial place of a Muslim holy man. (The New Shorter Oxford English Dictionary, 1993)
+
+lookout: keeping a watch upon events at sea or along the coast. (adapted from IHO Dictionary, S-32,5th Edition,2917)
+
+communication: transmitting and/or receiving electronic communication signals. (adapted from Digital Geographic Information Standard - DIGEST)
+
+television: broadcast of television signals.
+
+radio: broadcast of radio signals.
+
+radar: a method, system or technique of using beamed, reflected, and timed radio waves for detecting, locating, or tracking objects, and for measuring altitudes. (IHO Dictionary, S-32, 5th Edition,4158)
+
+light support: supporting a light
+
+microwave: broadcasting and receiving signals using microwaves.
+
+cooling: dissipating heat.
+
+observation: a place from which the surroundings can be observed but at which a watch is not habitually maintained. (adapted from IHO Dictionary, S-32, 5th Edition,2917)
+
+time ball: a visual time signal in form of a ball
+
+clock: visual time signal. (adapted from S-32, 5th Edition, 5536)
+
+control: used to control the flow of air, rail, or marine traffic. (Digital Geographic Information Standard - DIGEST)
+
+airship mooring: a facility to secure an airship. (adapted from Digital Geographic Information Standard - DIGEST)
+
+stadium: a large usually unroofed building with tiers of seats for spectators
+
+bus station: a location at which buses arrive and from which they depart.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HEIGHT Code: 95
+Height HEIGHT 95
+Attribute type: F
+
+
+Definition:
+
+ The value of the vertical distance to the highest point of the object, measured from a specified vertical datum.
+
+Minimum Value: 0
+
+References:
+
+ INT 1: IC 14; IE 4; IK 10-11;
+
+ M-4: 302; 352.4; 421.1-2;
+
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 73 for a height of 73 metres.
+
+
+Remarks:
+
+ Height must not be used for floating objects. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HUNITS Code: 96
+Height/length units HUNITS 96
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : metres
+ 2 : feet
+
+Definitions:
+
+metres: heights/lengths are specified in metres (SI units of length).
+
+feet: heights/lengths are specified in feet (imperial units of length).
+
+Remarks:
+
+ This attribute encodes the units of measurement for heights and lengths, but not depths for which the attribute depth units (DUNITS) is used. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HORACC Code: 97
+Horizontal accuracy HORACC 97
+Attribute type: F
+
+
+Definition:
+
+ The best estimate of the horizontal accuracy of horizontal clearance and distances.
+
+Minimum value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 0.5 for an error of 0.5 metre.
+
+
+Remarks:
+
+ The expected input is the radius of the two-dimensional error.
+
+ The error is assumed to be positive and negative. The plus/minus character shall not be encoded. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HORCLR Code: 98
+Horizontal clearance HORCLR 98
+Attribute type: F
+
+
+Definition:
+
+ The width of an object, such as a canal or a tunnel, which is available for safe navigation. This may, or may not, be the same as the total physical width of the object.
+
+Minimum Value: 0
+
+References:
+
+ INT 1: ID 21;
+
+ M-4: 380.2;
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 125 for a width of 125 metres.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HORLEN Code: 99
+Horizontal length HORLEN 99
+Attribute type: F
+
+
+Definition:
+
+ A measurement of the longer of two linear axis. (Digital Geographic Information Working Group -DGIWG, Oct.87)
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 95 for a length of 95 metres.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HORWID Code: 100
+Horizontal width HORWID 100
+Attribute type: F
+
+
+Definition:
+
+ A measurement of the shorter of two linear axis. (Digital Geographic Information Working Group -DGIWG, Oct.87)
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 12.6 for a width of 12.6 metres.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: ICEFAC Code: 101
+Ice factor ICEFAC 101
+Attribute type: F
+
+
+Definition:
+
+ The value of the maximum variation in the vertical clearance of an overhead cable due to an accumulation of ice.
+
+Minimum Value: 0
+
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 2.5 for a reduction of 2.5 metres in the vertical clearance.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: INFORM Code: 102
+Information INFORM 102
+Attribute type: S
+
+
+Definition:
+
+ Textual information about the object.
+
+References:
+
+ INT 1: IA 16;
+
+ M-4: 242.3-5;
+
+Remarks:
+
+ The textual information could be, for example, a list, a table or a text.
+
+ This attribute should be used, for example, to hold the information that is shown on paper charts by cautionary and explanatory notes.
+
+ No formatting of text is possible within INFORM. If formatted text is required, then the attribute TXTDSC must be used. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: JRSDTN Code: 103
+Jurisdiction JRSDTN 103
+Attribute type: E
+
+
+Definition:
+
+ The jurisdiction applicable to an administrative area.
+
+Expected input:
+
+ ID Meaning
+
+ 1 : international
+ 2 : national
+ 3 : national sub-division
+
+Definitions:
+
+international: involving more than one country; covering more than one national area.
+
+national: an area administered or controlled by a single nation.
+
+national sub-division: an area smaller than the nation in which it lies.
+
+Remarks:
+
+ No remarks; FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $JUSTH Code: 104
+Justification - horizontal $JUSTH 104
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : centre justified
+ 2 : right justified
+ 3 : left justified
+
+Definitions:
+
+centre justified: position refers to the centre of the text string.
+
+right justified: position refers to the right side of the last character in the text string.
+
+left justified: position refers to the left side of the first character in the text string.
+
+Remarks:
+
+ No remarks; FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $JUSTV Code: 105
+Justification - vertical $JUSTV 105
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : bottom justified
+ 2 : centre justified
+ 3 : top justified
+
+Definitions:
+
+bottom justified: position refers to the bottom of the text string.
+
+centre justified: position refers to the centre of the text string.
+
+top justified: position refers to the top of the text string.
+
+Remarks:
+
+ No remarks; FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: LIFCAP Code: 106
+Lifting capacity LIFCAP 106
+Attribute type: F
+
+
+Definition:
+
+ The specific safe lifting capacity of an object.
+
+References:
+
+ INT 1: IF 53.1-2;
+
+ M-4: 328.3;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: tonne (t)
+ Resolution: 0.1 t
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 120 for a lifting capacity of 120 tonnes.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: LITCHR Code: 107
+Light characteristic LITCHR 107
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fixed IP 10.1;
+ 2 : flashing IP 10.4;
+ 3 : long-flashing IP 10.5;
+ 4 : quick-flashing IP 10.6;
+ 5 : very quick-flashing IP 10.7;
+ 6 : ultra quick-flashing IP 10.8;
+ 7 : isophased IP 10.3;
+ 8 : occulting IP 10.2;
+ 9 : interrupted quick-flashing IP 10.6;
+ 10 : interrupted very quick-flashing IP 10.7;
+ 11 : interrupted ultra quick-flashing IP 10.8;
+ 12 : morse IP 10.9;
+ 13 : fixed/flash IP 10.10;
+ 14 : flash/long-flash
+ 15 : occulting/flash
+ 16 : fixed/long-flash
+ 17 : occulting alternating
+ 18 : long-flash alternating
+ 19 : flash alternating
+ 20 : group alternating
+ 21 : 2 fixed (vertical)
+ 22 : 2 fixed (horizontal)
+ 23 : 3 fixed (vertical)
+ 24 : 3 fixed (horizontal)
+ 25 : quick-flash plus long-flash
+ 26 : very quick-flash plus long-flash
+ 27 : ultra quick-flash plus long-flash
+ 28 : alternating
+ 29 : fixed and alternating flashing
+
+Definitions:
+
+fixed: a signal light that shows continuously, in any given direction, with constant luminous intensity and colour. (IHO Dictionary, S-32, 5th Edition, 2780)
+
+flashing: a rhythmic light in which the total duration of light in a period is clearly shorter than the total duration of darkness and all the appearances of light are of equal duration. (IHO Dictionary, S-32, 5th Edition, 2783)
+
+long-flashing: a flashing light in which a single flash of not less than two seconds duration is regularly repeated. (IHO Dictionary, S-32, 5th Edition, 2796)
+
+quick-flashing: a light exhibiting without interruption very rapid regular alternations of light and darkness. (IHO Dictionary, S-32, 5th Edition, 2803)
+
+very quick flashing: a flashing light in which flashes are repeated at a rate of not less than 80 flashes per minute but less than 160 flashes per minute.
+
+ultra quick flashing: a flashing light in which flashes are repeated at a rate of not less than 160 flashes per minute.
+
+isophased: a light with all durations of light and darkness equal. (IHO Dictionary, S-32, 5th Edition, 2779)
+
+occulting: a rhythmic light in which the total duration of light in a period is clearly longer than the total duration of darkness and all the eclipses are of equal duration. (IHO Dictionary, S-32, 5th Edition, 2801)
+
+interrupted quick flashing:
+ a quick light in which the sequence of flashes is interrupted by regularly repeated eclipses of constant and long duration. (IHO Dictionary, S-32, 5th Edition, 2790)
+
+interrupted very quick flashing:
+ a light in which the very rapid alterations of light and darkness are interrupted at regular intervals by eclipses of long duration. (IHO Dictionary, S-32, 5th Edition, 2792)
+
+interrupted ultra quick flashing:
+ a light in which the ultra quick flashes (160 or more per minute) are interrupted at regular intervals by eclipses of long duration. (IHO Dictionary, S-32, 5th Edition, 2791)
+
+morse: a rhythmic light in which appearances of light of two clearly different durations are grouped to represent a character or characters in the Morse code. (IHO Dictionary, S-32, 5th Edition, 2798)
+
+alternating: a signal light that shows, in any given direction, two or more colours in a regularly repeated sequence with a regular periodicity. (IHO Dictionary, S-32, 5th Edition, 2770)
+
+Remarks:
+
+ A selection of the above characteristics is defined and illustrated diagrammatically in IHO Chart Specifications, M-4, 471.2.
+
+Values 21-24 are no longer used. They are only included here for reasons of backward compatibility. Horizontally or vertically disposed lights should be encoded using the attributes category of light (CATLIT) and multiplicity of lights (MLTYLT). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: LITVIS Code: 108
+Light visibility LITVIS 108
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : high intensity IP 61.1; 476.2;
+ 2 : low intensity IP 61.2; 476.2;
+ 3 : faint IP 45; 475.3;
+ 4 : intensified IP 46; 475.5;
+ 5 : unintensified
+ 6 : visibility deliberately restricted IP 44; 475.3;
+ 7 : obscured IP 43; 475.3;
+ 8 : partially obscured
+
+Definitions:
+
+high intensity: non-marine lights with a higher power than marine lights and visible from well off shore (often Aero' lights). (adapted from IHO Chart Specifications, M-4)
+
+low intensity: non-marine lights with lower power than marine lights. (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+faint: a decrease in the apparent intensity of a light which may occur in the case of partial obstructions. (IHO Chart Specifications, M-4)
+
+intensified: a light in a sector is intensified (i.e. has longer range than other sectors). (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+unintensified: a light in a sector is unintensified (i.e. has shorter range than other sectors). (Bundesamt für Seeschiffahrt und Hydrographie, Germany)
+
+visibility deliberately restricted:
+ a light sector is deliberately reduced in intensity, for example to reduce its effect on a built-up area.
+
+obscured: said of the arc of a light sector designated by its limiting bearings in which the light is not visible from seaward. (IHO Dictionary, S-32, 5th Edition, 3492)
+
+partially obscured: this value specifies that parts of the sector are obscured.
+
+Remarks:
+
+ The attribute light visibility' encodes the specific visibility of a light, with respect to the light's intensity and ease of recognition. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: MARSYS Code: 109
+Marks navigational - System of MARSYS 109
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : IALA A IQ 130; 461;
+ 2 : IALA B IQ 130; 461;
+ 3 : modified US
+ 4 : old US
+ 5 : US intracoastal waterway
+ 6 : US uniform state
+ 7 : US western rivers
+ 8 : SIGNI
+ 9 : no system
+ 10 : other system 461;
+
+Definitions:
+
+IALA A: navigational aids conform to the International Association of Lighthouse Authorities - IALA A system.
+
+IALA B: navigational aids conform to the International Association of Lighthouse Authorities - IALA B system.
+
+no system: navigational aids do not conform to any defined system.
+
+other system: navigational aids conform to a defined system other than International Association of Lighthouse Authorities -IALA.
+
+Remarks:
+
+ No remarks. GEO AND META OBJECT ATTRIBUTES
+
+
+
+
+Acronym: MLTYLT Code: 110
+Multiplicity of lights MLTYLT 110
+Input type: I
+
+
+Definition:
+
+ The number of lights of identical character that exist as a co-located group.
+
+References:
+
+ INT 1: not specified;
+
+ M4: not specified
+
+Minimum Value: 2
+
+
+Indication:
+
+ Unit: none
+ Resolution: 1
+
+Format:
+
+ xx
+
+Example:
+
+ 5
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: NATION Code: 111
+Nationality NATION 111
+Attribute type: A
+
+
+Indication:
+
+ the nationality is encoded by a 2 character- code following ISO 3166 (refer to Annex A to S-57 Appendix A);
+
+Format:
+
+ c2 (mandatory)
+
+Remarks:
+
+ The attribute nationality' indicates the nationality of the specific object.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: NATCON Code: 112
+Nature of construction NATCON 112
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : masonry IF 4.3; 322.1;
+ 2 : concreted IF 4.3; 322.1;
+ 3 : loose boulders IF 4.2; 322.1;
+ 4 : hard surfaced ID 11; 365.2;
+ 5 : unsurfaced ID 12; 365.3;
+ 6 : wooden
+ 7 : metal
+ 8 : glass reinforced plastic (GRP)
+ 9 : painted IQ 101; 456.2;
+
+Definitions:
+
+masonry: constructed of brick or stone.
+
+concreted: constructed of concrete, a material made of sand and gravel that is united by cement into a hardened mass used for roads, foundations, etc. (adapted from the Illustrated Contemporary Dictionary, Encyclopaedic Edition, 1978)
+
+loose boulders: constructed from large stones or blocks of concrete, often placed loosely for protection against waves or water turbulence.
+
+hard surface: constructed with a surface of hard material, usually a term applied to roads surfaced with asphalt or concrete.
+
+unsurfaced: constructed with no extra protection, usually a term applied to roads not surfaced with a hard material.
+
+wooden: constructed from wood.
+
+metal: constructed from metal.
+
+glass reinforced plastic (GRP):
+ constructed from a plastic material strengthened with fibres of glass.
+
+painted: the application of paint to some other construction or natural feature.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: NATSUR Code: 113
+Nature of surface NATSUR 113
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : mud IJ 2,20;
+ 2 : clay IJ 3;
+ 3 : silt IJ 4;
+ 4 : sand IC 6; IJ 1,20; 312.2;
+ 5 : stone IC 7; IJ 5,20; 312.2; 425.5-6;
+ 6 : gravel IJ 6,20;
+ 7 : pebbles IJ 7;
+ 8 : cobbles IJ 8;
+ 9 : rock IJ 9,21; 426.2
+ 10 : marsh
+ 11 : lava
+ 12 : snow
+ 13 : ice
+ 14 : coral IJ 10,22; 425.5; 426.3;
+ 15 : swamp
+ 16 : bog/moor
+ 17 : shells IJ 11; 425.5-6;
+ 18 : boulder
+
+Definitions:
+
+mud: soft, wet earth.
+
+clay: (particles of less than 0.002mm); stiff, sticky earth that becomes hard when baked.
+
+silt: (particles of 0.002-0.0625mm); when dried on hand will rub off easily.
+
+sand: (particles of 0.0625-2.0mm); tiny grains of crushed or worn rock.
+
+stone: a general term for rock fragments ranging in size from pebbles and gravel to boulders or a large rock mass. (IHO Dictionary, S-32, 5th Edition, 5059)
+
+gravel: (particles of 2.0-4.0mm); small stones with coarse sand.
+
+pebbles: (particles of 4.0-64.0mm); small stones made smooth and round by being rolled in water.
+
+cobbles: (particles of 64.0-256.0mm); stones worn round and smooth by water and used for paving.
+
+rock: any formation of natural origin that constitutes an integral part of the lithosphere. The natural occurring material that forms firm, hard, and solid masses. (adapted from IHO Dictionary, S-32, 5th Edition, 4415)
+
+lava: the fluid or semi-fluid matter flowing from a volcano. The substance that results from the cooling of the molten rock. Part of the ocean bed is composed of lava. (IHO Dictionary, S-32, 5th Edition, 2680)
+
+coral: hard calcareous skeletons of many tribes of marine polyps. (IHO Dictionary, S- 32, 5th Edition, 1061)
+
+shells: exoskeletons of various water dwelling animals. (adapted from IHO Dictionary, S-32, 5th Edition, 4680)
+
+boulder a rounded rock with diameter of 256 mm or larger. (adapted from IHO Dictionary, S-32, 5th Edition, 527)
+
+
+Remarks:
+
+ The attribute nature of surface' encodes the general nature of the material of which the land surface or the sea bed is composed.
+
+ Mixed bottom: where the seabed comprises a mixture of material, the main constituent is given first e.g. fine sand with mud and shells would be indicated as 4,1,17.
+
+ Mud, sand, stone, rock are terms used for the general description.
+
+ Clay, silt, gravel, pebbles, cobbles are more specific terms related to particle size. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: NATQUA Code: 114
+Nature of surface - qualifying terms NATQUA 114
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : fine IJ 30; 425.5-6;
+ 2 : medium IJ 31; 425.5-6;
+ 3 : coarse IJ 32; 425.5-6;
+ 4 : broken IJ 33; 425.5-6;
+ 5 : sticky IJ 34; 425.5-6;
+ 6 : soft IJ 35; 425.5-6;
+ 7 : stiff IJ 36; 425.5-6;
+ 8 : volcanic IJ 37; 425.5-6;
+ 9 : calcareous IJ 38; 425.5-6;
+ 10 : hard IJ 39; 425.5-6;
+
+Definitions:
+
+fine: falls within the smallest size continuum for a particular nature of surface term. (M-4 425.6)
+
+medium: falls within the moderate size continuum for a particular nature of surface term. (M-4 425.6)
+
+coarse: falls within the largest size continuum for a particular nature of surface term. (M-4 425.6)
+
+broken: fractured or in pieces. (adapted from Webster's II New Riverside Dictionary, 1984)
+
+sticky: having an adhesive or glue like property. (adapted from Webster's II New Riverside Dictionary, 1984)
+
+soft: not hard or firm. (adapted from Webster's II New Riverside Dictionary, 1984)
+
+stiff: not pliant; thick, resistant to flow. (adapted from Webster's II New Riverside Dictionary, 1984)
+
+volcanic: composed of or containing material ejected from a volcano. (adapted from Webster's II New Riverside Dictionary, 1984)
+
+calcareous: composed of or containing calcium or calcium carbonate. (IHO Dictionary, S-32, 5th Edition, 603)
+
+hard: firm; usually refers to an area of the sea floor not covered by unconsolidated sediment. (IHO Dictionary, S-32, 5th Edition, 2194 and adapted from Webster's II New Riverside Dictionary, 1984)
+
+
+Remarks:
+
+ The attribute nature of surface - qualifying terms' encodes the nature of various forms of natural surface materials in terms of their size, morphology and consistency. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: NMDATE Code: 115
+Notice to Mariners date NMDATE 115
+Attribute type: A
+
+
+Indication:
+
+ The Notice to Mariners date should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the months (MM) (e.g. April = 04) and 2 digits for the day (DD), according to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+ 19950615 for 15 June 1995 as Notice to Mariners date.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: OBJNAM Code: 116
+Object name OBJNAM 116
+Attribute type: S
+
+
+Definition:
+
+ The individual name of an object.
+
+References:
+
+ INT 1: ID 7, IF 19, IN 12.2-3;
+
+ M-4: 371; 323.1-2; 431.2-3; 431.5;
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: ORIENT Code: 117
+Orientation ORIENT 117
+Attribute type: F
+
+
+Definition:
+
+ The angular distance measured from true north to the major axis of the object. (Digital Geographic Information Working Group -DGIWG, Oct.87)
+
+References:
+
+ INT 1: IM 1-4, 40; IP 20.1-2, 21, 30.1-2, 31; IS 3.5, 11;
+
+ M-4: 433.2-6; 434.1-2; 475.6-8; 487.2; 488;
+
+Minimum Value: 0
+
+Maximum Value: 360
+
+Indication:
+
+ Unit: degree ()
+ Resolution: 0.01 degree
+
+ Conversion factor: one tenth of a second = 0.000028 degree
+
+Format:
+
+ xxx.xx
+
+Example:
+
+ 246.7 for an orientation of 246.7 degrees
+
+Remarks
+
+ No remarks.
+
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PEREND Code: 118
+Periodic date end PEREND 118
+Attribute type: A
+
+
+Definition:
+
+ The end of the active period for a seasonal object (e.g. a buoy). See also date end'.
+
+References:
+
+ INT 1: IQ71;
+
+ M-4: 460.5;
+
+Indication:
+
+ the periodic date end' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). When no specific year is required (ie the object is removed at the same time each year) the following two cases may be considered:
+ - same day each year: --MMDD
+ - same month each year: --MM
+
+ This conforms to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDD (full date, mandatory)
+ --MMDD (same day each year, mandatory)
+ --MM (same month each year, mandatory)
+
+Example:
+
+ --1015 for an ending date of 15 October each year.
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PERSTA Code: 119
+Periodic date start PERSTA 119
+Attribute type: A
+
+
+Definition:
+
+ The start of the active period for a seasonal object (e.g. a buoy). See also date start'.
+
+References:
+
+ INT 1: IQ71;
+
+ M-4: 460.5;
+
+Indication:
+
+ the periodic date, start' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). When no specific year is required (ie the object is deployed at the same time each year) the following two cases may be considered:
+ - same day each year: --MMDD
+ - same month each year: --MM
+
+ This conforms to ISO 8601: 1988.
+
+
+Format:
+
+ CCYYMMDD (full date, mandatory)
+ --MMDD (same day each year, mandatory)
+ --MM (same month each year, mandatory)
+
+Example:
+
+--04 for an operation starting in April each year.
+
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PICREP Code: 120
+Pictorial representation PICREP 120
+Attribute type: S
+
+
+Definition:
+
+ Indicates whether a pictorial representation of the object is available.
+
+References:
+
+ INT 1: IE 3.1-2;
+
+ M-4: 456.5; 457.3;
+
+Indication:
+
+ the string encodes the file name of an external graphic file (pixel/vector)
+
+Remarks:
+
+ The pictorial representation' could be a drawing or a photo. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PILDST Code: 121
+Pilot district PILDST 121
+Attribute type: S
+
+
+Definition:
+
+ The area within which a particular pilotage service operates.
+
+References:
+
+ INT 1: IT 1.2;
+
+ M-4: 491.1-2;
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PUNITS Code: 189
+
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : metres
+ 2 : degrees of arc
+ 3 : millimeters
+ 4 : feet
+
+
+Definition:
+
+metres: Positional accuracy is specified in metres (SI units of positional accuracy).
+
+degrees of arc: Positional accuracy is specified in degrees of arc.
+
+millimeters: Positional accuracy is specified in millimeters.
+
+feet: Positional accuracy is specified in feet (imperial units of positional accuracy).
+
+
+Remarks:
+
+ This attribute encodes the units for positional accuracy which may be different from the unit for coordinates. The latter is specified at the dataset level in the COUN subfield of the DSPM record. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PRCTRY Code: 122
+Producing country PRCTRY 122
+Attribute type: A
+
+
+Definition:
+
+ The country responsible for data production.
+
+Indication:
+
+ country (c2): Two letter code according to ISO 3166 (refer to Annex A to S-57 Appendix A)
+
+Format:
+
+ c2 (mandatory)
+
+
+Example:
+
+ DK (Denmark)
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PRODCT Code: 123
+Product PRODCT 123
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : oil IE 32;IL 40.1-2; 376.1-2; 444.1;
+ 2 : gas IE 32;IL 40.1-2; 376.1-2; 444.1;
+ 3 : water IL 40.1; 444.4;
+ 4 : stone
+ 5 : coal
+ 6 : ore
+ 7 : chemicals IE 32; 376.1-2; 444.1;
+ 8 : drinking water
+ 9 : milk
+ 10 : bauxite
+ 11 : coke
+ 12 : iron ingots
+ 13 : salt
+ 14 : sand
+ 15 : timber
+ 16 : sawdust/wood chips
+ 17 : scrap metal
+ 18 : liquified natural gas (LNG)
+ 19 : liquified petroleum gas (LPG)
+ 20 : wine
+ 21 : cement
+ 22 : grain
+
+Definitions:
+
+oil: a thick, slippery liquid that will not dissolve in water, usually petroleum based in the context of storage tanks. (adapted from the Oxford Minidictionary, Third Edition)
+
+gas: a substance with particles that can move freely, usually a fuel substance in the context of storage tanks. (adapted from the Oxford Minidictionary, Third Edition)
+
+water: a colourless, odourless, tasteless liquid that is a compound of hydrogen and oxygen. (adapted from the Oxford Minidictionary, Third Edition)
+
+stone: a general term for rock fragments. (IHO Dictionary, S-32, 5th Edition, 5059)
+
+coal: a hard black mineral that is burned as fuel. (adapted from the Oxford Minidictionary, Third Edition)
+
+ore: a solid rock or mineral from which metal is obtained. (adapted form the Oxford Minidictionary, Third Edition)
+
+chemicals: any substance obtained by or used in a chemical process. (adapted from the Oxford Minidictionary, Third Edition)
+
+drinking water: water that is suitable for human consumption. (adapted from the Oxford Minidictionary, Third Edition)
+
+milk: a white fluid secreted by female mammals as food for their young. (adapted from the Oxford Minidictionary, Third Edition)
+
+bauxite: a mineral from which aluminum is obtained. (adapted from the Oxford Minidictionary, Third Edition)
+
+coke: a solid substance obtained after gas and tar have been extracted from coal, used as a fuel. (adapted from the Oxford Minidictionary, Third Edition)
+
+iron ingots: an oblong lump of cast iron metal. (adapted from the Oxford Minidictionary, Third Edition)
+
+salt: sodium chloride obtained from mines or by the evaporation of sea water. (adapted from the Oxford Minidictionary, Third Edition)
+
+sand: tiny grains of crushed or worn rock. (adapted from the Oxford Minidictionary, Third Edition)
+
+timber: wood prepared for use in building or carpentry. (adapted from the Oxford Minidictionary, Third Edition)
+
+sawdust/wood chips: powdery fragments of wood made in sawing timber or coarse chips produced for use in manufacturing pressed board. (adapted from the Oxford Minidictionary, Third Edition)
+
+scrap metal: discarded metal suitable for being reprocessed. (adapted from the Oxford Minidictionary, Third Edition)
+
+liquified natural gas (LNG):
+ a compressed gas consisting of flammable light hydrocarbons and derived from natural gas.
+
+liquified petroleum gas (LPG):
+ a compressed gas consisting of flammable light hydrocarbons and derived from petroleum. (adapted from Websters Third New)
+
+wine: the fermanted juice of grapes. (adapted from the Websters New World Dictionary)
+
+cement: a substance made of powdered lime and clay, mixed with water. (adapted from the Websters New World Dictionary)
+
+grain: a small hard seed, especially that of any cereal plant such as wheat, rice, corn, rye etc. (adapted from the Websters New World Dictionary)
+
+
+
+Remarks:
+
+ The attribute product' encodes the various substances which are transported, stored or exploited. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: PUBREF Code: 124
+Publication reference PUBREF 124
+Attribute type: S
+
+
+Definition:
+
+ A reference to a nautical publication.
+
+Indication:
+
+ The string encodes the reference to a specific paragraph from a nautical publication
+
+Example:
+
+ United States Coast Pilot No 1 1992 (27th) edition, Atlantic Coast, Eastport to Cape Cod, Chapter 3, Paragraph 2' FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: QUASOU Code: 125
+Quality of sounding measurement QUASOU 125
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : depth known
+ 2 : depth unknown IK 40; 422.9;
+ 3 : doubtful sounding II 2; 417; 424.4;
+ 4 : unreliable sounding II 14; 412.4;
+ 5 : no bottom found at value shown II 13; 412.3;
+ 6 : least depth known IK 26-27; 422.3-4;
+ 7 : least depth unknown, safe clearance at value shown IK 30; 422.7;
+ 8 : value reported (not surveyed) II 3.1; 417, 424.5;
+ 9 : value reported (not confirmed) II 4;
+ 10 : maintained depth II 23; 414.2;
+ 11 : not regularly maintained
+
+Definitions:
+
+depth known: the depth from chart datum to the bottom is a known value.
+
+depth unknown: the depth from chart datum to the bottom is unknown.
+
+doubtful sounding: a depth that may be less than indicated. (adapted from IHO Dictionary, S-32, 5th Edition, 4840)
+
+unreliable sounding: a depth that is considered to be an unreliable value.
+
+no bottom found at value shown:
+ upon investigation the bottom was not found at this depth. (adapted from IHO Dictionary, S-32, 5th Edition, 4848)
+
+least depth known: the shoalest depth over a feature is of known value. (adapted from IHO Dictionary, S-32, 5th Edition, 2705)
+
+least depth unknown, safe clearance at depth shown:
+ the least depth over a feature is unknown, but there is considered to be safe clearance at this depth.
+
+value reported (not surveyed):
+ depth value obtained from a report, but not fully surveyed.
+
+value reported (not confirmed):
+ depth value obtained from a report, which it has not been possible to confirm.
+
+maintained depth: the depth at which a channel is kept by human influence, usually by dredging. (IHO Dictionary, S-32, 5th Edition, 3057)
+
+not regularly maintained:
+ depths may be altered by human influence, but will not be routinely maintained.
+
+Remarks:
+
+ The attribute quality of sounding measurement' indicates the reliability of the value of sounding. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: QUAVEM Attribute type: E
+Quality of vertical measurement QUAVEM
+INT 1 Reference: not specified
+
+Chart Specification: not specified
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : measured
+ 2 : estimated
+
+
+Remarks:
+
+ The attribute quality of vertical measurement' indicates the quality of a vertical measurement.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility.
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RADWAL Code: 126
+Radar wave length RADWAL 126
+Attribute type: A
+
+
+Definition:
+
+ The distance between two successive peaks (or other points of identical phase) on an electromagnetic wave in the radar band of the electromagnetic spectrum.
+
+References:
+
+ INT 1: IS 3.1-4;
+
+ M-4: 486.3-4;
+
+Indication:
+
+ the wavelength and the band code character is indicated;
+
+ In the case where two bands should be encoded, these should be separated by a comma.
+
+ Unit :m
+ resolution: 0.01 m
+
+Format:
+
+ V.VV-B
+ V.VV-B,V.VV-B
+
+ VV.VV' encodes the value of wavelength.
+
+ B' encodes the band;
+ each separated by a hyphen (-')
+
+Example:
+
+ the radar transponder beacon wavelength 3cm (X) - Band' is indicated as 0.03-X'
+
+Remarks:
+
+ The attribute radar transponder beacon wavelength' encodes the specific wavelength at which a radar transponder beacon transmits.
+
+ Radar transponder beacons generally work on the following wavelengths:
+
+ - 3cm (X) - Band
+ - 10cm (S) - Band
+
+ Nevertheless, wavelengths outside the marine band are used.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RADIUS Code: 127
+Radius RADIUS 127
+Attribute type: F
+
+
+Definition:
+
+ The vector extending from the centre to the periphery of a circular or spherical object.
+
+References:
+
+ INT 1: IN 11.2;
+
+ M-4: not specified
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 26 for a radius of 26 metres.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RECDAT Code: 128
+Recording date RECDAT 128
+Attribute type: A
+
+
+Definition:
+
+ The date when the specific object or cartographic primitive was captured, edited or deleted.
+
+Reference:
+
+ INT 1: II 22;
+
+ M-4: 414.1;
+
+Indication:
+
+ The recording date should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD), according to ISO 8601: 1988.
+
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+19930112 for 12 January 1993 as recording date.
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RECIND Code: 129
+Recording indication RECIND 129
+Attribute type: A
+
+
+Definition:
+
+ The procedure for the encoding and entering of data.
+
+Indication:
+
+ country (c2): Two letter code according to ISO 3166 (refer to Annex A to S-57 Appendix A)
+
+ authority (c2): A string of two alphanumeric characters (refer to Annex A to S-57 Appendix A), e.g. German Bundesamt für Seeschiffahrt und Hydrographie = DE; US National Imagery and Mapping Agency = U1.
+
+ procedure (c4): digitized = digi
+ scanned = scan
+ alpha/numeric input = alph
+
+Format:
+
+ c2,c2,c4 (mandatory)
+
+Example:
+
+ DK,D1,digi FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RYRMGV Code: 130
+Reference year for magnetic variation RYRMGV 130
+Attribute type: A
+
+
+Definition:
+
+ The reference calendar year for magnetic variation values.
+
+References:
+
+ INT 1: IB 68.1, 70-71;
+
+ M-4: 270;
+
+Indication:
+
+ the reference calendar year for magnetic variation' should be encoded using a 4 digit year-indication (CCYY).
+
+Format:
+
+ CCYY (mandatory) FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: RESTRN Code: 131
+Restriction RESTRN 131
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : anchoring prohibited IN 20; 439.3-4;
+ 2 : anchoring restricted
+ 3 : fishing prohibited IN 21; 439.3-4;
+ 4 : fishing restricted
+ 5 : trawling prohibited
+ 6 : trawling restricted
+ 7 : entry prohibited IN 2.2; 439.3;
+ 8 : entry restricted
+ 9 : dredging prohibited
+ 10 : dredging restricted
+ 11 : diving prohibited
+ 12 : diving restricted
+ 13 : no wake
+ 14 : area to be avoided IM 29.1; 435.7;
+ 15 : construction prohibited
+
+Definitions:
+
+anchoring prohibited: an area within which anchoring is not permitted.
+
+anchoring restricted: a specified area designated by appropriate authority, within which anchoring is restricted in accordance with certain specified conditions.
+
+fishing prohibited: an area within which fishing is not permitted.
+
+fishing restricted: a specified area designated by appropriate authority, within which fishing is restricted in accordance with certain specified conditions.
+
+trawling prohibited: an area within which trawling is not permitted.
+
+trawling restricted: a specified area designated by appropriate authority, within which trawling is restricted in accordance with certain specified conditions.
+
+entry prohibited: an area within which navigation and/or anchoring is prohibited. (adapted from IHO Dictionary, S-32, 5th Edition, 4044)
+
+entry restricted: a specified area designated by appropriate authority, within which navigation is restricted in accordance with certain specified conditions. (adapted from IHO Dictionary, S-32, 5th Edition, 4366)
+
+dredging prohibited: an area within which dredging is not permitted.
+
+dredging restricted: a specified area designated by appropriate authority, within which dredging is restricted in accordance with certain specified conditions.
+
+diving prohibited: an area within which diving is not permitted.
+
+diving restricted: a specified area designated by appropriate authority, within which diving is restricted in accordance with certain specified conditions.
+
+no wake: mariners must adjust the speed of their vessels to reduce the wave or wash which may cause erosion or disturb moored vessels.
+
+area to be avoided: an IMO designated area to be avoided, defined as a routeing measure. (adapted from IHO Chart Specifications, M-4, 435.7)
+
+Construction prohibited: the erection of permanent or temporary fixed structures or artificial islands is prohibited.
+
+Remarks:
+
+ The official legal statue of each kind of restricted area defines the kind of restriction(s), e.g. the restriction for a game preserve' may be entry prohibited', the restriction for an anchoring prohibition' is anchoring prohibited'.
+
+ The complete information about the restriction(s), actually held in handbooks or other publications, may be encoded by the attribute TXTDSC'. A short explanation may be given by the use of the attribute INFORM'. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SCAMAX Code: 132
+Scale maximum SCAMAX 132
+Attribute type: I
+
+
+Definition:
+
+ The maximum scale at which the object may be used e.g. for ECDIS presentation.
+
+Minimum Value: 1
+
+Indication:
+
+ the modulus of the scale is indicated, that is 1:25 000 is encoded as 25000;
+
+ Unit: none
+ resolution: 1
+
+Format:
+
+ xxxxxxxx
+
+Example:
+
+ If a particular maximum scale is specified as 1:25 000 (encoded as 25000), an example of a larger scale would be 1:20 000 (encoded as 20000);
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SCAMIN Code: 133
+Scale minimum SCAMIN 133
+Attribute type: I
+
+
+Definition:
+
+ The minimum scale at which the object may be used e.g. for ECDIS presentation.
+
+Minimum Value: 1
+
+Indication:
+
+ the modulus of the scale is indicated, that is 1:1 250 000 is encoded as 1250000;
+
+ Unit: none
+ resolution: 1
+
+Format:
+
+ xxxxxxxx
+
+Example:
+
+ If a particular minimum scale is specified as 1:1 250 000 (encoded as 1250000), and example of a smaller scale would be 1:2 000 000 (encoded as 2000000);
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SCVAL1 Code: 134
+Scale value one SCVAL1 134
+Attribute type: I
+
+
+Definition:
+
+ The largest scale for the range of survey scale as used in source diagram information.
+
+Minimum Value: 1
+
+Indication:
+
+ the modulus of the scale is indicated, that is 1:25 000 is encoded as 25000.
+
+ Unit: none
+ Resolution: 1
+
+Format:
+
+ xxxxxxxx
+
+Example:
+
+ 25000 for a scale of 1:25 000.
+
+Remarks.
+
+ No remarks.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SCVAL2 Code: 135
+Scale value two SCVAL2 135
+Attribute type: I
+
+
+Definition:
+
+ The smallest scale for the range of survey scale as used in source diagram information.
+
+Minimum Value: 1
+
+Indication:
+
+ The modulus of the scale is indicated, that is 1:250 000 is encoded as 250000.
+
+ Unit: none
+ Resolution: 1
+
+Format:
+
+ xxxxxxxx
+
+Example:
+
+ 250000 for a scale of 1:250 000.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SECTR1 Code: 136
+Sector limit one SECTR1 136
+Attribute type: F
+
+
+Definition:
+
+ A sector is the part of a circle between two straight lines drawn from the centre to the circumference. (Advanced Learner's Dictionary, 2nd Edition)
+
+ Sector limit 1 specifies the first limit of the sector. The order of sector limit 1 and sector limit 2 is clockwise around the central object (e.g. a light).
+
+References:
+
+ INT 1: IP 40;
+
+ M-4: 475; 475.1;
+
+Minimum Value: 0
+
+Maximum Value: 360
+
+Indication:
+
+ Unit: degree ()
+ Resolution: 0.01 degree
+
+ Conversion factor: one tenth of a second = 0.000028 degree.
+
+Format:
+
+ xxx.xx
+
+Example:
+
+ 125 for a sector orientation of 125 degrees.
+
+Remarks:
+
+ The values given to the common limits of adjacent sectors should be identical.
+
+ The orientation of bearing is from seaward to the central object. This conforms with the method used in List of Lights' publications.
+
+ A generic term such as to shore' cannot be used; a specific bearing must be encoded. Where a light sector limit is defined as to the shore', it should be encoded using a value that ensures that, when the limit is drawn, it will fall entirely on land. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SECTR2 Code: 137
+Sector limit two SECTR2 137
+Attribute type: F
+
+
+Definition:
+
+ A sector is the part of a circle between two straight lines drawn from the centre to the circumference. (Advanced Learner's Dictionary, 2nd Edition)
+
+ The sector limit 2 specifies the second limit of the sector. The order of sector limit 1 and sector limit 2 is clockwise around the central object (e.g. a light).
+
+References:
+
+ INT 1: IP 40;
+
+ M-4: 475; 475.1;
+
+Minimum Value: 0
+
+Maximum Value: 360
+
+Indication:
+
+ Unit: degree.
+ Resolution: 0.01 degree
+
+ Conversion factor: one tenth of a second = 0.000028 degree.
+
+Format:
+
+ xxx.xx
+
+Example:
+
+ 220 for a sector orientation of 220 degrees.
+
+
+Remarks:
+
+ The values given to the common limits of adjacent sectors should be identical.
+
+ The orientation of bearing is from seaward to the central object. This to the method used in List of Lights' publications.
+
+ A generic term such as to shore' cannot be used; a specific bearing must be encoded. Where a light sector limit is defined as to the shore', it should be encoded using a value that ensures that, when the limit is drawn, it will fall entirely on land. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SHIPAM Code: 138
+Shift parameters SHIPAM
+Attribute type: A
+
+
+Definition:
+
+ Latitude and longitude offsets required to shift a position from one geodetic datum to another.
+
+Indication:
+
+ Lat: Shift parameter in latitude from the specified horizontal datum to the horizontal datum of the data.
+
+ Unit: minutes (), negative south.
+ Resolution: 0.001 minute.
+
+ Lon: Shift parameter in longitude from the specified horizontal datum to the horizontal datum of the data.
+
+ Unit: minutes (), negative west.
+ Resolution: 0.001 minute.
+
+Format:
+
+ sxx.xxx, syy.yyy
+
+ sxx.xxx: lat
+ syy.yyy: lon
+ s: sign, negative values only.
+
+Example:
+
+ -0.03,0.07 in the following case:
+
+
+ Position on specified datum: 20 40.36 (N) 085 20.05 (E)
+ Shift parameters (-0.03,0.07): -0.03 (S) 0.07 (E)
+ ============= ==============
+ Position on datum of data: 20 40.33 (N) 085 20.12 (E)
+
+Remarks
+
+ All necessary information for conversion of geographic coordinates from most of the Geodetic Datums in the above list to WGS-84 is contained in the "User's Handbook on Datum Transformations involving WGS-84", prepared by the US Defense Mapping Agency and which is available from the IHB as IHO Publication S-60 (English and French Versions), along with an associated standard datum transformation software on floppy disk called "MADTRAN". The resulting latitude and longitude offsets can be encoded in the attribute SHIPAM.
+
+Additional information on the transformation as indicated in IHO Publication S-60, e.g. TOY-M (Mean Solution), TOY-A (Japan), TOY-B (South Korea) or TOY-C (Okinawa) in relation to Tokyo Datum, may be encoded in the attribute INFORM or NINFORM. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SIGFRQ Code: 139
+Signal frequency SIGFRQ 139
+Attribute type: I
+
+
+Definition:
+
+ The frequency of a signal.
+
+Indication:
+
+ Unit: Hz
+ resolution: 1 Hz FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SIGGEN Code: 140
+Signal generation SIGGEN 140
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : automatically
+ 2 : by wave action IR 21-22; 454.1-2;
+ 3 : by hand
+ 4 : by wind
+
+Definitions:
+
+automatically: signal generation is initiated by a self regulating mechanism such as a timer or light sensor.
+
+by wave action: the signal is generated by the motion of the sea surface such as a bell in a buoy.
+
+by hand: the signal is generated by a manually operated mechanism such as a hand cranked siren.
+
+by wind: the signal is generated by the motion of air such as a wind driven whistle.
+
+Remarks:
+
+ The attribute signal generation' encodes the mechanism used to generate a fog signal. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SIGGRP Code: 141
+Signal group SIGGRP 141
+Attribute type: A
+
+
+Definition:
+
+ The number of signals, the combination of signals or the morse character(s) within one period of full sequence.
+
+References:
+
+ INT 1: IP 10.2-9; IR 20, 22;
+
+ M-4: 453; 453.1-4; 471.2;
+
+Indication:
+
+ The signal group of a light is encoded using brackets to separate the individual groups. A group of signals may be a single number, a chain of numbers separated by "+", a sequence of up to 4 letters or a letter and a number.
+
+ A fixed light has no signal group.
+
+ Where no specific signal group is given for one of the light characteristics, this should be shown by an empty pair of brackets.
+
+Format:
+
+ (c)(c)...
+
+Examples:
+
+ Light characteristic SIGGRP Indication
+
+ VQ(6)+LFl -> (6)(1)
+ Fl+LFl (2+3) -> (1)(2+3)
+ Fl(2)+Lfl(3) -> (2)(3)
+ FFl -> ()(1)
+ Mo(AA) -> (AA)
+ AlFl(2W+1R) -> (2+1)
+ AlLFlWR -> (2)
+ FOcW -> ()(1)
+ AlOc(4)WR -> (4) FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SIGPER Code: 142
+Signal period SIGPER 142
+Attribute type: F
+
+
+Definition:
+
+ The time occupied by an entire cycle of intervals of light and eclipse.
+
+References:
+
+ INT 1: IP 12; IR 20, 22;
+
+ M-4: 453.5; 471.5;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: second (s)
+ Resolution: 0.01 s
+
+Format:
+
+ xx.xx
+
+Example:
+
+ 12 for an interval of 12 seconds.
+
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SIGSEQ Code: 143
+Signal sequence SIGSEQ 143
+Attribute type: A
+
+
+Definition:
+
+ The sequence of times occupied by intervals of light and eclipse for all light characteristics' except for occulting where the sequence of times is occupied by intervals of eclipse and light.
+
+Indication:
+
+ Unit for value of intervals: second (s)
+ resolution: 0.01 s
+
+Format:
+
+ LL.L + (EE.E)
+
+Example:
+
+ 00.8+(02.2)+00.8+(05.2)
+
+ The above example encodes a signal sequence with two intervals of light and two intervals of eclipse.
+
+ For occulting lights, the signal sequence' is indicated using a fixed format to encode the values of intervals of eclipse (E) and (L).
+
+Format:
+
+ (EE.E)+LL.L
+
+Example:
+
+ (00.8)+02.2+(00.8)+05.2)
+
+ The above example encodes a signal sequence with two intervals of eclipse and two intervals of light.
+
+Remarks:
+
+ The signal sequence' for all light characteristics' except for occulting is indicated using a fixed format to encode the value of intervals of light (L) and eclipse (E). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SOUACC Code: 144
+Sounding accuracy SOUACC 144
+Attribute type: F
+
+Expected input:
+
+ The maximum of the one-dimensional error.
+
+ The error is assumed to be positive and negative. The plus/minus character shall not be encoded.
+
+
+Definition:
+
+ The best estimate of the accuracy of the sounding data.
+
+Minimum value: 0
+
+Indication:
+
+ Unit: defined in the DUNI subfield of the DSPM record or in the DUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 fm or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 0.3 for a maximum error of 0.3 metre.
+
+
+Remarks:
+
+ No remarks
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SDISMX Code: 145
+Sounding distance - maximum SDISMX 145
+Attribute type: I
+
+
+Definition:
+
+ The maximum spacing of the principal sounding lines of a survey.
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 1 m or 1 ft
+Format:
+
+ xxxx
+
+Example:
+
+ 150 for a maximum spacing of 150 metres.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SDISMN Code: 146
+Sounding distance - minimum SDISMN 146
+Attribute type: I
+
+
+Definition:
+
+ The minimum spacing of the principal sounding lines of a survey.
+
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 1 m or 1 ft
+
+Format:
+
+ xxxx
+
+Example:
+
+ 50 for a minimum spacing of 50 metres.
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SORDAT Code: 147
+Source date SORDAT 147
+Attribute type: A
+
+
+Definition:
+
+ The production date of the source, e.g. the date of measurement.
+
+Indication:
+
+ The source should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the months (MM) and 2 digits for the Day (DD), according to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDD (mandatory)
+
+Example:
+
+ 19820506 for 6 May 1982 as source date.
+
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SORIND Code: 148
+Source indication SORIND 148
+Attribute type: A
+
+
+Definition:
+
+ Information about the source of the object.
+
+Indication:
+
+ Country (c2): (mandatory)
+ Two letter code from ISO 3166 (refer to Annex A to S-57 Appendix A)
+
+ Authority (c2): (mandatory)
+ A string of two alphanumeric characters (refer to Annex A to S-57 Appendix A), e.g. German Bundesamt für Seeschiffahrt und Hydrographie = DE; US National Imagery and Mapping Agency = U1.
+
+ Source (c5): Graphic e.g. plotting sheet, paper chart = graph
+ Report e.g. wreck report = reprt
+
+ ID-Code (c...): e.g. Code of paper chart
+
+Format:
+
+ c2,c2,c5,c...
+
+Example:
+
+ DK,D1,graph,chart196 FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: STATUS Code: 149
+Status STATUS 149
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : permanent
+ 2 : occasional IP 50; 473.2;
+ 3 : recommended IN 10; 431.1;
+ 4 : not in use IL 14, 44; 444.7;
+ 5 : periodic/intermittent IC 21; IQ 71; 353.3; 460.5;
+ 6 : reserved IN 12.9;
+ 7 : temporary IP 54;
+ 8 : private IQ 70;
+ 9 : mandatory
+ 10 : destroyed/ruined
+ 11 : extinguished
+ 12 : illuminated
+ 13 : historic
+ 14 : public
+ 15 : synchronized
+ 16 : watched
+ 17 : un-watched
+ 18 : existence doubtful
+
+Definitions:
+
+permanent: intended to last or function indefinitely. (The Concise Oxford Dictionary, 7th Edition)
+
+occasional: acting on special occasions; happening irregularly. (The Concise Oxford Dictionary, 7th Edition)
+
+recommended: presented as worthy of confidence, acceptance, use, etc. (The Macquarie Dictionary, 1988)
+
+not in use: no longer used for the purpose intended; disused.
+
+periodic/intermittent: recurring at intervals. (The Concise Oxford Dictionary, 7th Edition)
+
+reserved: set apart for some specific use. (adapted from The Concise Oxford Dictionary, 7th Edition)
+
+temporary: meant to last only for a time. (The Concise Oxford Dictionary)
+
+private: not in public ownership or operation.
+
+mandatory: compulsory; enforced. (The Concise Oxford Dictionary, 7th Edition)
+
+extinguished: no longer lit
+
+illuminated: lit by floodlights, strip lights, etc.
+
+historic: famous in history; of historical interest. (The Concise Oxford Dictionary, 7th Edition)
+
+public: belonging to, available to, used or shared by, the community as a whole and not restricted to private use. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+synchronized: occur at a time, coincide in point of time, be contemporary or simultaneous. (The New Shorter Oxford English Dictionary, 1993)
+
+watched: looked at or observed over a period of time especially so as to be aware of any movement or change. (adapted from The New Shorter Oxford English Dictionary, 1993)
+
+un-watched: usually automatic in operation, without any permanently-stationed personnel to superintend it. (adapted from IHO Dictionary, S-32, 5th Edition, 2814)
+
+existence doubtful: an object that has been reported but has not been definitely determined to exist.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+ DELETED - DO NOT USE
+
+
+Acronym: SUPLIT Attribute type: E
+Supervision of light SUPLIT
+INT 1 Reference: IP 53;
+
+Chart Specification: 473.1;
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : watched light
+ 2 : unwatched light
+
+
+Remarks:
+
+ The attribute supervision of light' encodes whether the light is watched or not.
+
+This attribute is obsolete. It is only shown here for reasons of backward compatibility. These values have been transferred to the attribute status (STATUS).
+
+ DELETED - DO NOT USE FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SURATH Code: 150
+Survey authority SURATH 150
+Attribute type: S
+
+
+Definition:
+
+ The authority which was responsible for the survey.
+
+Example:
+
+ Hydrographic Service, Royal Australian Navy
+ Port of Melbourne Authority
+
+Remarks:
+
+ The attribute survey authority' encodes the name of the source survey authority. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SUREND Code: 151
+Survey date - end SUREND 151
+Attribute type: A
+
+
+Definition:
+
+ The end date of the survey.
+
+Indication:
+
+ The survey date, end' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). When no specific month and/or day is required/known, indication of the month and/or the day is omitted. This conforms to ISO 8601: 1988.
+
+
+Format:
+
+ CCYYMMDD (full date, mandatory)
+ CCYYMM (no specific day required, mandatory)
+ CCYY (no specific month required, mandatory)
+
+Example:
+
+ 19781127 for a survey ending on 27 November 1978.
+
+
+Remarks;
+
+ No remarks.
+
+
+
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SURSTA Code: 152
+Survey date - start SURSTA 152
+Attribute type: A
+
+
+Definition:
+
+ The start date of the survey.
+
+Indication:
+
+ The survey date, start' should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). When no specific month and/or day is required/known, indication of the month and/or the day is omitted. This conforms to ISO8601: 1988.
+
+Format:
+
+ CCYYMMDD (full date, mandatory)
+ CCYYMM (no specific day required, mandatory)
+ CCYY (no specific month required, mandatory)
+
+Example:
+
+ 198403 for a survey starting in March 1984.
+
+Remarks.
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: SURTYP Code: 153
+Survey type SURTYP 153
+Attribute type: L
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : reconnaissance/sketch survey
+ 2 : controlled survey
+ 3 : unsurveyed
+ 4 : examination survey
+ 5 : passage survey
+ 6 : remotely sensed
+
+Definitions:
+
+reconnaissance/sketch survey:
+ a survey made to a lower degree of accuracy and detail than the chosen scale would normally indicate. (IHO Dictionary, S-32, 5th Edition, 5219)
+
+controlled survey: a thorough survey usually conducted with reference to guidelines.
+
+examination survey: a survey principally aimed at the investigation of underwater obstructions and dangers.
+
+passage survey: a survey where soundings are acquired by vessels on passage.
+
+remotely sensed: a survey where features have been positioned and delimited using remote sensing techniques.
+
+Remarks:
+
+ No remarks.
+
+Value number 3 (unsurveyed) should now be encoded using the object unsurveyed area (UNSARE). FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $SCALE Code: 154
+Symbol scaling factor $SCALE 154
+Attribute type: F
+
+
+Expected input:
+
+ a scaling factor relative to the standard symbol size.
+
+Indication:
+
+ Unit: none
+ Resolution: 0.1
+
+Format:
+
+ x.x
+
+Example:
+
+ 1.5
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $SCODE Code: 155
+Symbolization code $SCODE 155
+Attribute type: A
+
+
+Expected input:
+
+ see the applicable application profile.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TECSOU Code: 156
+Technique of sounding measurement TECSOU 156
+Attribute type: L
+
+INT 1 Reference: II 24; IK 2, 27, 42;
+
+Chart Specification: 415; 415.1-2; 422.3-4; 422.9;
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : found by echo-sounder
+ 2 : found by side scan sonar
+ 3 : found by multi-beam
+ 4 : found by diver
+ 5 : found by lead-line
+ 6 : swept by wire-drag II 24;IK 2,27,42; 415; 422.3; 422.9;
+ 7 : found by laser
+ 8 : swept by vertical acoustic system
+ 9 : found by electromagnetic sensor
+ 10 : photogrammetry
+ 11 : satellite imagery
+ 12 : found by levelling
+ 13 : swept by side-scan sonar
+ 14 : computer generated
+
+Definitions:
+
+found by echo-sounder: the depth was determined by using an instrument that determines depth of water by measuring the time interval between emission of a sonic or ultrasonic signal and return of its echo from the bottom. (adapted from IHO Dictionary, S-32, 1547)
+
+found by side-scan-sonar:
+ the depth was computed from a record produced by active sonar in which fixed acoustic beams are directed into the water perpendicularly to the direction of travel to scan the bottom and generate a record of the bottom configuration. (adapted from IHO Dictionary, S-32, 4710)
+
+found by multi-beam: the depth was determined by using a wide swath echo sounder that uses multiple beams to measure depths directly below and transverse to the ship's track. (adapted from IHO Dictionary, S-32, 3339)
+
+found by diver: the depth was determined by a person skilled in the practice of diving. (adapted from IHO Dictionary, S-32, 1422)
+
+found by lead-line: the depth was determined by using a line, graduated with attached marks and fastened to a sounding lead. (adapted from IHO Dictionary, S-32, 2698)
+
+swept by wire-drag: the given area was determined to be free from navigational dangers to a certain depth by towing a buoyed wire at the desired depth by two launches, or a least depth was identified using the same technique. (adapted from IHO Dictionary, S-32, 5248, 6013)
+
+found by laser: the depth was determined by using an instrument that measures distance by emitting timed pulses of laser light and measuring the time between emission and reception of the reflected pulses. (adapted from IHO Dictionary, S-32, 2763)
+
+swept by vertical acoustic system:
+ the given area has been swept using a system comprised of multiple echo sounder transducers attached to booms deployed from the survey vessel.
+
+found by electromagnetic sensor:
+ the depth was determined by using an instrument that compares electromagnetic signals. (adapted from IHO Dictionary, S-32, 1571)
+
+photogrammetry: the depth was determined by applying mathematical techniques to photographs. (adapted from IHO Dictionary, S-32, 3791)
+
+satellite imagery: the depth was determined by using instruments placed aboard an artificial satellite. (adapted from IHO Dictionary, S-32, 4509)
+
+found by levelling: the depth was determined by using levelling techniques to find the elevation of the point relative to a datum. (adapted from IHO Dictionary, S-32, 2741)
+
+swept by side-scan-sonar:
+ the given area was determined to be free from navigational dangers to a certain depth by towing a side-scan-sonar. (adapted from IHO Dictionary, S-32, 5248, 4710) [415.2]
+
+computer generated: the sounding was determined from a bottom model constructed using a computer.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $TXSTR Code: 157
+Text string $TXSTR 157
+Attribute type: S
+
+
+Expected input:
+
+ the content of the legend to be displayed.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TXTDSC Code: 158
+Textual description TXTDSC 158
+Attribute type: S
+
+
+Indication:
+
+ the string encodes the file name of an external text file that contains the text in English.
+
+Remarks:
+
+ The attribute textual description' indicates that a file containing text extracted from relevant pilot books or navigational publications is available. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TS_TSP Code: 159
+Tidal stream - panel values TS_TSP 159
+Attribute type: A
+
+
+Indication:
+
+ The direction in degrees and velocity in knots are encoded in pairs. Each value separated by a comma.
+
+Example:
+
+ 63230,Darwin,HW,124,2.2,128,2.1,125,2.9,116,2.8,110,2.0,095,0.6,020,0.2,320,1.9,315,2.1,300,2. 8,268,2.6,200,2.4,165,2.5
+
+Remarks:
+
+ The attribute Tidal stream - panel values' encodes the identification of the reference station with reference water level and the direction of the flow and the springs rate from 6 hours before to 6 hours after high water (HW) or low water (LW) at the reference station, at hourly intervals.
+
+ The relationship to a reference station is encoded using a collection object. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TS_TSV Code: 160
+Tidal stream - time series values TS_TSV 160
+Attribute type: A
+
+
+Indication:
+
+ The direction in degrees and velocity in knots are encoded in pairs. Each value separated by a comma.
+
+Example:
+
+ 135,1.5,156,1.9,301,1.1,342,0.9
+
+Remarks:
+
+ The attribute Tidal stream, current - time series values' encodes values for a direction and velocity time series. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_ACWL Code: 161
+Tide - accuracy of water level T_ACWL 161
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : better than 0.1 m and 10 minutes
+ 2 : worse than 0.1 m or 10 minutes
+
+Remarks:
+
+ The attribute Tide - accuracy of water level' encodes the accuracy of the water level, to the confidence level of 95%. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_HWLW Code: 162
+Tide - high and low water values T_HWLW 162
+Attribute type: A
+
+
+Indication:
+
+ Dates/times and heights are to be encoded in pairs, each value separated by a comma.
+
+ The date/time should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (eg April = 04) and 2 digits for the day (DD), separated by a capital "T" from the hour (hh) and minutes (mm) which should each be encoded using 2 digits. This conforms to ISO 8601: 1988. Seconds should not be used.
+
+ The height should be given in metres (xx.x) with a resolution of 0.1 metre.
+
+Format:
+
+ CCYYMMDDThhmm,xx.x,CCYYMMDDThhmm,xx.x
+
+Example:
+
+ 19950428T1020,1.2,19950428T1455,4.8,...
+
+Remarks:
+
+ The attribute tide - high and low water values' encodes information on the times and heights of high and low waters for each day of the duration of the time series.
+
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_MTOD Code: 163
+Tide - method of tidal prediction T_MTOD 163
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : simplified harmonic method of tidal prediction
+ 2 : full harmonic method of tidal prediction
+ 3 : time and height difference non-harmonic method
+
+Definitions:
+
+simplified harmonic method of tidal prediction:
+ prediction of tidal heights by combining a simplified set of harmonic constituents into a single time/height curve.
+
+full harmonic method of tidal prediction:
+ prediction of tidal heights by combining a complete set of harmonic constituents into a single time/height curve.
+
+time and height difference non-harmonic method:
+ prediction of high and low water times and heights by modification of the high and low water times and heights of a known time/height curve.
+
+Remarks:
+
+ The attribute Tide - method of tidal prediction' encodes the various methods of tidal prediction. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_THDF Code: 164
+Tide - time and height differences T_THDF 164
+Attribute type: A
+
+
+Indication:
+
+ time difference in hours and minutes: hhmm (according to ISO 8106: 1988)
+ height difference: metres (preceded with "-" if negative value)
+ rate difference: knots (preceded with "-" if negative value)
+
+Example:
+
+ Tidal height: 63230, Darwin,-0040,-0.7,0.9
+
+ Tidal stream: 59060, Cairns,+0130,1.2,-0.7
+
+Remarks:
+
+ The attribute tide - time and height differences' encodes the time and tidal height or tidal stream rate difference comparative to a reference station.
+
+ The format is the same for tides and tidal streams, with height difference being replaced by rate difference. The relation to a reference station is encoded by the use of a collection object.
+
+ The attribute is used to contain the identification of the reference station and , encoded in triplets, mean time difference (+ or -), height or rate difference for mean high water or mean high rate (preceded with "-" if negative value), height or rate difference for mean low water or mean low rate (preceded with "-" if negative value), each value separated by a comma. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_TSVL Code: 166
+Tide - time series values T_TSVL 166
+Attribute type: A
+
+
+Indication:
+
+ the height above or below (-ve) datum. Each value separated by a comma.
+
+Example:
+
+ 0.2,0.1,0.0,-0.1,-0.2,-0.1,0.0,0.1
+
+Remarks:
+
+ The attribute tide - time series values' encodes the values of a time series. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_VAHC Code: 167
+Tide - value of harmonic constituents T_VAHC 167
+Attribute type: A
+
+
+Definition:
+
+ Harmonic constituents are the harmonic elements in a mathematical expression for the tide producing force and in the corresponding formula for the tidal curve. Each constituent represents a periodic change or variation in the relative positions of the earth, moon and sun.
+
+Indication:
+
+ the first is the number of columns (C, always 2) and the second is the number of rows (R). The next value(s) (C times) indicates the name(s) of the columns, and the next value(s) (R times) indicates the name(s) of the rows (ie constituents). Here after follow the values (C x R times) of amplitude and phase.
+
+Example:
+
+ the following example encodes the amplitude and the phase for M2, S2, K1 and O1.
+
+ 2,4,amplitude,phase,M2,S2,K1,O1,0.962,165,0.361,243,1.223,097,0.875,143
+
+
+amplitudephaseM20.962165S20.361243K11.223097O10.875143
+
+Remarks:
+
+ The attribute tide - value of harmonic constituents' contains a 2 dimensional array of harmonic constituents. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: T_TINT Code: 165
+Tide - time interval of values T_TINT 165
+Attribute type: I
+
+
+Indication:
+
+ Unit: minutes
+
+Remarks:
+
+ The attribute Tide, current - time interval of values' encodes the interval between the values in any time series, e.g. tidal, current or other data. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TIMEND Code: 168
+Time end TIMEND 168
+Attribute type: A
+
+
+Indication:
+
+ The time end' will consist of a date and a time separated by a capital "T". The date should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). The time should be encoded using 2 digits for the hour (hh), 2 digits for the minutes (mm) and 2 digits for the seconds (ss). This conforms to ISO 8601: 1988.
+
+Format:
+
+ CCYYMMDDThhmmss (mandatory)
+
+
+Example:
+
+ 19940426T094500 for a period ending at 09:45 am on 26 April 1994.
+
+
+Remarks:
+
+ The attribute time end' indicates the end of a active period. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TIMSTA Code: 169
+Time start TIMSTA 169
+Attribute type: A
+
+
+Indication:
+
+ The time start' will consist of a date and a time separated by a capital "T". The date should be encoded using 4 digits for the calendar year (CCYY), 2 digits for the month (MM) (e.g. April = 04) and 2 digits for the day (DD). The time should be encoded using 2 digits for the hour (hh), 2 digits for the minutes (mm) and 2 digits for the seconds (ss). This conforms to ISO 8601: 1988.
+
+
+Format:
+
+ CCYYMMDDThhmmss (mandatory)
+
+Example:
+
+ 19940212T162000 for a period starting at 04:20 pm on 12 February 1994.
+
+
+Remarks:
+
+ The attribute time start' indicates the start of an active period. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: $TINTS Code: 170
+Tint $TINTS 170
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : darkest blue
+ 2 : medium blue
+ 3 : lightest blue
+
+Remarks:
+
+ The attribute tint' is used to indicate that a polygon should be filled with a given colour tint. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TOPSHP Code: 171
+Topmark/daymark shape TOPSHP 171
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : cone, point up
+ 2 : cone, point down
+ 3 : sphere
+ 4 : 2 spheres
+ 5 : cylinder (can)
+ 6 : board
+ 7 : x-shape (St. Andrew's cross)
+ 8 : upright cross (St George's cross)
+ 9 : cube, point up
+ 10 : 2 cones, point to point
+ 11 : 2 cones, base to base
+ 12 : rhombus (diamond)
+ 13 : 2 cones (points upward)
+ 14 : 2 cones (points downward)
+ 15 : besom, point up (broom or perch)
+ 16 : besom, point down (broom or perch)
+ 17 : flag
+ 18 : sphere over rhombus
+ 19 : square
+ 20 : rectangle, horizontal
+ 21 : rectangle, vertical
+ 22 : trapezium, up
+ 23 : trapezium, down
+ 24 : triangle, point up
+ 25 : triangle, point down
+ 26 : circle
+ 27 : two upright crosses (one over the other)
+ 28 : T-shape
+ 29 : triangle pointing up over a circle
+ 30 : upright cross over a circle
+ 31 : rhombus over a circle
+ 32 : circle over a triangle pointing up
+ 33 : other shape (see INFORM)
+
+Definitions:
+
+cone: a solid figure generated by straight lines drawn from a fixed point (the vertex) to a circle in a plane not containing the vertex. (The New Shorter Oxford English Dictionary. 1993. vol 2)
+ cones are commonly used as International Association of Lighthouse Authorities - IALA topmarks (lateral).
+cone, point up: is where the vertex points up.
+cone, point down: is where the vertex points down.
+
+sphere: a body the surface of which is at all points equidistant from the centre. (The New Shorter Oxford English Dictionary. 1993. vol 2)
+ spheres are commonly used as International Association of Lighthouse Authorities - IALA topmarks (safe water).
+
+2 spheres: two black spheres are commonly used as an International Association of Lighthouse Authorities - IALA topmark (isolated danger).
+
+cylinder: a solid geometrical figure generated by straight lines fixed in direction and describing with one of point a closed curve, especially a circle (in which case the figure is circular cylinder, it's ends being parallel circles). (The New Shorter Oxford English Dictionary. 1993. vol 2).
+ cylinders are commonly used as International Association of Lighthouse Authorities - IALA topmarks (lateral).
+
+board: usually of rectangular shape, made from timber or metal and used to provide a contrast with the natural background of a daymark. The actual daymark is often painted on to this board.
+
+x-shape: having a shape or a cross-section like the capital letter X. (The New Shorter Oxford English Dictionary. 1993. vol 2)
+ an x-shape as an International Association of Lighthouse Authorities - IALA topmark should be 3 dimensional in shape. It is made of at least three crossed bars.
+
+upright cross: a cross with one vertical member and one horizontal member, i.e. similar in shape to the character +'.
+
+cube: a solid contained by six equal squares; a regular hexahedron (The New Shorter Oxford English Dictionary. 1993. vol 2)
+cube, point up: a cube standing on one of its vertexes.
+
+2 cones, point to point: 2 cones, one above the other, with their vertices together in the centre.
+
+2 cones, base to base: 2 cones, one above the other, with their bases together in the centre and their vertices pointing up and down.
+
+rhombus: a plane figure having four equal sides and equal opposite angles (two acute and two obtuse); an oblique equilateral parallelogram. (The New Shorter Oxford English Dictionary. 1993. vol 2)
+
+besom: a bundle of rods or twigs. (The New Shorter Oxford English Dictionary. 1993. vol 1)
+perch: a staff placed on top of a buoy, rock or shoal as a mark for navigation. (IHO Dictionary, S-32, 5th Edition, 3734)
+
+flag: a flag mounted on a short pole.
+
+sphere over rhombus: A sphere located above a rhombus.
+
+square: a plane figure with four right angles and four equal straight sides (The New Shorter Oxford English Dictionary. 1993. vol 2)
+
+rectangle: a plane figure with four right angles and four straight sides, opposite sides being parallel and equal in length (The New Shorter Oxford English Dictionary. 1993. vol 2)
+horizontal rectangle: where the two longer opposite sides are standing horizontally.
+vertical rectangle: where the two longer opposite sides are standing vertically.
+
+trapezium: a quadrilateral having one pair of opposite sides parallel. (The New Shorter Oxford English Dictionary. 1993. vol 2)
+trapezium, up: which stands on its longer parallel side.
+trapezium, down: which stands on its shorter parallel side.
+
+triangle: a figure having three angles and three sides. (New Shorter Oxford English Dictionary. 1993. vol 2)
+
+circle: a perfectly round plane figure whose circumference is everywhere equidistant from its centre. (The New Shorter Oxford English Dictionary. 1993. vol 1)
+
+two upright crosses: two upright crosses, generally vertically disposed one above the other.
+
+T-shape: having a shape like the capital letter T.
+
+triangle pointing up over a circle:
+ a triangle, vertex uppermost, located above a circle.
+
+upright cross over a circle:
+ an upright cross located above a circle.
+
+rhombus over a circle: a rhombus located above a circle.
+
+circle over a triangle pointing up
+ a circle located over a triangle, vertex uppermost.
+
+References:
+
+ INT 1: IQ 9;
+
+ M-4: 463.1 (for International Association of Lighthouse Authorities - IALA systems only)
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: TRAFIC Code: 172
+Traffic flow TRAFIC 172
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : inbound
+ 2 : outbound
+ 3 : one-way
+ 4 : two-way
+
+Definitions:
+
+inbound: traffic flow in a general direction toward a port or similar destination.
+
+outbound: traffic flow in a general direction away from a port or similar point of origin.
+
+one-way: traffic flow in one general direction only.
+
+two-way: traffic flow in two generally opposite directions.
+
+References:
+
+ INT 1: IM 40;
+
+ M-4: 488;
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALACM Code: 173
+Value of annual change in magnetic variation VALACM 173
+Attribute type: F
+
+
+Definition:
+
+ The annual change in magnetic variation values.
+
+References:
+
+ INT 1: IB 68.1, 71;
+
+ M-4: 272.1;
+
+Indication:
+
+ Unit: minute (), negative west
+ Resolution: 0.1'
+
+Format:
+
+ sxx.x
+ s: sign, negative values only
+
+Example:
+
+ -7.1 for an annual change of 7.1 minutes in the westerly direction.
+
+
+Remarks:
+
+ A positive value, i.e. unsigned, indicates a change in an easterly direction and a negative value indicates a change in a westerly direction.
+
+ Distinction: value of magnetic variation; FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALDCO Code: 174
+Value of depth contour VALDCO 174
+Attribute type: F
+
+
+Definition:
+
+ The depth of a sea bottom contour.
+
+References:
+
+ INT 1: II 30;
+
+ M-4: 410; 411;
+
+Indication:
+
+ Unit: defined in the DUNI subfield of the DSPM record or in the DUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 fm or 0.1 ft
+
+Format:
+
+ sxxxxx.x
+ s: sign, negative values only.
+
+Example:
+
+ 50 for a depth contour of 50 metres.
+
+
+Remarks:
+
+ Drying contours are indicated by a negative value. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALLMA Code: 175
+Value of local magnetic anomaly VALLMA 175
+Attribute type: F
+
+
+Definition:
+
+ The value of the deviation from the normal magnetic variation.
+
+References:
+
+ INT 1: IB 82.1-2;
+
+ M-4: 274;
+
+Indication:
+
+ Unit: minute ()
+ Resolution: 0.1'
+
+Format:
+
+ xx.x
+
+Example:
+
+ 2.3 for a deviation of 2.3 minutes.
+
+Remarks:
+
+ The deviation is assumed to be positive and negative. The plus/minus character shall not be encoded. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALMAG Code: 176
+Value of magnetic variation VALMAG 176
+Attribute type: F
+
+
+Definition:
+
+ The magnetic variation value.
+
+References:
+
+ INT 1: IB 68.1, 71;
+
+ M-4: 272.1;
+
+Indication:
+
+ Unit: degree (), negative west.
+ Resolution: 0.01 degree
+
+ Conversion factor: one tenth of a second = 0.000028 degree.
+
+Format:
+
+ sxx.xx
+ s: sign, negative values only.
+
+Example:
+
+ 2.3 for a magnetic north oriented at 2.3 degrees east from the geographic (true) north.
+
+Remarks:
+
+ A positive value, i.e. unsigned, indicates variation in an easterly direction and a negative value indicates variation in a westerly direction.
+
+ Distinction: value of annual change in magnetic variation; FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALMXR Code: 177
+Value of maximum range VALMXR 177
+Attribute type: F
+
+
+Definition:
+
+ The extreme distance at which an object can be seen or a signal detected.
+
+References:
+
+ INT 1: not specified;
+
+ M-4: not specified;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: nautical mile (M)
+ Resolution: 0.1 M
+
+Format:
+
+ xx.x
+
+Example:
+
+ 17 for a maximum range of 17 nautical miles.
+
+Remarks:
+
+ This attribute does not apply to lights where the attribute value of nominal range' should be used. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALNMR Code: 178
+Value of nominal range VALNMR 178
+Attribute type: F
+
+
+Definition:
+
+ The nominal range at which an object can be seen or a signal detected.
+
+References:
+
+ INT 1: IB 45; IP 14;
+
+ M-4: 451.1; 471.7;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: nautical mile (M)
+ Resolution: 0.1 M
+
+Format:
+
+ xx.x
+
+Example:
+
+ 14 for a nominal range of 14 nautical miles.
+
+Remarks:
+
+ The nominal range is normally the luminous range of a light in a homogeneous atmosphere in which the meteorological visibility is 10 sea miles. (IHO Hydrographic Dictionary, S-32, 5th Edition, 4218) FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VALSOU Code: 179
+Value of sounding VALSOU 179
+Attribute type: F
+
+
+Definition:
+
+ The value of the measurement of a sounding relative to the chart datum.
+
+References:
+
+ INT 1: II 10, 11, 14, 15;
+
+ M-4: 410; 412 413.1;
+
+Indication:
+
+ Unit: defined in the DUNI subfield of the DSPM record or in the DUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 fm or 0.1 ft
+
+Format:
+
+ sxxxxx.xx
+ s: sign, negative values only.
+
+Examples:
+
+ 18.2 for a sounding of 18.2 metres.
+ -2.4 for a drying height of 2.4 metres.
+
+
+Remarks:
+
+ A drying height is indicated by a negative value. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERACC Code: 180
+Vertical accuracy VERACC 180
+Attribute type: F
+
+Expected input:
+
+ The one-dimensional error.
+
+ The error is assumed to be positive and negative. The plus/minus character shall not be encoded.
+
+Definition:
+
+ The best estimate of the vertical accuracy of heights, vertical distances and vertical clearances, excluding sounding measurements.
+
+Minimum value: 0
+
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 1.2 for an error of 1.2 metres.
+
+
+Remarks:
+
+ No remarks.
+ FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERCLR Code: 181
+Vertical clearance VERCLR 181
+Attribute type: F
+
+
+Definition:
+
+ The vertical clearance measured from the plane towards the object overhead.
+
+References:
+
+ INT 1: ID 25-28;
+
+ M-4: 380; 380.1; 382; 383;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 7.6 for a vertical clearance of 7.6 metres.
+
+Remarks:
+
+ In the case of cables carrying high voltages an additional clearance of from 2 to 5 metres may be needed to avoid an electrical discharge. When known, the authorized safe clearance (known in the UK as the Safe Overhead Clearance) which is the physical clearance minus a safety margin shall be stated. (IHO Chart Specifications, M-4).
+
+ See also vertical clearance safe'. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERCCL Code: 182
+Vertical clearance, closed VERCCL 182
+Attribute type: F
+
+
+Definition:
+
+ The vertical clearance of an object in closed condition (e.g. a closed lifting bridge) measured from the plane towards the object overhead.
+
+References:
+
+ INT 1: ID 23.3;
+
+ M-4: 380; 380.1; 381.3;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 11.2 for a vertical clearance of 11.2 metres.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERCOP Code: 183
+Vertical clearance, open VERCOP 183
+Attribute type: F
+
+
+Definition:
+
+ The vertical clearance of an object in opened condition (e.g. an opened lifting bridge) measured from the plane towards the object overhead.
+
+References:
+
+ INT 1: ID 23.3;
+
+ M-4: 380; 380.2; 381.3;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 17.8 for a vertical clearance of 17.8 metres.
+
+Remarks:
+
+ No remarks. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERCSA Code: 184
+Vertical clearance, safe VERCSA 184
+Attribute type: F
+
+
+Definition:
+
+ The safe vertical clearance measured from the plane towards the object overhead.
+
+References:
+
+ INT 1: ID 26;
+
+ M-4: 382.1;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xx.x
+
+Example:
+
+ 7.2 for a vertical clearance of 7.2 metres.
+
+Remarks:
+
+ In the case of cables carrying high voltages, the quoted vertical clearance (VERCLR) may have to be reduced by 2-5m to avoid electrical discharge. When known, this authorized safe clearance (known in the UK as the Safe Overhead Clearance) which is the physical clearance minus a safety margin shall, be stated. (IHO Chart Specifications, M-4).
+
+ See also Vertical Clearance' FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERDAT Code: 185
+Vertical datum VERDAT 185
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : Mean low water springs
+ 2 : Mean lower low water springs
+ 3 : Mean sea level
+ 4 : Lowest low water
+ 5 : Mean low water
+ 6 : Lowest low water springs
+ 7 : Approximate mean low water springs
+ 8 : Indian spring low water
+ 9 : Low water springs
+ 10 : Approximate lowest astronomical tide
+ 11 : Nearly lowest low water
+ 12 : Mean lower low water
+ 13 : Low water
+ 14 : Approximate mean low water
+ 15 : Approximate mean lower low water
+ 16 : Mean high water
+ 17 : Mean high water springs
+ 18 : High water
+ 19 : Approximate mean sea level
+ 20 : High water springs
+ 21 : Mean higher high water
+ 22 : Equinoctial spring low water
+ 23 : Lowest astronomical tide
+ 24 : Local datum
+ 25 : International Great Lakes Datum 1985
+ 26 : Mean water level
+ 27 : Lower low water large tide
+ 28 : Higher high water large tide
+ 29 : Nearly highest high water
+
+Definitions:
+
+mean low water springs:
+ (MLWS) - the average height of the low waters of spring tides. Also called spring low water. (IHO Dictionary, S-32, 5th Edition, 3150)
+
+mean lower low water springs:
+ (MLLWS) - the average height of lower low water springs at a place. (IHO Dictionary, S-32, 5th Edition, 3146)
+
+
+
+mean sea level: (MSL) - the average height of the surface of the sea at a tide station for all stages of the tide over a 19-year period, usually determined from hourly height readings measured from a fixed predetermined reference level. (IHO Dictionary, S-32, 5th Edition, 3156)
+
+lowest low water: an arbitrary level conforming to the lowest tide observed at a place, or some what lower.
+
+mean low water: (MLW) - the average height of all low waters at a place over a 19-year period. (IHO Dictionary, S-32, 5th Edition, 3147)
+
+lowest low water springs:
+ an arbitrary level conforming to the lowest water level observed at a place at spring tides during a period of time shorter than 19 years. (Hydrographic Service, Royal Australian Navy)
+
+approximate mean low water springs:
+ an arbitrary level, usually within 0.3m from that of mean low water springs (MLWS). (Hydrographic Service, Royal Australian Navy)
+
+Indian spring low water: (ISLW) - an arbitrary tidal datum approximating the level of the mean of the lower low water at spring tides. Also called Indian tidal plane. (IHO Dictionary, S-32, 5th Edition, 2427)
+
+ A tidal datum approximating the lowest water level observed at a place, originated by G.H. Darwin for the tides of India at a level below MSL being equal to the sum of amplitudes of the harmonic constituents M2, S2, K1 and O1; usually below that of the lower low water at spring tides. Also called Indian tide plane. (Hydrographic Service, Royal Australian Navy).
+
+low water springs: an arbitrary level, approximating that of mean low water springs (MLWS). (Hydrographic Service, Royal Australian Navy)
+
+approximate lowest astronomical tide:
+ an arbitrary level, usually within 0.3m from that of lowest astronomical tide (LAT). (Hydrographic Service, Royal Australian Navy)
+
+nearly lowest low water:
+ an arbitrary level approximating the lowest water level observed at a place, usually equivalent to the Indian spring low water (ISLW). (Hydrographic Service, Royal Australian Navy)
+
+mean lower low water: (MLLW) - the average height of the lower low waters at a place over a 19-year period. (IHO Dictionary, S-32, 5th Edition, 3145)
+
+low water: an approximation of mean low water adopted as the reference level for a limited area, irrespective of better determinations at a later date. Used mostly in harbour and river engineering.
+
+ used in inland (non-tidal) waters. It is generally defined as a level which the daily mean water level would fall below less than 5% of the time and by no more than 0.2 metres during the navigation season. A single level surface is usually chosen as the low water datum for a whole lake. On a river, low water datum is a sloping surface which approximates the river surface at a low state. (Canadian Hydrographic Service)
+
+approximate mean low water:
+ an arbitrary level, usually within 0.3m from that of mean low water (MLW). (Hydrographic Service, Royal Australian Navy)
+
+
+approximate mean lower low water:
+ an arbitrary level, usually within 0.3m from that of mean lower low water (MLLW). (Hydrographic Service, Royal Australian Navy)
+
+mean high water: (MHW) - the average height of all high waters at a place over a 19-year period. (IHO Dictionary, S-32, 5th Edition, 3141)
+
+mean high water springs:
+ (MHWS) - the average height of the high waters of spring tides. Also called spring high water. (IHO Dictionary, S-32, 5th Edition, 3144)
+
+high water: the highest level reached at a place by the water surface in one tidal cycle. Also called high tide. (IHO Dictionary, S-32, 5th Edition, 2251)
+
+ when used on inland (non-tidal) waters it is generally defined as a level which the daily mean water level exceeds less than 5% of the time.
+
+approximate mean sea level:
+ an arbitrary level, usually within 0.3m from that of mean sea level (MSL). (Hydrographic Service, Royal Australian Navy)
+
+high water springs: an arbitrary level, approximating that of mean high water springs (MHWS). (Hydrographic Service, Royal Australian Navy)
+
+mean higher high water:
+ (MHHW) - the average height of higher high waters at a place over a 19-year period. (IHO Dictionary, S-32, 5th Edition, 3140)
+
+equinoctial spring low water:
+ the level of low water springs near the time of an equinox.
+
+lowest astronomical tide:
+ (LAT) - the lowest tide level which can be predicted to occur under average meterological conditions and under any combination of astronomical conditions. (IHO Dictionary, S-32, 5th Edition, 2936)
+
+local datum: an arbitrary datum defined by a local harbour authority, from which levels and tidal heights are measured by this authority.
+
+international great lakes datum 1985:
+ (IGLD 1985) - a vertical reference system with its zero based on the mean water level at Rimouski/Pointe-au-Pére, Quebec, over the period 1970 to 1988.
+
+mean water level: the average of all hourly water levels over the available period of record.
+
+lower low water large tide:
+ (LLWLT) - the average of the lowest low waters, one from each of 19 years of observations.
+
+higher high water large tide:
+ (HHWLT) - the average of the highest high waters, one from each of 19 years of observations.
+
+nearly highest high water:
+ an arbitrary level approximating the highest water level observed at a place, usually equivalent to the high water springs.
+
+
+
+
+
+Remarks:
+
+ This attribute is used to specify the datum to which both heights (vertical datum, see S-57 Part 3) and soundings (sounding datum, see S-57 Part 3) are referred.
+
+ When the vertical datum is unknown, such as water areas above locks, the value local datum' is to be used, and further details may be encoded using INFORM'.
+
+ The 0.3m approximation quoted in the "approximate" levels is somehow arbitrary and follows the British example of their definition for "approximate LAT". FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: VERLEN Code: 186
+Vertical length VERLEN 186
+Attribute type: F
+
+
+Definition:
+
+ The total vertical length of an object.
+
+References:
+
+ INT 1: IE 5; IL 21.3;
+
+ M-4: 303;
+
+Minimum Value: 0
+
+Indication:
+
+ Unit: defined in the HUNI subfield of the DSPM record or in the HUNITS attribute of the M_UNIT meta object class, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 ft
+
+Format:
+
+ xxx.x
+
+Example:
+
+ 24.5 for a vertical length of 24.5 metres.
+
+Remarks:
+
+ For floating objects:
+ the vertical distance from the surface of water to the highest point of that object.
+
+ For fixed objects: the vertical distance from seabed or ground to the highest point of that object.
+
+ For objects on top of other objects:
+ the vertical distance from the lowest to the highest point of that object.
+
+ Vertical length measurements do not require a datum. FEATURE OBJECT ATTRIBUTES
+
+
+
+
+Acronym: WATLEV Code: 187
+Water level effect WATLEV 187
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : partly submerged at high water IF 33.2; 378.1;
+ 2 : always dry IF 6.1; IK 10; 313.4; 421.1;
+ 3 : always under water/submerged IF 6.3; IK 13; 421.4;
+ 4 : covers and uncovers IF 6.2; IK 11; 421.2;
+ 5 : awash IK 12; 421.3;
+ 6 : subject to inundation or flooding
+
+Definitions:
+
+partly submerged at high water:
+ partially covered and partially dry at high water.
+
+always dry: not covered at high water under average meteorological conditions.
+
+always under water/submerged:
+ remains covered by water at all times under average meteorological conditions.
+
+covers and uncovers: expression intended to indicate an area of a reef or other projection from the bottom of a body of water which periodically extends above and is submerged below the surface. Also referred to as dries or uncovers. (IHO Dictionary, S-32, 5th Edition, 1111)
+
+awash: flush with, or washed by the waves at low water under average meteorological conditions. (adapted from IHO Dictionary, S-32, 5th Edition, 308)
+
+subject to inundation or flooding:
+ an area periodically covered by flood water, excluding tidal waters. (Digital Geographic Information Standard - DIGEST 1.2)
+
+Remarks:
+
+ The attribute water level effect' encodes the effect of the surrounding water on an object. 2.3 National Language Attributes
+ NATIONAL LANGUAGE ATTRIBUTES
+
+
+
+
+Acronym: NINFOM Code: 300
+Information in national language NINFOM 300
+Attribute type: S
+
+
+References:
+
+ INT 1: IA 16;
+
+ M-4: 242.3-5;
+
+Indication:
+
+ Text (c...): Textual information in national language characters
+
+Format:
+
+ c...
+
+Remarks:
+
+ The attribute information in national language' encodes any textual information about an object using a specified national language.
+
+ The textual information could be, for example, a list, a table or a text.
+
+ This attribute should be used, for example, to hold the information that is shown on paper charts by cautionary and explanatory notes. NATIONAL LANGUAGE ATTRIBUTES
+
+
+
+
+Acronym: NOBJNM Code: 301
+Object name in national language NOBJNM 301
+Attribute type: S
+
+
+References:
+
+ INT 1: ID 7, IF 19, IN 12.2-3;
+
+ M-4: 371; 323.1-2; 431.2-3; 431.5;
+
+Indication:
+
+ Name of object (c...): string of national language characters
+
+Format:
+
+ c...
+
+Remarks:
+
+ The attribute object name in national language' encodes the individual name of an object in the specified national language. NATIONAL LANGUAGE ATTRIBUTES
+
+
+
+
+Acronym: NPLDST Code: 302
+Pilot district in national language NPLDST 302
+Attribute type: S
+
+
+References:
+
+ INT 1: IT 1.2;
+
+ M-4: 491.1-2;
+
+Indication:
+
+ Pilot district (c...): string of national language characters
+
+Format:
+
+ c...
+
+Remarks:
+
+ The attribute pilot district in national language' encodes the pilot district for which a pilot station is responsible in the specified national language. NATIONAL LANGUAGE ATTRIBUTES
+
+
+
+
+Acronym: $NTXST Code: 303
+Text string in national language $NTXST 303
+Attribute type: S
+
+
+Expected input: the content of the legend to be displayed in a national language other than English.
+Remarks:
+
+ No remarks. NATIONAL LANGUAGE ATTRIBUTES
+
+
+
+
+Acronym: NTXTDS Code: 304
+Textual description in national language NTXTDS 304
+Attribute type: S
+
+
+Indication:
+
+ the string encodes the file name of an external text file that contains the text in a national language.
+
+Remarks:
+
+ The attribute textual description in national language' indicates whether a text file containing text extracted from relevant pilot books or navigational publications is available. 2.4 Spatial and Meta Object Attributes
+
+
+
+Some attributes qualify the location of an object, as opposed to defining the characteristics of the individual object itself.
+
+Attributes specifying the accuracy and quality of a position (x,y - coordinates) and the reference datum for horizontal measurement are considered to be attributes of spatial objects.
+
+Within a data set encoded according to S-57, the attributes of spatial objects are held in the Spatial Record Attribute field (refer to S-57 Part 3).
+ SPATIAL AND META OBJECT ATTRIBUTES
+
+
+
+
+Acronym: HORDAT Code: 400
+Horizontal datum HORDAT 400
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning
+
+ 1 : WGS 72
+ 2 : WGS 84
+ 3 : European 1950
+ 4 : Potsdam Datum
+ 5 : Adindan
+ 6 : Afgooye
+ 7 : Ain el Abd 1970
+ 8 : Anna 1 Astro 1965
+ 9 : Antigua Island Astro 1943
+ 10 : Arc 1950
+ 11 : Arc 1960
+ 12 : Ascension Island 1958
+ 13 : Astro beacon "E" 1945
+ 14 : Astro DOS 71/4
+ 15 : Astro Tern Island (FRIG) 1961
+ 16 : Astronomical Station 1952
+ 17 : Australian Geodetic 1966
+ 18 : Australian Geodetic 1984
+ 19 : Ayabelle Lighthouse
+ 20 : Bellevue (IGN)
+ 21 : Bermuda 1957
+ 22 : Bissau
+ 23 : Bogota Observatory
+ 24 : Bukit Rimpah
+ 25 : Camp Area Astro
+ 26 : Campo Inchauspe 1969
+ 27 : Canton Astro 1966
+ 28 : Cape
+ 29 : Cape Canaveral
+ 30 : Carthage
+ 31 : Chatam Island Astro 1971
+ 32 : Chua Astro
+ 33 : Corrego Alegre
+ 34 : Dabola
+ 35 : Djakarta (Batavia)
+ 36 : DOS 1968
+ 37 : Easter Island 1967
+ 38 : European 1979
+ 39 : Fort Thomas 1955
+ 40 : Gan 1970
+ 41 : Geodetic Datum 1949
+ 42 : Graciosa Base SW 1948
+ 43 : Guam 1963
+ 44 : Gunung Segara
+ 45 : GUX 1 Astro
+ 46 : Herat North
+ 47 : Hjorsey 1955
+ 48 : Hong Kong 1963
+ 49 : Hu-Tzu-Shan
+ 50 : Indian
+ 51 : Indian 1954
+ 52 : Indian 1975
+ 53 : Ireland 1965
+ 54 : ISTS 061 Astro 1968
+ 55 : ISTS 073 Astro 1969
+ 56 : Johnston Island 1961
+ 57 : Kandawala
+ 58 : Kerguelen Island 1949
+ 59 : Kertau 1948
+ 60 : Kusaie Astro 1951
+ 61 : L. C. 5 Astro 1961
+ 62 : Leigon
+ 63 : Liberia 1964
+ 64 : Luzon
+ 65 : Mahe 1971
+ 66 : Massawa
+ 67 : Merchich
+ 68 : Midway Astro 1961
+ 69 : Minna
+ 70 : Montserrat Island Astro 1958
+ 71 : M'Poraloko
+ 72 : Nahrwan
+ 73 : Naparima, BWI
+ 74 : North American 1927
+ 75 : North American 1983
+ 76 : Observatorio Meteorologico 1939
+ 77 : Old Egyptian 1907
+ 78 : Old Hawaiian
+ 79 : Oman
+ 80 : Ordnance Survey of Great Britain 1936
+ 81 : Pico de las Nieves
+ 82 : Pitcairn Astro 1967
+ 83 : Point 58
+ 84 : Pointe Noire 1948
+ 85 : Porto Santo 1936
+ 86 : Provisional South American 1956
+ 87 : Provisional South Chilean 1963 (also known as Hito XVIII 1963)
+ 88 : Puerto Rico
+ 89 : Qatar national
+ 90 : Qornoq
+ 91 : Reunion
+ 92 : Rome 1940
+ 93 : Santo (DOS) 1965
+ 94 : Sao Braz
+ 95 : Sapper Hill 1943
+ 96 : Schwarzeck
+ 97 : Selvagem Grande 1938
+ 98 : South American 1969
+ 99 : South Asia
+ 100 : Tananarive Observatory 1925
+ 101 : Timbalai 1948
+ 102 : Tokyo
+ 103 : Tristan Astro 1968
+ 104 : Viti Levu 1916
+ 105 : Wake-Eniwetok 1960
+ 106 : Wake Island Astro 1952
+ 107 : Yacare
+ 108 : Zanderij
+ 109 : American Samoa 1962
+ 110 : Deception Island
+ 111 : Indian 1960
+ 112 : Indonesian 1974
+ 113 : North Sahara 1959
+ 114 : Pulkovo 1942
+ 115 : S-42 (Pulkovo 1942)
+ 116 : S-JYSK
+ 117 : Voirol 1950
+118 : Average Terrestrial System 1977
+ 119 : Compensation Gèodèsique du Quèbec 1977
+ 120 : Finnish (KKJ)
+121 : Ordnance Survey of Ireland
+122 : Revised Kertau
+123 : Revised Nahrwan
+124 : GGRS 76 (Greece)
+ 125 : Nouvelle Triangulation de France
+ 126 : RT 90 (Sweden)
+127 : Geocentric Datum of Australia (GDA)
+128 : BJZ54 (A954 Beijing Coordinates)
+129 : Modified BJZ54
+130 : GDZ80
+131 : Local datum
+
+
+References:
+
+ INT 1: IS 50;
+
+ M-4: not specified;
+
+Remarks:
+
+ All necessary information for conversion of geographic coordinates from most of the Geodetic Datums in the above list to WGS-84 is contained in the "User's Handbook on Datum Transformations involving WGS-84", prepared by the US Defense Mapping Agency and which is available from the IHB as IHO Publication S-60 (English and French Versions), along with an associated standard datum transformation software on floppy disk called "MADTRAN". The resulting latitude and longitude offsets can be encoded in the attribute SHIPAM.
+
+ SPATIAL AND META OBJECT ATTRIBUTES
+
+
+
+
+Acronym: POSACC Code: 401
+Positional Accuracy POSACC 401
+Attribute type: F
+
+Expected input:
+
+ The expected input is the maximum of the two-dimensional error.
+
+ The error is assumed to be positive and negative. The plus/minus character shall not be encoded.
+
+Definition:
+
+ The best estimate of the accuracy of a position.
+
+Minimum value: 0
+
+
+Indication:
+
+ Unit: defined in the PUNI subfield of the DSPM record, e.g. metre (m)
+ Resolution: 0.1 m or 0.1 mm
+
+Format:
+
+ xxxx.x
+
+Example:
+
+ 25 for an error of 25 metres.
+
+Remarks
+
+ No remarks SPATIAL AND META OBJECT ATTRIBUTES
+
+
+
+
+Acronym: QUAPOS Code: 402
+Quality of position QUAPOS 402
+Attribute type: E
+
+
+Expected input:
+
+ ID Meaning INT 1 M-4
+
+ 1 : surveyed IC 1; 310.1;
+ 2 : unsurveyed IC 2; II 25; 311; 410;
+ 3 : inadequately surveyed II 25; 410;
+ 4 : approximate IB 7, 33; IC 12; II 31; 305.1; 351.4; 411.2;
+ 5 : position doubtful II 1; 424.3;
+ 6 : unreliable
+ 7 : reported (not surveyed)
+ 8 : reported (not confirmed) II 3.1-2, 4;
+ 9 : estimated
+ 10 : precisely known
+ 11 : calculated
+
+Definitions:
+
+surveyed: the position(s) was(were) determined by the operation of making measurements for determining the relative position of points on, above or beneath the earth's surface. Survey implies a regular, controlled survey of any date. (adapted from IHO Dictionary, S-32, 5195, & IHO Chart Specifications, M-4, 175.2)
+
+unsurveyed: survey data is does not exist or is very poor. (adapted from IHO Dictionary, S- 32, 5732)
+
+inadequately surveyed: position data is of a very poor quality. (adapted from IHO Dictionary, S-32, 5732)
+
+approximate: a position that is considered to be less than third-order accuracy, but is generally considered to be within 30.5 metres of its correct geographic location. Also may apply to an object whose position does not remain fixed. (adapted from IHO Dictionary, S-32, 213, 3967, & IHO Specifications, M-4, 424.1)
+
+position doubtful: an object whose position has been reported but which is considered to be doubtful.
+
+unreliable: an object's position obtained from questionable or unreliable data.
+
+reported (not surveyed):
+ an object whose position has been reported and its position confirmed by some means other than a formal survey such as an independent report of the same object.
+
+reported (not confirmed):
+ an object whose position has been reported and its position has not been confirmed.
+
+estimated: the most probable position of an object determined from incomplete data or data of questionable accuracy. (adapted from IHO Dictionary, S-32, 3960)
+
+precisely known: a position that is of a known value, such as the position of an anchor berth or other defined object.
+
+calculated: a position that is computed from data.
+
+Remarks:
+
+ No remarks.
\ No newline at end of file
Added: packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.dia
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.dia
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.png
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/contrib/S52/doc/boylat24.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/contrib/S52/doc/libS52-layout.dia
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/doc/libS52-layout.dia (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/doc/libS52-layout.dia 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1830 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+ <dia:diagramdata>
+ <dia:attribute name="background">
+ <dia:color val="#ffffff"/>
+ </dia:attribute>
+ <dia:attribute name="pagebreak">
+ <dia:color val="#000099"/>
+ </dia:attribute>
+ <dia:attribute name="paper">
+ <dia:composite type="paper">
+ <dia:attribute name="name">
+ <dia:string>#Letter#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="tmargin">
+ <dia:real val="2.54"/>
+ </dia:attribute>
+ <dia:attribute name="bmargin">
+ <dia:real val="2.54"/>
+ </dia:attribute>
+ <dia:attribute name="lmargin">
+ <dia:real val="2.54"/>
+ </dia:attribute>
+ <dia:attribute name="rmargin">
+ <dia:real val="2.54"/>
+ </dia:attribute>
+ <dia:attribute name="is_portrait">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ <dia:attribute name="scaling">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="fitto">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="grid">
+ <dia:composite type="grid">
+ <dia:attribute name="width_x">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="width_y">
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="visible_x">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="visible_y">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:composite type="color"/>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#d8e5e5"/>
+ </dia:attribute>
+ <dia:attribute name="guides">
+ <dia:composite type="guides">
+ <dia:attribute name="hguides"/>
+ <dia:attribute name="vguides"/>
+ </dia:composite>
+ </dia:attribute>
+ </dia:diagramdata>
+ <dia:layer name="Background" visible="true">
+ <dia:object type="Standard - Box" version="0" id="O0">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-5,-5"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-5.05,-5.05;24.05,28.9912"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="-5,-5"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="29"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="33.9412"/>
+ </dia:attribute>
+ <dia:attribute name="inner_color">
+ <dia:color val="#ffc0cb"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ <dia:attribute name="line_style">
+ <dia:enum val="4"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O1">
+ <dia:attribute name="obj_pos">
+ <dia:point val="12,2"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="12,0.9675;21.6825,4.165"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#libS52 dependency
+layout --SEP2004#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="1.4"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="12,2"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O2">
+ <dia:attribute name="obj_pos">
+ <dia:point val="11.6,11.55"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="11.6,10.9;11.6,11.9"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="11.6,11.55"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Flowchart - Magnetic Disk" version="0" id="O3">
+ <dia:attribute name="obj_pos">
+ <dia:point val="12,10"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="11.95,9.95;14.9571,13.2642"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="12,10"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="2.90711"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3.21421"/>
+ </dia:attribute>
+ <dia:attribute name="line_width">
+ <dia:real val="0.1"/>
+ </dia:attribute>
+ <dia:attribute name="line_colour">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="fill_colour">
+ <dia:color val="#ffffff"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ <dia:attribute name="line_style">
+ <dia:enum val="0"/>
+ <dia:real val="1"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#S52raz#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="13.4536,12.125"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="1"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:attribute name="flip_horizontal">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="flip_vertical">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O4">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,6"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,5.35;8,6.35"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,6"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O5">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,8.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.93805,8.03805;20.1873,11.4941"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,8.1"/>
+ <dia:point val="20,11"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O10" connection="6"/>
+ <dia:connection handle="1" to="O16" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O6">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2,4.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="1.9398,4.0398;10.1642,6.49802"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="2,4.1"/>
+ <dia:point val="10,6"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O12" connection="6"/>
+ <dia:connection handle="1" to="O10" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Polygon" version="0" id="O7">
+ <dia:attribute name="obj_pos">
+ <dia:point val="16,30"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="15.95,-11.05;32.05,35.05"/>
+ </dia:attribute>
+ <dia:attribute name="poly_points">
+ <dia:point val="16,30"/>
+ <dia:point val="26,30"/>
+ <dia:point val="26,-6"/>
+ <dia:point val="16,-6"/>
+ <dia:point val="16,-11"/>
+ <dia:point val="32,-11"/>
+ <dia:point val="32,35"/>
+ <dia:point val="16,35"/>
+ </dia:attribute>
+ <dia:attribute name="inner_color">
+ <dia:color val="#add8e6"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O8">
+ <dia:attribute name="obj_pos">
+ <dia:point val="20,-9"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="20,-9.93;27.43,-8.34"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#libgv.a (OpenEV)#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="1.2"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="20,-9"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O9">
+ <dia:attribute name="obj_pos">
+ <dia:point val="20,13.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.6127,13.0293;20.0707,23.3905"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="20,13.1"/>
+ <dia:point val="10,23"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O16" connection="6"/>
+ <dia:connection handle="1" to="O37" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O10">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,6"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="7.95,5.95;12.05,8.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="8,6"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O11">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,7.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,6.4;10.1,7.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52PL#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,7.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O10" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O12">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,2"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-0.05,1.95;4.05,4.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="0,2"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O13">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,3.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="0,2.4;2.15,3.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52GL#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="0,3.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O12" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O14">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,33"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-0.05,32.95;4.05,35.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="0,33"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O15">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,34.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="0,33.4;2.6,34.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># OpenGL#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="0,34.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O14" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O16">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,11"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="17.95,10.95;22.05,13.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="18,11"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O17">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,12.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="18,11.4;20.2,12.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52CS#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="18,12.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O16" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O18">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,15"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="7.95,14.95;12.05,17.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="8,15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O19">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,16.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,15.4;10.1,16.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S57gv#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,16.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O18" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O20">
+ <dia:attribute name="obj_pos">
+ <dia:point val="11,-8"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="10.95,-8.05;15.05,-5.85"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="11,-8"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O21">
+ <dia:attribute name="obj_pos">
+ <dia:point val="11,-6.95"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="11,-7.6;14.75,-6.6"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># gvS57Layer#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="11,-6.95"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O20" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O22">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-2,25.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-2.5,25.05;-1.5,30.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="-2,25.1"/>
+ <dia:point val="-2,30"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O35" connection="6"/>
+ <dia:connection handle="1" to="O49" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O23">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,23"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="17.95,22.95;22.05,25.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="18,23"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O24">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="18,23.4;20.75,24.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52type#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="18,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O23" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O25">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,8.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.5,8.05;10.5,15.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,8.1"/>
+ <dia:point val="10,15"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O10" connection="6"/>
+ <dia:connection handle="1" to="O18" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O26">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,-16"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-0.05,-16.05;15.05,-12.95"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="0,-16"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="3"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O27">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,-15"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="3,-15.6713;13.2713,-13.8075"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#s52plugin (to test default build)
+s52test & s52osg (debug/static)#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="3,-15"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O28">
+ <dia:attribute name="obj_pos">
+ <dia:point val="15,-14.5"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="14.9382,-14.5618;16.4945,-10.8146"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="15,-14.5"/>
+ <dia:point val="16,-11"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O26" connection="4"/>
+ <dia:connection handle="1" to="O7" connection="8"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O29">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,19"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="17.95,18.95;22.05,21.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="18,19"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O30">
+ <dia:attribute name="obj_pos">
+ <dia:point val="18,20.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="18,19.4;20.7,20.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52utils#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="18,20.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O29" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O31">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,30"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="7.95,29.95;12.05,32.05"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="8,30"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O32">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,31"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,30.35;11.6,31.35"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># PROJ (OGR)#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,31"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O31" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - ZigZagLine" version="0" id="O33">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2,4.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="1.5,4.05;2.5,33.05"/>
+ </dia:attribute>
+ <dia:attribute name="orth_points">
+ <dia:point val="2,4.1"/>
+ <dia:point val="2,8"/>
+ <dia:point val="2,8"/>
+ <dia:point val="2,33"/>
+ </dia:attribute>
+ <dia:attribute name="orth_orient">
+ <dia:enum val="1"/>
+ <dia:enum val="0"/>
+ <dia:enum val="1"/>
+ </dia:attribute>
+ <dia:attribute name="autorouting">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O12" connection="6"/>
+ <dia:connection handle="1" to="O14" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O34">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,8.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.93209,8.03209;13.7384,10.4622"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,8.1"/>
+ <dia:point val="13.4536,10"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O10" connection="6"/>
+ <dia:connection handle="1" to="O3" connection="2"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O35">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-4,23"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-4.05,22.95;0.05,25.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="-4,23"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O36">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-4,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-4,23.4;-1.3,24.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52OSG#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="-4,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O35" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O37">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,23"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="7.95,22.95;12.05,25.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="8,23"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O38">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,23.4;10.85,24.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S57data#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,24.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O37" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O39">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,19"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.95,18.95;7.05,21.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="3,19"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O40">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,20.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="3,19.4;5.45,20.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S57ogr#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="3,20.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O39" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O41">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5,21.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="4.9355,21.0355;10.2243,23.4852"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="5,21.1"/>
+ <dia:point val="10,23"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O39" connection="6"/>
+ <dia:connection handle="1" to="O37" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O42">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,-2"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="7.95,-2.05;12.05,0.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="8,-2"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O43">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,0.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.5,0.05;10.5,6.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,0.1"/>
+ <dia:point val="10,6"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O42" connection="6"/>
+ <dia:connection handle="1" to="O10" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O44">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,0.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="1.83582,0.0397996;10.0602,2.49802"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,0.1"/>
+ <dia:point val="2,2"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O42" connection="6"/>
+ <dia:connection handle="1" to="O12" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O45">
+ <dia:attribute name="obj_pos">
+ <dia:point val="2,4.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-2.49952,4.04073;2.05927,23.1524"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="2,4.1"/>
+ <dia:point val="-2,23"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O12" connection="6"/>
+ <dia:connection handle="1" to="O35" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O46">
+ <dia:attribute name="obj_pos">
+ <dia:point val="8,-0.95"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="8,-1.6;9.4,-0.6"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="8,-0.95"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O42" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O47">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,17.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.5,17.05;10.5,23.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,17.1"/>
+ <dia:point val="10,23"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O18" connection="6"/>
+ <dia:connection handle="1" to="O37" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O48">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,17.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="4.77565,17.0355;10.0645,19.4852"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,17.1"/>
+ <dia:point val="5,19"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O18" connection="6"/>
+ <dia:connection handle="1" to="O39" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O49">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-4,30"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-4.05,29.95;0.05,32.15"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="-4,30"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O50">
+ <dia:attribute name="obj_pos">
+ <dia:point val="-4,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-4,30.4;-2.5,31.4"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># OSG#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="-4,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O49" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - ZigZagLine" version="0" id="O51">
+ <dia:attribute name="obj_pos">
+ <dia:point val="0,31.05"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="-0.05,30.95;2.5,33.05"/>
+ </dia:attribute>
+ <dia:attribute name="orth_points">
+ <dia:point val="0,31.05"/>
+ <dia:point val="0,31"/>
+ <dia:point val="2,31"/>
+ <dia:point val="2,33"/>
+ </dia:attribute>
+ <dia:attribute name="orth_orient">
+ <dia:enum val="1"/>
+ <dia:enum val="0"/>
+ <dia:enum val="1"/>
+ </dia:attribute>
+ <dia:attribute name="autorouting">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O49" connection="4"/>
+ <dia:connection handle="1" to="O14" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O52">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,-8"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.95,-8.05;8.05,-5.85"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="3,-8"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="5"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2.1"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Box" version="0" id="O53">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,30"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="2.95,29.95;7.05,32.05"/>
+ </dia:attribute>
+ <dia:attribute name="elem_corner">
+ <dia:point val="3,30"/>
+ </dia:attribute>
+ <dia:attribute name="elem_width">
+ <dia:real val="4"/>
+ </dia:attribute>
+ <dia:attribute name="elem_height">
+ <dia:real val="2"/>
+ </dia:attribute>
+ <dia:attribute name="show_background">
+ <dia:boolean val="true"/>
+ </dia:attribute>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O54">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,31"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="3,30.35;4.5,31.35"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># OGR#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="3,31"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O53" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O55">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5,21.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="4.5,21.05;5.5,30.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="5,21.1"/>
+ <dia:point val="5,30"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O39" connection="6"/>
+ <dia:connection handle="1" to="O53" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O56">
+ <dia:attribute name="obj_pos">
+ <dia:point val="3,-6.95"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="3,-7.6;7.25,-6.6"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string># S52glxsimple#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="0.8"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="3,-6.95"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O52" connection="3"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O57">
+ <dia:attribute name="obj_pos">
+ <dia:point val="13,-5.9"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.5732,-5.97012;13.0701,-1.65551"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="13,-5.9"/>
+ <dia:point val="10,-2"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O20" connection="6"/>
+ <dia:connection handle="1" to="O42" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O58">
+ <dia:attribute name="obj_pos">
+ <dia:point val="5.5,-5.9"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="5.42947,-5.97053;10.3652,-1.58941"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="5.5,-5.9"/>
+ <dia:point val="10,-2"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O52" connection="6"/>
+ <dia:connection handle="1" to="O42" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O59">
+ <dia:attribute name="obj_pos">
+ <dia:point val="16,-8.5"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="12.8685,-8.55754;16.0575,-7.49858"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="16,-8.5"/>
+ <dia:point val="13,-8"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O7" connection="7"/>
+ <dia:connection handle="1" to="O20" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O60">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,25.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.5,25.05;10.5,30.05"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,25.1"/>
+ <dia:point val="10,30"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O37" connection="6"/>
+ <dia:connection handle="1" to="O31" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Line" version="0" id="O61">
+ <dia:attribute name="obj_pos">
+ <dia:point val="10,17.1"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="9.92951,17.0295;21.4129,30.3625"/>
+ </dia:attribute>
+ <dia:attribute name="conn_endpoints">
+ <dia:point val="10,17.1"/>
+ <dia:point val="21,30"/>
+ </dia:attribute>
+ <dia:attribute name="numcp">
+ <dia:int val="1"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_length">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:attribute name="end_arrow_width">
+ <dia:real val="0.5"/>
+ </dia:attribute>
+ <dia:connections>
+ <dia:connection handle="0" to="O18" connection="6"/>
+ <dia:connection handle="1" to="O7" connection="1"/>
+ </dia:connections>
+ </dia:object>
+ <dia:object type="Standard - Text" version="0" id="O62">
+ <dia:attribute name="obj_pos">
+ <dia:point val="20,33"/>
+ </dia:attribute>
+ <dia:attribute name="obj_bb">
+ <dia:rectangle val="20,32.07;27.43,33.66"/>
+ </dia:attribute>
+ <dia:attribute name="text">
+ <dia:composite type="text">
+ <dia:attribute name="string">
+ <dia:string>#libgv.a (OpenEV)#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="font">
+ <dia:font family="sans" style="0" name="Helvetica"/>
+ </dia:attribute>
+ <dia:attribute name="height">
+ <dia:real val="1.2"/>
+ </dia:attribute>
+ <dia:attribute name="pos">
+ <dia:point val="20,33"/>
+ </dia:attribute>
+ <dia:attribute name="color">
+ <dia:color val="#000000"/>
+ </dia:attribute>
+ <dia:attribute name="alignment">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
+ </dia:object>
+ </dia:layer>
+</dia:diagram>
Added: packages/openev/branches/upstream/current/contrib/S52/doc/obj.txt
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/doc/obj.txt (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/doc/obj.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8848 @@
+
+
+
+ S-57 Appendix A
+ IHO Object Catalogue
+
+ Edition 3.0
+ Page intentionally left blank
+ CONTENTS
+
+
+
+Introduction
+
+Object Classes Chapter 1
+
+Attributes Chapter 2
+
+IHB Codes for Producing Agency Annex A
+
+Attributes/Object Classes Cross Reference Annex B
+ Page intentionally left blank
+Introduction
+
+The Object Catalogue is the data schema for "S-57 - The IHO Transfer
+Standard for Digital Hydrographic Data". Its primary function is to
+provide a means of describing real world entities. That is entities
+which actually exist (either physically such as a beacon or legally
+such as an anchorage area) in the real world. The Object Catalogue is
+based on the theoretical model described in Part 2 of this Standard.
+The model assumes that real world entities can be categorized into a
+finite number of types, such as lights, wrecks, built up areas etc.
+These entity types are termed feature object classes in the Object
+Catalogue. An instance of a feature object class, referred to as a
+feature object, (that is one specific light or wreck or built up area)
+can be more precisely described by assigning to it a number of
+attributes and then specifying values for those attributes. A
+particular real world entity is encoded by specifying the appropriate
+feature object class, attributes and attribute values. For example, a
+red lateral buoy would be encoded as follows:- feature object class:
+buoy lateral; attribute: colour; attribute value: red.
+
+The data model defines four types of feature object:
+
+Geo containing the descriptive characteristics of a real world
+ entity.
+
+Meta containing information about other objects (eg.
+ compilation scale, vertical datum).
+
+Collection containing information about the relationships
+ between other objects.
+
+Cartographic containing information about the cartographic
+ representation of a real world entity.
+
+Chapter 1 contains a description of each feature object class. This
+includes a definition of the class and a list of the attributes that
+are allowed for that class. Instructions on how to interpret the
+information associated with each feature object class are given in the
+introduction to Chapter 1.
+
+The Object Catalogue does not mandate the use of any attributes.
+However, for each instance of a feature object, a particular attribute
+may only be used once. In general terms it is up to the encoder to
+select from the appropriate list the attributes that are relevant to a
+particular object instance. However, for some applications, certain
+attributes may be designated as mandatory for specific object classes.
+These attributes will be listed in the appropriate product
+specification (see S-57 Appendix B).
+
+A description of each attribute is contained in Chapter 2. This
+includes a definition of the attribute and, where appropriate, a list
+of allowable values, also with definitions. Instructions on how to
+interpret the information associated with each attribute are given in
+the introduction to Chapter 2.
+
+For the purposes of backward compatibility, changes from edition 2.0
+of S-57 have been emphasized in the table of contents by striking out
+object classes or attributes that have been deleted and by marking
+those that have been added in the margin. In addition, pages in the
+Object Catalogue relating to deleted object classes or attributes have
+been retained with the remark "DELETED - DO NOT USE". Where a deleted
+object class or attribute has been replaced by another one, this is
+specified at the bottom of the page in bold characters.
+ Page intentionally left blank
+
+
+
+ S-57 Appendix A
+ Chapter 1 - Object Classes
+
+ Edition 3.0
+ Page intentionally left blank
+ CONTENTS
+Acronym Code
+
+1.1 Introduction 1.1
+
+1.2 Geo Object Classes 1.2
+Administration Area (Named) ADMARE 1 1.3
+Airport/airfield AIRARE 2 1.4
+Anchor ACHPNT 1.5
+Anchor berth ACHBRT 3 1.6
+Anchorage area ACHARE 4 1.7
+Beacon, cardinal BCNCAR 5 1.8
+Beacon, isolated danger BCNISD 6 1.9
+Beacon, lateral BCNLAT 7 1.10
+Beacon, safe water BCNSAW 8 1.11
+Beacon, special purpose/general BCNSPP 9 1.12
+Berth BERTHS 10 1.13
+Berthing facility BRTFAC 1.14
+Bridge BRIDGE 11 1.15
+Building, religious BUIREL 1.16
+Building, single BUISGL 12 1.17
+Built-up area BUAARE 13 1.18
+Buoy, cardinal BOYCAR 14 1.19
+Buoy, installation BOYINB 15 1.20
+Buoy, isolated danger BOYISD 16 1.21
+Buoy, lateral BOYLAT 17 1.22
+Buoy, safe water BOYSAW 18 1.23
+Buoy, special purpose/general BOYSPP 19 1.24
+Cable area CBLARE 20 1.25
+Cable, overhead CBLOHD 21 1.26
+Cable, submarine CBLSUB 22 1.27
+Cairn CAIRNS 1.28
+Canal CANALS 23 1.29
+Canal bank CANBNK 24 1.30
+Cargo transhipment area CTSARE 25 1.31
+Causeway CAUSWY 26 1.32
+Caution area CTNARE 27 1.33
+Cemetery CEMTRY 1.34
+Chain/Wire CHNWIR 1.35
+Checkpoint CHKPNT 28 1.36
+Chimney CHIMNY 1.37
+Coastguard station CGUSTA 29 1.38
+Coastline COALNE 30 1.39
+Contiguous zone CONZNE 31 1.40
+Continental shelf area COSARE 32 1.41
+Control point CTRPNT 33 1.42
+Conveyor CONVYR 34 1.43
+Crane CRANES 35 1.44
+Current - non-gravitational CURENT 36 1.45
+Custom zone CUSZNE 37 1.46
+Dam DAMCON 38 1.47
+Daymark DAYMAR 39 1.48
+Deep water route centerline DWRTCL 40 1.49
+Deep water route part DWRTPT 41 1.50
+Depth area DEPARE 42 1.51
+Depth contour DEPCNT 43 1.52
+Diffuser DIFFUS 1.53
+Dish aerial DSHAER 1.54
+Distance mark DISMAR 44 1.55
+Dock area DOCARE 45 1.56
+Dredged area DRGARE 46 1.57
+Dry dock DRYDOC 47 1.58
+Dumping ground DMPGRD 48 1.59
+Dune DUNARE 1.60
+Dyke DYKCON 49 1.61
+Dyke area DYKARE 1.62
+Dyke crown DYKCRW 1.63
+Exclusive economic zone EXEZNE 50 1.64
+Fairway FAIRWY 51 1.65
+Fence/wall FNCLNE 52 1.66
+Ferry route FERYRT 53 1.67
+Fish haven FSHHAV 1.68
+Fishery zone FSHZNE 54 1.69
+Fishing facility FSHFAC 55 1.70
+Fishing ground FSHGRD 56 1.71
+Flagstaff/Flagpole FLGSTF 1.72
+Flare stack FLASTK 1.73
+Floating dock FLODOC 57 1.74
+Fog signal FOGSIG 58 1.75
+Fortified structure FORSTC 59 1.76
+Free port area FRPARE 60 1.77
+Gate GATCON 61 1.78
+Gridiron GRIDRN 62 1.79
+Harbour area (administrative) HRBARE 63 1.80
+Harbour facility HRBFAC 64 1.81
+Hill HILARE 1.82
+Hulk HULKES 65 1.83
+Ice area ICEARE 66 1.84
+Incineration area ICNARE 67 1.85
+Inshore traffic zone ISTZNE 68 1.86
+Intertidal area ITDARE 1.87
+Lake LAKARE 69 1.88
+Lake shore LAKSHR 70 1.89
+Land area LNDARE 71 1.90
+Land elevation LNDELV 72 1.91
+Land region LNDRGN 73 1.92
+Landing place LNDPLC 1.93
+Landing stairs LNDSTS 1.94
+Landmark LNDMRK 74 1.95
+Light LIGHTS 75 1.96
+Light float LITFLT 76 1.97
+Light, moiré effect LITMOI 1.98
+Light vessel LITVES 77 1.99
+Local magnetic anomaly LOCMAG 78 1.100
+Lock basin LOKBSN 79 1.101
+Log pond LOGPON 80 1.102
+Magnetic variation MAGVAR 81 1.103
+Marine farm/culture MARCUL 82 1.104
+Mast MSTCON 1.105
+Military practice area MIPARE 83 1.106
+Monument MONUMT 1.107
+Mooring/Warping facility MORFAC 84 1.108
+National territorial area NATARE 1.109
+Navigation line NAVLNE 85 1.110
+Obstruction OBSTRN 86 1.111
+Offshore platform OFSPLF 87 1.112
+Offshore production area OSPARE 88 1.113
+Oil barrier OILBAR 89 1.114
+Pile PILPNT 90 1.115
+Pilot boarding place PILBOP 91 1.116
+Pingo PINGOS 1.117
+Pipeline area PIPARE 92 1.118
+Pipeline, overhead PIPOHD 93 1.119
+Pipeline, submarine/on land PIPSOL 94 1.120
+Pontoon PONTON 95 1.121
+Precautionary area PRCARE 96 1.122
+Production installation PRDINS 1.123
+Production/storage area PRDARE 97 1.124
+Pylon/bridge support PYLONS 98 1.125
+Radar dome RADDOM 1.126
+Radar line RADLNE 99 1.127
+Radar range RADRNG 100 1.128
+Radar reflector RADRFL 101 1.129
+Radar station RADSTA 102 1.130
+Radar transponder beacon RTPBCN 103 1.131
+Radio calling-in point RDOCAL 104 1.132
+Radio station RDOSTA 105 1.133
+Railway RAILWY 106 1.134
+Ramp RMPARE 1.135
+Rapids RAPIDS 107 1.136
+Recommended route centerline RCRTCL 108 1.137
+Recommended track RECTRC 109 1.138
+Recommended traffic lane part RCTLPT 110 1.139
+Rescue station RSCSTA 111 1.140
+Restricted area RESARE 112 1.141
+Retro-reflector RETRFL 113 1.142
+River RIVERS 114 1.143
+River bank RIVBNK 115 1.144
+Road ROADWY 116 1.145
+Road crossing RODCRS 1.146
+Road part ROADPT 1.147
+Runway RUNWAY 117 1.148
+Salt pan SLTPAN 1.149
+Sand waves SNDWAV 118 1.150
+Sea area/named water area SEAARE 119 1.151
+Sea-plane landing area SPLARE 120 1.152
+Seabed area SBDARE 121 1.153
+Shoreline construction SLCONS 122 1.154
+Signal station, traffic SISTAT 123 1.155
+Signal station, warning SISTAW 124 1.156
+Silo SILBUI 1.157
+Silo/tank SILTNK 125 1.158
+Slipway SLIPWY 1.159
+Slope topline SLOTOP 126 1.160
+Sloping ground SLOGRD 127 1.161
+Small craft facility SMCFAC 128 1.162
+Sounding SOUNDG 129 1.163
+Spoil ground SPOGRD 1.164
+Spring SPRING 130 1.165
+Square SQUARE 131 1.166
+Straight territorial sea baseline STSLNE 132 1.167
+Submarine transit lane SUBTLN 133 1.168
+Swept Area SWPARE 134 1.169
+Tank TNKCON 1.170
+Telepheric TELPHC 1.171
+Territorial sea area TESARE 135 1.172
+Tidal stream - flood/ebb TS_FEB 160 1.173
+Tidal stream - harmonic prediction TS_PRH 136 1.174
+Tidal stream - non-harmonic prediction TS_PNH 137 1.175
+Tidal stream panel data TS_PAD 138 1.176
+Tidal stream - time series TS_TIS 139 1.177
+Tide - harmonic prediction T_HMON 140 1.178
+Tide - non-harmonic prediction T_NHMN 141 1.179
+Tide - time series T_TIMS 142 1.180
+Tideway TIDEWY 143 1.181
+Topmark TOPMAR 144 1.182
+Tower TOWERS 1.183
+Traffic separation line TSELNE 145 1.184
+Traffic separation scheme boundary TSSBND 146 1.185
+Traffic separation scheme crossing TSSCRS 147 1.186
+Traffic separation scheme lane part TSSLPT 148 1.187
+Traffic separation scheme roundabout TSSRON 149 1.188
+Traffic separation zone TSEZNE 150 1.189
+Tree TREPNT 1.190
+Tunnel TUNNEL 151 1.191
+Tunnel entrance TNLENT 1.192
+Two-way route part TWRTPT 152 1.193
+Underwater/awash rock UWTROC 153 1.194
+Unsurveyed area UNSARE 154 1.195
+Vegetation VEGATN 155 1.196
+Vegetation area VEGARE 1.197
+Water turbulence WATTUR 156 1.198
+Waterfall WATFAL 157 1.199
+Weed/Kelp WEDKLP 158 1.200
+Weir WIRLNE 1.201
+Windmill WNDMIL 1.202
+Windmotor WIMCON 1.203
+Wreck WRECKS 159 1.204
+Zero metre - contour ZEMCNT 1.205
+
+1.3 Meta Object Classes 1.207
+Accuracy of data M_ACCY 300 1.208
+Compilation scale of data M_CSCL 301 1.209
+Coverage M_COVR 302 1.210
+Horizontal datum of data M_HDAT 303 1.211
+Horizontal datum shift parameters M_HOPA 304 1.212
+Nautical publication information M_NPUB 305 1.213
+Navigational system of marks M_NSYS 306 1.214
+Production information M_PROD 307 1.215
+Quality of data M_QUAL 308 1.216
+Sounding datum M_SDAT 309 1.217
+Survey reliability M_SREL 310 1.218
+Survey source M_SSOR 1.219
+Units of measurement of data M_UNIT 311 1.220
+Vertical datum of data M_VDAT 312 1.221
+
+1.4 Collection Object Classes 1.223
+Aggregation C_AGGR 400 1.224
+Association C_ASSO 401 1.225
+Stacked on/stacked under C_STAC 402 1.226
+
+1.5 Cartographic Object Classes 1.227
+Cartographic area $AREAS 500 1.228
+Cartographic line $LINES 501 1.229
+Cartographic symbol $CSYMB 502 1.230
+Closing line $CLOLN 1.231
+Compass $COMPS 503 1.232
+Shallow water blue $SHABL 1.233
+Text $TEXTS 504 1.234
+
+
+
+
+
+
+ Page intentionally left blank
+1.1 Introduction
+
+
+Each object class is specified in a standardized way, under the
+following headings:
+
+· Object Class: object class name
+
+· Acronym: six_character code for the object class
+
+· Code: integer code to be used in the coding of data
+
+· For each object class the set of relevant attributes is
+ defined. This set is divided into three subsets:
+
+* subset `Attribute_A': Attributes in this subset define the
+ individual characteristics of an object;
+
+* subset `Attribute_B': Attributes in this subset provide
+ information relevant to the use of the data, e.g. for
+ presentation or for an information system;
+
+* subset `Attribute_C': Attributes in this subset provide
+ administrative information about the object and the data
+ describing it;
+
+Each subset shows a list of ASCII attribute acronyms. For the
+description of each attribute see Chapter 2.
+
+· Definition: Where possible each object class is
+ defined and the source of the definition is quoted.
+
+· References:
+
+* INT 1: reference to the number of the paper chart feature in
+ the `International Chart Series INT 1 _ Symbols,
+ Abbreviations, Terms used on Charts'. INT 1 was one of the
+ major guidelines for the definition of object classes.
+
+* M-4: reference to the paragraph number in the `Chart
+ Specifications of the IHO', publication M-4. This was
+ another guideline used in the definition and description of
+ object classes.
+
+· Remarks: Under `Remarks' further comments and notes
+ are given. Related but separate object classes are listed
+ under the heading `Distinction'.
+
+ 1.2 Geo Object Classes
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Administration Area (Named)
+
+Acronym: ADMARE Code: 1
+Administration Area (Named) ADMARE 1
+
+ Set Attribute_A: JRSDTN; NATION; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A defined (and possibly named) administrative area.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction : land region; contiguous zone; continental shelf
+ area; exclusive economic zone; fishery zone; territorial sea
+ area;
+
+
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Airport/airfield
+
+Acronym: AIRARE Code: 2
+Airport/airfield AIRARE 2
+
+Set Attribute_A: CATAIR; CONDTN; CONVIS; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area containing at least one runway, used for landing, take_off,
+and movement of aircraft.
+
+References:
+
+INT 1: ID 17;
+
+M-4: 366;
+
+Remarks:
+
+Distinction : runway; sea-plane landing area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Anchor
+
+Acronym: ACHPNT
+Anchor ACHPNT
+INT 1 Reference: IQ 42;
+
+Chart Specification: 431.6;
+
+
+Set Attribute_A: DATEND; DATSTA; NOBJNM; OBJNAM; PEREND;
+ PERSTA; QUASOU; STATUS; TECSOU; VALSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A heavy forging or casting comprising a shank with large shackle or
+ring at one end and two arms with palms at the other, so shaped as to
+grip the sea bottom, and by means of a cable or rope hold a vessel,
+boat, or any other floating structure in a desired position regardless
+of wind and current. (International Maritime Dictionary, 2nd Ed.)
+
+
+Remarks:
+
+Distinction: chain/wire;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. An anchor should be encoded as an obstruction (OBSTRN)
+with a category of obstruction (CATOBS) value 9.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Anchor berth
+
+Acronym: ACHBRT Code: 3
+Anchor berth ACHBRT 3
+
+Set Attribute_A: CATACH; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; RADIUS; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A designated area of water where a single vessel, sea plane, etc...
+may anchor.
+
+Reference:
+
+INT 1: IN 11.1_2;
+
+M-4: 431.2;
+
+Remarks:
+
+ In general the anchor berth is defined by the centre
+ point and a swinging circle.
+
+Distinction : anchorage area; berth; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Anchorage area
+
+Acronym: ACHARE Code: 4
+Anchorage area ACHARE 4
+
+Set Attribute_A: CATACH; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area in which vessels anchor or may anchor. (IHO Dictionary, S-32,
+5th Edition, 130)
+
+References:
+
+INT 1: IN 12.1-9;
+
+M-4: 431.3;
+
+Remarks:
+
+Distinction: anchor berth; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Beacon, cardinal
+
+Acronym: BCNCAR Code: 5
+Beacon, cardinal BCNCAR 5
+
+Set Attribute_A: BCNSHP; CATCAM; COLOUR; COLPAT; CONDTN;
+ CONVIS; CONRAD; DATEND; DATSTA; ELEVAT; HEIGHT; MARSYS;
+ NATCON; NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A beacon is a prominent, specially constructed object forming a
+conspicuous mark as a fixed aid to navigation or for use in
+hydrographic survey (IHO Dictionary, S-32, 5th Edition, 420).
+
+A cardinal beacon is used in conjunction with the compass to indicate
+where the mariner may find the best navigable water. It is placed in
+one of the four quadrants (North, East, South and West), bounded by
+inter-cardinal bearings from the point marked. (UKHO NP 735, 5th
+Edition)
+
+References:
+
+INT 1: IQ 130.3;
+
+M-4: 461;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: daymark; beacon lateral; beacon safe water; beacon
+ isolated danger; beacon special purpose/general;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Beacon, isolated danger
+
+Acronym: BCNISD Code: 6
+Beacon, isolated danger BCNISD 6
+
+Set Attribute_A: BCNSHP; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; ELEVAT; HEIGHT; MARSYS; NATCON;
+ NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A beacon is a prominent specially constructed object forming a
+conspicuous mark as a fixed aid to navigation or for use in
+hydrographic survey (IHO Dictionary, S-32, 5th Edition, 420).
+
+An isolated danger beacon is a beacon erected on an isolated danger of
+limited extent, which has navigable water all around it. (UKHO NP735,
+5th Edition)
+
+References:
+
+INT 1: IQ 130.4;
+
+M-4: 463.1;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: daymark; beacon lateral; beacon safe water; beacon
+ cardinal; beacon special purpose/general;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Beacon, lateral
+
+Acronym: BCNLAT Code: 7
+Beacon, lateral BCNLAT 7
+
+Set Attribute_A: BCNSHP; CATLAM; COLOUR; COLPAT; CONDTN;
+ CONRAD; CONVIS; DATEND; DATSTA; ELEVAT; HEIGHT; MARSYS;
+ NATCON; NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A beacon is a prominent specially constructed object forming a
+conspicuous mark as a fixed aid to navigation or for use in
+hydrographic survey (IHO Dictionary, S-32, 5th Edition, 420).
+
+A lateral beacon is used to indicate the port or starboard hand side
+of the route to be followed. They are generally used for well defined
+channels and are used in conjunction with a conventional direction of
+buoyage. (UKHO NP 735, 5th Edition)
+
+References:
+
+INT 1: IQ 91-92, 130.1;
+
+M-4: not specified;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: daymark; beacon cardinal; beacon safe water;
+ beacon isolated danger; beacon special purpose/general;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Beacon, safe water
+
+Acronym: BCNSAW Code: 8
+Beacon, safe water BCNSAW 8
+
+Set Attribute_A: BCNSHP; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; ELEVAT; HEIGHT; MARSYS; NATCON;
+ NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A safe water beacon is a prominent specially constructed object
+forming a conspicuous mark as a fixed aid to navigation or for use in
+hydrographic survey (IHO Dictionary, S-32, 5th Edition, 420).
+
+A safe water beacon may be used to indicate that there is navigable
+water around the mark. (UKHO NP735, 5th Edition)
+
+References:
+
+INT 1: IQ 130.5;
+
+M-4: 456.4;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: daymark; beacon cardinal; beacon lateral; beacon
+ isolated danger; beacon special purpose/general;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Beacon, special purpose/general
+
+Acronym: BCNSPP Code: 9
+Beacon, special purpose/general BCNSPP 9
+
+Set Attribute_A: BCNSHP; CATSPM; COLOUR; COLPAT; CONDTN;
+ CONRAD; CONVIS; DATEND; DATSTA; ELEVAT; HEIGHT; MARSYS;
+ NATCON; NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A beacon is a prominent specially constructed object forming a
+conspicuous mark as a fixed aid to navigation or for use in
+hydrographic survey (IHO Dictionary, S-32, 5th Edition, 420).
+
+A special purpose beacon is primarily used to indicate an area or
+feature, the nature of which is apparent from reference to a chart,
+Sailing Directions or Notices to Mariners. (UKHO NP 735, 5th Edition)
+
+Beacon in general: A beacon whose appearance or purpose is not
+adequately known.
+
+References:
+
+INT 1: IQ 130.6;
+
+M-4: 456.4;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: daymark; beacon lateral; beacon safe water; beacon
+ isolated danger; beacon cardinal; distance mark;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Berth
+
+Acronym: BERTHS Code: 10
+Berth BERTHS 10
+
+Set Attribute_A: DATEND; DATSTA; DRVAL1; NOBJNM; OBJNAM;
+ PEREND; PERSTA; QUASOU; SOUACC; STATUS; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A named or numbered place where a vessel is moored at a wharf. (IHO
+Dictionary, S-32, 5th Edition, 470)
+
+References:
+
+INT 1: IF 19;
+
+M-4: 321.1;
+
+Remarks:
+
+Distinction: anchor berth; dock area; mooring/warping
+ facility; shoreline construction;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Berthing facility
+
+Acronym: BRTFAC
+Berthing facility BRTFAC
+INT 1 Reference: IF 13;
+
+Chart Specification: 321.1;
+
+
+Set Attribute_A: CONDTN; DATEND; DATSTA; NATCON; NOBJNM;
+ OBJNAM; STATUS; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Line; Area;
+
+
+Definition:
+-----------
+
+The designated
+- length along the limit of land area or along a shoreline construction
+_ area at a dolphin
+ where a ship may be tied on and may safely lie.
+
+
+Remarks:
+
+Distinction: dock area;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A berthing facility should be encoded as a berth
+(BERTHS).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Bridge
+
+Acronym: BRIDGE Code: 11
+Bridge BRIDGE 11
+
+Set Attribute_A: CATBRG; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HORACC; HORCLR; NATCON; NOBJNM;
+ OBJNAM;; VERACC; VERCCL; VERCLR; VERCOP; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A structure erected over a depression or an obstacle such as a body of
+water, railroad, etc... to provide a roadway for vehicles, pedestrians
+or to carry utility services. (IHO Dictionary, S-32, 5th Edition, 544)
+
+References:
+
+INT 1: ID 20, 21, 22, 23.1-6, 24;
+
+M-4: 381.1-3;
+
+ Remarks:
+
+A bridge may consist of portions which cover the land and the water.
+
+The bridge supports are encoded as pylon/bridge supports (PYLONS).
+
+Distinction: pylon/bridge support;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Building, religious
+
+Acronym: BUIREL
+Building, religious BUIREL
+INT 1: IE 10.1-10.4, 13-18;
+
+M-4: 373.1-5;
+
+
+Set Attribute_A: BUISHP; CATREB; COLOUR; CONDTN; CONRAD;
+ CONVIS; HEIGHT; NATCON; NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A structure designed for religious use.
+
+
+Remarks:
+
+Distinction: building, single;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A religious building should be encoded as a single
+building (BUISGL) with an appropriate function (FUNCTN) value.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Building, single
+
+Acronym: BUISGL Code: 12
+Building, single BUISGL 12
+
+Set Attribute_A: BUISHP; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; ELEVAT; FUNCTN; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A relatively permanent structure, roofed and usually walled. It is
+designed for some particular use which it may be important to
+indicate. (Digital Geographic Information Working Group, Oct.87)
+
+References:
+
+INT 1: ID 5-6, 13; IE 10.1, 10.3, 11, 13-18, 28-30.1; IF 51,
+ 60-63;
+
+M-4: 325.1-3; 328.1; 362.2; 370.3,5; 372.1; 373.1-4; 375.1,2;
+ 487.3;
+
+Remarks:
+
+This object class is used to encode single buildings, including those
+with a particular function or service of major interest.
+
+Distinction: built-up area; coastguard station; landmark;
+ rescue station;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Built_up area
+
+Acronym: BUAARE Code: 13
+Built_up area BUAARE 13
+
+Set Attribute_A: CATBUA; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NOBJNM; OBJNAM; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area containing a concentration of buildings and the supporting
+road or rail infrastructure.
+
+References:
+
+INT 1: ID 1-4;
+
+M-4: 370.3-4; 370.6-7;
+
+ Remarks:
+
+Distinction: building, single; road; square;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, cardinal
+
+Acronym: BOYCAR Code: 14
+Buoy, cardinal BOYCAR 14
+
+Set Attribute_A: BOYSHP; CATCAM; COLOUR; COLPAT; CONRAD;
+ DATEND; DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND;
+ PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary S-32 5th Edition, 565).
+
+A cardinal buoy is used in conjunction with the compass to indicate
+where the mariner may find the best navigable water. It is placed in
+one of the four quadrants (North, East, South and West), bounded by
+inter-cardinal bearings from the point marked. (UKHO NP 735, 5th
+Edition)
+
+References:
+
+INT 1: IQ 130.3;
+
+M-4: 461; 462.5, 462.6;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: buoy lateral; buoy safe water; buoy isolated
+ danger; buoy special purpose/general; mooring/warping
+ facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, installation
+
+Acronym: BOYINB Code: 15
+Buoy, installation BOYINB 15
+
+Set Attribute_A: BOYSHP; CATINB; COLOUR; COLPAT; CONRAD;
+ DATEND; DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND;
+ PERSTA; PRODCT; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary, S-32, 5th Edition, 565).
+
+An installation buoy is a buoy used for loading tankers with gas or
+oil. (IHO Chart Specifications, M-4)
+
+References:
+
+INT 1: IL 16
+
+M-4: 445.4;
+
+ Remarks:
+
+Distinction: buoy special purpose/general; mooring/warping
+ facility; offshore platform;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, isolated danger
+
+Acronym: BOYISD Code: 16
+Buoy, isolated danger BOYISD 16
+
+Set Attribute_A: BOYSHP; COLOUR; COLPAT; CONRAD; DATEND;
+ DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND; PERSTA;
+ STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary, S-32, 5th Edition, 565).
+
+A isolated danger buoy is a buoy moored on or above an isolated danger
+of limited extent, which has navigable water all around it. (UKHO
+NP735, 5th Edition)
+
+References:
+
+INT 1: IQ 130.4;
+
+M-4: 461;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: buoy lateral; buoy safe water; buoy cardinal; buoy
+ special purpose/general; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, lateral
+
+Acronym: BOYLAT Code: 17
+Buoy, lateral BOYLAT 17
+
+Set Attribute_A: BOYSHP; CATLAM; COLOUR; COLPAT; CONRAD;
+ DATEND; DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND;
+ PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary, S-32, 5th Edition, 565).
+
+A lateral buoy is used to indicate the port or starboard hand side of
+the route to be followed. They are generally used for well defined
+channels and are used in conjunction with a conventional direction of
+buoyage. (UKHO NP 735, 5th Edition)
+
+References:
+
+INT 1: IQ 130.1;
+
+M-4: 461;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: buoy cardinal; buoy safe water; buoy isolated
+ danger; buoy special purpose/general; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, safe water
+
+Acronym: BOYSAW Code: 18
+Buoy, safe water BOYSAW 18
+
+Set Attribute_A: BOYSHP; COLOUR; COLPAT; CONRAD; DATEND;
+ DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND; PERSTA;
+ STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary, S-32, 5th Edition, 565).
+
+A safe water buoy is used to indicate that there is navigable water
+around the mark. (UKHO NP735, 5th Edition)
+
+References:
+
+INT 1: IQ 130.5;
+
+M-4: 461;
+
+Remarks:
+
+A safe water mark may be used as a centerline, mid-channel or landfall
+buoy, or to indicate the best point of passage under a fixed bridge.
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: buoy cardinal; buoy lateral; buoy isolated
+ danger; buoy special purpose/general; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Buoy, special purpose/general
+
+Acronym: BOYSPP Code: 19
+Buoy, special purpose/general BOYSPP 19
+
+Set Attribute_A: BOYSHP; CATSPM; COLOUR; COLPAT; CONRAD;
+ DATEND; DATSTA; MARSYS; NATCON; NOBJNM; OBJNAM; PEREND;
+ PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A buoy is a floating object moored to the bottom in a particular
+place, as an aid to navigation or for other specific purposes. (IHO
+Dictionary, S-32, 5th Edition, 565).
+
+A special purpose buoy is primarily used to indicate an area or
+feature, the nature of which is apparent from reference to a chart,
+Sailing Directions or Notices to Mariners. (UKHO NP 735, 5th Edition)
+
+Buoy in general: A buoy whose appearance or purpose is not adequately
+known.
+
+References:
+
+INT 1: IQ 130.6;
+
+M-4: 461;
+
+Remarks:
+
+Topmark, light, fog signal, radar reflector and retro-reflector are
+separate objects.
+
+Distinction: buoy lateral; buoy safe water; buoy isolated
+ danger; buoy cardinal; buoy installation; mooring/warping
+ facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Cable area
+
+Acronym: CBLARE Code: 20
+Cable area CBLARE 20
+
+Set Attribute_A: CATCBL; DATEND; DATSTA; NOBJNM; OBJNAM;
+ RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area which contains one or more submarine cables.
+
+References:
+
+INT 1: IL 30.2, 31.2
+
+M-4: 439.3; 443.2;
+
+Remarks:
+
+Distinction: cable, overhead; cable, submarine;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Cable, overhead
+
+Acronym: CBLOHD Code: 21
+Cable, overhead CBLOHD 21
+
+Set Attribute_A: CATCBL; CONDTN; CONRAD; CONVIS; DATEND;
+ DATSTA; ICEFAC; NOBJNM; OBJNAM; STATUS; VERACC; VERCLR;
+ VERCSA; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An overhead cable is an assembly of wires or fibres, or a wire rope or
+chain, which is supported by structures such as poles or pylons and
+passing over or nearby navigable waters. (Hydrographic Service, Royal
+Australian Navy).
+
+References:
+
+INT 1: ID 26, 27
+
+M-4: 382; 382.1-2;
+
+Remarks:
+
+The cable supports are encoded as pylon/bridge supports (PYLONS).
+
+Distinction: cable area; cable, submarine; conveyor;
+ pylon/bridge support;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Cable, submarine
+
+Acronym: CBLSUB Code: 22
+Cable, submarine CBLSUB 22
+
+Set Attribute_A: BURDEP; CATCBL; CONDTN; DATEND; DATSTA;
+ DRVAL1; DRVAL2; NOBJNM; OBJNAM; STATUS; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An assembly of wires or fibres, or a wire rope or chain which has
+been laid underwater or buried beneath the seabed (Hydrographic
+Service, Royal Australian Navy)
+
+
+References:
+
+INT 1: IL 30.1, 31.1, 32
+
+M-4: 443.1; 443.3; 443.7;
+
+Remarks:
+
+Distinction: cable, overhead; cable area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Cairn
+
+Acronym: CAIRNS
+Cairn CAIRNS
+INT 1: IQ 100;
+
+M-4: 456.2;
+
+
+Set Attribute_A: COLOUR; COLPAT; CONDTN; CONRAD; CONVIS;
+ DATEND; DATSTA; HEIGHT; NOBJNM; OBJNAM; QUAVEM; STATUS;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A mound of stones, usually conical or pyramidal, raised as a landmark
+or to designate a point of importance in surveying. (IHO Dictionary,
+S-32, 4th Edition)
+
+Remarks:
+
+If a cairn bears the colour(s) specified by a navigational mark
+system, it is to be encoded as a beacon.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A cairn should be encoded as a landmark (LNDMRK) with a
+category of landmark (CATLMK) value 1.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Canal
+
+Acronym: CANALS Code: 23
+Canal CANALS 23
+
+Set Attribute_A: CATCAN; CONDTN; DATEND; DATSTA; HORACC;
+ HORCLR; HORWID; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An artificial waterway with no flow, or a controlled flow, used for
+navigation, or for draining or irrigating land (ditch). (United States
+Geological Survey, Jan.89)
+
+References:
+
+INT 1: IF 40;
+
+M-4: 361.6;
+
+Remarks:
+
+The object `canal' describes the area of the canal, the object `canal
+bank' the banks.
+
+Distinction: canal bank; river; lake; tideway;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Canal bank
+
+Acronym: CANBNK Code: 24
+Canal bank CANBNK 24
+
+Set Attribute_A: CONDTN; DATEND; DATSTA; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The limit line between the water area of a canal and the area of land.
+
+References:
+
+INT 1: IF 40;
+
+M-4: 361.6;
+
+Remarks:
+
+Distinction: canal; coastline; lake shore; river bank;
+ shoreline construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Cargo transhipment area
+
+Acronym: CTSARE Code: 25
+Cargo transhipment area CTSARE 25
+
+Set Attribute_A: DATEND; DATSTA; NOBJNM; OBJNAM; PEREND;
+ PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area designated for the transfer of cargo from one vessel to
+another. (adapted from IHO Dictionary, S-32, 5th Edition, 5593).
+
+References:
+
+INT 1: IN 64;
+
+M-4: 449.4;
+
+ Remarks:
+
+The transhipment of cargo is often known as `lightering' and the area
+may be known as `lightering area' or `cargo transfer area'. (IHO Chart
+Specifications, M-4)
+
+Distinction: dock area; harbour area (administrative); harbour
+ facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Causeway
+
+Acronym: CAUSWY Code: 26
+Causeway CAUSWY 26
+
+Set Attribute_A: CONDTN; NATCON; NOBJNM; OBJNAM; STATUS; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A raised way across low or wet ground or water. (IHO Dictionary, S-32,
+5th Edition, 662)
+
+References:
+
+INT 1: IF 3;
+
+M-4: 313.3;
+
+ Remarks:
+
+Distinction: dam; road;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Caution area
+
+Acronym: CTNARE Code: 27
+Caution area CTNARE 27
+
+Set Attribute_A: DATEND; DATSTA; PEREND; PERSTA;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Generally, an area where the mariner has to be made aware of
+circumstances influencing the safety of navigation.
+
+References:
+
+INT 1: IM 29.2;
+
+M-4: not specified;
+
+Remarks:
+
+This object class may be required to identify:
+
+_ a danger
+_ a risk
+_ a rule
+_ advice
+
+which is not directly related to a specific object.
+
+Distinction: wrecks; underwater rocks; obstructions;
+ unsurveyed area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Cemetery
+
+Acronym: CEMTRY
+Cemetery CEMTRY
+
+Set Attribute_A: CONDTN; CONVIS; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of land for burying the dead with two or more graves. (United
+States Geological Survey, Jan.89)
+
+References:
+
+INT 1: IE 19;
+
+M-4: 373.6;
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A cemetery should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 2.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Chain/Wire
+
+Acronym: CHNWIR
+Chain/Wire CHNWIR
+INT 1: IQ 42;
+
+M-4: 431.6;
+
+
+Set Attribute_A: DATEND; DATSTA; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line;
+
+
+Definition:
+-----------
+
+A connection between two independent objects, e.g.
+ - between an anchor and a mooring buoy
+ _ between an anchor and an offshore platform
+ _ between a hulk and a bollard on land
+ _ etc.
+
+ Remarks:
+
+Distinction: anchor;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A chain/wire should be encoded either as a cable
+(CBLSUB) with a category of cable (CATCBL) value 6, or as a
+mooring/warping facility (MORFAC) with a category of mooring/warping
+facility (CATMOR) value 6.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Checkpoint
+
+Acronym: CHKPNT Code: 28
+Checkpoint CHKPNT 28
+
+Set Attribute_A: CATCHP; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An official place to register, declare or check goods and people.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The object `checkpoint' does not include facilities such as buildings,
+gates or other installations.
+
+Distinction: custom zone;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Chimney
+
+Acronym: CHIMNY
+Chimney CHIMNY
+INT 1: IE 22;
+
+M-4: 374.1;
+
+
+Set Attribute_A: COLOUR; COLPAT; CONDTN; CONRAD; CONVIS;
+ HEIGHT; NATCON; NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A chimney is a vertical structure containing a passage or flue for
+discharging smoke and gases of combustion. (Digital Geographic
+Information Working Group, Oct.87)
+
+Remarks:
+
+Where a chimney carries a light, the light should be encoded as a
+separate object.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A chimney should be encoded as a landmark (LNDMRK) with
+a category of landmark (CATLMK) value 3.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Coastguard station
+
+Acronym: CGUSTA Code: 29
+Coastguard station CGUSTA 29
+
+Set Attribute_A: DATEND; DATSTA; NOBJNM; OBJNAM; PEREND;
+ PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Watch keeping stations at which a watch is kept either continuously,
+or at certain times only. (IHO Chart Specifications, M-4)
+
+References:
+
+INT 1: IT 10;
+
+M-4: 492;
+
+Remarks:
+
+This object class is used to describe the function of the coastguard
+rather than the building in which the coastguard is sited.
+
+Distinction: building, single; rescue station;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Coastline
+
+Acronym: COALNE Code: 30
+Coastline COALNE 30
+
+Set Attribute_A: CATCOA; COLOUR; CONRAD; CONVIS; ELEVAT;
+ NOBJNM; OBJNAM; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The line where shore and water meet. Although the terminology of
+coasts and shores is rather confused, shoreline and coastline are
+generally used as synonyms. (IHO Dictionary, S-32, 5th Edition,
+858,4695)
+
+References:
+
+INT 1: IC 1-8, 32-33;
+
+M-4: 310; 312.1-4;
+
+Remarks:
+
+Distinction: canal bank; lake shore; river bank; shoreline
+ construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Contiguous zone
+
+Acronym: CONZNE Code: 31
+Contiguous zone CONZNE 31
+
+Set Attribute_A: DATEND; DATSTA; NATION; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A zone contiguous to a coastal State's territorial sea, which may not
+extend beyond 24 nautical miles from the baselines from which the
+breadth of the territorial sea is measured. The coastal state may
+exercise certain control in this zone subject to the provisions of
+International Law. (IHO Dictionary, S-32, 5th Edition, 993)
+
+References:
+
+INT 1: IN 44;
+
+M-4: 440.6;
+
+Remarks:
+
+Distinction: administrative area; continental area; exclusive
+ economic zone; fishing zone; territorial sea area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Continental shelf area
+
+Acronym: COSARE Code: 32
+Continental shelf area COSARE 32
+
+Set Attribute_A: NATION; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The continental shelf of a coastal State comprises the sea bed and
+subsoil of the submarine areas that extend beyond its territorial sea
+throughout the natural prolongation of its land territory to the outer
+edge of the continental margin, or to a distance of 200 nautical miles
+from the baselines from which the breadth of the territorial sea is
+measured where the outer edge of the continental margin does not
+extend out to that distance. (IHO Publication S-51)
+
+References:
+
+INT 1: IN 46;
+
+M-4: 440.8;
+
+Remarks:
+
+Distinction: administrative area; contiguous zone; exclusive
+ economic zone; fishery zone; territorial sea area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Control point
+
+Acronym: CTRPNT Code: 33
+Control point CTRPNT 33
+
+Set Attribute_A: CATCTR; DATEND; DATSTA; ELEVAT; NOBJNM;
+ OBJNAM; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A point on the ground where position (horizontal and vertical) is used
+as a base for a dependent survey. Also referred to as a control
+station. (IHO Dictionary, S-32, 5th Edition, 1026)
+
+References:
+
+INT 1: IB 20-24;
+
+M-4: 304.1-3; 305.1; 306;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Conveyor
+
+Acronym: CONVYR Code: 34
+Conveyor CONVYR 34
+
+Set Attribute_A: CATCON; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HEIGHT; LIFCAP; NOBJNM; OBJNAM;
+ PRODCT; STATUS; VERACC; VERCLR; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A mechanical apparatus for moving bulk material or people from place
+to place (as by a moving belt or chain of receptacles).
+
+References:
+
+INT 1: ID25;
+
+M-4: 382.3;
+
+Remarks:
+
+The conveyor supports are encoded as pylon/bridge supports (PYLONS).
+
+Distinction: cable, overhead; pylon/bridge support;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Crane
+
+Acronym: CRANES Code: 35
+Crane CRANES 35
+
+Set Attribute_A: CATCRN; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; HEIGHT; LIFCAP; NOBJNM; OBJNAM; ORIENT; RADIUS;
+ STATUS; VERACC; VERCLR; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A machine for lifting, shifting and lowering objects or materials by
+means of a swinging boom or with a lifting apparatus supported on an
+overhead track. (Digital Geographic Information Working Group, Oct.87)
+
+References:
+
+INT 1: IF 53.1-3;
+
+M-4: 328.3;
+
+Remarks:
+
+The position of a sheerlegs or a travelling crane is defined as its
+resting position.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Current - non-gravitational
+
+Acronym: CURENT Code: 36
+Current - non-gravitational CURENT
+
+Set Attribute_A: CURVEL; DATEND; DATSTA; NOBJNM; OBJNAM;
+ ORIENT; PEREND; PERSTA;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Currents (non-gravitational) include either singly or in combination:
+ocean currents (wind and/or density driven), inter-oceanic equalising
+currents, currents of navigable rivers, river outflow effects offshore
+and other non-tidal flows.
+
+References:
+
+INT 1: IH 42-43;
+
+M-4: 408.2-3;
+
+Remarks:
+
+Distinction: tidal stream - harmonic prediction; tidal stream -
+ non-harmonic prediction; tidal stream panel data; tidal stream
+ - time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Custom zone
+
+Acronym: CUSZNE Code: 37
+Custom zone CUSZNE 37
+
+Set Attribute_A: NATION;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The area within which national custom regulations are in force.
+
+References:
+
+INT 1: IN 48;
+
+M-4: 440.2;
+
+Remarks:
+
+Distinction: check point; free port area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dam
+
+Acronym: DAMCON Code: 38
+Dam DAMCON 38
+
+Set Attribute_A: CATDAM; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A barrier to check or confine anything in motion; particularly one
+constructed to hold back water and raise its level to form a
+reservoir, or to prevent flooding. (IHO Dictionary, S-32, 5th Edition,
+1196)
+
+References:
+
+INT 1: IF 44
+
+M-4: 364.2;
+
+Remarks:
+
+Distinction: causeway; dyke; road;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Daymark
+
+Acronym: DAYMAR Code: 39
+Daymark DAYMAR 39
+
+Set Attribute_A: CATSPM; COLOUR; COLPAT; DATEND; DATSTA;
+ ELEVAT; HEIGHT; NATCON; NOBJNM; OBJNAM; PEREND; PERSTA;
+ STATUS; TOPSHP; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The identifying characteristics of an aid to navigation which serve to
+facilitate its recognition against a daylight viewing background. On
+those structures that do not by themselves present an adequate viewing
+area to be seen at the required distance, the aid is made more visible
+by affixing a daymark to the structure. A daymark so affixed has a
+distinctive colour and shape depending on the purpose of the aid. (IHO
+Dictionary, S-32, 5th Edition, 1248)
+
+References:
+
+INT 1: IQ 101;
+
+M-4: 456.2;
+
+Remarks:
+
+Distinction: beacon, lateral; beacon, safe water; beacon,
+ isolated danger; beacon, cardinal; beacon special
+ purpose/general; topmark;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Deep water route centerline
+
+Acronym: DWRTCL Code: 40
+Deep water route centerline DWRTCL 40
+
+Set Attribute_A: CATTRK; DATEND; DATSTA; DRVAL1; DRVAL2;
+ NOBJNM; OBJNAM; ORIENT; QUASOU; SOUACC; STATUS; TECSOU;
+ TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A deep water route is a route in a designated area, within defined
+limits, which has been accurately surveyed for clearance of sea bottom
+and submerged obstacles to a minimum indicated depth of water. (IHO
+Dictionary, S-32, 5th Edition, 1280)
+
+The deep water route centerline indicates the centerline of a route,
+the width of which is not explicitly defined.
+
+References:
+
+INT 1: IM 27.3;
+
+M-4: 435.3;
+
+Remarks:
+
+Additional information can be found in IHO Technical Resolution A1.17.
+
+Distinction: deep water route part;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Deep water route part
+
+Acronym: DWRTPT Code: 41
+Deep water route part DWRTPT 41
+
+Set Attribute_A: DATEND; DATSTA; DRVAL1; DRVAL2; NOBJNM;
+ OBJNAM; ORIENT; QUASOU; RESTRN; SOUACC; STATUS; TECSOU;
+ TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A deep water route is a route in a designated area, within defined
+limits, which has been accurately surveyed for clearance of sea bottom
+and submerged obstacles to a minimum indicated depth of water. (IHO
+Dictionary, S-32, 5th Edition, 1280)
+
+References:
+
+INT 1: IM 27.1_2;
+
+M-4: 435, 435.3; 436.3;
+
+Remarks:
+
+The complete deep water route consists of one or more parts depending
+on the shape of the deep water route.
+
+The orientation of the route part is defined by the middle line of the
+part relating to the general direction of the deep water route.
+
+Additional information can be found in IHO Technical Resolution A1.17.
+
+Distinction: deep water route centerline; two way route part;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Depth area
+
+Acronym: DEPARE Code: 42
+Depth area DEPARE 42
+
+Set Attribute_A: DRVAL1; DRVAL2; QUASOU; SOUACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A depth area is a water area whose depth is within a defined range of
+values.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Intertidal areas are encoded as depth areas. These do not have to
+include soundings.
+
+The depth range within a depth area is defined by the attributes
+`DRVAL1' and `DRVAL2'.
+
+Distinction: depth contour; dredged area; sounding;
+ obstruction; sea area/named water area; unsurveyed area;
+ wreck;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Depth contour
+
+Acronym: DEPCNT Code: 43
+Depth contour DEPCNT 43
+
+Set Attribute_A: VALDCO; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A line connecting points of equal water depth which is sometimes
+significantly displaced outside of soundings, symbols and other chart
+detail for clarity as well as generalization. Depth contours,
+therefore, often represent an approximate location of the line of
+equal depth as related to the surveyed line delineated on the source.
+Also referred to as depth curve. (IHO Dictionary, S-32, 5th Edition,
+1314, 1315)
+
+References:
+
+INT 1: II 15, 30, 31;
+
+M-4: 404.2; 410; 411, 411.2; 413-413.2;
+
+Remarks:
+
+Drying contours are encoded with negative values.
+
+Distinction: sounding; depth area; coastline;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Diffuser
+
+Acronym: DIFFUS
+Diffuser DIFFUS
+INT 1: IL 43;
+
+M-4: not specified
+
+
+Set Attribute_A: CONDTN; DATEND; DATSTA; EXPSOU; PRODCT;
+ QUASOU; SOUACC; TECSOU; VALSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+An artificial installation at or below water level, where liquids
+(e.g. cooling water, spillage) are spread out.
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A diffuser should be encoded as an obstruction (OBSTRN)
+with a category of obstruction (CATOBS) value 3.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Dish aerial
+
+Acronym: DSHAER
+Dish aerial DSHAER
+INT 1: IE 31;
+
+M-4: 375.4;
+
+
+Set Attribute_A: COLOUR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A parabolic aerial for the receipt and transmission of high frequency
+radio signals. (IHO Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A dish aerial should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 4.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Distance mark
+
+Acronym: DISMAR Code: 44
+Distance mark DISMAR 44
+
+Set Attribute_A: CATDIS; DATEND; DATSTA; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A distance mark indicates the distance measured from an origin and
+consists of either a solid visible structure or a distinct location
+without special installation. Usually found on canals.
+
+References:
+
+INT 1: IF 40;
+
+M-4: 361.3; 307;
+
+Remarks:
+
+Distinction: beacon, special purpose;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dock area
+
+Acronym: DOCARE Code: 45
+Dock area DOCARE 45
+
+Set Attribute_A: CATDOC; CONDTN; DATEND; DATSTA; HORACC;
+ HORCLR; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A dock is an artificially enclosed area within which ships may moor
+and which may have gates to regulate water level (adapted from IHO
+Chart Specifications, M-4).
+
+Reference:
+
+INT 1: IF 27,28;
+
+M-4: 326.3-4;
+
+Remarks:
+
+Distinction: harbour area (administrative); cargo transhipment
+ area; berth; harbour facility; gate; floating dock; dry dock;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dredged area
+
+Acronym: DRGARE Code: 46
+Dredged area DRGARE 46
+
+Set Attribute_A: DRVAL1; DRVAL2; NOBJNM; OBJNAM; QUASOU;
+ RESTRN; SOUACC; TECSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of the bottom of a body of water which has been deepened by
+dredging. (IHO Dictionary, S-32, 5th Edition, 1462)
+
+References:
+
+INT 1: II 20-23;
+
+M-4: 414.1-2; 414.4;
+
+Remarks:
+
+Distinction: depth area; dumping ground; swept area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dry dock
+
+Acronym: DRYDOC Code: 47
+Dry dock DRYDOC 47
+
+Set Attribute_A: CONDTN; DRVAL1; HORACC; HORCLR; HORLEN;
+ HORWID; NOBJNM; OBJNAM; QUASOU; SOUACC; STATUS; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An artificial basin fitted with a gate or caisson, into which vessels
+can be floated and the water pumped out to expose the vessel's
+bottom. Also called graving dock. (IHO Dictionary, S-32, 5th Edition,
+1426)
+
+Remarks:
+
+INT 1: IF 25;
+
+M-4: 326.1;
+
+Distinction: floating dock; gate; dock area; shoreline
+ construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dumping ground
+
+Acronym: DMPGRD Code: 48
+Dumping ground DMPGRD 48
+
+Set Attribute_A: CATDPG; NOBJNM; OBJNAM; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A sea area where dredged material or other potentially more harmful
+material, e.g. explosives, chemical waste, is deliberately deposited.
+(Derived from IHO Chart Specifications, M-4).
+
+References:
+
+INT 1: IN 23-24, 62.1-2;
+
+M-4: 442.1-4; 446a;
+
+Remarks:
+
+ Distinction: dredged area; incineration area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Dune
+
+Acronym: DUNARE
+Dune DUNARE
+
+Set Attribute_A: COLOUR; CONRAD; CONVIS; HEIGHT; NATSUR;
+ NATQUA; NOBJNM; OBJNAM; QUAVEM; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A mound, ridge or hill of drifted material on the sea coast or in a
+desert. (IHO Dictionary, S-32, 4th Edition)
+
+References:
+
+INT 1: IC 8;
+
+M-4: 312.3;
+
+Remarks:
+
+Distinction: sand waves;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A dune should be encoded as sloping ground (SLOGRD)
+with a category of slope (CATSLO) value 3.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Dyke
+
+Acronym: DYKCON Code: 49
+Dyke DYKCON 49
+
+Set Attribute_A: CONDTN; CONRAD; DATEND; DATSTA; HEIGHT;
+ NATCON; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A dyke (or dike) is an artificial embankment to contain or hold back
+water.(IHO Dictionary, S-32, 5th Edition, 1361)
+
+References:
+
+INT 1: IF 1;
+
+M-4: 313.1;
+
+ Remarks:
+
+Distinction: dam; sloping ground; slope top line;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Dyke area
+
+Acronym: DYKARE
+Dyke area DYKARE
+INT 1 Reference: IF 1;
+
+Chart Specification: 313.1;
+
+Set Attribute_A: CATDYK; CONDTN; NATCON;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+Geometric Primitive: Area;
+
+Definition:
+-----------
+
+A dyke (or dike) is an artificial embankment to contain or hold back
+water. (IHO Dictionary, S-32, 4th Edition)
+
+The dyke area is the base of the dyke.
+
+Remarks:
+
+A system of winter and summer dykes may form an area of polder or koog.
+
+It is necessary to record the dyke base as an area for a complete
+two-dimensional description of reality.
+
+Distinction: dam; dyke crown;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A dyke area should be encoded as a dyke (DYKCON).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Dyke crown
+
+Acronym: DYKCRW
+Dyke crown DYKCRW
+INT 1: IF 1;
+
+M-4: 313.1;
+
+
+Set Attribute_A: CATDYK; CONDTN; CONRAD; NATCON; NOBJNM;
+ OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line;
+
+
+Definition:
+-----------
+
+A dyke (or dike) is an artificial embankment to contain or hold back
+water.
+(IHO Dictionary, S-32, 4th Edition)
+
+The dyke crown is the top line of the dyke.
+
+ Remarks:
+
+A system of winter and summer dykes may form an area of polder or koog.
+
+The dyke crown records the third dimension of the dyke. Only the crown
+of the dyke construction is relevant to Radar.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A dyke crown should be encoded as a slope top line
+(SLOTOP).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Exclusive economic zone
+
+Acronym: EXEZNE Code: 50
+Exclusive economic zone EXEZNE 50
+
+Set Attribute_A: NATION;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area, not exceeding 200 nautical miles from the baselines from
+which the breadth of the territorial sea is measured, subject to a
+specific legal regime established in the United Nations Convention on
+the Law of the Sea under which the coastal state has certain rights
+and jurisdiction. (IHO Dictionary, S-32, 5th Edition, 1723)
+
+References:
+
+INT 1: IN 47;
+
+M-4: 440.9;
+
+Remarks:
+
+Distinction: administrative area; contiguous zone; continental
+ shelf area; fishery zone; territorial sea area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fairway
+
+Acronym: FAIRWY Code: 51
+Fairway FAIRWY 51
+
+Set Attribute_A: DATEND; DATSTA; DRVAL1; NOBJNM; OBJNAM;
+ ORIENT; QUASOU; RESTRN; SOUACC; STATUS; TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+That part of a river, harbour and so on, where the main navigable
+channel for vessels of larger size lies. It is also the usual course
+followed by vessels entering or leaving harbours, called `ship
+channel'. (International Maritime Dictionary, 2nd Ed.)
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: deep water route centerline; deep water route
+ part; traffic separation scheme lane part;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fence/wall
+
+Acronym: FNCLNE Code: 52
+Fenceline FNCLNE 52
+
+
+Set Attribute_A: CATFNC; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; ELEVAT; HEIGHT; NATCON; NOBJNM; OBJNAM; STATUS;
+ VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+Definition:
+-----------
+
+A natural or man_made barrier used as an enclosure or boundary or for
+protection. (adapted from Didital Geographic Information Working
+Group, Oct.1987)
+
+References:
+
+INT 1: not specified
+
+M-4: not specified
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Ferry route
+
+Acronym: FERYRT Code: 53
+Ferry route FERYRT 53
+
+Set Attribute_A: CATFRY; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A route in a body of water where a ferry crosses from one shoreline to
+another. (Digital Geographic Information Working Group, Oct.87)
+
+References:
+
+INT 1: IM 50, 51;
+
+M-4: 438.1, 438.2;
+
+Remarks:
+
+No remarks
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Fish haven
+
+Acronym: FSHHAV
+Fish haven FSHHAV
+
+Set Attribute_A: EXPSOU; NOBJNM; OBJNAM; QUASOU; TECSOU;
+ VALSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Areas established by private interests, usually sport fishermen, to
+simulate natural reefs and wrecks that attract fish. The reefs are
+constructed by dumping assorted junk in areas which may be of very
+small extent or may stretch considerable distance along a depth
+contour. Also called fishery reefs. (IHO Dictionary, S-32, 5th
+Edition, 1812).
+
+References:
+
+INT 1: IK 46.1-2;
+
+M-4: 447.5;
+
+
+Remarks:
+
+Distinction: fishing facility; marine farm/culture;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A fish haven should be encoded as an obstruction
+(OBSTRN) with a category of obstruction (CATOBS) value 5.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fishery zone
+
+Acronym: FSHZNE Code: 54
+Fishery zone FSHZNE 54
+
+Set Attribute_A: NATION; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The offshore zone in which exclusive fishing rights and management are
+held by the coastal nation. (IHO Dictionary, S-32, 5th Edition, 1816)
+
+References:
+
+INT 1: IN 45;
+
+M-4: 440.7;
+
+Remarks:
+
+The fishery zone commonly coincides with other zones such as:
+ _ Continental Shelf
+ _ Exclusive Economic Zone.
+
+Distinction: administrative area; contiguous zone; continental
+ shelf area; exclusive economic zone; fishing ground;
+ restricted area; territorial sea area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fishing facility
+
+Acronym: FSHFAC Code: 55
+Fishing facility FSHFAC 55
+
+Set Attribute_A: CATFIF; NOBJNM; OBJNAM; PEREND; PERSTA;
+ STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A structure in shallow water for fishing purposes which can be an
+obstruction to ships in general. The position of these structures may
+vary frequently over time.
+
+References:
+
+INT 1: IK 44.1-2, 45;
+
+M-4: 447.1-3;
+
+Remarks:
+
+Distinction: marine farm/culture; obstruction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fishing ground
+
+Acronym: FSHGRD Code: 56
+Fishing ground FSHGRD 56
+
+Set Attribute_A: NOBJNM; OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A water area in which fishing is frequently carried on. (IHO
+Dictionary, S-32, 5th Edition, 1814)
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: fishery zone;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Flagstaff/Flagpole
+
+Acronym: FLGSTF
+Flagstaff/Flagpole FLGSTF
+INT 1: IE 27;
+
+M-4: 374.7;
+
+
+Set Attribute_A: COLOUR; CONRAD; CONVIS; HEIGHT; NOBJNM; OBJNAM;
+QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A pole on which a flag is hoisted and displayed. (International
+Maritime Dictionary, 2nd Ed.)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A flagstaff should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 5.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Flare stack
+
+Acronym: FLASTK
+Flare stack FLASTK
+INT 1: IE 23; IL 11;
+
+M-4: 374,1; 445,6;
+
+
+Set Attribute_A: COLOUR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NATCON; NOBJNM; OBJNAM; QUAVEM; STATUS; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A tall structure used for burning-off waste oil or gas. (IHO
+Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+A Flare stack is generally located at refineries or at other
+production installations and it is normally showing a flame.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A flare stack should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 6.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Floating dock
+
+Acronym: FLODOC Code: 57
+Floating dock FLODOC 57
+
+Set Attribute_A: COLOUR; COLPAT; CONDTN; CONRAD; CONVIS;
+ DATEND; DATSTA; DRVAL1; HORACC; HORCLR; HORLEN; HORWID;
+ LIFCAP; NOBJNM; OBJNAM; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A form of dry dock consisting of a floating structure of one or more
+sections which can be partly submerged by controlled flooding to
+receive a vessel, then raised by pumping out the water so that the
+vessel's bottom can be exposed. (IHO Dictionary, S-32, 5th Edition,
+1427)
+
+References:
+
+INT 1: IF 26
+
+M-4: 326.2;
+
+Remarks:
+
+Distinction: dry dock; dock area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fog signal
+
+Acronym: FOGSIG Code: 58
+Fog signal FOGSIG 58
+
+Set Attribute_A: CATFOG; DATEND; DATSTA; NOBJNM; OBJNAM;
+ SIGFRQ; SIGGEN; SIGGRP; SIGPER; SIGSEQ; STATUS; VALMXR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A warning signal transmitted by a vessel, or aid to navigation,
+during periods of low visibility. Also, the device producing such a
+signal. (IHO Dictionary, S-32, 5th Edition, 1890)
+
+References:
+
+INT 1: IR 1, 10-16, 20-22;
+
+M-4: 452-452.8;
+
+Remarks:
+
+Distinction: signal station, warning;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Fortified structure
+
+Acronym: FORSTC Code: 59
+Fortified structure FORSTC 59
+
+Set Attribute_A: CATFOR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NATCON; NOBJNM; OBJNAM; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A structure for the military defence of a site.
+
+References:
+
+INT 1: IE 34.1-3;
+
+M-4: 379.1-2;
+
+Remarks:
+
+A fortified structure is often disused, decayed or used for
+non_defence purpose. Such structures range from major castles and
+forts to minor lookout posts. (IHO Chart Specifications, M-4)
+
+Distinction: building single;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Free port area
+
+Acronym: FRPARE Code: 60
+Free port area FRPARE 60
+
+Set Attribute_A: NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A port where certain import and export duties are waived (unless goods
+pass into the country) to facilitate reshipment to other countries.
+(IHO Dictionary, S-32, 5th Edition, 1927)
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: custom zone; production/storage area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Gate
+
+Acronym: GATCON Code: 61
+Gate GATCON 61
+
+Set Attribute_A: CATGAT; CONDTN; DRVAL1; HORACC; HORCLR;
+ NATCON; NOBJNM; OBJNAM; QUASOU; SOUACC; STATUS; VERACC;
+ VERCLR; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A structure that may be swung, drawn, or lowered to block an entrance
+or passageway. (United States Geological Survey, Jan.89)
+
+References:
+
+INT 1: IF 27, 41.1-2, 42-43;
+
+M-4: 326.3; 326.5; 326.6; 326.7;
+
+Remarks:
+
+This object class is used to encode gates that control the flow of
+water.
+
+Distinction: dry dock; floating dock;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Gridiron
+
+Acronym: GRIDRN Code: 62
+Gridiron GRIDRN 62
+
+Set Attribute_A: HORACC; HORLEN; HORWID; NATCON; NOBJNM;
+ OBJNAM; STATUS; VERACC; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A timber structure in the intertidal zone serving as a support for
+vessels at low stages of the tide to permit work on the exposed
+portion of the vessel's hull. Also called careening grid.
+(adapted from IHO Dictionary, S-32, 5th Edition, 649)
+
+References:
+
+INT 1: IF 24;
+
+M-4: 326.8;
+
+Remarks:
+
+No remarks
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Harbour area (administrative)
+
+Acronym: HRBARE Code: 63
+Harbour area (administrative) HRBARE 63
+
+Set Attribute_A: NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The area over which a harbour authority has jurisdiction.
+
+References:
+
+INT 1: IN 49;
+
+M-4: 430.1;
+
+Remarks:
+
+Distinction: dock area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Harbour facility
+
+Acronym: HRBFAC Code: 64
+Harbour facility HRBFAC 64
+
+Set Attribute_A: CATHAF; CONDTN; DATEND; DATSTA; NATCON;
+ NOBJNM; OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A harbour installation with a service or commercial operation of
+public interest.
+
+References:
+
+INT 1: IF 10, 50; IU 1.1,
+
+M-4: 320.1-2; 321.5; 328.2;
+
+Remarks:
+
+Distinction: small craft facility;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Hill
+
+Acronym: HILARE
+Hill HILARE
+INT 1: IC 4;
+
+M-4: 312.1;
+
+
+Set Attribute_A: CONRAD; CONVIS; HEIGHT; NATQUA; NATSUR;
+ NOBJNM; OBJNAM; QUAVEM; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Area;
+
+
+Definition:
+-----------
+
+A small isolated elevation, smaller than a mountain. (IHO Dictionary,
+S-32, 4th Edition)
+
+Remarks:
+
+Distinction: dune;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A hill should be encoded as sloping ground (SLOGRD)
+with a category of slope (CATSLO) value 4.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Hulk
+
+Acronym: HULKES Code: 65
+Hulk HULKES 65
+
+Set Attribute_A: CATHLK; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; HORACC; HORLEN; HORWID; NOBJNM; OBJNAM; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A permanently moored ship.
+
+References:
+
+INT 1: IF 34;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: wreck;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Ice area
+
+Acronym: ICEARE Code: 66
+Ice area ICEARE 66
+
+Set Attribute_A: CATICE; CONVIS; ELEVAT; HEIGHT; NOBJNM;
+ OBJNAM; PEREND; PERSTA; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of ice over land or water.
+
+References:
+
+INT 1: IC 25; IN 60.1-2;
+
+M-4: 353.8; 449.1;
+
+Remarks:
+
+Distinction: depth area; land area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Incineration area
+
+Acronym: ICNARE Code: 67
+Incineration area ICNARE 67
+
+Set Attribute_A: NOBJNM; OBJNAM; PEREND; PERSTA; RESTRN;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An offshore area officially designated as suitable for the burning of
+chemical waste by specially equipped ships. (IHO Dictionary, S-32, 5th
+Edition, 2408)
+
+References:
+
+INT 1: IN 65;
+
+M-4: 449.3;
+
+Remarks:
+
+Distinction: dumping ground;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Inshore traffic zone
+
+Acronym: ISTZNE Code: 68
+Inshore traffic zone ISTZNE 68
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A routeing measure comprising a designated area between the landward
+boundary of a traffic separation scheme and the adjacent coast, to be
+used in accordance with the provisions of the International
+Regulations for Preventing Collisions at Sea. (IHO Dictionary, S-32,
+5th Edition, 2457)
+
+References:
+
+INT 1: IM 25.1;
+
+M-4: 435.1;
+
+Remarks:
+
+Distinction: traffic separation scheme crossing; traffic
+ separation scheme lane part; traffic separation scheme
+ roundabout; traffic separation zone; precautionary area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Intertidal area
+
+Acronym: ITDARE
+Intertidal area ITDARE
+INT 1: IJ 20 _ 22;
+
+M-4: 426.1 _ 3;
+
+
+Set Attribute_A: NATQUA; NATSUR; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Line; Area;
+
+
+Definition:
+-----------
+
+An intertidal zone is the zone generally considered to be between mean
+high water and mean low water levels. (IHO Dictionary, S-32, 4th
+Edition)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. Intertidal areas should be coded as depth areas
+(DEPARE) with negative DRVAL1 and DRVAL2 attributes. The bottom
+characteristics of intertidal areas should be coded as sea bed areas
+(SBDARE) using the attribute nature of surface (NATSUR) and qualifying
+terms of nature of surface (NATQUA).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Lake
+
+Acronym: LAKARE Code: 69
+Lake LAKARE 69
+
+Set Attribute_A: ELEVAT; NOBJNM; OBJNAM; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A large body of water entirely surrounded by land. (IHO
+Dictionary, S-32, 5th Edition, 2629)
+
+References:
+
+INT 1: IC 23;
+
+M-4: 353.6;
+
+Remarks:
+
+Distinction: canal; depth area; lake shore; river;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Lake shore
+
+Acronym: LAKSHR Code: 70
+Lake shore LAKSHR 70
+
+Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The limit line between the water area of a lake and the area of land.
+
+References:
+
+INT 1: IC 23;
+
+M-4: 353, 353.6;
+
+Remarks:
+
+Distinction: canal bank; coastline; lake area; river bank;
+ shoreline construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Land area
+
+Acronym: LNDARE Code: 71
+Land area LNDARE 71
+
+ Set Attribute_A: CONDTN; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The solid portion of the Earth's surface, as opposed to sea, water.
+(IHO Dictionary, S-32, 5th Edition, 2635)
+
+References:
+
+INT 1: IK 10;
+
+M-4: 421.1;
+
+Remarks:
+
+Distinction: canal; coastline; depth area; lake; land region;
+ river; sea bed area; shoreline construction; vegetation;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Land elevation
+
+Acronym: LNDELV Code: 72
+Land elevation LNDELV 72
+
+Set Attribute_A: CONVIS; ELEVAT; NOBJNM; OBJNAM; VERACC;
+ VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An elevation is the vertical distance of a point or a level, on, or
+affixed to, the surface of the earth, measured from a specified
+vertical datum. (IHO Dictionary, S-32, 5th Edition, 1590)
+
+References:
+
+INT 1: IC 10-13;
+
+M-4: 351; 352.1_2;
+
+Remarks:
+
+This object class is used to encode both spot heights and land
+(height) contours.
+
+Distinction: slope top line;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Land region
+
+Acronym: LNDRGN Code: 73
+Land region LNDRGN 73
+
+Set Attribute_A: CATLND; NATQUA; NATSUR; NOBJNM; OBJNAM;
+ WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of natural scenery on land. It is defined by its geographical
+characteristics and may be known by its proper name.
+
+References:
+
+INT 1: IC 24, 26, 33;
+
+M-4: 312.1-4; 355;
+
+Remarks:
+
+Distinction: sea area; land area; vegetation;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Landing place
+
+Acronym: LNDPLC
+Landing place LNDPLC
+
+Set Attribute_A: CONDTN; NATCON; NOBJNM; OBJNAM; STATUS;
+ WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A landing is a place where boats receive or discharge passengers,
+freight, etc.. (IHO Dictionary, S-32, 4th Edition)
+
+References:
+
+INT 1: IF 17;
+
+M-4: 324.2;
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A landing place should be encoded as a small craft
+facility (SMCFAC) with a category of small craft facility (CATSCF)
+value 28.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Landing stairs
+
+Acronym: LNDSTS
+Landing stairs LNDSTS
+
+Set Attribute_A: CONDTN; NATCON; QUAVEM; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Steps at the shoreline as the connection between land and water on
+different levels.
+
+References:
+
+INT 1: IF 18
+
+M-4: not specified
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. Landing stairs should be encoded as a shoreline
+construction (SLCONS) with a category of shoreline construction
+(CATSLC) value 11.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Landmark
+
+Acronym: LNDMRK Code: 74
+Landmark LNDMRK 74
+
+Set Attribute_A: CATLMK; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; ELEVAT; FUNCTN; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A prominent object at a fixed location which can be used in
+determining a location or a direction. (adapted from IHO Dictionary,
+S-32, 5th Edition, 2643).
+
+References:
+
+INT 1: ID 5-6, 13; IE 10.1-20, 22-30.1, 30.3-4, 31; IL 11; IQ
+ 100;
+
+M-4: 373.6; 374.1; 374.4; 374.5; 374.6; 374.7; 375.1-2; 375.4;
+ 445.6; 456.2; 487.3;
+
+Remarks:
+
+Distinction: beacon, special purpose/general; building single;
+ daymark; pylon/bridge support; topmark;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Light
+
+Acronym: LIGHTS Code: 75
+Light LIGHTS 75
+
+Set Attribute_A: CATLIT; COLOUR; DATEND; DATSTA; EXCLIT;
+ HEIGHT; LITCHR; LITVIS; MARSYS; MLTYLT; NOBJNM; OBJNAM;
+ ORIENT; PEREND; PERSTA; SECTR1; SECTR2; SIGGRP; SIGPER;
+ SIGSEQ; STATUS; VERACC; VALNMR; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A luminous or lighted aid to navigation. (adapted from IHO Dictionary,
+S-32, 5th Edition, 2766)
+
+References:
+
+INT 1: IP 1-30.3, 40-65;
+
+M-4: 470-473.5; 475-475.7; 476-478,5;
+
+Remarks:
+
+A light may be fixed on a buoy, beacon, tower etc. These are separate
+objects.
+
+Distinction: beacon, cardinal; beacon, isolated danger;
+ beacon, lateral; beacon, safe water; beacon special
+ purpose/general; buoy, cardinal; buoy, installation; buoy,
+ isolated danger; buoy, lateral; buoy, safe water; buoy,
+ special purpose/general; light vessel; light float;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Light float
+
+Acronym: LITFLT Code: 76
+Light float LITFLT 76
+
+Set Attribute_A: COLOUR; COLPAT; CONRAD; CONVIS; DATEND;
+ DATSTA; HORACC; HORLEN; HORWID; NATCON; NOBJNM; OBJNAM;
+ PEREND; PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A boat-like structure used instead of a light buoy in waters where
+strong streams or currents are experienced, or when a greater
+elevation than that of a light buoy is necessary (IHO Dictionary,
+S-32, 5th Edition, 2821).
+
+References:
+
+INT 1: IQ 30-31;
+
+M-4: 462.8;
+
+Remarks:
+
+The light of a light float is a separate object, handled as with
+buoys, beacons, etc.
+
+Distinction: buoy, cardinal; buoy, installation; buoy,
+ isolated danger; buoy, lateral; buoy, safe water; buoy,
+ special purpose/general; light vessel;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Light, moiré effect
+
+Acronym: LITMOI
+Light, moiré effect LITMOI
+INT 1: IP 31;
+
+M-4: 475.8;
+
+
+Set Attribute_A: COLOUR; DATEND; DATSTA; HEIGHT; NOBJNM;
+ OBJNAM; ORIENT; PEREND; PERSTA; QUAVEM; STATUS; VALNMR; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+The moiré effect is the effect created by transmitting light through
+two separate, overlapping families of parallel lines. (IHO Dictionary,
+S-32, 4th Edition)
+
+Remarks:
+
+The attribute `orientation' indicates the orientation of the leading
+line of the moiré effect light measured from the water towards the
+light.
+
+Distinction: light;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A moiré effect light should be encoded as a light
+(LIGHTS) with a category of light (CATLIT) value 16.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Light vessel
+
+Acronym: LITVES Code: 77
+Light vessel LITVES 77
+
+Set Attribute_A: COLOUR; COLPAT; CONRAD; CONVIS; DATEND;
+ DATSTA; HORACC; HORLEN; HORWID; NATCON; NOBJNM; OBJNAM;
+ PEREND; PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A distinctively marked vessel anchored or moored at a charted point,
+to serve as an aid to navigation. By night, it displays a
+characteristic light(s) and is usually equipped with other devices,
+such as fog signal, submarine sound signal, and radio-beacon, to
+assist navigation. Also called light ship. (IHO Dictionary, S-32, 5th
+Edition, 2828,2829)
+
+References:
+
+INT 1: IP 6;
+
+M-4: 474.1_3; 474.5_6;
+
+Remarks:
+
+The light(s), fog signal etc of a light vessel is a separate object,
+handled as with buoys, beacons etc.
+
+Distinction: beacon, cardinal; beacon, isolated danger;
+ beacon, lateral; beacon, safe water; beacon special
+ purpose/general; buoy, cardinal; buoy, installation; buoy,
+ isolated danger; buoy, lateral; buoy, safe water; buoy,
+ special purpose/general; light float;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Local magnetic anomaly
+
+Acronym: LOCMAG Code: 78
+Local magnetic anomaly LOCMAG 78
+
+Set Attribute_A: NOBJNM; OBJNAM; VALLMA;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An anomaly of the magnetic field of the Earth, extending over a
+relatively small area, due to local magnetic influences. (IHO
+Dictionary, S-32, 5th Edition, 2874, 2984)
+
+References:
+
+INT 1: IB 82.1_2;
+
+M-4: 274;
+
+Remarks:
+
+The value of the deviation from the normal magnetic variation is
+stored in the VALLMA attribute.
+
+Distinction: magnetic variation;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Lock basin
+
+Acronym: LOKBSN Code: 79
+Lock basin LOKBSN 79
+
+Set Attribute_A: DATEND; DATSTA; HORACC; HORCLR; HORLEN;
+ HORWID; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A lock basin is a wet dock in a waterway, permitting a ship to pass
+from one level to another. (adapted from IHO Dictionary, S-32, 5th
+Edition, 2881)
+
+References:
+
+INT 1: IF 41.1;
+
+M-4: 326.6;
+
+Remarks:
+
+The lock gates are encoded as separate gate objects (GATCON).
+
+Distinction: gate;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Log pond
+
+Acronym: LOGPON Code: 80
+Log pond LOGPON 80
+
+Set Attribute_A: NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A maritime area enclosed with connected floating timbers used as a
+staging area for sawn logs.
+
+References:
+
+INT 1: IN 61;
+
+M-4: 449.2;
+
+Remarks:
+
+Also known as booming ground.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Magnetic variation
+
+Acronym: MAGVAR Code: 81
+Magnetic variation MAGVAR 81
+
+Set Attribute_A: DATEND; DATSTA; RYRMGV; VALACM; VALMAG;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The angle between the magnetic and geographic (true) north at a
+location, expressed in degrees east or west from the direction of true
+north.
+
+References:
+
+INT 1: IB 64-66, 71;
+
+M-4: 261; 272.1,3;
+
+Remarks:
+
+No remarks.
+
+Distinction: local magnetic anomaly;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Marine farm/culture
+
+Acronym: MARCUL Code: 82
+Marine farm/culture MARCUL 82
+
+Set Attribute_A: CATMFA; DATEND; DATSTA; EXPSOU; NOBJNM;
+ OBJNAM; PEREND; PERSTA; QUASOU; RESTRN; SOUACC; STATUS;
+ VALSOU; VERACC; VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An assemblage of cages, nets, rafts and floats or posts where fish,
+including shellfish, are artificially cultivated. Also called fish
+farm. (IHO Dictionary, S-32, 5th Edition, 1811)
+
+References:
+
+INT 1: IK 47, 48.1_2;
+
+M-4: 447.4,6;
+
+Remarks:
+
+Distinction: fishing facility; obstruction;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Mast
+
+Acronym: MSTCON
+Mast MSTCON
+INT 1: IE 28, 30.1;
+
+M-4: 375.1-2;
+
+
+Set Attribute_A: CATMST; COLOUR; COLPAT; CONRAD; CONVIS;
+ HEIGHT; NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A straight piece of timber or a hollow cylinder of wood or metal set
+up vertically or nearly so. (International Maritime Dictionary, 2nd
+Ed.)
+
+Remarks:
+
+The object `mast' is independent of associated equipment e.g. radar
+station.
+
+A mast could be constructed of any material, including those mentioned
+above.
+
+Distinction: pylon;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A mast should be encoded as a landmark (LNDMRK) with
+category of landmark (CATLMK) value 7.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Military practice area
+
+Acronym: MIPARE Code: 83
+Military practice area MIPARE 83
+
+Set Attribute_A: CATMPA; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which naval, military or aerial exercises are carried
+out. Also called an exercise area. (adapted from IHO Dictionary, S-32,
+5th Edition, 1722)
+
+References:
+
+INT 1: IN 30-33;
+
+M-4: 441.1_6;
+
+Remarks:
+
+Distinction: caution area; restricted area; submarine transit
+ lane;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Monument
+
+Acronym: MONUMT
+Monument MONUMT
+INT 1: IE 24;
+
+M-4: 374.4;
+
+
+Set Attribute_A: BUISHP; CATMNT; COLOUR; CONDTN; CONRAD;
+ CONVIS; HEIGHT; NATCON; NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A structure erected or maintained as a memorial to a person or event.
+(Digital Geographic Information Working Group, Oct.87)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A monument should be encoded as a landmark (LNDMRK)
+with category of landmark (CATLMK) value 9.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Mooring/Warping facility
+
+Acronym: MORFAC Code: 84
+Mooring/Warping facility MORFAC 84
+
+Set Attribute_A: BOYSHP; CATMOR; COLOUR; COLPAT; CONDTN;
+ CONRAD; CONVIS; DATEND; DATSTA; HEIGHT; NATCON; NOBJNM;
+ OBJNAM; PEREND; PERSTA; STATUS; VERACC; VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The equipment or structure used to secure a vessel (adapted from IHO
+Dictionary, S-32, 5th Edition, 3322)
+
+References:
+
+INT 1: IF 20,21,22; IG 181; IQ 40-43;
+
+M-4: 327.1-2,3; 431.5-6;
+
+Remarks:
+
+Distinction: buoy, special purpose/general;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: National territorial area
+
+Acronym: NATARE
+National territorial area NATARE
+
+Set Attribute_A: NATION;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The whole area of a nation defined by authorities. The area is
+delimited by boundaries established by agreement between adjacent or
+opposite states.
+
+References:
+
+INT 1: IN 40, 41;
+
+M-4: 440.1, 440.3;
+
+Remarks:
+
+Distinction: territorial sea area;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A national territorial area should be encoded as an
+administrative area (ADMARE) with jurisdiction (JRSDTN) value 2.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Navigation line
+
+Acronym: NAVLNE Code: 85
+Navigation line NAVLNE 85
+
+Set Attribute_A: CATNAV; DATEND; DATSTA; ORIENT; PEREND;
+ PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A navigation line is a straight line extending towards an area of
+navigational interest and generally generated by two navigational aids
+or one navigational aid and a bearing. (Service Hydrographique et
+Océanographique de la Marine, France)
+
+References:
+
+INT 1: IM 1-3;
+
+M-4: 433-433.5;
+
+Remarks:
+
+The portion of a navigation line that a ship should use for navigation
+is known as a recommended track.
+
+The extent of the navigation line depends on the visibility of the
+navigational aid(s).
+
+The attribute `orientation' (ORIENT) specifies the orientation of the
+navigation line measured from the water towards the navigational
+aid(s).
+
+The recommended track is that portion of a `navigation line' that a
+ship should use for navigation. (see below)
+
+ RECTRC
+<>
+ Navaid Navaid
+X--------------X---------
+
+NAVLNE
+<>
+
+Distinction: recommended route; recommended track;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Obstruction
+
+Acronym: OBSTRN Code: 86
+Obstruction OBSTRN 86
+
+Set Attribute_A: CATOBS; CONDTN; EXPSOU; HEIGHT; NATCON;
+ NATQUA; NATSUR; NOBJNM; OBJNAM; PRODCT; QUASOU; SOUACC;
+ STATUS; TECSOU; VALSOU; VERACC; VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+In marine navigation, anything that hinders or prevents movement,
+particularly anything that endangers or prevents passage of a vessel.
+The term is usually used to refer to an isolated danger to
+navigation... (IHO Dictionary, S-32, 5th Edition, 3503)
+
+References:
+
+INT 1: IK 1, 31, 40-43, 46.1-2; IL 21, 23; IQ 42;
+
+M-4: 422.8-9; 431.6; 445.1; 447.5;
+
+Remarks:
+
+Distinction: wreck; fishing facility; marine farm/culture;
+ depth area; underwater/awash rock; water turbulence;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Offshore platform
+
+Acronym: OFSPLF Code: 87
+Offshore platform OFSPLF 87
+
+Set Attribute_A: CATOFP; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ PRODCT; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A permanent offshore structure, either fixed or floating, used in the
+production of oil or natural gas. (IHO Dictionary, S-32, 5th Edition,
+3895)
+
+References:
+
+INT 1: IL 2, 10, 11-15, 17;
+
+M-4: 445.2; 445.3; 445.4; 445.6;
+
+Remarks:
+
+Distinction: buoy, installation; offshore production area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Offshore production area
+
+Acronym: OSPARE Code: 88
+Offshore production area OSPARE 88
+
+Set Attribute_A: CATPRA; CONDTN; CONRAD; CONVIS; DATEND;
+ DATSTA; HEIGHT; NOBJNM; OBJNAM; PRODCT; RESTRN; STATUS;
+ VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area at sea within which there are production facilities.
+
+References:
+
+INT 1: IL 4;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: offshore platform; exclusive economic zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Oil barrier
+
+Acronym: OILBAR Code: 89
+Oil barrier OILBAR 89
+
+Set Attribute_A: CATOLB; CONDTN; DATEND; DATSTA; NOBJNM;
+ OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A construction to dam oil flow on water.
+
+References:
+
+INT 1: IF 29.1-2;
+
+M-4: not specified;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pile
+
+Acronym: PILPNT Code: 90
+Pile PILPNT 90
+
+Set Attribute_A: CATPLE; COLOUR; COLPAT; CONDTN; CONVIS;
+ DATEND; DATSTA; HEIGHT; NOBJNM; OBJNAM; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A long heavy timber or section of steel, wood, concrete, etc.. forced
+into the earth which may serve as a support, as for a pier, or a free
+standing pole within a marine environment. (Adapted from IHO
+Dictionary, S-32, 5th Edition, 3840)
+
+References:
+
+INT 1: IF 22;
+
+M-4: 327.3;
+
+Remarks:
+
+Distinction: beacon, cardinal; beacon, isolated danger;
+ beacon, lateral; beacon, safe water; beacon special
+ purpose/general; mooring/warping facility;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pilot boarding place
+
+Acronym: PILBOP Code: 91
+Pilot boarding place PILBOP 91
+
+Set Attribute_A: CATPIL; COMCHA; DATEND; DATSTA; NOBJNM;
+ NPLDST; OBJNAM; PEREND; PERSTA; PILDST; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The meeting place to which the pilot comes out. (IHO Chart
+Specifications, M-4)
+
+References:
+
+INT 1: IT 1.1-4;
+
+M-4: 491.1_2;
+
+Remarks:
+
+No remarks
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Pingo
+
+Acronym: PINGOS
+Pingo PINGOS
+INT 1: not specified
+
+M-4: not specified
+
+
+Set Attribute_A: CONRAD; CONVIS; EXPSOU; HEIGHT; NATQUA;
+ NATSUR; NOBJNM; OBJNAM; QUASOU; QUAVEM; TECSOU; VALSOU;
+ VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+Geometric Primitive: Point, Area;
+
+
+Definition:
+-----------
+
+Small conical hills having a large central core of ice formed from the
+encroachment of permafrost and the resulting hydrostatic pressure.
+(IHO Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+Distinction: hill;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A pingo should be encoded as sloping ground (SLOGRD)
+with a category of slope (CATSLO) value 5.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pipeline area
+
+Acronym: PIPARE Code: 92
+Pipeline area PIPARE 92
+
+Set Attribute_A: CATPIP; CONDTN; DATEND; DATSTA; NOBJNM;
+ OBJNAM; PRODCT; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area containing one or more pipelines.
+
+References:
+
+INT 1: IL 40.2, 41.2;
+
+M-4: 439.3; 444.2;
+
+Remarks:
+
+Distinction: pipeline, overhead; pipeline, submarine/on land;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pipeline, overhead
+
+Acronym: PIPOHD Code: 93
+Pipeline, overhead PIPOHD 93
+
+Set Attribute_A: CATPIP; CONDTN; CONRAD; CONVIS; DATEND;
+ DATSTA; NOBJNM; OBJNAM; PRODCT; STATUS; VERACC; VERCLR; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A pipeline is a string of interconnected pipes used for the transport
+of matter, nowadays mainly oil or gas. (IHO Dictionary, S-32, 5th
+Edition, 3857)
+
+An overhead pipeline is a pipeline supported by pylons and passing
+over or nearby navigable waters.
+
+References:
+
+INT 1: ID 28;
+
+M-4: 383;
+
+Remarks:
+
+Distinction: pipeline area; pipeline, submarine/on land;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pipeline, submarine/on land
+
+Acronym: PIPSOL Code: 94
+Pipeline, submarine/on land PIPSOL 94
+
+Set Attribute_A: BURDEP; CATPIP; CONDTN; DATEND; DATSTA;
+ DRVAL1; DRVAL2; NOBJNM; OBJNAM; PRODCT; STATUS; VERACC;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A pipeline is a string of interconnected pipes used for the transport
+of matter, nowadays mainly oil or gas. (IHO Dictionary, S-32, 5th
+Edition, 3857)
+
+A submarine or land pipeline is a pipeline lying on or buried under
+the seabed or the land.
+
+References:
+
+INT 1: ID 29; IL 40.1, 41.1, 42, 44;
+
+M-4: 377; 444.1; 444.4-5; 444.7;
+
+Remarks:
+
+It must be assumed that the pipes are vulnerable to damage from
+anchoring or trawling.... They may be a potential danger to
+navigation. (IHO Chart Specifications, M-4)
+
+Distinction: pipeline area; pipeline, overhead;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pontoon
+
+Acronym: PONTON Code: 95
+Pontoon PONTON 95
+
+Set Attribute_A: CONDTN; CONRAD; CONVIS; DATEND; DATSTA;
+ NATCON; NOBJNM; OBJNAM; PEREND; PERSTA; STATUS; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A floating structure, usually rectangular in shape which serves as
+landing, pier head or bridge support. (IHO Dictionary, S-32, 5th
+Edition, 3947)
+
+References:
+
+INT 1: IF 16;
+
+M-4: 326.9;
+
+Remarks:
+
+Distinction: bridge; mooring/warping facility; shoreline
+ construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Precautionary area
+
+Acronym: PRCARE Code: 96
+Precautionary area PRCARE 96
+
+Set Attribute_A: DATEND; DATSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A routeing measure comprising an area within defined limits where
+ships must navigate with particular caution and within which the
+direction of traffic flow may be recommended. (IHO Dictionary, S-32,
+5th Edition, 3982)
+
+References:
+
+INT 1: IM 16, 24;
+
+M-4: 435.2;
+
+Remarks:
+
+Distinction: caution area; inshore traffic zone; restricted
+ area; all traffic separation scheme elements;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Production installation
+
+Acronym: PRDINS
+Production installation PRDINS
+INT 1 Reference: IL 20, 21.1-3;
+
+Chart Specification: 445; 445.1; 445.5;
+
+
+Set Attribute_A: CATPRI; CONDTN; CONRAD; CONVIS; DATEND;
+ DATSTA; EXPSOU; HEIGHT; NOBJNM; OBJNAM; PRODCT; QUASOU;
+ QUAVEM; STATUS; TECSOU; VALSOU; VERDAT; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; PICREP; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+An installation for the exploitation of natural resources.
+
+Remarks:
+
+Distinction: offshore platform; Exclusive Economic Zone;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A production installation should be encoded as either
+an obstruction (OBSTRN) with an appropriate category of obstruction
+(CATOBS) value, or as a production area (PRDARE) with an appropriate
+category of production area (CATPRA) value.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Production/storage area
+
+Acronym: PRDARE Code: 97
+Production/storage area PRDARE 97
+
+Set Attribute_A: CATPRA; CONDTN; CONRAD; CONVIS; DATEND;
+ DATSTA; ELEVAT; HEIGHT; NOBJNM; OBJNAM; PRODCT; STATUS;
+ VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area on land for the exploitation or storage of natural resources.
+
+References:
+
+INT 1: IE 35.1-2, 36; IF 52
+
+M-4: 367.1-2;
+
+Remarks:
+
+Distinction: free port area; offshore production area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Pylon/bridge support
+
+Acronym: PYLONS Code: 98
+Pylon/bridge support PYLONS 98
+
+Set Attribute_A: CATPYL; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ VERACC; VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A vertical construction consisting, for example, of a steel framework
+or pre-stressed concrete to carry cables, a bridge, etc.
+
+References:
+
+INT 1: ID 26;
+
+M-4: 382.1;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Radar dome
+
+Acronym: RADDOM
+Radar dome RADDOM
+INT 1: IE 30.4;
+
+M-4: 487.3;
+
+
+Set Attribute_A: COLOUR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NOBJNM; OBJNAM; QUAVEM; RADIUS; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A dome shaped structure used to protect the antenna of a radar
+installation. (IHO Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+Distinction: radar station;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A radar dome should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 15.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radar line
+
+Acronym: RADLNE Code: 99
+Radar line RADLNE 99
+
+Set Attribute_A: NOBJNM; OBJNAM; ORIENT; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A track along which ships may be guided by coastal radar stations in
+the event of bad visibility. Also known as a radar guided track. (IHO
+Dictionary, S-32, 5th Edition, 4146).
+
+References:
+
+INT 1: IM 32.1-2;
+
+M-4: 487.2;
+
+Remarks:
+
+Distinction: radar range; recommended track;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radar range
+
+Acronym: RADRNG Code: 100
+Radar range RADRNG 100
+
+Set Attribute_A: COMCHA; DATEND; DATSTA; NOBJNM; OBJNAM;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Indicates the coverage of a sea area by a radar surveillance station.
+Inside this area a vessel may request shore-based radar assistance,
+particularly in poor visibility.
+
+References:
+
+INT 1: IM 31;
+
+M-4: 487.1;
+
+Remarks:
+
+Many large ports have a radar surveillance system covering their
+approaches to provide guidance for vessels, particularly in poor
+visibility...
+
+The maximum range of the system forms an arc or series of overlapping
+arcs... (IHO Chart Specifications, M-4)
+
+Distinction: radar line;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radar reflector
+
+Acronym: RADRFL Code: 101
+Radar reflector RADRFL 101
+
+Set Attribute_A: HEIGHT; STATUS; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A device capable of, or intended for, reflecting radar signals. (IHO
+Dictionary, S-32, 5th Edition, 4147)
+
+A radar reflector is usually a `tetrahedron or pentagonal corner
+reflector (...) to facilitate reflection towards the sender'.
+(International Maritime Dictionary, 2nd Ed.)
+
+References:
+
+INT 1: IS 4;
+
+M-4: 465.1_2;
+
+Remarks:
+
+The object `radar reflector' is only used to encode a device
+specifically intended to reflect radar signals. If any other object,
+e.g. topmark, buoy, beacon etc.. is radar conspicuous, because of its
+construction, the attribute `CONRAD' must be used.
+
+Distinction: retro-reflector;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radar station
+
+Acronym: RADSTA Code: 102
+Radar station RADSTA 102
+
+Set Attribute_A: CATRAS; COMCHA; DATEND; DATSTA; HEIGHT;
+ NOBJNM; OBJNAM; STATUS; VALMXR; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A station with a transmitter emitting pulses of ultra_high frequency
+radio waves which are reflected by solid objects and are detected upon
+their return to the sending station. (International Maritime
+Dictionary, 2nd Ed.)
+
+References:
+
+INT 1: IM 30; IS 1;
+
+M-4: 485.1; 487.3;
+
+Remarks:
+
+The object `radar station' is used to encode the technical equipment
+itself independent of the building or structure where it is
+installed. This building or structure, e.g. mast, tower, building,
+radar dome is a different object.
+
+Distinction: radar line; radar range; radar transponder beacon;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radar transponder beacon
+
+Acronym: RTPBCN Code: 103
+Radar transponder beacon RTPBCN 103
+
+Set Attribute_A: CATRTB; DATEND; DATSTA; NOBJNM; OBJNAM;
+ RADWAL; SECTR1; SECTR2; SIGGRP; SIGSEQ; STATUS; VALMXR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A transponder beacon transmitting a coded signal on radar frequency,
+permitting an interrogating craft to determine the bearing and range
+of the transponder. Also called racon. (IHO Dictionary, S-32, 5th
+Edition, 4137)
+
+References:
+
+INT 1: IS 2-3;
+
+M-4: 486.1-3;
+
+Remarks:
+
+The object class `radar transponder beacon' is only used to encode the
+technical equipment independent of the structure on which it is
+located (e.g. a beacon, light-vessel or tower).
+
+Distinction: radar line; radar range; radar station;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radio calling_in point
+
+Acronym: RDOCAL Code: 104
+Radio calling_in point RDOCAL 104
+
+Set Attribute_A: COMCHA; DATEND; DATSTA; NOBJNM; OBJNAM;
+ ORIENT; PEREND; PERSTA; STATUS; TRAFIC;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Also called radio reporting points, they have been established in
+certain busy waterways and port approaches to assist traffic control.
+On passing these points or crossing a defined line vessels are
+required to report on VHF to a Traffic Control Centre. (adapted from
+IHO Chart Specifications, M-4)
+
+References:
+
+INT 1: IM 40;
+
+M-4: 488;
+
+Remarks:
+
+The attribute `orientation' (ORIENT) encodes the orientation of the
+traffic flow at that point.
+
+Distinction: radio station; pilot boarding place;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Radio station
+
+Acronym: RDOSTA Code: 105
+Radio station RDOSTA 105
+
+Set Attribute_A: CALSGN; CATROS; COMCHA; DATEND; DATSTA;
+ ESTRNG; NOBJNM; OBJNAM; ORIENT; PEREND; PERSTA; SIGFRQ; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A place equipped to transmit radio waves. Such a station may be either
+stationary or mobile, and may also be provided with a radio receiver.
+In British terminology, also called w/t station. (IHO Dictionary,
+S-32, 5th Edition, 4191)
+
+References:
+
+INT 1: IS 10-16;
+
+M-4: 480.1; 481.1-3; 482; 483; 484;
+
+Remarks:
+
+The transmission of a radio station may serve to provide mariners with
+a line of position. (IHO Chart Specifications, M-4)
+
+The object "radio station" is used to encode the point of transmission
+of the signal.
+
+Distinction: radio calling in point; radar station;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Railway
+
+Acronym: RAILWY Code: 106
+Railway RAILWY 106
+
+Set Attribute_A: CONDTN; HEIGHT; NOBJNM; OBJNAM; STATUS;
+ VERACC;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A rail or set of parallel rails on which a train or tram runs.
+(Digital Geographic Information Working Group, Oct.87)
+
+References:
+
+INT 1: ID 13;
+
+M-4: 328.4; 362.1_2;
+
+Remarks:
+
+Distinction: road; tunnel;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Ramp
+
+Acronym: RMPARE
+Ramp RMPARE
+INT 1: IF 23;
+
+M-4: not specified
+
+
+Set Attribute_A: CONDTN; HORCLR; HORLEN; HORWID; NATCON;
+ NOBJNM; OBJNAM; STATUS; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line; Area;
+
+
+Definition:
+-----------
+
+A sloping structure that can either be used as a landing place at
+variable water levels, for small vessels, landing ships, or a ferry
+boat, or for hauling a cradle carrying a vessel. (IHO
+Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+Distinction: slipway;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A ramp should be encoded as a shoreline construction
+(SLCONS) with a category of shoreline construction (CATSLC) value 12.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Rapids
+
+Acronym: RAPIDS Code: 107
+Rapids RAPIDS 107
+
+Set Attribute_A: NOBJNM; OBJNAM; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Portions of a stream with accelerated current where it descends
+rapidly but without a break in the slope of the bed sufficient to form
+a waterfall. Usually used in the plural. (IHO Dictionary, S-32, 5th
+Edition, 4228)
+
+References:
+
+INT 1: IC 22;
+
+M-4: 353.5;
+
+Remarks:
+
+Distinction: current - non-gravitational; tidal stream -
+ harmonic prediction; tidal stream - non-harmonic prediction;
+ tidal stream panel data; tidal stream - time series; water
+ turbulence; waterfall;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Recommended route centerline
+
+Acronym: RCRTCL Code: 108
+Recommended route centerline RCRTCL 108
+
+Set Attribute_A: CATTRK; DATEND; DATSTA; DRVAL1; DRVAL2;
+ NOBJNM; OBJNAM; ORIENT; PEREND; PERSTA; QUASOU; SOUACC;
+ STATUS; TECSOU; TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A recommended route is a route of undefined width, for the convenience
+of ships in transit, which is often marked by centerline buoys. (IHO
+Dictionary, S-32, 5th Edition, 4448)
+
+The recommended route centerline indicates the `centerline' of a
+recommended route.
+
+References:
+
+INT 1: IM 28.1;
+
+M-4: 435.4;
+
+Remarks:
+
+A recommended route describes the regulation of navigation for
+non_hydrographic reasons such as the prevention of collision or the
+avoidance of pollution risks. It is generally laid down by a national
+or international authority other than the hydrographic authority. (IHO
+Chart Specifications, M-4)
+
+Distinction: recommended traffic lane part; recommended track;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Recommended track
+
+Acronym: RECTRC Code: 109
+Recommended track RECTRC 109
+
+Set Attribute_A: CATTRK; DATEND; DATSTA; DRVAL1; DRVAL2;
+ NOBJNM; OBJNAM; ORIENT; PEREND; PERSTA; QUASOU; SOUACC;
+ STATUS; TECSOU; TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A track recommended to all or only certain vessels. (IHO Dictionary,
+S-32, 5th Edition, 5576)
+
+References:
+
+INT 1: IM 3-4, 5.1, 5.2, 6;
+
+M-4: 432.1; 434;
+
+Remarks:
+
+Recommended tracks include all channels recommended for hydrographic
+reasons to lead safely between shoal depths. The use of such tracks is
+generally left to the discretion of the mariner and will depend on the
+vessel's draught, the state of the tide, adequacy of navigational aids
+and so on. (IHO Chart Specifications, M-4)
+
+The recommended track is that portion of a `navigation line' that a
+ship should use for navigation. (see below)
+
+ RECTRC
+<>
+ Navaid Navaid
+X--------------X---------
+
+NAVLNE
+<>
+
+In the case of a two-way recommended track, only one value of
+orientation is encoded (in the attribute ORIENT); the other value can
+be deduced (i.e. the value in ORIENT + 180 degrees) .
+
+Distinction: navigation line; recommended route centerline;
+ recommended traffic lane part;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Recommended traffic lane part
+
+Acronym: RCTLPT Code: 110
+Recommended traffic lane part RCTLPT 110
+
+Set Attribute_A: DATEND; DATSTA; ORIENT; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An optional part of an IMO_adopted routing measure.... Several
+Hydrographic Offices, in consultation with their Ministries of
+Transport, have added recommended directions in areas such as the
+outer approaches to major ports in order to show the best routes for
+crossing traffic or to minimize head_on encounters.(...) (IHO Chart
+Specifications, M-4)
+
+References:
+
+INT 1: IM 26.1-2;
+
+M-4: 435.5;
+
+Remarks:
+
+The object `recommended traffic lane part' indicates the recommended
+traffic flow e.g.
+_ between two TSS
+_ in the entrance areas of a TSS
+_ beside a deep water route.
+
+The complete recommended traffic lane consists of one or more parts
+depending on the various shapes of the recommended traffic lane.
+
+The orientation of the recommended traffic lane part is defined by the
+middle_line of the recommended traffic lane part relating to the
+general direction of the recommended traffic lane part.
+
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Rescue station
+
+Acronym: RSCSTA Code: 111
+Rescue station RSCSTA 111
+
+Set Attribute_A: CATRSC; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A place at which life saving equipment is held. (IHO Chart
+Specifications, M-4)
+
+References:
+
+INT 1: IT 12-14; IQ 124;
+
+M-4: 493; 493.1-2;
+
+Remarks:
+
+This object encodes the service available at this location. The
+structure housing the service should be coded separately.
+
+Distinction: beacon special purpose/general; building single;
+ coastguard station;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Restricted area
+
+Acronym: RESARE Code: 112
+Restricted area RESARE 112
+
+Set Attribute_A: CATREA; DATEND; DATSTA; NOBJNM; OBJNAM;
+ PEREND; PERSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A specified area designated by an appropriate authority within which
+navigation is restricted in accordance with certain specified
+conditions. (adapted from IHO Dictionary, S-32, 5th Edition, 4366)
+
+References:
+
+INT 1: IL 3; IN 2.1-2, 20-22, 25-26, 31, 34;
+
+M-4: 431.4; 439.2-4; 441.8; 445.2; 448.1-2; 449.5;
+
+Remarks:
+
+Distinction: anchorage area; cable area; caution area; dumping
+ ground; depth area; fairway; dredged area; deep water route;
+ military practice area; pipeline area; swept area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Retro-reflector
+
+Acronym: RETRFL Code: 113
+Retro-reflector RETRFL 113
+
+Set Attribute_A: COLOUR; COLPAT; HEIGHT; MARSYS; STATUS;
+ VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A means of distinguishing unlighted marks at night. Retro-reflective
+material is secured to the mark in a particular pattern to reflect
+back light. (Adapted from the UKHO NP735, 5th Edition).
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The body carrying the retro-reflector is a separate object.
+
+Distinction: beacon, cardinal; beacon, isolated danger;
+ beacon, lateral; beacon, safe water; beacon special
+ purpose/general; buoy, cardinal; buoy, installation; buoy,
+ isolated danger; buoy, lateral; buoy, safe water; buoy,
+ special purpose/general; radar reflector;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: River
+
+Acronym: RIVERS Code: 114
+River RIVERS 114
+
+Set Attribute_A: NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A relatively large natural stream of water. (IHO Dictionary, S-32, 5th
+Edition, 4405)
+
+References:
+
+INT 1: IC 20, 21;
+
+M-4: 353.1_4;
+
+Remarks:
+
+The object `river' describes the area of the river, the object `river
+bank' its banks.
+
+Distinction: canal; lake; river bank; sea area/named water
+ area; tideway;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: River bank
+
+Acronym: RIVBNK Code: 115
+River bank RIVBNK 115
+
+Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The limit line between the water area of a river and the area of land.
+
+References:
+
+INT 1: IC 20, 21;
+
+M-4: 353.1-4;
+
+Remarks:
+
+Distinction: canal bank; coastline; lake shore; river;
+ shoreline construction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Road
+
+Acronym: ROADWY Code: 116
+Road ROADWY
+
+Set Attribute_A: CATROD; CONDTN; NATCON; NOBJNM; OBJNAM;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A road is an open way for the passage of vehicles. (United States
+Geological Survey, Jan.89)
+
+References:
+
+INT 1: ID 10-12;
+
+M-4: 365.1-3;
+
+Remarks:
+
+Distinction: causeway; railway; square;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Road crossing
+
+Acronym: RODCRS
+Road crossing RODCRS
+INT 1: ID 10-12;
+
+M-4: 465.1-3;
+
+
+Set Attribute_A: CATROD; CONDTN; NATCON; NOBJNM; OBJNAM;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+The area where two roads are crossing.
+
+Remark:
+
+Distinction: road part; square; built-up area;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A road crossing should be encoded as a road (ROADWY)
+with a category of road (CATROD) value 7.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Road part
+
+Acronym: ROADPT
+Road part ROADPT
+
+Set Attribute_A: CATROD; CONDTN; NATCON; NOBJNM; OBJNAM;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A road is an open way for passage of vehicles. (United States
+Geological Survey, Jan.89)
+
+References:
+
+INT 1: ID 10-12;
+
+M-4: 365.1-3;
+
+Remarks:
+
+The symbolization for paper chart presentation in small scales is
+related to the category of road (attribute `CATROD').
+
+Distinction: square; built_up area; road crossing;
+
+This object class is obsolete. It is only shown here for reasons of
+backward compatibility. Roads should be encoded using the object class
+road (ROADWY).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Runway
+
+Acronym: RUNWAY Code: 117
+Runway RUNWAY 117
+
+Set Attribute_A: CATRUN; CONDTN; CONVIS; NATCON; NOBJNM;
+ OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A defined rectangular area, on a land aerodrome, prepared for the
+landing and take-off run of aircraft along its length. (IHO
+Dictionary, S-32, 5th Edition, 4465)
+
+A site on which helicopters may land and take off. (IHO Dictionary,
+S-32, 5th Edition, 2232)
+
+References:
+
+INT 1: ID 17;
+
+M-4: 366;
+
+Remarks:
+
+Distinction: airport area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Salt pan
+
+Acronym: SLTPAN
+Salt pan SLTPAN
+INT 1: IC 24;
+
+M-4: 353.7;
+
+
+Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Area;
+
+
+Definition:
+-----------
+
+A flat area of the natural surface covered with salt deposits which
+result from the evaporation of sea water. (Digital Geographic
+Information Working Group, Oct 1987)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A salt pan should be encoded as a land region (LNDRGN)
+with a category of land region (CATLND) value 15.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Sand waves
+
+Acronym: SNDWAV Code: 118
+Sand waves SNDWAV 118
+
+Set Attribute_A: VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A large mobile wave-like sediment feature in shallow water and
+composed of sand. The wavelength may reach 100 metres, the amplitude
+may be up to 20 metres.
+
+References:
+
+INT 1: IJ 14;
+
+M-4: 428.1;
+
+Remarks:
+
+Distinction: seabed area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Sea area/named water area
+
+Acronym: SEAARE Code: 119
+Sea area/named water area SEAARE 119
+
+Set Attribute_A: CATSEA; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A geographically defined part of the sea or other navigable waters. It
+may be specified within its limits by its proper name.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Each sea area is defined independent of any other. Smaller sea areas
+may be located within larger sea areas.
+
+Distinction: depth area; seabed area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Sea_plane landing area
+
+Acronym: SPLARE Code: 120
+Sea_plane landing area SPLARE 120
+
+Set Attribute_A: NOBJNM; OBJNAM; PEREND; PERSTA; RESTRN;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A designated portion of water for the landing and take-off of
+sea_planes.
+
+References:
+
+INT 1: IN 13;
+
+M-4: 449.6;
+
+Remarks:
+
+Distinction: airport area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Seabed area
+
+Acronym: SBDARE Code: 121
+Seabed area SBDARE 121
+
+Set Attribute_A: COLOUR; NATQUA; NATSUR; NOBJNM; OBJNAM;
+ WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of the sea where the nature of bottom is homogeneous.
+
+The nature of bottom includes the material of which it is composed and
+its physical characteristics. Also called character (or
+characteristics) of the bottom, or quality of the bottom. (IHO
+Dictionary, S-32, 5th Edition, 515).
+
+References:
+
+INT 1: IJ 1-11, 30-39;
+
+M-4: 425.5-6; 426; 427;
+
+Remarks:
+
+Generally, it is not possible to define a seabed area by its real
+extent. For that reason, the characteristics of the seabed area may be
+represented at one single position.
+
+Distinction: sand wave; sea area/named water area; weed/kelp;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Shoreline construction
+
+Acronym: SLCONS Code: 122
+Shoreline construction SLCONS 122
+
+Set Attribute_A: CATSLC; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; DATEND; DATSTA; HEIGHT; HORACC; HORCLR; HORLEN;
+ HORWID; NATCON; NOBJNM; OBJNAM; STATUS; VERACC; VERDAT;
+ VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A fixed (not afloat) artificial structure between the water and the
+land, i.e. a man-made coastline.
+
+References:
+
+INT 1: IF 2, 4, 5, 6, 12-15, 18,23, 33;
+
+M-4: 313.2, 4; 321.1-4; 322.1-2; 324.1;
+
+Remarks:
+
+Distinction: canal bank; coastline; lake shore; land area;
+ pontoon; river bank;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Signal station, traffic
+
+Acronym: SISTAT Code: 123
+Signal station, traffic SISTAT 123
+
+Set Attribute_A: CATSIT; COMCHA; DATEND; DATSTA; NOBJNM;
+ OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A signal station is a place on shore from which signals are made to
+ships at sea. (IHO Dictionary, S-32, 5th Edition, 4742)
+
+Traffic signal stations regulate the movement of traffic. (IHO Chart
+Specifications, M-4)
+
+References:
+
+INT 1: IT 21-25.2;
+
+M-4: 495.1-5;
+
+Remarks:
+
+This object class is used to describe the function of the signal
+station rather than the structure on which the station is sited.
+
+Distinction: signal station, warning;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Signal station, warning
+
+Acronym: SISTAW Code: 124
+Signal station, warning SISTAW 124
+
+Set Attribute_A: CATSIW; COMCHA; DATEND; DATSTA; NOBJNM;
+ OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A signal station is a place on shore from which signals are made to
+ships at sea. (IHO Dictionary, S-32, 5th Edition, 4742)
+
+References:
+
+INT 1: IT 20, 26, 28-36;
+
+M-4: 490.3; 494.1-2; 496.1-3; 497;
+
+Remarks:
+
+This object class is used to describe the function of the signal
+station rather than the structure on which the station is sited.
+
+Distinction: signal station, traffic;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Silo
+
+Acronym: SILBUI
+Silo SILBUI
+INT 1 Reference: IE 33;
+
+Chart Specification: 376.3;
+
+
+Set Attribute_A: BUISHP; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; HEIGHT; NATCON; NOBJNM; OBJNAM; PRODCT; QUAVEM;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; PICREP; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+An enclosed container, used for storing grain or fodder. (Digital
+Geographic Information Working Group, Oct.87)
+
+Remarks:
+
+Distinction: tank;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A silo should be encoded as a silo/tank (SILTNK) with a
+category of silo (CATSIL) value 1.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Silo/tank
+
+Acronym: SILTNK Code: 125
+Silo/tank SILTNK 125
+
+Set Attribute_A: BUISHP; CATSIL; COLOUR; COLPAT; CONDTN;
+ CONRAD; CONVIS; ELEVAT; HEIGHT; NATCON; NOBJNM; OBJNAM;
+ PRODCT; STATUS; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An enclosed container, used for storage (Digital Geographic
+Information Working Group, Oct.87)
+
+References:
+
+INT 1: IE 2, 32-33;
+
+M-4: 340.2; 376.2-3;
+
+Remarks:
+
+Distinction: landmark; production/storage area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Slipway
+
+Acronym: SLIPWY
+Slipway SLIPWY
+INT 1: IF 23
+
+M-4: 324,1;
+
+
+Set Attribute_A: CONDTN; HORCLR; HORLEN; HORWID; NATCON;
+ NOBJNM; OBJNAM; STATUS; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line; Area;
+
+
+Definition:
+-----------
+
+The prepared, and usually reinforced, inclined surface on which keel-
+and bilge-blocks are laid for supporting a vessel under construction.
+(IHO Dictionary, S-32, 4th Edition)
+
+Remarks:
+
+Distinction: ramp;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A slipway should be encoded as a shoreline construction
+(SLCONS) with a category of shoreline construction (CATSLC) value 13.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Slope topline
+
+Acronym: SLOTOP Code: 126
+Slope topline SLOTOP 126
+
+Set Attribute_A: CATSLO; COLOUR; CONRAD; CONVIS; ELEVAT;
+ NATCON; NATQUA; NATSUR; NOBJNM; OBJNAM; VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The upper marking of a slope, e.g. the ridge line or the separation
+line between two different gradients.
+
+References:
+
+INT 1: IC 3; ID 14, 15;
+
+M-4: 312.1; 363.2; 364.1;
+
+Remarks:
+
+no remark.
+
+Distinction: land elevation; sloping ground;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Sloping ground
+
+Acronym: SLOGRD Code: 127
+Sloping ground SLOGRD 127
+
+Set Attribute_A: CATSLO; COLOUR; CONRAD; CONVIS; NATCON;
+ NATQUA; NATSUR; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An inclined surface (adapted from IHO Dictionary, S-32, 5th Edition,
+4776).
+
+References:
+
+INT 1: IC 3, 4, 8; ID 14, 15; IF 1;
+
+M-4: 312.1; 312.3; 313.1; 313.2;
+
+Remarks:
+
+Distinction: slope topline;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Small craft facility
+
+Acronym: SMCFAC Code: 128
+Small craft facility SMCFAC 128
+
+Set Attribute_A: CATSCF; NOBJNM; OBJNAM; PEREND; PERSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A place at which a service generally of interest to small craft or
+pleasure boats is available.
+
+References:
+
+INT 1: IU 2, 3-4, 6-13, 15-31;
+
+M-4: not specified;
+
+Remarks:
+
+This object class encodes the service available at this location. The
+structure housing the service should be encoded separately.
+
+Distinction: building, single; harbour facility; shoreline
+ construction.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Sounding
+
+Acronym: SOUNDG Code: 129
+Sounding SOUNDG 129
+
+Set Attribute_A: EXPSOU; NOBJNM; OBJNAM; QUASOU; SOUACC;
+ STATUS; TECSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A measured water depth or spot which has been reduced to a vertical
+datum (may be a drying height).
+
+References:
+
+INT 1: II 10-15;
+
+M-4: 403.1; 410; 412-412.4; 413.1; 417.3;
+
+Remarks:
+
+The value of the sounding is encoded in the 3-D Coordinate field of
+the Spatial Record Structure (see S-57 Part 3).
+
+Drying heights (drying soundings) are indicated by a negative value.
+
+Distinction: depth area; wreck; underwater/awash rock;
+ obstruction;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Spoil ground
+
+Acronym: SPOGRD
+Spoil ground SPOGRD
+INT 1: IN 62.1-2;
+
+M-4: 446.1-2;
+
+
+Set Attribute_A: NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A sea area where dredged material is deposited. (IHO Dictionary, S-32,
+4th Edition)
+
+Remarks:
+
+The significance of spoil grounds to the mariner is that very large
+quantities of material may be dumped, decreasing the depth of water
+available. (IHO Chart Specifications, M-4)
+
+
+Distinction: dumping ground; dredged area;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A spoil ground should be encoded as a dumping ground
+(DMPGRD) with a category of dumping ground (CATDPG) value 5.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Spring
+
+Acronym: SPRING Code: 130
+Spring SPRING 130
+
+Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A natural issue of water or other substances from the earth. One on
+the bottom of the sea is called a submarine spring. (IHO Dictionary,
+S-32, 5th Edition, 4939)
+
+References:
+
+INT 1: IJ 15;
+
+M-4: 428.3;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Square
+
+Acronym: SQUARE Code: 131
+Square SQUARE 131
+
+Set Attribute_A: CONDTN; NATCON; NOBJNM; OBJNAM; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An open area within a built_up area surrounded by roads.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: road; built_up area; building, single;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Straight territorial sea baseline
+
+Acronym: STSLNE Code: 132
+Straight territorial sea baseline STSLNE 132
+
+Set Attribute_A: NATION;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A baseline is the line from which the outer limits of the territorial
+sea and certain other outer limits are measured. (IHO Dictionary,
+S-32, 5th Edition, 390)
+
+Straight baselines are a system of straight lines joining specified or
+discrete points on the low-water line, usually known as straight
+baseline turning points. (IHO Dictionary, S-32, 5th Edition, 393)
+
+References:
+
+INT 1: IN 42;
+
+M-4: 440.4;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Submarine transit lane
+
+Acronym: SUBTLN Code: 133
+Submarine transit lane SUBTLN 133
+
+Set Attribute_A: NOBJNM; OBJNAM; RESTRN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area where submarines may navigate under water or at the surface.
+
+References:
+
+INT 1: IN 33;
+
+M-4: 441.5;
+
+Remarks:
+
+Distinction: military practice area;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Swept Area
+
+Acronym: SWPARE Code: 134
+Swept Area SWPARE 134
+
+ Set Attribute_A: DRVAL1; QUASOU; SOUACC; TECSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area that has been determined to be clear of navigational dangers
+to a specified depth (adapted from IHO Dictionary, S-32, 5th Edition,
+5248).
+
+References:
+
+INT 1: II 24;
+
+M-4: 415.1; 415.2;
+
+Remarks:
+
+Distinction: depth area; dredged area; unsurveyed area;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Tank
+
+Acronym: TNKCON
+Tank TNKCON
+
+Set Attribute_A: COLOUR; COLPAT; CONDTN; CONRAD; CONVIS;
+ HEIGHT; NATCON; NOBJNM; OBJNAM; PRODCT; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A fixed structure for storing liquids or gases. (Derived from IHO
+Dictionary, S-32, 4th Edition)
+
+References:
+
+INT 1: IE 32;
+
+M-4: 376.1_2;
+
+Remarks:
+
+Distinction: silo;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A tank should be encoded as a silo/tank (SILTNK) with a
+category of silo (CATSIL) value 2.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Telepheric
+
+Acronym: TELPHC
+Telepheric TELPHC
+INT 1: ID 25;
+
+M-4: 382.3;
+
+
+Set Attribute_A: CONDTN; CONRAD; CONVIS; DATEND; DATSTA;
+ LIFCAP; NOBJNM; OBJNAM; QUAVEM; STATUS; VERCLR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line;
+
+
+Definition:
+-----------
+
+A construction of cables strung between elevated supports on which
+carrier units are suspended.
+
+Remarks:
+
+The elevated supports are separate objects.
+
+Distinction: cable, overhead;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A telepheric should be encoded as a conveyor (CONVYR)
+with a category of conveyor (CATCON) value 1.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Territorial sea area
+
+Acronym: TESARE Code: 135
+Territorial sea area TESARE 135
+
+Set Attribute_A: NATION; RESTRN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The territorial sea is a belt of water of a defined breadth but not
+exceeding 12 nautical miles measured seaward from the territorial sea
+baseline. (IHO Dictionary, S-32, 5th Edition, 5360)
+
+References:
+
+INT 1: IN 43;
+
+M-4: 440.5;
+
+Remarks:
+
+Distinction: administrative area; contiguous zone; continental
+ shelf area; exclusive economic zone; fishery zone; restricted
+ area;
+
+
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tidal stream - flood/ebb
+
+Acronym: TS_FEB Code: 160
+
+
+Set Attribute_A: CAT_TS; CURVEL; DATEND; DATSTA; NOBJNM; OBJNAM;
+ORIENT; PEREND; PERSTA;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A tidal stream (or tidal current) is a horizontal movement of water
+associated with the rise and fall of the tide caused by tide-producing
+forces. (Adapted from IHO Dictionary, S-32, 5th Edition)
+
+Approximate tidal stream rates may be given as discrete rate values
+for flood and ebb flow during springs.
+
+References:
+
+INT 1: IH 40-41;
+
+M-4: 407.4;
+
+Remarks:
+
+Distinction: tidal stream - harmonic prediction; tidal stream -
+ non harmonic prediction; tidal stream panel data; tidal stream
+ - time series;
+
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tidal stream - harmonic prediction
+
+Acronym: TS_PRH Code: 136
+Tidal stream - harmonic prediction TS_PRH 136
+
+Set Attribute_A: NOBJNM; OBJNAM; T_MTOD; T_VAHC; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A tidal stream (or tidal current) is an alternating horizontal
+movement of water associated with the rise and fall of the tide caused
+by tide-producing forces. (IHO Dictionary, S-32, 5th Edition, 1169)
+
+Predicted tidal stream rates may be calculated using parameters
+(harmonic constituents) and an appropriate harmonic calculation
+algorithm.
+
+References:
+
+INT 1: IH 40-41;
+
+M-4: 407.4; 408.2;
+
+Remarks:
+
+The object `tidal stream - harmonic prediction' encodes parameters for
+use when predicting tidal streams by harmonic methods.
+
+The supplier of any parameters must be consulted on how to use data
+provided using this object class, and which calculation algorithms to
+use with the data.
+
+Distinction: current - non-gravitational; tidal stream -
+ non-harmonic prediction; tidal stream panel data; tidal stream
+ - time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tidal stream - non-harmonic prediction
+
+Acronym: TS_PNH Code: 137
+Tidal stream - non-harmonic prediction TS_PNH 137
+
+Set Attribute_A: NOBJNM; OBJNAM; T_THDF; T_MTOD; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A tidal stream (or tidal current) is an alternating horizontal
+movement of water associated with the rise and fall of the tide caused
+by tide-producing forces. (IHO Dictionary, S-32, 5th Edition, 1169)
+
+Predicted tidal stream rates may be calculated using time and rate
+differences with respect to a reference station (and associated tidal
+stream predictions).
+
+References:
+
+INT 1: IH 40-41;
+
+M-4: 407.4; 408.2;
+
+Remarks:
+
+The object `tidal stream - non-harmonic prediction' encodes
+information for use when predicting times and rates for tidal streams
+by non-harmonic methods.
+
+The supplier of any parameters must be consulted on how to use this
+data, and which calculation algorithms to use with the data.
+
+Distinction: current - non-gravitational; tidal stream -
+ harmonic prediction; tidal stream panel data; tidal stream -
+ time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tidal stream panel data
+
+Acronym: TS_PAD Code: 138
+Tidal stream panel data TS_PAD 138
+
+Set Attribute_A: NOBJNM; OBJNAM; TS_TSP;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A tidal stream (or tidal current) is an alternating horizontal
+movement of water associated with the rise and fall of the tide caused
+by tide-producing forces. (IHO Dictionary, S-32, 5th Edition, 1169)
+
+Approximate tidal stream rates may be given as discrete rate values at
+a specified interval before or after a high water.
+
+References:
+
+INT 1: IH 40-41;
+
+M-4: 407.4; 408.2;
+
+Remarks:
+
+The object `tidal stream panel data' encodes data for use in a tidal
+panel.
+
+Distinction: current - non-gravitational; tidal stream -
+ harmonic prediction; tidal stream - non-harmonic prediction;
+ tidal stream - time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tidal stream - time series
+
+Acronym: TS_TIS Code: 139
+Tidal stream - time series TS_TIS 139
+
+Set Attribute_A: NOBJNM; OBJNAM; TIMEND; TIMSTA; T_TINT;
+ TS_TSV; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A tidal stream (or tidal current) is an alternating horizontal
+movement of water associated with the rise and fall of the tide caused
+by tide-producing forces. (IHO Dictionary, S-32, 5th Edition, 1169)
+
+Tidal stream rates over time may be approximated by a series of rate
+values given at regular time intervals, starting from a specified
+moment in time.
+
+References:
+
+INT 1: IH 40-41;
+
+M-4: 407.4; 408.2;
+
+Remarks:
+
+The object `tidal stream - time series' encodes rates of tidal stream
+at equal time intervals.
+
+Distinction: current - non-gravitational;tidal stream -
+ harmonic prediction; tidal stream - non-harmonic prediction;
+ tidal stream panel data;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tide - harmonic prediction
+
+Acronym: T_HMON Code: 140
+Tide - harmonic prediction T_HMON 140
+
+Set Attribute_A: NOBJNM; OBJNAM; T_ACWL; T_MTOD; T_VAHC; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Tide - the periodic rise and fall of the surface of the sea, due
+principally to the gravitational interaction between moon, sun and
+earth. (adopted from IHO Dictionary, S-32, 5th Edition, 5429)
+
+Predicted tidal heights may be calculated using parameters (harmonic
+constituents) and an appropriate harmonic calculation algorithm.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The object `tide - harmonic predictions' encodes parameters for use
+when predicting tidal heights by harmonic methods.
+
+The supplier of any parameters must be consulted on how to use this
+data, and which calculation algorithms to use with the data.
+
+Distinction: tide - non-harmonic prediction; tide - time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tide - non-harmonic prediction
+
+Acronym: T_NHMN Code: 141
+Tide - non-harmonic prediction T_NHMN 141
+
+Set Attribute_A: NOBJNM; OBJNAM; T_ACWL; T_MTOD; T_THDF; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Tide - the periodic rise and fall of the surface of the sea, due
+principally to the gravitational interaction between moon, sun and
+earth. (adopted from IHO Dictionary, S-32, 5th Edition, 5429)
+
+Predicted tidal heights may be calculated using time and height
+differences with respect to a reference port (and associated tidal
+predictions).
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The object `tide - non-harmonic prediction' encodes information for
+use when predicting times and heights for high and low waters by
+non-harmonic methods.
+
+The supplier of any parameters must be consulted on how to use data
+provided using this object class, and which calculation algorithms to
+use with the data.
+
+Distinction: tide - harmonic prediction; tide - time series;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tide - time series
+
+Acronym: T_TIMS Code: 142
+Tide - time series T_TIMS 142
+
+Set Attribute_A: NOBJNM; OBJNAM; T_ACWL; T_HWLW; T_TINT;
+ T_TSVL; TIMEND; TIMSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Tide - the periodic rise and fall of the surface of the sea, due
+principally to the gravitational interaction between moon, sun and
+earth. (adopted from IHO Dictionary, S-32, 5th Edition, 5429)
+
+Tidal heights over time may be approximated by a series of height
+values given at regular time intervals, starting from a specified
+moment in time.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The object `tide - time series' encodes tidal heights at equal time
+intervals and times and heights of high waters and low waters.
+
+Distinction: tide - harmonic prediction; tide - non-harmonic
+ prediction;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tideway
+
+Acronym: TIDEWY Code: 143
+Tideway TIDEWY 143
+
+Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A natural water course in intertidal areas where water flows during
+the ebb or flow.
+
+A channel through which a tidal current runs. (IHO Dictionary, S-32,
+5th Edition, 5502)
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: canal; river; sea area/named water area
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Topmark
+
+Acronym: TOPMAR Code: 144
+Topmark TOPMAR 144
+
+Set Attribute_A: COLOUR; COLPAT; HEIGHT; MARSYS; STATUS;
+ TOPSHP; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A characteristic shape secured at the top of a buoy or beacon to aid
+in its identification. (IHO Dictionary, S-32, 5th Edition, 5548)
+
+References:
+
+INT 1: IQ 9;
+
+M-4: 463.1;
+
+Remarks:
+
+The body carrying the topmark is a separate object.
+
+Distinction: beacon, cardinal; beacon, isolated danger;
+ beacon, lateral; beacon, safe water; beacon special
+ purpose/general; buoy, cardinal; buoy, installation; buoy,
+ isolated danger; buoy, lateral; buoy, safe water; buoy,
+ special purpose/general; daymark;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Tower
+
+Acronym: TOWERS
+Tower TOWERS
+
+
+Set Attribute_A: CATTOW; COLOUR; COLPAT; CONDTN; CONRAD;
+ CONVIS; HEIGHT; NATCON; NOBJNM; OBJNAM; QUAVEM; STATUS;
+ VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A relatively tall structure which may be used for observation,
+support, storage or communication etc.. (Digital Geographic
+Information Working Group, Oct.87)
+
+References:
+
+INT 1: IE 20-21, 29, 30.2;
+
+M-4: 374,2-3; 375,2-3; 487;
+
+Remarks:
+
+The object `tower' is independent of any equipment carried upon it.
+This is specified by other objects. e.g. radar station, light.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A tower should be encoded as a landmark (LNDMRK) with
+category of landmark (CATLMK) value 17.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation line
+
+Acronym: TSELNE Code: 145
+Traffic separation line TSELNE 145
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+A traffic separation line is a line separating traffic lanes in which
+ships are travelling in opposite or nearly opposite directions; or
+separating traffic lanes designated for particular classes of ships
+proceeding in the same direction (IMO Ships Routeing, 6th Edition).
+
+References:
+
+INT 1: IM 12;
+
+M-4: 435.1;
+
+Remarks:
+
+Distinction: traffic separation scheme boundary; traffic
+ separation scheme crossing; traffic separation scheme lane
+ part; traffic separation scheme roundabout; traffic separation
+ zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation scheme boundary
+
+Acronym: TSSBND Code: 146
+Traffic separation scheme boundary TSSBND 146
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+The boundary of a traffic separation scheme is the outer limit of a
+traffic lane part or a traffic separation scheme roundabout.
+
+References:
+
+INT 1: not specified;
+
+M-4: 436;
+
+Remarks:
+
+Distinction: traffic separation line; traffic separation scheme
+ crossing; traffic separation scheme lane part; traffic
+ separation scheme roundabout; traffic separation zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation scheme crossing
+
+Acronym: TSSCRS Code: 147
+Traffic separation scheme crossing TSSCRS 147
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+A traffic separation scheme crossing is a defined area where traffic
+lanes cross.
+
+References:
+
+INT 1: IM 23;
+
+M-4: 435.1;
+
+Remarks:
+
+Distinction: traffic separation line; traffic separation
+ scheme boundary; traffic separation scheme lane part; traffic
+ separation scheme roundabout; traffic separation zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation scheme lane part
+
+Acronym: TSSLPT Code: 148
+Traffic separation scheme lane part TSSLPT 148
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; ORIENT; RESTRN;
+ STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+A traffic lane is an area within defined limits in which one-way
+traffic flow is established (IMO Ships Routeing, 6th Edition).
+
+A traffic separation scheme lane part is an area of a traffic lane in
+which the direction of flow of traffic is uniform.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+The complete traffic lane may consist of one or more lane parts
+depending on the shape of the lane.
+
+Distinction: recommended traffic lane part; traffic separation
+ line; traffic separation scheme boundary; traffic separation
+ scheme crossing; traffic separation scheme roundabout; traffic
+ separation zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation scheme roundabout
+
+Acronym: TSSRON Code: 149
+Traffic separation scheme roundabout TSSRON 149
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; RESTRN; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+A roundabout is a traffic separation scheme in which traffic moves in
+a counter-clockwise direction around a specified point or zone. (IHO
+Dictionary, S-32, 5th Edition, 4448)
+
+References:
+
+INT 1: IM 21;
+
+M-4: 435.1;
+
+Remarks:
+
+Distinction: traffic separation line; traffic separation
+ scheme boundary; traffic separation scheme crossing; traffic
+ separation scheme lane part; traffic separation zone;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Traffic separation zone
+
+Acronym: TSEZNE Code: 150
+Traffic separation zone TSEZNE 150
+
+Set Attribute_A: CATTSS; DATEND; DATSTA; STATUS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A traffic separation scheme is a scheme which aims to reduce the risk
+of collision in congested and/or converging areas by separating
+traffic moving in opposite, or nearly opposite, directions. (IHO
+Dictionary, S-32, 5th Edition, 5585)
+
+A traffic separation zone is a zone separating the lanes in which
+ships are proceeding in opposite or nearly opposite directions; or
+separating traffic lanes designated for particular classes of ships
+proceeding in the same direction (IMO Ships Routeing, 6th Edition).
+
+References:
+
+INT 1: IM 13, 20.1;
+
+M-4: 435.1;
+
+Remarks:
+
+Distinction: traffic separation line; traffic separation
+ scheme boundary; traffic separation scheme crossing; traffic
+ separation scheme lane part; traffic separation scheme
+ roundabout;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Tree
+
+Acronym: TREPNT
+Tree TREPNT
+INT 1: IC 31-31.8;
+
+M-4: 354.2;
+
+
+Set Attribute_A: CATTRE; CONVIS; HEIGHT; NOBJNM; OBJNAM;
+ QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A woody perennial plant having a self supporting main stem or trunk
+and a definite crown. (United States Geological Survey, Jan.89)
+
+Remarks:
+
+Distinction: vegetation;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A tree should be encoded as vegetation (VEGATN) with an
+appropriate category of vegetation (CATVEG) value.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Tunnel
+
+Acronym: TUNNEL Code: 151
+Tunnel TUNNEL 151
+
+Set Attribute_A: BURDEP; CONDTN; HORACC; HORCLR; NOBJNM;
+ OBJNAM; STATUS; VERACC; VERCLR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A passage that is open to the atmosphere at both ends, buried under
+the sea bed or laid over the sea floor or bored under the ground or
+through mountains.
+
+References:
+
+INT 1: ID 16;
+
+M-4: 363.1;
+
+Remarks:
+
+Distinction: railway; road;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Tunnel entrance
+
+Acronym: TNLENT
+Tunnel entrance TNLENT
+INT 1: ID 16;
+
+M-4: 363.1;
+
+
+Set Attribute_A: HORCLR; NOBJNM; OBJNAM; VERCLR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Line;
+
+
+Definition:
+-----------
+
+An opening that affords entry to an underground or underwater passage.
+(United States Geological Survey, Jan.89)
+
+Remarks:
+
+No remarks
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A tunnel should be encoded using the object class
+tunnel (TUNNEL).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Two_way route part
+
+Acronym: TWRTPT Code: 152
+Two_way route part TWRTPT 152
+
+Set Attribute_A: CATTRK; DATEND; DATSTA; DRVAL1; DRVAL2;
+ ORIENT; QUASOU; SOUACC; STATUS; TECSOU; TRAFIC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A two-way route is a route within defined limits inside which two-way
+traffic is established, aimed at providing safe passage of ships
+through waters where navigation is difficult or dangerous. (IHO
+Dictionary, S-32, 5th Edition, 5712)
+
+A two-way route part is an area of a two-way route within which
+traffic flow is generally along one bearing (and possibly its
+reciprocal).
+
+References:
+
+INT 1: IM 28.2;
+
+M-4: 435.6;
+
+Remarks:
+
+The complete two_way route consists of one or more parts depending on
+the shape of the two_way route.
+
+The orientation of the two_way route part is defined by its centerline
+and is related to the general direction of the two_way route.
+
+Distinction: deep water route part; recommended traffic lane
+ part; traffic separation scheme lane part;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Underwater/awash rock
+
+Acronym: UWTROC Code: 153
+Underwater/awash rock UWTROC 153
+
+Set Attribute_A: EXPSOU; NATQUA; NATSUR; NOBJNM; OBJNAM;
+ QUASOU; SOUACC; STATUS; TECSOU; VALSOU; VERDAT; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A concreted mass of stony material or coral which dries, is awash or
+is below the water surface.
+
+References:
+
+INT 1: IK 12, 13, 14-16;
+
+M-4: 421.3_5;
+
+Remarks:
+
+Distinction: obstruction; sounding; wreck;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Unsurveyed area
+
+Acronym: UNSARE Code: 154
+Unsurveyed area UNSARE 154
+
+Set Attribute_A:
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area for which no bathymetric survey information is available.
+
+References:
+
+INT 1: not specified;
+
+M-4: 417.8;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Vegetation
+
+Acronym: VEGATN Code: 155
+Vegetation VEGATN 155
+
+Set Attribute_A: CATVEG; CONVIS; ELEVAT; HEIGHT, NOBJNM;
+ OBJNAM; VERACC; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Collections of, or individual plants.
+
+References:
+
+INT 1: IC 14, 30, 31.1-8, 32;
+
+M-4: 312.4; 354.1-2,4;
+
+Remarks:
+
+Distinction: seabed area; weed/kelp;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Vegetation area
+
+Acronym: VEGARE
+Vegetation area VEGARE
+
+Set Attribute_A: CATVEG; CONVIS; HEIGHT, NOBJNM; OBJNAM;
+ VERACC; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A land area or an intertidal area, covered by any kind of plants.
+
+References:
+
+INT 1: IC 14, 30, 32;
+
+M-4: 312.4; 354;
+
+Remarks:
+
+Distinction: coastline; seabed area; tree; weed/kelp;
+
+This object class is obsolete. It is only included here for reasons of
+backward compatibility. Vegetation areas should be encoded as
+vegetation (VEGATN).
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Water turbulence
+
+Acronym: WATTUR Code: 156
+Water turbulence WATTUR 156
+
+Set Attribute_A: CATWAT; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The disturbance of water caused by the interaction of any combination
+of waves, currents, tidal streams, wind, shoal patches and
+obstructions.
+
+References:
+
+INT 1: IH 44, 45; IK 17;
+
+M-4: 423.1; 423.2; 423.3;
+
+Remarks:
+
+No remarks.
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Waterfall
+
+Acronym: WATFAL Code: 157
+Waterfall WATFAL 157
+
+Set Attribute_A: CONVIS; NOBJNM; OBJNAM; VERACC; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A sudden descent of water over a step in the bed of a river. In place
+names commonly shortened to fall or falls, e.g. Niagara Falls.
+
+References:
+
+INT 1: IC 22;
+
+M-4: 353.5;
+
+Remarks:
+
+Distinction: rapids;
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Weed/Kelp
+
+Acronym: WEDKLP Code: 158
+Weed/Kelp WEDKLP 158
+
+Set Attribute_A: CATWED; NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Seaweed is the general name for marine plants of the Algae class which
+grow in long narrow ribbons. (International Maritime Dictionary, 2nd
+Ed.)
+
+Kelp is one of an order (laminariales) of usually large, blade-shaped
+or vine-like brown algae. (IHO Dictionary, S-32, 5th Edition, 2611)
+
+References:
+
+INT 1: IJ 13.1, 13.2;
+
+M-4: 428.2;
+
+Remarks:
+
+Kelp is often an indication of the presence of submerged rocks. (IHO
+Chart Specifications M-4)
+
+Distinction: seabed area; vegetation;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Weir
+
+Acronym: WIRLNE
+Weir WIRLNE
+
+Set Attribute_A: CONDTN; DATEND; DATSTA; NATCON; NOBJNM;
+ OBJNAM; QUAVEM; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A dam erected across a river to raise the level of the water. The word
+is now restricted to smaller works, the larger are called dams. (IHO
+Dictionary, S-32, 5th Edition, 5967)
+
+References:
+
+INT 1: IF 44;
+
+M-4: 364.2;
+
+Remarks:
+
+Distinction: causeway; dam;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A weir should be encoded as a dam (DAMCON) with a
+category of dam (CATDAM) value 1.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Windmill
+
+Acronym: WNDMIL
+Windmill WNDMIL
+INT 1: IE 25.1, 25.2;
+
+M-4: 374.5;
+
+
+Set Attribute_A: COLOUR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NATCON; NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point; Area;
+
+
+Definition:
+-----------
+
+A mill that runs on the energy generated by a wheel of adjustable
+blades or flats rotated by the wind. (United States Geological
+Survey, Jan.89)
+
+Remarks:
+
+Distinction: windmotor;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A windmill should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 18.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Windmotor
+
+Acronym: WIMCON
+Windmotor WIMCON
+INT 1: IE 26;
+
+M-4: 374.6;
+
+
+Set Attribute_A: COLOUR; CONDTN; CONRAD; CONVIS; HEIGHT;
+ NOBJNM; OBJNAM; QUAVEM; VERDAT; VERLEN;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Point;
+
+
+Definition:
+-----------
+
+A modern structure for use of wind power. (IHO Chart Specifications,
+M-4)
+
+
+Remarks:
+
+Distinction: windmill;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A windmotor should be encoded as a landmark (LNDMRK)
+with a category of landmark (CATLMK) value 19.
+
+ DELETED - DO NOT USE
+ GEO OBJECT CLASSES
+
+
+
+Object Class: Wreck
+
+Acronym: WRECKS Code: 159
+Wreck WRECKS 159
+
+Set Attribute_A: CATWRK; CONRAD; CONVIS; EXPSOU; HEIGHT;
+ NOBJNM; OBJNAM; QUASOU; SOUACC; STATUS; TECSOU; VALSOU;
+ VERACC; VERDAT; VERLEN; WATLEV;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+The ruined remains of a stranded or sunken vessel which has been
+rendered useless. (IHO Dictionary, S-32, 5th Edition, 6027)
+
+References:
+
+INT 1: IK 20-30;
+
+M-4: 422-422.8;
+
+Remarks:
+
+Distinction: depth area; hulk; obstruction; sounding;
+ underwater/awash rock;
+ GEO OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Zero metre _ contour
+
+Acronym: ZEMCNT
+Zero metre _ contour ZEMCNT
+INT 1: II 30;
+
+M-4: 404.2; 410-411;
+
+
+Set Attribute_A: VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; SCAMAX; SCAMIN;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Geometric Primitive: Line;
+
+
+Definition:
+-----------
+
+The limit line between an area permanently covered by water and an
+intertidal area.
+
+Remarks:
+
+Distinction: coastline; depth contour;
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. A zero metre contour should be encoded as a depth
+contour (DEPCNT) with a value of depth contour (VALDCO) of zero.
+
+ DELETED - DO NOT USE
+ Page intentionally left blank
+
+
+ 1.3 Meta Object Classes
+ META OBJECT CLASSES
+
+
+
+Object Class: Accuracy of data
+
+Acronym: M_ACCY Code: 300
+Accuracy of data M_ACCY 300
+
+Set Attribute_A: HORACC; POSACC; SOUACC; VERACC;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which the best estimate of the overall accuracy of the
+data is uniform. The overall accuracy takes into account for example
+the source accuracy, chart scale, digitising accuracy etc.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: quality of data; survey reliability;
+ META OBJECT CLASSES
+
+
+
+Object Class: Compilation scale of data
+
+Acronym: M_CSCL Code: 301
+Compilation scale of data M_CSCL 301
+
+Set Attribute_A: CSCALE;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which the data was originally compiled at a uniform
+scale. For example, it may define the scale of the paper chart from
+which the data was digitised.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+No remarks.
+ META OBJECT CLASSES
+
+
+
+Object Class: Coverage
+
+Acronym: M_COVR Code: 302
+Coverage M_COVR
+
+Set Attribute_A: CATCOV;
+
+Set Attribute_B: INFORM; NINFOM;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+Definition:
+-----------
+
+A geographical area that describes the coverage and extent of spatial
+objects.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+This object class is intended to support an indication of coverage.
+ META OBJECT CLASSES
+
+
+
+Object Class: Horizontal datum of data
+
+Acronym: M_HDAT Code: 303
+Horizontal datum of data M_HDAT 303
+
+Set Attribute_A: HORDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of uniform horizontal datum.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: horizontal datum shift parameters;
+ META OBJECT CLASSES
+
+
+
+Object Class: Horizontal datum shift parameters
+
+Acronym: M_HOPA Code: 304
+Horizontal datum shift parameters M_HOPA
+
+Set Attribute_A: HORDAT; SHIPAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMAX; SCAMIN;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which a uniform shift exists between a specific
+geodetic datum and the datum of the data within this area.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: horizontal datum of data;
+ META OBJECT CLASSES
+
+
+
+Object Class: Nautical publication information
+
+Acronym: M_NPUB Code: 305
+Nautical publication information M_NPUB 305
+
+Set Attribute_A:
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; PUBREF;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Used to relate additional nautical information or publications to the
+data.
+
+References:
+
+INT 1: not specified
+
+M-4: not specified
+
+Remarks:
+
+For example, geographic areas may be defined that relate to sections
+in Sailing Directions (Coast Pilots).
+ META OBJECT CLASSES
+
+
+
+Object Class: Navigational system of marks
+
+Acronym: M_NSYS Code: 306
+Navigational system of marks M_NSYS 306
+
+Set Attribute_A: MARSYS; ORIENT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; SCAMIN; SCAMAX;
+ TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which a specific system of navigational marks applies
+and/or a common direction of buoyage.
+
+References:
+
+INT 1: IQ 130-130.6;
+
+M-4: 461.1-4;
+
+Remarks:
+
+No remarks.
+ META OBJECT CLASSES
+
+
+
+Object Class: Production information
+
+Acronym: M_PROD Code: 307
+Production information M_PROD 307
+
+Set Attribute_A: AGENCY; CPDATE; NATION; NMDATE; PRCTRY;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which uniform data production parameters apply.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+No remarks.
+ META OBJECT CLASSES
+
+
+
+Object Class: Quality of data
+
+Acronym: M_QUAL Code: 308
+Quality of data M_QUAL 308
+
+Set Attribute_A: CATQUA; CATZOC; DRVAL1; DRVAL2; POSACC;
+ SOUACC; SUREND; SURSTA; TECSOU; VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which a uniform assessment of the quality of the data
+exists.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: accuracy of data; survey reliability;
+ META OBJECT CLASSES
+
+
+
+Object Class: Sounding datum
+
+Acronym: M_SDAT Code: 309
+Sounding datum M_SDAT 309
+
+Set Attribute_A: VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of uniform sounding datum.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: vertical datum;
+ META OBJECT CLASSES
+
+
+
+Object Class: Survey reliability
+
+Acronym: M_SREL Code: 310
+Survey reliability M_SREL 310
+
+Set Attribute_A: QUAPOS; QUASOU; SCVAL1; SCVAL2; SDISMN;
+ SDISMX; SURATH; SUREND; SURSTA; SURTYP; TECSOU;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area within which a uniform assessment of the reliability of source
+survey information exists.
+
+References:
+
+INT 1: not specified;
+
+M-4: 170.2; 178;
+
+Remarks:
+
+Distinction: accuracy of data; quality of data;
+ META OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Survey source
+
+Acronym: M_SSOR
+Survey source M_SSOR
+
+Set Attribute_A: DATEND; DATSTA; SCVAL1; SCVAL2; SURATH;
+ SUREND; SURSTA; SURTYP; TECSOU;
+
+Set Attribute_B: INFORM; NINFOM;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+This object class defines an area within which the details of the
+source survey(s) used for chart compilation are uniform.
+
+References:
+
+INT 1: Not specified
+
+M-4: 170; 171; 174; 175; 176; 177; 178;
+
+Remarks:
+
+The source data provides a guide to the degree of confidence a mariner
+should have in the adequacy and accuracy of charted depths and
+positions.
+
+This object is obsolete. It is only shown here for reasons of backward
+compatibility. Survey source should be encoded under survey
+reliability (M_SREL).
+
+ DELETED - DO NOT USE
+ META OBJECT CLASSES
+
+
+
+Object Class: Units of measurement of data
+
+Acronym: M_UNIT Code: 311
+Units of measurement of data M_UNIT 311
+
+Set Attribute_A: DUNITS; HUNITS; PUNITS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of uniform units of depth and/or height measurement.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+No remarks;
+ META OBJECT CLASSES
+
+
+
+Object Class: Vertical datum of data
+
+Acronym: M_VDAT Code: 312
+Vertical datum of data M_VDAT 312
+
+Set Attribute_A: VERDAT;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area of uniform vertical datum.
+
+References:
+
+INT 1: not specified;
+
+M-4: not specified;
+
+Remarks:
+
+Distinction: sounding datum;
+ Page intentionally left blank
+
+ 1.4 Collection Object Classes
+ COLLECTION OBJECT CLASSES
+
+
+
+Object Class: Aggregation
+
+Acronym: C_AGGR Code: 400
+Aggregation C_AGGR 400
+
+ Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Used to identify an aggregation of two or more objects. This
+aggregation may be named.
+
+Remarks:
+
+An aggregation could be used to combine objects that are related in
+some way (is-a-part-of, is-a-component-of) into a higher level object.
+
+For example: an aggregation relationship may be used to form a traffic
+separation scheme from traffic separation lane parts, boundaries, etc.
+
+Distinction : association; stacked on/stacked under;
+ COLLECTION OBJECT CLASSES
+
+
+
+Object Class: Association
+
+Acronym: C_ASSO Code: 401
+Association C_ASSO 401
+
+ Set Attribute_A: NOBJNM; OBJNAM;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Used to identify an association between two or more objects. The
+association may be named.
+
+Remarks:
+
+For example: an association relationship may be used to indicate that
+a buoy marks a wreck.
+
+Distinction : aggregation; stacked on/stacked under;
+ COLLECTION OBJECT CLASSES
+
+
+
+Object Class: Stacked on/stacked under
+
+Acronym: C_STAC Code: 402
+Stacked on/stacked under C_STAC 402
+
+Set Attribute_A:
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+Used to identify the order of stacking of objects (eg. bridge on top
+ of road).
+
+Remarks:
+
+The order in which objects are stacked is indicated in the Feature
+Record to Feature Object Pointer field (FFPT, refer to S-57 Part 3).
+
+Distinction: aggregation; association;
+
+ 1.5 Cartographic Object Classes
+ CARTOGRAPHIC OBJECT CLASSES
+
+
+
+Object Class: Cartographic area
+
+Acronym: $AREAS Code: 500
+Cartographic area $AREAS 500
+
+ Set Attribute_A: COLOUR; ORIENT; $SCODE; $TINTS;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area in which a certain cartographic symbolization is required.
+
+Remarks:
+
+No remarks.
+ CARTOGRAPHIC OBJECT CLASSES
+
+
+
+Object Class: Cartographic line
+
+Acronym: $LINES Code: 501
+Cartographic line $LINES 501
+
+ Set Attribute_A: $SCODE;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A line with a certain cartographic symbolization.
+
+Remarks:
+
+No remarks.
+ CARTOGRAPHIC OBJECT CLASSES
+
+
+
+Object Class: Cartographic symbol
+
+Acronym: $CSYMB Code: 502
+Cartographic symbol $CSYMB 502
+
+ Set Attribute_A: ORIENT; $SCALE; $SCODE;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A point with a certain cartographic symbolization.
+
+Remarks:
+
+No remarks.
+ CARTOGRAPHIC OBJECT CLASSES
+
+ DELETED - DO NOT USE
+
+Object Class: Closing line
+
+Acronym: $CLOLN
+Closing line $CLOLN
+
+ Set Attribute_A:
+
+Set Attribute_B: SCAMAX; SCAMIN;
+
+Set Attribute_C:
+
+
+Definition:
+-----------
+
+Remarks:
+
+This object is obsolete. It is only shown here for reasons of
+backward compatibility. Closing lines should be encoded using the
+Masking indicator subfield (MASK) of the Feature Record to Spatial
+Record Pointer field (FSPT, refer to S-57 Part 3).
+
+ DELETED - DO NOT USE
+ CARTOGRAPHIC OBJECT CLASSES
+
+
+
+Object Class: Compass
+
+Acronym: $COMPS Code: 503
+Compass $COMPS 503
+
+ Set Attribute_A: $CSIZE; RYRMGV; VALACM; VALMAG;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A circle graduated in degrees clockwise form 0 (north) to 360 used to
+facilitate measurements of direction. May be oriented to true or
+magnetic north. (adapted from IHO Dictionary, S-32, 5th Edition, 942)
+
+Remarks:
+
+This object is used to transfer the parameters required to represent
+the magnetic and/or true compass cartographically.
+ CARTOGRAPHIC OBJECT CLASSES
+
+DELETED - DO NOT USE
+
+Object Class: Shallow water blue
+
+Acronym: $SHABL
+Shallow water blue $SHABL
+
+ Set Attribute_A: $TINTS
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+An area that is to be cartographically represented by a `shallow water
+blue' tint.
+
+Remarks:
+
+To be used to define depth areas which need to be coloured blue (since
+the limits of the shallow water blue areas on paper charts are not
+universally standardised). Corresponding cartographic objects are not
+required for land area (buff tint) and intertidal area (green tint),
+since these can be deduced from existing real world objects.
+
+This object class is obsolete. It is only included here for reasons of
+backward compatibility. Shallow water blue areas should be encoded
+using the object class cartographic area ($AREAS).
+
+DELETED - DO NOT USE
+ CARTOGRAPHIC OBJECT CLASSES
+
+
+
+Object Class: Text
+
+Acronym: $TEXTS Code: 504
+Text $TEXTS 504
+
+ Set Attribute_A: $CHARS; COLOUR; $JUSTH; $JUSTV; $NTXST;
+ $SPACE; $TXSTR;
+
+Set Attribute_B: INFORM; NINFOM; NTXTDS; PICREP; SCAMAX;
+ SCAMIN; TXTDSC;
+
+Set Attribute_C: RECDAT; RECIND; SORDAT; SORIND;
+
+
+Definition:
+-----------
+
+A text string that is to be represented using a certain cartographic
+symbolization.
+
+Remarks:
+
+May be used for all text strings which are required to be represented
+in graphical form with particular positioning and display
+characteristics.
+
+Rotation and curving of text can be handled by the use of 2 or more
+x,y coordinate pairs in the associated spatial object.
Added: packages/openev/branches/upstream/current/contrib/S52/ex0_xwin.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/ex0_xwin.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/ex0_xwin.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,227 @@
+/***********************************************************************/
+/* This example code demonstrates an OpenGL application program that */
+/* displays a blue cube and a red pyramid in a simple X window. */
+/* */
+/* */
+/* The features of this example include: */
+/* - Opens an X window */
+/* - Creates an OpenGL viewport */
+/* - Renders a simple static world */
+/* */
+/* Considerations: */
+/* - A lot of code is necessary to open the GLX window (X w/ OpenGL) */
+/* - The main loop would typically watch for many more X Events */
+/* */
+/* This application uses the files: */
+/* - shapes.c (Bill Sherman's simple OpenGL shapes) */
+/* */
+/* Copyright 1998, University of Illinois Board of Trustees */
+/***********************************************************************/
+#include <stdio.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include "S52GL.h"
+
+#include <stdlib.h> // exit()
+
+
+void draw_world();
+extern void setupData();
+static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 4, None};
+static int dblBuf[] = {GLX_RGBA,
+ GLX_DEPTH_SIZE, 4,
+ GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE,3,
+ GLX_GREEN_SIZE,3,
+ GLX_BLUE_SIZE,3,
+ GLX_STENCIL_SIZE,1,
+ None};
+
+Display *dpy;
+Window win;
+GLboolean doubleBuffer = GL_TRUE;
+
+
+int main(int argc, char* argv[])
+{
+ XVisualInfo *vi;
+ Colormap cmap;
+ XSetWindowAttributes swa;
+ GLXContext cx;
+ XEvent event;
+ int dummy;
+
+ /********************************/
+ /*** Initialize GLX routines ***/
+ /********************************/
+ /*** open a connection to the X server ***/
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL) {
+ perror("could not open display");
+ exit(0);
+ }
+
+ /*** make sure OpenGL's GLX extension supported ***/
+ if (!glXQueryExtension(dpy, &dummy, &dummy)) {
+ perror("X server has no OpenGL GLX extension");
+ exit(0);
+ }
+
+ /*** find an appropriate visual ***/
+ /* find an OpenGL-capable RGB visual with depth buffer */
+ vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
+ if (vi == NULL) {
+ vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
+ if (vi == NULL) {
+ perror("no RGB visual with depth buffer");
+ exit(0);
+ }
+ doubleBuffer = GL_FALSE;
+ }
+ if (vi->class != TrueColor) {
+ perror("TrueColor visual required for this program");
+ exit(0);
+ }
+
+ /*** create an OpenGL rendering context ***/
+ /* create an OpenGL rendering context */
+ cx = glXCreateContext(dpy, vi, /* no sharing of display lists */ None,
+ /* direct rendering if possible */ GL_TRUE);
+ if (cx == NULL) {
+ perror("could not create rendering context");
+ exit(0);
+ }
+
+ /*** create an X window with the selected visual ***/
+ /* create an X colormap since probably not using default visual */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ swa.colormap = cmap;
+ swa.border_pixel = 0;
+ swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
+ win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 493, 493, 0, vi->depth,
+ InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
+ XSetStandardProperties(dpy, win, "glxsimple", "glxsimple", None, argv, argc, NULL);
+
+ /*** bind the rendering context to the window ***/
+ glXMakeCurrent(dpy, win, cx);
+
+ /*** request the X window to be displayed on the screen ***/
+ XMapWindow(dpy, win);
+
+ /*** configure the OpenGL context for rendering ***/
+ //z glEnable(GL_DEPTH_TEST);/* enable depth buffering */
+ glDepthFunc(GL_LESS); /* pedantic, GL_LESS is the default */
+ glClearDepth(1.0); /* pedantic, 1.0 is the default */
+ /* frame buffer clears should be to black */
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ /* set up projection transform */
+ //glMatrixMode(GL_PROJECTION);
+ //glLoadIdentity();
+ //glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
+ /* establish initial viewport */
+ glViewport(0, 0, 493, 493); /* pedantic, full window size is default viewport */
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // glOrtho(0,100, 100,0, -1,1);
+ int width = 493;
+ int height = 493;
+ glOrtho(-width/2.0, width/2.0, -height/2.0, height/2.0, -1000.0f, 1000.0f);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_DITHER);
+ glShadeModel(GL_FLAT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glRotated(0.0, 0.0, 0.0, 1.0);
+ // glScale(1500, 1500,1.0);
+ glScaled(3944, 3944,1.0);
+
+ glTranslated(-10.4375, -55.44625, 0.0);
+
+ S52_GL_initGL(dpy, 0);
+ if (!S52_GL_validCtx()){
+ printf("not a proper context. Exiting ...");
+ exit(1);
+ }
+
+ setupData();
+ fprintf(stderr, "Now starting ... \n");
+ /***************************/
+ /*** do world simulation ***/
+ /***************************/
+ while (1) {
+ do {
+ XNextEvent(dpy, &event);
+ switch (event.type) {
+ case ConfigureNotify:
+ ;// glViewport(0, 0, event.xconfigure.width, event.xconfigure.height);
+ }
+ } while (XPending(dpy));
+
+ /*** Handle projection ***/
+ // glMatrixMode(GL_MODELVIEW);
+ // glLoadIdentity();
+ // glTranslatef(0.0, -2.0, -3.0);
+
+ /*** Render the world ***/
+ // draw_world();
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ S52_GL_draw(0);
+ /*** Swap buffers (or flush GL cue) ***/
+ if (doubleBuffer)
+ glXSwapBuffers(dpy, win);
+ else
+ glFlush();
+ glXMakeCurrent(dpy, win, cx);
+ }
+
+ return 1;
+}
+
+
+
+/* ----------------8<-----------------8<-----------------8<----------------*/
+/* In a non-example applicatation, the following would be a separate file. */
+
+/**************************/
+/**************************/
+/** The Graphics section **/
+/**************************/
+/**************************/
+
+void draw_cube();
+void draw_pyramid();
+
+
+/*********************/
+/* draw_world(): ... */
+/*********************/
+void draw_world(void)
+{
+ glShadeModel(GL_SMOOTH);
+
+ /**************************************/
+ /* clear the screen -- very important */
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClearDepth(1.0);
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+ /************************/
+ /* draw all the objects */
+
+ /* a blue cube */
+ glColor3ub(100, 100, 255);
+ glTranslatef(-2.0, 1.0, -6.0);
+ // draw_cube();
+
+ /* a red pyramid */
+ glColor3ub(255, 100, 100);
+ glTranslatef(4.0, 0.0, 0.0);
+ // draw_pyramid();
+}
Added: packages/openev/branches/upstream/current/contrib/S52/gvS57layer.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/gvS57layer.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/gvS57layer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,221 @@
+// gvS57layer.c: S57 layer classe for OpenEV
+//
+// Project: OpENCview/OpenEV
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#include "gvS57layer.h"
+
+#include "S52GL.h" // S52_GL_objectSetup()
+#include "S52PL.h" // S52_PL_lookup(), S52_LUP, S52_LUPtnm
+#include "S57src.h" // S57_loadObject()
+#include "S52utils.h" // PRINTF()
+
+#include <stdlib.h>
+#include <stdio.h> // printf()
+#include <string.h> // strncmp()
+
+#include <gtk/gtksignal.h>
+//#include <gtkgl/gdkgl.h> // GdkGLContext
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <gmodule.h> // g_module_init()
+
+#include <glib.h> // GQuark, datalist, ...
+
+static GModule *self = NULL; // handel to libS52.so (this)
+
+static void _motion_handle_hint(GtkWidget *view, GdkEventMotion *event)
+{
+ if (event->type==GDK_BUTTON_RELEASE && event->state & GDK_SHIFT_MASK) {
+ S57_geo *geoData = S52_GL_doPick(event->x, event->y);
+ S57_unlinkObj(geoData);
+
+ //gtk_signal_emit_by_name(GTK_OBJECT(view), "gldraw");
+ }
+}
+
+static void gv_S57_layer_setup(GvLayer *rlayer, GvViewArea *view)
+// load S57 layer's objects
+{
+ static int first = 1;
+ //static int debug = 0;
+ GdkVisual *_visual;
+ GdkGLContext *_glcontext = NULL;
+
+ int i = 0;
+ gint nShapes = 0;
+ char *name = NULL;
+
+ if (NULL == rlayer) {
+ PRINTF("ERROR no layer\n");
+ return;
+ }
+
+ // at this point we can connect the signal from class view
+ if (first) {
+ ////////////////////////////////////////////////////////////////
+ //
+ // set visual & get GL info
+ //
+ {
+ int attrlist[] = {
+ GDK_GL_RGBA,
+ GDK_GL_DOUBLEBUFFER,
+ //GDK_GL_DEPTH_SIZE, 4,
+ GDK_GL_RED_SIZE, 3,
+ GDK_GL_GREEN_SIZE, 3,
+ GDK_GL_BLUE_SIZE, 3,
+ GDK_GL_STENCIL_SIZE, 1,
+ GDK_GL_NONE
+ };
+
+ printf("gv_S57_layer_setup initialising \n");
+ if (!S52_GL_validCtx()) {
+ // check/setup GL for S52 rendering
+
+ //g_return_if_fail(GTK_WIDGET_REALIZED(GTK_WIDGET(view)));
+
+ //gtk_gl_area_make_current(GTK_GL_AREA(view));
+ _visual = gdk_gl_choose_visual(attrlist);
+ if (_visual == NULL) {
+ PRINTF("gdk_gl_choose_visual.. failed \n");
+ exit(0);
+ //return 0;
+ }
+
+ //old_glcontext = *glcontext;
+ //glcontext = gdk_gl_context_share_new(visual, NULL , TRUE);
+ _glcontext = gdk_gl_context_share_new(_visual, NULL , TRUE);
+ if (_glcontext == NULL || !S52_GL_validCtx()) {
+ PRINTF("gdk_gl_context_share_new.. failed \n");
+ exit(0);
+ //return 0;
+ }
+
+ }
+ S52_GL_init(GDK_DISPLAY(),0);
+ }
+
+ gtk_signal_connect_object(GTK_OBJECT(view), "gldraw",
+ GTK_SIGNAL_FUNC(S52_GL_draw),
+ GTK_OBJECT(view));
+
+ gtk_signal_connect_object(GTK_OBJECT(view), "button-release-event",
+ GTK_SIGNAL_FUNC(_motion_handle_hint),
+ GTK_OBJECT(view));
+
+ first = 0;
+
+ /*
+ {
+ // set
+ S57_geo *geoData = S57_loadObject("NORTHAR1", NULL);
+ S52_obj *obj = S52_PL_getObj(geoData);
+ S52_GL_objectSetup(obj);
+ }
+ */
+ }
+
+ nShapes = gv_shapes_num_shapes(GV_SHAPES_LAYER(rlayer)->data);
+ name = (char *)gv_data_get_name(GV_DATA(rlayer));
+ printf("LAYER NAME: %s (%d)\n", name, nShapes);
+
+ for (i=0; i<nShapes; ++i) {
+ GvShape *shape = gv_shapes_get_shape(GV_SHAPES_LAYER(rlayer)->data, i);
+
+ S52_loadObject(name, (srcData*)shape);
+ }
+
+ return;
+}
+
+
+//-----------------------------------------------
+//
+// INIT SECTION
+//
+//-----------------------------------------------
+
+static void gv_S57_layer_init(GvS57Layer *rlayer)
+{
+ // layer's pre-init stuff goes here
+ //PRINTF("connecting 'setup' signal\n");
+
+ gtk_signal_connect_object(GTK_OBJECT(layer), "setup",
+ GTK_SIGNAL_FUNC(gv_S57_layer_setup),
+ GTK_OBJECT(layer));
+}
+
+#if 0
+static void gv_S57_layer_finalize (GvS57Layer *rlayer, GvViewArea *view)
+{
+ return;
+}
+#endif
+
+
+//--------------------------------------------------
+//
+// PLUD-IN SECTION
+//
+//--------------------------------------------------
+
+
+void _layer_init(GvShapesLayer *layer)
+{
+ return gv_S57_layer_init(layer);
+}
+
+const gchar * _ogr_driver_name()
+{
+ // FIXME: get this programaticaly
+ //OGRSFDriverH hDriver = ... load_S57_driver_ ...
+ //return OGR_Dr_GetName(hDriver);
+
+ // pulled from: gdal/ogr/ogrsf_frmts/s57/ogrs57driver.cpp:69
+ // in 'const char *OGRS57Driver::GetName()'
+ return "S57";
+}
+
+const gchar *g_module_check_init(GModule *module)
+{
+ PRINTF("loading libS52.so ...\n");
+
+ if (NULL == self) {
+ self = module;
+ g_print("self name = %s\n", g_basename(g_module_name(self)));
+ // will print "self name = libS52.so"
+ }
+ return NULL;
+}
+
+void g_module_unload()
+{
+ PRINTF("unloading libS52.so ...\n");
+
+ S52_PL_done();
+ S52_GL_done();
+
+ return;
+}
Added: packages/openev/branches/upstream/current/contrib/S52/gvS57layer.h
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/gvS57layer.h (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/gvS57layer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,65 @@
+// gvS57layer.h: S57 layer classe header for OpenEV
+//
+// Project: OpENCview/OpenEV
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+#ifndef _GVS57LAYER_H_
+#define _GVS57LAYER_H_
+
+#include "gvshapeslayer.h" // GvShapes
+#include <gmodule.h> // GModule
+
+
+#define GV_TYPE_S57_LAYER (gv_S57_layer_get_type ())
+#define GV_S57_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_S57_LAYER, GvS57Layer))
+#define GV_S57_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_S57_LAYER, GvS57LayerClass))
+#define GV_IS_S57_LAYER(obj) (GTK_CHECK_TYPE ((obj),GV_TYPE_S57_LAYER))
+#define GV_IS_S57_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
+ GV_TYPE_S57_LAYER))
+
+typedef struct _GvS57Layer GvS57Layer;
+typedef struct _GvS57LayerClass GvS57LayerClass;
+
+
+struct _GvS57Layer
+{
+ GvShapesLayer layer;
+};
+
+struct _GvS57LayerClass
+{
+ GvShapesLayerClass parent_class;
+};
+
+GtkType gv_S57_layer_get_type(void);
+GtkObject* gv_S57_layer_new(GvShapes *shapes);
+
+void gv_S57_layer_init(GvShapesLayer *layer);
+
+// used in plug-in mode --put here for 'completess'
+// since it's part of the interface
+void _layer_init(GvShapesLayer *layer);
+const gchar *_ogr_driver_name();
+const gchar *g_module_check_init(GModule *module);
+void g_module_unload();
+
+#endif /* __GVS57LAYER_H__ */
+
Added: packages/openev/branches/upstream/current/contrib/S52/ogrS57layers.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/ogrS57layers.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/ogrS57layers.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,118 @@
+// ogrS57layers.c: load feature from OGR directly (used by ex0)
+//
+// Project: OpENCview
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+#include "S52utils.h" // PRINTF()
+
+#include "ogr_api.h" // OGROpen(), etc.
+
+#include "S57src.h" // S57_loadObject()
+#include "S52PL.h" // S52_PL_getLUP()
+#include "S52GL.h" // S52_GL_objectSetup()
+
+
+static int _loadVector(const char *filename, int iLayer)
+{
+
+ OGRDataSourceH hDS;
+ OGRSFDriverH hDriver;
+ hDS = OGROpen( filename, FALSE, &hDriver );
+ int cntFeature = 0;
+
+ if (!hDS){
+ printf("Could not load file !! \n");
+ return 0;
+ }
+
+ for (iLayer=0; iLayer<OGR_DS_GetLayerCount(hDS); iLayer++) {
+ OGRFeatureH hFeature = NULL;
+ OGRLayerH hLayer = OGR_DS_GetLayer(hDS, iLayer);
+ OGRFeatureDefnH defn = OGR_L_GetLayerDefn(hLayer);
+ const char *name = OGR_FD_GetName(defn);
+
+ while ( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) {
+ S57_geo *geoData = S57_loadObject(hFeature);
+ // OGR_F_Destroy(hFeature); I see dumps here :-(
+
+ if (!geoData){
+ printf("missed a feature !!!\n");
+ continue;
+ }
+ cntFeature++;
+
+
+ // FIXME: not multi-thread because of LUP->cmdList not locked
+ S52_LUP *LUP = S52_PL_getLUP(name, geoData);
+
+ if (LUP == NULL)
+ PRINTF("NO look-up for Object: %s\n", name);
+ else
+ S52_GL_objectSetup(LUP, geoData, 0);
+
+ }
+ }
+
+ OGR_DS_Destroy (hDS);
+
+ return cntFeature;
+}
+
+
+void setupData(int loadData)
+{
+ { // setup env. var for OGR/S57
+ char *env = g_getenv("OGR_S57_OPTIONS");
+
+
+ if (!env ||
+ NULL == strstr(env, "UPDATES:ON") ||
+ NULL == strstr(env, "LNAM_REFS:ON") ||
+ NULL == strstr(env, "SPLIT_MULTIPOINT:ON"))
+ {
+ // env = g_string_new(env);
+#ifdef SOLARIS
+ putenv("OGR_S57_OPTIONS=LNAM_REFS:ON,UPDATES:ON,SPLIT_MULTIPOINT:ON");
+#else
+ setenv("OGR_S57_OPTIONS", "LNAM_REFS:ON,UPDATES:ON,SPLIT_MULTIPOINT:ON", 1);
+#endif
+ }
+
+ OGRRegisterAll();
+
+ if (!loadData)
+ return;
+
+ {
+ valueBuf chartPath = {'\0'};
+ //char chartPath[200];
+ if (0 == S52_getConfig(CONF_CHART, &chartPath)) {
+ printf(" .. exiting !\n");
+ exit(0);
+ } else {
+ _loadVector(chartPath, 0);
+ //_loadVector(VecViewFront, chartPath, 0);
+ }
+ }
+
+ }
+}
Added: packages/openev/branches/upstream/current/contrib/S52/s52test.c
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/s52test.c (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/s52test.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,481 @@
+// s52test.c: test driver for libS52.a, libgv.a, libGDAL.so --no python
+// Derived from Frank Warmerdan openev/testmain.c rev 1.28
+//
+// Project: OpENCview/OpenEV
+
+/*
+ This file is part of the OpENCview project, a viewer of ENC
+ Copyright (C) 2000-2004 Sylvain Duclos sduclos at users.sourceforgue.net
+
+ 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
+*/
+
+
+//#include "gvS57layer.h" // gv_S57_layer_new()
+#include "S52utils.h" // PRINTF()
+#include "S57data.h" // geocoord
+
+#include <gtk/gtk.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtkgl/gtkglarea.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include <glib.h> // GString
+
+#include "gvviewarea.h" // GV_VIEW_AREA()
+#include "gvtoolbox.h" // GvToolBox
+#include "gvviewlink.h" // GvViewLink
+#include "gvundo.h" // gv_undo_register_data()
+#include "gvselecttool.h" // gv_selection_tool_new()
+#include "gvzoompantool.h" // gv_zoompan_tool_new()
+#include "gvpointtool.h" // gv_point_tool_new()
+#include "gvlinetool.h" // gv_line_tool_new()
+#include "gvareatool.h" // gv_area_tool_new()
+#include "gvnodetool.h" // gv_node_tool_new()
+#include "gvroitool.h" // gv_roi_tool_new()
+#include "ogr_api.h" // OGROpen(), etc.
+
+//#include <math.h> // HUGE_VAL
+
+
+
+static GvToolbox *toolbox = NULL;
+static GvViewLink *link = NULL;
+
+static GtkWidget *VecViewBack = NULL;
+static GtkWidget *VecViewFront = NULL;
+static GtkWidget *VecView = NULL;
+static GtkWidget *glarea = NULL;
+
+static const char *_filename = NULL;
+
+// FOXME: get this programmaticaly
+#define DRVNAME "S57"
+
+static void _key_press_cb( GtkObject * object, GdkEventKey * event )
+
+{
+ GvViewArea *view = GV_VIEW_AREA(object);
+
+ if( event->keyval == 't' ) {
+ GTimeVal cur_time;
+ //double start_time = g_get_current_time_as_double();
+ double start_time = 0.0;
+ double end_time, spf;
+ int i, frame_count = 20;
+
+ g_get_current_time( &cur_time );
+ start_time = cur_time.tv_sec + cur_time.tv_usec / 1000000.0;
+
+ for( i = 0; i < frame_count; i++ )
+ gv_view_area_expose(GTK_WIDGET(view), NULL);
+
+ g_get_current_time( &cur_time );
+ end_time = cur_time.tv_sec + cur_time.tv_usec / 1000000.0;
+ //end_time = g_get_current_time_as_double();
+
+ spf = (end_time - start_time) / frame_count;
+ printf( "Speed is %.2ffps\n", 1.0 / spf );
+ }
+}
+
+
+static void _toolbar_callback(GtkWidget *widget, gpointer data)
+{
+ gv_toolbox_activate_tool(toolbox, (gchar*)data);
+}
+
+
+static void _link_callback(GtkWidget *widget, gpointer data)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+ gv_view_link_enable(link);
+ else
+ gv_view_link_disable(link);
+}
+
+
+static void _create_toolbar()
+{
+ GtkWidget *win;
+ GtkWidget *toolbar;
+ GtkWidget *but;
+
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ toolbar = gtk_toolbar_new(GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_TEXT);
+ gtk_container_add(GTK_CONTAINER(win), toolbar);
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ NULL,
+ "Zoom",
+ "Zoom tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "zoompan");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Select",
+ "Selection tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "select");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Points",
+ "Point drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "point");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Line",
+ "Line drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "line");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Area",
+ "Area drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "area");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Edit Node",
+ "Node edit tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "node");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw ROI",
+ "ROI drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_toolbar_callback),
+ (void *) "roi");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
+ NULL,
+ "Link",
+ "Link views together",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(_link_callback),
+ NULL);
+
+ gtk_signal_connect(GTK_OBJECT(win), "delete-event",
+ GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+ gtk_widget_show(toolbar);
+ gtk_widget_show(win);
+}
+
+static void _gv_loadLayer_cb(OGRLayerH ogrlayer, void *drvName)
+// callback to load the layer into GV
+{
+ GtkObject *gvlayer = NULL;
+ GvShapes *shape_data = GV_SHAPES(gv_shapes_from_ogr_layer(ogrlayer));
+
+ gv_data_set_property(GV_DATA(shape_data), "_filename", _filename);
+ gv_data_set_property(GV_DATA(shape_data), "_ogr_driver_name", DRVNAME);
+
+ gv_undo_register_data(GV_DATA(shape_data));
+
+ gvlayer = gv_shapes_layer_new(shape_data);
+
+ gv_view_area_add_layer(view, gvlayer);
+ gv_view_area_set_active_layer(view, gvlayer);
+
+ return;
+}
+
+static void _loadCell(const char *filename)
+{
+ GvViewArea *view = GV_VIEW_AREA(VecView);
+
+ S52_loadCell(filename, _gv_loadLayer_cb);
+
+ return;
+}
+
+static gint _init(GtkWidget *widget)
+{
+ // OpenGL functions can be called only if make_current returns true
+ if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) {
+ glViewport(0,0, widget->allocation.width, widget->allocation.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0,100, 100,0, -1,1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ }
+
+ return TRUE;
+}
+
+
+static gint _draw(GtkWidget *widget, GdkEventExpose *event)
+// When widget is exposed it's contents are redrawn.
+{
+ // Draw only last expose.
+ if (event->count > 0)
+ return TRUE;
+
+ // OpenGL functions can be called only if make_current returns true
+ if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) {
+
+ // Draw simple triangle
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor3f(1,1,1);
+ glBegin(GL_TRIANGLES);
+ glVertex2f(10,10);
+ glVertex2f(10,90);
+ glVertex2f(90,90);
+ glEnd();
+
+ // Swap backbuffer to front
+ gtk_gl_area_swapbuffers(GTK_GL_AREA(widget));
+
+ }
+
+ return TRUE;
+}
+
+static gint _reshape(GtkWidget *widget, GdkEventConfigure *event)
+// When glarea widget size changes, viewport size is set to match the new size
+{
+ // OpenGL functions can be called only if make_current returns true
+ if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) {
+ glViewport(0,0, widget->allocation.width, widget->allocation.height);
+ }
+
+ return TRUE;
+}
+
+static gint _glareaNew(GtkWidget *window)
+{
+ int attrlist[] = {
+ GDK_GL_RGBA,
+ GDK_GL_DOUBLEBUFFER,
+ GDK_GL_DEPTH_SIZE, 4,
+ GDK_GL_RED_SIZE, 3,
+ GDK_GL_GREEN_SIZE, 3,
+ GDK_GL_BLUE_SIZE, 3,
+ GDK_GL_STENCIL_SIZE, 1,
+ GDK_GL_NONE
+ };
+
+ // Create new OpenGL widget.
+ glarea = GTK_WIDGET(gtk_gl_area_new(attrlist));
+ // Events for widget must be set before X Window is created
+ gtk_widget_set_events(GTK_WIDGET(glarea),
+ GDK_EXPOSURE_MASK|
+ GDK_BUTTON_PRESS_MASK);
+
+ // Connect signal handlers
+ // Redraw image when exposed.
+ gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
+ GTK_SIGNAL_FUNC(_draw), NULL);
+ // When window is resized viewport needs to be resized also.
+ gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
+ GTK_SIGNAL_FUNC(_reshape), NULL);
+ // Do initialization when widget has been realized.
+ gtk_signal_connect(GTK_OBJECT(glarea), "realize",
+ GTK_SIGNAL_FUNC(_init), NULL);
+
+ // set minimum size
+ gtk_widget_set_usize(GTK_WIDGET(glarea), 100,100);
+
+ // put glarea into window and show it all
+ gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(glarea));
+ gtk_widget_show(GTK_WIDGET(glarea));
+
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ GtkWidget *win;
+ GtkWidget *swin;
+ GString *genv = NULL;
+
+ //g_thread_init(NULL);
+ //gdk_threads_init();
+
+ gtk_init(&argc, &argv);
+ //printf("after gtk_init\n");
+
+ VecView = gv_view_area_new();
+ VecViewBack = VecView;
+ //VecViewBack = gv_view_area_new();
+ //VecViewFront = gv_view_area_new();
+
+ if (NULL == VecViewBack){
+ printf("main.c:ERROR: VecView == NULL!! no OpenGL .. exit!\n");
+ exit(0);
+ }
+
+ { //unsigned int value = HUGE_VAL;
+ //int nan = NaN; printf
+ //PRINTF("int infinity value = -2147483648 = HUGE_VAL = %i\n", value);
+ //PRINTF("int infinity size = 8 = sizeof(HUGE_VAL) = %i\n", sizeof(value));
+ //PRINTF("int : sizeof(int) = %i\n", sizeof(int));
+ //PRINTF("float : sizeof(float) = %i\n", sizeof(float));
+ //PRINTF("double : sizeof(double) = %i\n", sizeof(double));
+ //PRINTF("unsigned long: sizeof(unsigned long)= %i\n",sizeof(unsigned long));
+ //exit(0);
+ }
+
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ //glareaNew(win);
+
+ toolbox = GV_TOOLBOX(gv_toolbox_new());
+ gv_toolbox_add_tool(toolbox, "select", gv_selection_tool_new());
+ gv_toolbox_add_tool(toolbox, "zoompan", gv_zoompan_tool_new());
+ gv_toolbox_add_tool(toolbox, "point", gv_point_tool_new());
+ gv_toolbox_add_tool(toolbox, "line", gv_line_tool_new());
+ gv_toolbox_add_tool(toolbox, "area", gv_area_tool_new());
+ gv_toolbox_add_tool(toolbox, "node", gv_node_tool_new());
+ gv_toolbox_add_tool(toolbox, "roi", gv_roi_tool_new());
+
+ link = GV_VIEW_LINK(gv_view_link_new());
+
+
+ { // setup env. var for OGR/S57
+ gchar *env = g_getenv("OGR_S57_OPTIONS");
+
+
+ if (env == NULL ||
+ NULL == strstr(env, "UPDATES:ON") ||
+ NULL == strstr(env, "LNAM_REFS:ON") ||
+ NULL == strstr(env, "SPLIT_MULTIPOINT:ON"))
+ {
+ genv = g_string_new(env);
+ setenv("OGR_S57_OPTIONS", "LNAM_REFS:ON,UPDATES:ON,SPLIT_MULTIPOINT:ON", 1);
+ }
+
+ //PRINTF("CURRENT SETUP:\n");
+ //PRINTF(" OGR_S57_OPTIONS = %s \n", g_getenv("OGR_S57_OPTIONS"));
+ //PRINTF(" S57_CSV = %s \n", g_getenv("S57_CSV"));
+ //PRINTF(" OGRMakefile CFG = %s \n", g_getenv("CFG"));
+ //PRINTF(" gvgeocoord size = %i \n", sizeof(geocoord));
+ //PRINTF(" libgv HAVE_OGR = %s \n", (gv_have_ogr_support())? "Yes":"No");
+ //PRINTF(" libgv HAVE_S52 = %s \n", (gv_have_S52_support())? "Yes":"No");
+
+
+ g_assert(gv_have_ogr_support());
+ //g_assert(gv_have_S52_support());
+ //g_on_error_query (NULL);
+ }
+
+ gtk_window_set_default_size( GTK_WINDOW(win), 512, 512 );
+// gtk_window_set_default_size( GTK_WINDOW(win), 200, 200 );
+
+ // 2D
+ gv_view_area_set_mode(GV_VIEW_AREA(VecViewBack ), 0);
+ //gv_view_area_set_mode(GV_VIEW_AREA(VecViewFront), 0);
+
+ gtk_drawing_area_size(GTK_DRAWING_AREA(VecViewBack ), 500, 500);
+ //gtk_drawing_area_size(GTK_DRAWING_AREA(VecViewFront), 200, 200);
+// gtk_drawing_area_size(GTK_DRAWING_AREA(VecView), 200, 200);
+
+ swin = gtk_scrolled_window_new(NULL, NULL);
+
+ gtk_container_add(GTK_CONTAINER(win), swin);
+ gtk_container_add(GTK_CONTAINER(swin), VecViewBack);
+
+
+ //gv_view_area_add_layer(GV_VIEW_AREA(view), gv_shapes_layer_new(shapes));
+
+ gtk_signal_connect_object(GTK_OBJECT(VecViewBack), "key-press-event",
+ GTK_SIGNAL_FUNC(_key_press_cb),
+ GTK_OBJECT(VecViewBack) );
+
+ //gtk_signal_connect_object(GTK_OBJECT(VecViewFront), "key-press-event",
+ // GTK_SIGNAL_FUNC(_key_press_cb),
+ // GTK_OBJECT(VecViewFront) );
+
+ gtk_widget_show(VecViewBack );
+ //gtk_widget_show(VecViewFront);
+ gtk_widget_show(swin);
+ gtk_widget_show(win);
+ gtk_widget_grab_focus(VecViewBack);
+
+ gtk_signal_connect(GTK_OBJECT(win), "delete-event",
+ GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+ gtk_quit_add_destroy(1, GTK_OBJECT(win));
+
+ gv_tool_activate(GV_TOOL(toolbox), GV_VIEW_AREA(VecViewBack));
+ gv_view_link_register_view(link, GV_VIEW_AREA(VecViewBack));
+ //gv_view_link_register_view(link, GV_VIEW_AREA(VecViewFront));
+ gv_toolbox_activate_tool( toolbox, "zoompan" );
+
+
+ _create_toolbar();
+
+ {
+ valueBuf chartPath = {'\0'};
+ if (0 == S52_getConfig(CONF_CHART, &chartPath)) {
+ printf(" .. exiting !\n");
+ exit(0);
+ } else {
+ _loadCell(chartPath);
+ }
+ }
+
+ gdk_threads_enter();
+ gtk_main();
+ gdk_threads_leave();
+
+ // put back env. var. as it was
+ if (NULL != genv){
+ setenv("OGR_S57_OPTIONS", genv->str, 1);
+ g_string_free(genv, TRUE);
+ }
+
+ // FIXME: check this --for mem leak
+ //g_mem_profile ()
+
+ return 0;
+}
Added: packages/openev/branches/upstream/current/contrib/S52/s52test.conf
===================================================================
--- packages/openev/branches/upstream/current/contrib/S52/s52test.conf (rev 0)
+++ packages/openev/branches/upstream/current/contrib/S52/s52test.conf 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,40 @@
+# s52test.conf: basic configuration file for testing
+#
+# line with '#' are ignore
+#
+# entry are made of LABEL/VALUE strings pair (space delimited)
+#
+# Replace <your_full_path_to_ENC> to suit your setup for label CHART.
+# Label PLIB, and OGR_S57_OPTIONS have hardcoded default value.
+
+
+### HARDCODED ####
+# lib path & name
+#PLIB <some_path>
+
+### DEFAULT CHART TO LOAD ###
+#
+#CHART <your_full_path_to_ENC>
+CHART /home/user/dev/gis/data/S57/a/CA49995A.000
+#CHART /home/user/dev/gis/data/S57/b/CA49995B.000
+#CHART /home/user/dev/gis/data/S57/c/CA49995C.000
+#CHART /home/user/dev/gis/data/S57/d/CA49995D.000
+#CHART /home/user/dev/gis/data/S57/i/CA39995I.000
+
+# chart catalog path
+#CATALOG <your_full_path_to_file>
+#CATALOG /home/user/gis/data/S57/a/CATALOG.030
+
+
+### ENVIRONNEMENT VARIAVLE OVERRIDE ###
+#
+# path to IHOOCDD.XXX or s57objectclasses.csv/s57attributes.csv
+#S57_CSV
+
+# OGR behaviour
+#OGR_S57_OPTIONS=LNAM_REFS,UPDATES,SPLIT_MULTIPOINT,ADD_SOUNDG_DEPTH
+#FIXME: define behaviour options (!?)
+
+
+
+
Added: packages/openev/branches/upstream/current/crs.c
===================================================================
--- packages/openev/branches/upstream/current/crs.c (rev 0)
+++ packages/openev/branches/upstream/current/crs.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,485 @@
+/***************************************************************************/
+/***************************************************************************/
+/*
+ CRS.C - Center for Remote Sensing rectification routines
+
+ Written By: Brian J. Buckley
+
+ At: The Center for Remote Sensing
+ Michigan State University
+ 302 Berkey Hall
+ East Lansing, MI 48824
+ (517)353-7195
+
+ Written: 12/19/91
+
+ Last Update: 12/26/91 Brian J. Buckley
+ Last Update: 1/24/92 Brian J. Buckley
+ Added printout of trnfile. Triggered by BDEBUG.
+ Last Update: 1/27/92 Brian J. Buckley
+ Fixed bug so that only the active control points were used.
+*/
+/***************************************************************************/
+/***************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "crs.h"
+
+typedef double DOUBLE;
+
+/* STRUCTURE FOR USE INTERNALLY WITH THESE FUNCTIONS. THESE FUNCTIONS EXPECT
+ SQUARE MATRICES SO ONLY ONE VARIABLE IS GIVEN (N) FOR THE MATRIX SIZE */
+
+struct MATRIX
+{
+ int n; /* SIZE OF THIS MATRIX (N x N) */
+ DOUBLE *v;
+};
+
+/* CALCULATE OFFSET INTO ARRAY BASED ON R/C */
+
+#define M(row,col) m->v[(((row)-1)*(m->n))+(col)-1]
+
+/***************************************************************************/
+/*
+*/
+/***************************************************************************/
+
+#define MSUCCESS 1 /* SUCCESS */
+#define MNPTERR 0 /* NOT ENOUGH POINTS */
+#define MUNSOLVABLE -1 /* NOT SOLVABLE */
+#define MMEMERR -2 /* NOT ENOUGH MEMORY */
+#define MPARMERR -3 /* PARAMETER ERROR */
+#define MINTERR -4 /* INTERNAL ERROR */
+
+/***************************************************************************/
+/*
+ FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
+*/
+/***************************************************************************/
+
+static int calccoef(struct Control_Points *,double *,double *,int);
+static int calcls(struct Control_Points *,struct MATRIX *,
+ DOUBLE *,DOUBLE *,double *,double *);
+static int exactdet(struct Control_Points *,struct MATRIX *,
+ DOUBLE *,DOUBLE *,double *,double *);
+static int solvemat(struct MATRIX *,DOUBLE *,DOUBLE *,double *,double *);
+static DOUBLE term(int,double,double);
+
+/***************************************************************************/
+/*
+ TRANSFORM A SINGLE COORDINATE PAIR.
+*/
+/***************************************************************************/
+
+int
+CRS_georef (
+ double e1, /* EASTINGS TO BE TRANSFORMED */
+ double n1, /* NORTHINGS TO BE TRANSFORMED */
+ double *e, /* EASTINGS TO BE TRANSFORMED */
+ double *n, /* NORTHINGS TO BE TRANSFORMED */
+ double E[], /* EASTING COEFFICIENTS */
+ double N[], /* NORTHING COEFFICIENTS */
+ int order /* ORDER OF TRANSFORMATION TO BE PERFORMED, MUST MATCH THE
+ ORDER USED TO CALCULATE THE COEFFICIENTS */
+)
+ {
+ DOUBLE e3, e2n, en2, n3, e2, en, n2;
+
+ switch(order)
+ {
+ case 1:
+
+ *e = E[0] + E[1] * e1 + E[2] * n1;
+ *n = N[0] + N[1] * e1 + N[2] * n1;
+ break;
+
+ case 2:
+
+ e2 = e1 * e1;
+ n2 = n1 * n1;
+ en = e1 * n1;
+
+ *e = E[0] + E[1] * e1 + E[2] * n1 +
+ E[3] * e2 + E[4] * en + E[5] * n2;
+ *n = N[0] + N[1] * e1 + N[2] * n1 +
+ N[3] * e2 + N[4] * en + N[5] * n2;
+ break;
+
+ case 3:
+
+ e2 = e1 * e1;
+ en = e1 * n1;
+ n2 = n1 * n1;
+ e3 = e1 * e2;
+ e2n = e2 * n1;
+ en2 = e1 * n2;
+ n3 = n1 * n2;
+
+ *e = E[0] +
+ E[1] * e1 + E[2] * n1 +
+ E[3] * e2 + E[4] * en + E[5] * n2 +
+ E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
+ *n = N[0] +
+ N[1] * e1 + N[2] * n1 +
+ N[3] * e2 + N[4] * en + N[5] * n2 +
+ N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
+ break;
+
+ default:
+
+ return(MPARMERR);
+ break;
+ }
+
+ return(MSUCCESS);
+ }
+
+/***************************************************************************/
+/*
+ COMPUTE THE GEOREFFERENCING COEFFICIENTS BASED ON A SET OF CONTROL POINTS
+*/
+/***************************************************************************/
+
+int
+CRS_compute_georef_equations (struct Control_Points *cp, double E12[], double N12[], double E21[], double N21[], int order)
+ {
+ double *tempptr;
+ int status;
+
+ if(order < 1 || order > MAXORDER)
+ return(MPARMERR);
+
+ /* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
+
+ status = calccoef(cp,E12,N12,order);
+ if(status != MSUCCESS)
+ return(status);
+
+ /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS */
+
+ tempptr = cp->e1;
+ cp->e1 = cp->e2;
+ cp->e2 = tempptr;
+ tempptr = cp->n1;
+ cp->n1 = cp->n2;
+ cp->n2 = tempptr;
+
+ /* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
+
+ status = calccoef(cp,E21,N21,order);
+
+ /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS BACK */
+
+ tempptr = cp->e1;
+ cp->e1 = cp->e2;
+ cp->e2 = tempptr;
+ tempptr = cp->n1;
+ cp->n1 = cp->n2;
+ cp->n2 = tempptr;
+
+ return(status);
+ }
+
+/***************************************************************************/
+/*
+ COMPUTE THE GEOREFFERENCING COEFFICIENTS BASED ON A SET OF CONTROL POINTS
+*/
+/***************************************************************************/
+
+static int
+calccoef (struct Control_Points *cp, double E[], double N[], int order)
+ {
+ struct MATRIX m;
+ DOUBLE *a;
+ DOUBLE *b;
+ int numactive; /* NUMBER OF ACTIVE CONTROL POINTS */
+ int status, i;
+
+ /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
+
+ for(i = numactive = 0 ; i < cp->count ; i++)
+ {
+ if(cp->status[i] > 0)
+ numactive++;
+ }
+
+ /* CALCULATE THE MINIMUM NUMBER OF CONTROL POINTS NEEDED TO DETERMINE
+ A TRANSFORMATION OF THIS ORDER */
+
+ m.n = ((order + 1) * (order + 2)) / 2;
+
+ if(numactive < m.n)
+ return(MNPTERR);
+
+ /* INITIALIZE MATRIX */
+
+ m.v = (DOUBLE *)G_calloc(m.n*m.n,sizeof(DOUBLE));
+ if(m.v == NULL)
+ {
+ return(MMEMERR);
+ }
+ a = (DOUBLE *)G_calloc(m.n,sizeof(DOUBLE));
+ if(a == NULL)
+ {
+ G_free((char *)m.v);
+ return(MMEMERR);
+ }
+ b = (DOUBLE *)G_calloc(m.n,sizeof(DOUBLE));
+ if(b == NULL)
+ {
+ G_free((char *)m.v);
+ G_free((char *)a);
+ return(MMEMERR);
+ }
+
+ if(numactive == m.n)
+ status = exactdet(cp,&m,a,b,E,N);
+ else
+ status = calcls(cp,&m,a,b,E,N);
+
+ G_free((char *)m.v);
+ G_free((char *)a);
+ G_free((char *)b);
+
+ return(status);
+ }
+
+/***************************************************************************/
+/*
+ CALCULATE THE TRANSFORMATION COEFFICIENTS WITH EXACTLY THE MINIMUM
+ NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.
+*/
+/***************************************************************************/
+
+static int exactdet (
+ struct Control_Points *cp,
+ struct MATRIX *m,
+ DOUBLE a[],
+ DOUBLE b[],
+ double E[], /* EASTING COEFFICIENTS */
+ double N[] /* NORTHING COEFFICIENTS */
+)
+ {
+ int pntnow, currow, j;
+
+ currow = 1;
+ for(pntnow = 0 ; pntnow < cp->count ; pntnow++)
+ {
+ if(cp->status[pntnow] > 0)
+ {
+ /* POPULATE MATRIX M */
+
+ for(j = 1 ; j <= m->n ; j++)
+ {
+ M(currow,j) = term(j,cp->e1[pntnow],cp->n1[pntnow]);
+ }
+
+ /* POPULATE MATRIX A AND B */
+
+ a[currow-1] = cp->e2[pntnow];
+ b[currow-1] = cp->n2[pntnow];
+
+ currow++;
+ }
+ }
+
+ if(currow - 1 != m->n)
+ return(MINTERR);
+
+ return(solvemat(m,a,b,E,N));
+ }
+
+/***************************************************************************/
+/*
+ CALCULATE THE TRANSFORMATION COEFFICIENTS WITH MORE THAN THE MINIMUM
+ NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION. THIS
+ ROUTINE USES THE LEAST SQUARES METHOD TO COMPUTE THE COEFFICIENTS.
+*/
+/***************************************************************************/
+
+static int calcls (
+ struct Control_Points *cp,
+ struct MATRIX *m,
+ DOUBLE a[],
+ DOUBLE b[],
+ double E[], /* EASTING COEFFICIENTS */
+ double N[] /* NORTHING COEFFICIENTS */
+)
+ {
+ int i, j, n, numactive = 0;
+
+ /* INITIALIZE THE UPPER HALF OF THE MATRIX AND THE TWO COLUMN VECTORS */
+
+ for(i = 1 ; i <= m->n ; i++)
+ {
+ for(j = i ; j <= m->n ; j++)
+ M(i,j) = 0.0;
+ a[i-1] = b[i-1] = 0.0;
+ }
+
+ /* SUM THE UPPER HALF OF THE MATRIX AND THE COLUMN VECTORS ACCORDING TO
+ THE LEAST SQUARES METHOD OF SOLVING OVER DETERMINED SYSTEMS */
+
+ for(n = 0 ; n < cp->count ; n++)
+ {
+ if(cp->status[n] > 0)
+ {
+ numactive++;
+ for(i = 1 ; i <= m->n ; i++)
+ {
+ for(j = i ; j <= m->n ; j++)
+ M(i,j) += term(i,cp->e1[n],cp->n1[n]) * term(j,cp->e1[n],cp->n1[n]);
+
+ a[i-1] += cp->e2[n] * term(i,cp->e1[n],cp->n1[n]);
+ b[i-1] += cp->n2[n] * term(i,cp->e1[n],cp->n1[n]);
+ }
+ }
+ }
+
+ if(numactive <= m->n)
+ return(MINTERR);
+
+ /* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
+
+ for(i = 2 ; i <= m->n ; i++)
+ {
+ for(j = 1 ; j < i ; j++)
+ M(i,j) = M(j,i);
+ }
+
+ return(solvemat(m,a,b,E,N));
+ }
+
+/***************************************************************************/
+/*
+ CALCULATE THE X/Y TERM BASED ON THE TERM NUMBER
+
+ORDER\TERM 1 2 3 4 5 6 7 8 9 10
+ 1 e0n0 e1n0 e0n1
+ 2 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2
+ 3 e0n0 e1n0 e0n1 e2n0 e1n1 e0n2 e3n0 e2n1 e1n2 e0n3
+*/
+/***************************************************************************/
+
+static DOUBLE term (int term, double e, double n)
+ {
+ switch(term)
+ {
+ case 1: return((DOUBLE)1.0);
+ case 2: return((DOUBLE)e);
+ case 3: return((DOUBLE)n);
+ case 4: return((DOUBLE)(e*e));
+ case 5: return((DOUBLE)(e*n));
+ case 6: return((DOUBLE)(n*n));
+ case 7: return((DOUBLE)(e*e*e));
+ case 8: return((DOUBLE)(e*e*n));
+ case 9: return((DOUBLE)(e*n*n));
+ case 10: return((DOUBLE)(n*n*n));
+ }
+ return((DOUBLE)0.0);
+ }
+
+/***************************************************************************/
+/*
+ SOLVE FOR THE 'E' AND 'N' COEFFICIENTS BY USING A SOMEWHAT MODIFIED
+ GAUSSIAN ELIMINATION METHOD.
+
+ | M11 M12 ... M1n | | E0 | | a0 |
+ | M21 M22 ... M2n | | E1 | = | a1 |
+ | . . . . | | . | | . |
+ | Mn1 Mn2 ... Mnn | | En-1 | | an-1 |
+
+ and
+
+ | M11 M12 ... M1n | | N0 | | b0 |
+ | M21 M22 ... M2n | | N1 | = | b1 |
+ | . . . . | | . | | . |
+ | Mn1 Mn2 ... Mnn | | Nn-1 | | bn-1 |
+*/
+/***************************************************************************/
+
+static int solvemat (struct MATRIX *m,
+ DOUBLE a[], DOUBLE b[], double E[], double N[])
+{
+ int i, j, i2, j2, imark;
+ DOUBLE factor, temp;
+ DOUBLE pivot; /* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
+
+ for(i = 1 ; i <= m->n ; i++)
+ {
+ j = i;
+
+ /* find row with largest magnitude value for pivot value */
+
+ pivot = M(i,j);
+ imark = i;
+ for(i2 = i + 1 ; i2 <= m->n ; i2++)
+ {
+ temp = fabs(M(i2,j));
+ if(temp > fabs(pivot))
+ {
+ pivot = M(i2,j);
+ imark = i2;
+ }
+ }
+
+ /* if the pivot is very small then the points are nearly co-linear */
+ /* co-linear points result in an undefined matrix, and nearly */
+ /* co-linear points results in a solution with rounding error */
+
+ if(pivot == 0.0)
+ return(MUNSOLVABLE);
+
+ /* if row with highest pivot is not the current row, switch them */
+
+ if(imark != i)
+ {
+ for(j2 = 1 ; j2 <= m->n ; j2++)
+ {
+ temp = M(imark,j2);
+ M(imark,j2) = M(i,j2);
+ M(i,j2) = temp;
+ }
+
+ temp = a[imark-1];
+ a[imark-1] = a[i-1];
+ a[i-1] = temp;
+
+ temp = b[imark-1];
+ b[imark-1] = b[i-1];
+ b[i-1] = temp;
+ }
+
+ /* compute zeros above and below the pivot, and compute
+ values for the rest of the row as well */
+
+ for(i2 = 1 ; i2 <= m->n ; i2++)
+ {
+ if(i2 != i)
+ {
+ factor = M(i2,j) / pivot;
+ for(j2 = j ; j2 <= m->n ; j2++)
+ M(i2,j2) -= factor * M(i,j2);
+ a[i2-1] -= factor * a[i-1];
+ b[i2-1] -= factor * b[i-1];
+ }
+ }
+ }
+
+ /* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
+ COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
+
+ for(i = 1 ; i <= m->n ; i++)
+ {
+ E[i-1] = a[i-1] / M(i,i);
+ N[i-1] = b[i-1] / M(i,i);
+ }
+
+ return(MSUCCESS);
+ }
Added: packages/openev/branches/upstream/current/crs.h
===================================================================
--- packages/openev/branches/upstream/current/crs.h (rev 0)
+++ packages/openev/branches/upstream/current/crs.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/***************************************************************************/
+/*
+ CRS.H - Center for Remote Sensing rectification routines
+
+ Written By: Brian J. Buckley
+
+ At: The Center for Remote Sensing
+ Michigan State University
+ 302 Berkey Hall
+ East Lansing, MI 48824
+ (517)353-7195
+
+ Written: 12/19/91
+
+ Last Update: 12/26/91 Brian J. Buckley
+*/
+/***************************************************************************/
+/***************************************************************************/
+
+#define MAXORDER 3
+
+#define G_calloc calloc
+#define G_free free
+
+struct Control_Points
+{
+ int count;
+ double *e1;
+ double *n1;
+ double *e2;
+ double *n2;
+ int *status;
+};
+
+/* crs.c */
+int CRS_georef(double, double, double *, double *, double [], double [], int);
+int CRS_compute_georef_equations(struct Control_Points *,
+ double [], double [], double [], double [], int);
+
Added: packages/openev/branches/upstream/current/dbfopen.c
===================================================================
--- packages/openev/branches/upstream/current/dbfopen.c (rev 0)
+++ packages/openev/branches/upstream/current/dbfopen.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1448 @@
+/******************************************************************************
+ * $Id: dbfopen.c,v 1.44 2002/05/07 13:46:11 warmerda Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Implementation of .dbf access API documented in dbf_api.html.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: dbfopen.c,v $
+ * Revision 1.44 2002/05/07 13:46:11 warmerda
+ * Added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.43 2002/02/13 19:39:21 warmerda
+ * Fix casting issues in DBFCloneEmpty().
+ *
+ * Revision 1.42 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.41 2002/01/15 14:31:49 warmerda
+ * compute rather than copying nHeaderLength in DBFCloneEmpty()
+ *
+ * Revision 1.40 2002/01/09 04:32:35 warmerda
+ * fixed to read correct amount of header
+ *
+ * Revision 1.39 2001/12/11 22:41:03 warmerda
+ * improve io related error checking when reading header
+ *
+ * Revision 1.38 2001/11/28 16:07:31 warmerda
+ * Cleanup to avoid compiler warnings as suggested by Richard Hash.
+ *
+ * Revision 1.37 2001/07/04 05:18:09 warmerda
+ * do last fix properly
+ *
+ * Revision 1.36 2001/07/04 05:16:09 warmerda
+ * fixed fieldname comparison in DBFGetFieldIndex
+ *
+ * Revision 1.35 2001/06/22 02:10:06 warmerda
+ * fixed NULL shape support with help from Jim Matthews
+ *
+ * Revision 1.33 2001/05/31 19:20:13 warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.32 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.31 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.30 2000/12/05 14:43:38 warmerda
+ * DBReadAttribute() white space trimming bug fix
+ *
+ * Revision 1.29 2000/10/05 14:36:44 warmerda
+ * fix bug with writing very wide numeric fields
+ *
+ * Revision 1.28 2000/09/25 14:18:07 warmerda
+ * Added some casts of strlen() return result to fix warnings on some
+ * systems, as submitted by Daniel.
+ *
+ * Revision 1.27 2000/09/25 14:15:51 warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.26 2000/07/07 13:39:45 warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.25 2000/05/29 18:19:13 warmerda
+ * avoid use of uchar, and adding casting fix
+ *
+ * Revision 1.24 2000/05/23 13:38:27 warmerda
+ * Added error checks on return results of fread() and fseek().
+ *
+ * Revision 1.23 2000/05/23 13:25:49 warmerda
+ * Avoid crashing if field or record are out of range in dbfread*attribute().
+ *
+ * Revision 1.22 1999/12/15 13:47:24 warmerda
+ * Added stdlib.h to ensure that atof() is prototyped.
+ *
+ * Revision 1.21 1999/12/13 17:25:46 warmerda
+ * Added support for upper case .DBF extention.
+ *
+ * Revision 1.20 1999/11/30 16:32:11 warmerda
+ * Use atof() instead of sscanf().
+ *
+ * Revision 1.19 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.18 1999/07/27 00:53:28 warmerda
+ * ensure that whole old field value clear on write of string
+ *
+ * Revision 1.1 1999/07/05 18:58:07 warmerda
+ * New
+ *
+ * Revision 1.17 1999/06/11 19:14:12 warmerda
+ * Fixed some memory leaks.
+ *
+ * Revision 1.16 1999/06/11 19:04:11 warmerda
+ * Remoted some unused variables.
+ *
+ * Revision 1.15 1999/05/11 03:19:28 warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.14 1999/05/04 15:01:48 warmerda
+ * Added 'F' support.
+ *
+ * Revision 1.13 1999/03/23 17:38:59 warmerda
+ * DBFAddField() now actually does return the new field number, or -1 if
+ * it fails.
+ *
+ * Revision 1.12 1999/03/06 02:54:46 warmerda
+ * Added logic to convert shapefile name to dbf filename in DBFOpen()
+ * for convenience.
+ *
+ * Revision 1.11 1998/12/31 15:30:34 warmerda
+ * Improved the interchangability of numeric and string attributes. Add
+ * white space trimming option for attributes.
+ *
+ * Revision 1.10 1998/12/03 16:36:44 warmerda
+ * Use r+b instead of rb+ for binary access.
+ *
+ * Revision 1.9 1998/12/03 15:34:23 warmerda
+ * Updated copyright message.
+ *
+ * Revision 1.8 1997/12/04 15:40:15 warmerda
+ * Added newline character after field definitions.
+ *
+ * Revision 1.7 1997/03/06 14:02:10 warmerda
+ * Ensure bUpdated is initialized.
+ *
+ * Revision 1.6 1996/02/12 04:54:41 warmerda
+ * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
+ *
+ * Revision 1.5 1995/10/21 03:15:12 warmerda
+ * Changed to use binary file access, and ensure that the
+ * field name field is zero filled, and limited to 10 chars.
+ *
+ * Revision 1.4 1995/08/24 18:10:42 warmerda
+ * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
+ * as on the Sun.
+ *
+ * Revision 1.3 1995/08/04 03:15:16 warmerda
+ * Fixed up header.
+ *
+ * Revision 1.2 1995/08/04 03:14:43 warmerda
+ * Added header.
+ */
+
+static char rcsid[] =
+ "$Id: dbfopen.c,v 1.44 2002/05/07 13:46:11 warmerda Exp $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+static int nStringFieldLen = 0;
+static char * pszStringField = NULL;
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/* DBFWriteHeader() */
+/* */
+/* This is called to write out the file header, and field */
+/* descriptions before writing any actual data records. This */
+/* also computes all the DBFDataSet field offset/size/decimals */
+/* and so forth values. */
+/************************************************************************/
+
+static void DBFWriteHeader(DBFHandle psDBF)
+
+{
+ unsigned char abyHeader[XBASE_FLDHDR_SZ];
+ int i;
+
+ if( !psDBF->bNoHeader )
+ return;
+
+ psDBF->bNoHeader = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Initialize the file header information. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[0] = 0x03; /* memo field? - just copying */
+
+ /* date updated on close, record count preset at zero */
+
+ abyHeader[8] = psDBF->nHeaderLength % 256;
+ abyHeader[9] = psDBF->nHeaderLength / 256;
+
+ abyHeader[10] = psDBF->nRecordLength % 256;
+ abyHeader[11] = psDBF->nRecordLength / 256;
+
+/* -------------------------------------------------------------------- */
+/* Write the initial 32 byte file header, and all the field */
+/* descriptions. */
+/* -------------------------------------------------------------------- */
+ fseek( psDBF->fp, 0, 0 );
+ fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+ fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
+
+/* -------------------------------------------------------------------- */
+/* Write out the newline character if there is room for it. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
+ {
+ char cNewline;
+
+ cNewline = 0x0d;
+ fwrite( &cNewline, 1, 1, psDBF->fp );
+ }
+}
+
+/************************************************************************/
+/* DBFFlushRecord() */
+/* */
+/* Write out the current record if there is one. */
+/************************************************************************/
+
+static void DBFFlushRecord( DBFHandle psDBF )
+
+{
+ int nRecordOffset;
+
+ if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
+ {
+ psDBF->bCurrentRecordModified = FALSE;
+
+ nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
+ + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ }
+}
+
+/************************************************************************/
+/* DBFOpen() */
+/* */
+/* Open a .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFOpen( const char * pszFilename, const char * pszAccess )
+
+{
+ DBFHandle psDBF;
+ unsigned char *pabyBuf;
+ int nFields, nHeadLen, nRecLen, iField, i;
+ char *pszBasename, *pszFullname;
+
+/* -------------------------------------------------------------------- */
+/* We only allow the access strings "rb" and "r+". */
+/* -------------------------------------------------------------------- */
+ if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
+ && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
+ && strcmp(pszAccess,"r+b") != 0 )
+ return( NULL );
+
+ if( strcmp(pszAccess,"r") == 0 )
+ pszAccess = "rb";
+
+ if( strcmp(pszAccess,"r+") == 0 )
+ pszAccess = "rb+";
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszFilename)+5);
+ strcpy( pszBasename, pszFilename );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.dbf", pszBasename );
+
+ psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
+ psDBF->fp = fopen( pszFullname, pszAccess );
+
+ if( psDBF->fp == NULL )
+ {
+ sprintf( pszFullname, "%s.DBF", pszBasename );
+ psDBF->fp = fopen(pszFullname, pszAccess );
+ }
+
+ free( pszBasename );
+ free( pszFullname );
+
+ if( psDBF->fp == NULL )
+ {
+ free( psDBF );
+ return( NULL );
+ }
+
+ psDBF->bNoHeader = FALSE;
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Read Table Header info */
+/* -------------------------------------------------------------------- */
+ pabyBuf = (unsigned char *) malloc(500);
+ if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+ {
+ fclose( psDBF->fp );
+ free( pabyBuf );
+ free( psDBF );
+ return NULL;
+ }
+
+ psDBF->nRecords =
+ pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
+
+ psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
+ psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
+
+ psDBF->nFields = nFields = (nHeadLen - 32) / 32;
+
+ psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
+
+/* -------------------------------------------------------------------- */
+/* Read in Field Definitions */
+/* -------------------------------------------------------------------- */
+
+ pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
+ psDBF->pszHeader = (char *) pabyBuf;
+
+ fseek( psDBF->fp, 32, 0 );
+ if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+ {
+ fclose( psDBF->fp );
+ free( pabyBuf );
+ free( psDBF );
+ return NULL;
+ }
+
+ psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
+ psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
+ psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
+ psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
+
+ for( iField = 0; iField < nFields; iField++ )
+ {
+ unsigned char *pabyFInfo;
+
+ pabyFInfo = pabyBuf+iField*32;
+
+ if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16];
+ psDBF->panFieldDecimals[iField] = pabyFInfo[17];
+ }
+ else
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
+ psDBF->panFieldDecimals[iField] = 0;
+ }
+
+ psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
+ if( iField == 0 )
+ psDBF->panFieldOffset[iField] = 1;
+ else
+ psDBF->panFieldOffset[iField] =
+ psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
+ }
+
+ return( psDBF );
+}
+
+/************************************************************************/
+/* DBFClose() */
+/************************************************************************/
+
+void SHPAPI_CALL
+DBFClose(DBFHandle psDBF)
+{
+/* -------------------------------------------------------------------- */
+/* Write out header if not already written. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->bNoHeader )
+ DBFWriteHeader( psDBF );
+
+ DBFFlushRecord( psDBF );
+
+/* -------------------------------------------------------------------- */
+/* Update last access date, and number of records if we have */
+/* write access. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->bUpdated )
+ {
+ unsigned char abyFileHeader[32];
+
+ fseek( psDBF->fp, 0, 0 );
+ fread( abyFileHeader, 32, 1, psDBF->fp );
+
+ abyFileHeader[1] = 95; /* YY */
+ abyFileHeader[2] = 7; /* MM */
+ abyFileHeader[3] = 26; /* DD */
+
+ abyFileHeader[4] = psDBF->nRecords % 256;
+ abyFileHeader[5] = (psDBF->nRecords/256) % 256;
+ abyFileHeader[6] = (psDBF->nRecords/(256*256)) % 256;
+ abyFileHeader[7] = (psDBF->nRecords/(256*256*256)) % 256;
+
+ fseek( psDBF->fp, 0, 0 );
+ fwrite( abyFileHeader, 32, 1, psDBF->fp );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Close, and free resources. */
+/* -------------------------------------------------------------------- */
+ fclose( psDBF->fp );
+
+ if( psDBF->panFieldOffset != NULL )
+ {
+ free( psDBF->panFieldOffset );
+ free( psDBF->panFieldSize );
+ free( psDBF->panFieldDecimals );
+ free( psDBF->pachFieldType );
+ }
+
+ free( psDBF->pszHeader );
+ free( psDBF->pszCurrentRecord );
+
+ free( psDBF );
+
+ if( pszStringField != NULL )
+ {
+ free( pszStringField );
+ pszStringField = NULL;
+ nStringFieldLen = 0;
+ }
+}
+
+/************************************************************************/
+/* DBFCreate() */
+/* */
+/* Create a new .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreate( const char * pszFilename )
+
+{
+ DBFHandle psDBF;
+ FILE *fp;
+ char *pszFullname, *pszBasename;
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszFilename)+5);
+ strcpy( pszBasename, pszFilename );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.dbf", pszBasename );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Create the file. */
+/* -------------------------------------------------------------------- */
+ fp = fopen( pszFullname, "wb" );
+ if( fp == NULL )
+ return( NULL );
+
+ fputc( 0, fp );
+ fclose( fp );
+
+ fp = fopen( pszFullname, "rb+" );
+ if( fp == NULL )
+ return( NULL );
+
+ free( pszFullname );
+
+/* -------------------------------------------------------------------- */
+/* Create the info structure. */
+/* -------------------------------------------------------------------- */
+ psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
+
+ psDBF->fp = fp;
+ psDBF->nRecords = 0;
+ psDBF->nFields = 0;
+ psDBF->nRecordLength = 1;
+ psDBF->nHeaderLength = 33;
+
+ psDBF->panFieldOffset = NULL;
+ psDBF->panFieldSize = NULL;
+ psDBF->panFieldDecimals = NULL;
+ psDBF->pachFieldType = NULL;
+ psDBF->pszHeader = NULL;
+
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+ psDBF->pszCurrentRecord = NULL;
+
+ psDBF->bNoHeader = TRUE;
+
+ return( psDBF );
+}
+
+/************************************************************************/
+/* DBFAddField() */
+/* */
+/* Add a field to a newly created .dbf file before any records */
+/* are written. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAddField(DBFHandle psDBF, const char * pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals )
+
+{
+ char *pszFInfo;
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Do some checking to ensure we can add records to this file. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nRecords > 0 )
+ return( -1 );
+
+ if( !psDBF->bNoHeader )
+ return( -1 );
+
+ if( eType != FTDouble && nDecimals != 0 )
+ return( -1 );
+
+/* -------------------------------------------------------------------- */
+/* SfRealloc all the arrays larger to hold the additional field */
+/* information. */
+/* -------------------------------------------------------------------- */
+ psDBF->nFields++;
+
+ psDBF->panFieldOffset = (int *)
+ SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldSize = (int *)
+ SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+
+ psDBF->panFieldDecimals = (int *)
+ SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+
+ psDBF->pachFieldType = (char *)
+ SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+
+/* -------------------------------------------------------------------- */
+/* Assign the new field information fields. */
+/* -------------------------------------------------------------------- */
+ psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
+ psDBF->nRecordLength += nWidth;
+ psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
+ psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
+
+ if( eType == FTString )
+ psDBF->pachFieldType[psDBF->nFields-1] = 'C';
+ else
+ psDBF->pachFieldType[psDBF->nFields-1] = 'N';
+
+/* -------------------------------------------------------------------- */
+/* Extend the required header information. */
+/* -------------------------------------------------------------------- */
+ psDBF->nHeaderLength += 32;
+ psDBF->bUpdated = FALSE;
+
+ psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+
+ pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
+
+ for( i = 0; i < 32; i++ )
+ pszFInfo[i] = '\0';
+
+ if( (int) strlen(pszFieldName) < 10 )
+ strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
+ else
+ strncpy( pszFInfo, pszFieldName, 10);
+
+ pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
+
+ if( eType == FTString )
+ {
+ pszFInfo[16] = nWidth % 256;
+ pszFInfo[17] = nWidth / 256;
+ }
+ else
+ {
+ pszFInfo[16] = nWidth;
+ pszFInfo[17] = nDecimals;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Make the current record buffer appropriately larger. */
+/* -------------------------------------------------------------------- */
+ psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+ psDBF->nRecordLength);
+
+ return( psDBF->nFields-1 );
+}
+
+/************************************************************************/
+/* DBFReadAttribute() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
+ char chReqType )
+
+{
+ int nRecordOffset;
+ unsigned char *pabyRec;
+ void *pReturnField = NULL;
+
+ static double dDoubleField;
+
+/* -------------------------------------------------------------------- */
+/* Verify selection. */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ return( NULL );
+
+ if( iField < 0 || iField >= psDBF->nFields )
+ return( NULL );
+
+/* -------------------------------------------------------------------- */
+/* Have we read the record? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
+ {
+ fprintf( stderr, "fseek(%d) failed on DBF file.\n",
+ nRecordOffset );
+ return NULL;
+ }
+
+ if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
+ 1, psDBF->fp ) != 1 )
+ {
+ fprintf( stderr, "fread(%d) failed on DBF file.\n",
+ psDBF->nRecordLength );
+ return NULL;
+ }
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/* Ensure our field buffer is large enough to hold this buffer. */
+/* -------------------------------------------------------------------- */
+ if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
+ {
+ nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
+ pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Extract the requested field. */
+/* -------------------------------------------------------------------- */
+ strncpy( pszStringField,
+ ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
+ psDBF->panFieldSize[iField] );
+ pszStringField[psDBF->panFieldSize[iField]] = '\0';
+
+ pReturnField = pszStringField;
+
+/* -------------------------------------------------------------------- */
+/* Decode the field. */
+/* -------------------------------------------------------------------- */
+ if( chReqType == 'N' )
+ {
+ dDoubleField = atof(pszStringField);
+
+ pReturnField = &dDoubleField;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Should we trim white space off the string attribute value? */
+/* -------------------------------------------------------------------- */
+#ifdef TRIM_DBF_WHITESPACE
+ else
+ {
+ char *pchSrc, *pchDst;
+
+ pchDst = pchSrc = pszStringField;
+ while( *pchSrc == ' ' )
+ pchSrc++;
+
+ while( *pchSrc != '\0' )
+ *(pchDst++) = *(pchSrc++);
+ *pchDst = '\0';
+
+ while( pchDst != pszStringField && *(--pchDst) == ' ' )
+ *pchDst = '\0';
+ }
+#endif
+
+ return( pReturnField );
+}
+
+/************************************************************************/
+/* DBFReadIntAttribute() */
+/* */
+/* Read an integer attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ double *pdValue;
+
+ pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+ if( pdValue == NULL )
+ return 0;
+ else
+ return( (int) *pdValue );
+}
+
+/************************************************************************/
+/* DBFReadDoubleAttribute() */
+/* */
+/* Read a double attribute. */
+/************************************************************************/
+
+double SHPAPI_CALL
+DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ double *pdValue;
+
+ pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+ if( pdValue == NULL )
+ return 0.0;
+ else
+ return( *pdValue );
+}
+
+/************************************************************************/
+/* DBFReadStringAttribute() */
+/* */
+/* Read a string attribute. */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+}
+
+/************************************************************************/
+/* DBFIsAttributeNULL() */
+/* */
+/* Return TRUE if value for field is NULL. */
+/* */
+/* Contributed by Jim Matthews. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ const char *pszValue;
+ int i;
+
+ pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+ if( pszValue == NULL )
+ return TRUE;
+
+ switch(psDBF->pachFieldType[iField])
+ {
+ case 'N':
+ case 'F':
+ /*
+ ** We accept all asterisks or all blanks as NULL
+ ** though according to the spec I think it should be all
+ ** asterisks.
+ */
+ if( pszValue[0] == '*' )
+ return TRUE;
+
+ for( i = 0; pszValue[i] != '\0'; i++ )
+ {
+ if( pszValue[i] != ' ' )
+ return FALSE;
+ }
+ return TRUE;
+
+ case 'D':
+ /* NULL date fields have value "00000000" */
+ return strncmp(pszValue,"00000000",8) == 0;
+
+ case 'L':
+ /* NULL boolean fields have value "?" */
+ return pszValue[0] == '?';
+
+ default:
+ /* empty string fields are considered NULL */
+ return strlen(pszValue) == 0;
+ }
+}
+
+/************************************************************************/
+/* DBFGetFieldCount() */
+/* */
+/* Return the number of fields in this table. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldCount( DBFHandle psDBF )
+
+{
+ return( psDBF->nFields );
+}
+
+/************************************************************************/
+/* DBFGetRecordCount() */
+/* */
+/* Return the number of records in this table. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetRecordCount( DBFHandle psDBF )
+
+{
+ return( psDBF->nRecords );
+}
+
+/************************************************************************/
+/* DBFGetFieldInfo() */
+/* */
+/* Return any requested information about the field. */
+/************************************************************************/
+
+DBFFieldType SHPAPI_CALL
+DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
+ int * pnWidth, int * pnDecimals )
+
+{
+ if( iField < 0 || iField >= psDBF->nFields )
+ return( FTInvalid );
+
+ if( pnWidth != NULL )
+ *pnWidth = psDBF->panFieldSize[iField];
+
+ if( pnDecimals != NULL )
+ *pnDecimals = psDBF->panFieldDecimals[iField];
+
+ if( pszFieldName != NULL )
+ {
+ int i;
+
+ strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
+ pszFieldName[11] = '\0';
+ for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
+ pszFieldName[i] = '\0';
+ }
+
+ if( psDBF->pachFieldType[iField] == 'N'
+ || psDBF->pachFieldType[iField] == 'F'
+ || psDBF->pachFieldType[iField] == 'D' )
+ {
+ if( psDBF->panFieldDecimals[iField] > 0 )
+ return( FTDouble );
+ else
+ return( FTInteger );
+ }
+ else
+ {
+ return( FTString );
+ }
+}
+
+/************************************************************************/
+/* DBFWriteAttribute() */
+/* */
+/* Write an attribute record to the file. */
+/************************************************************************/
+
+static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue )
+
+{
+ int nRecordOffset, i, j;
+ unsigned char *pabyRec;
+ char szSField[400], szFormat[20];
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Translate NULL value to valid DBF file representation. */
+/* */
+/* Contributed by Jim Matthews. */
+/* -------------------------------------------------------------------- */
+ if( pValue == NULL )
+ {
+ switch(psDBF->pachFieldType[iField])
+ {
+ case 'N':
+ case 'F':
+ /* NULL numeric fields have value "****************" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ case 'D':
+ /* NULL date fields have value "00000000" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ case 'L':
+ /* NULL boolean fields have value "?" */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?',
+ psDBF->panFieldSize[iField] );
+ break;
+
+ default:
+ /* empty string fields are considered NULL */
+ memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '\0',
+ psDBF->panFieldSize[iField] );
+ break;
+ }
+ return TRUE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Assign all the record fields. */
+/* -------------------------------------------------------------------- */
+ switch( psDBF->pachFieldType[iField] )
+ {
+ case 'D':
+ case 'N':
+ case 'F':
+ if( psDBF->panFieldDecimals[iField] == 0 )
+ {
+ int nWidth = psDBF->panFieldSize[iField];
+
+ if( sizeof(szSField)-2 < nWidth )
+ nWidth = sizeof(szSField)-2;
+
+ sprintf( szFormat, "%%%dd", nWidth );
+ sprintf(szSField, szFormat, (int) *((double *) pValue) );
+ if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
+ szSField[psDBF->panFieldSize[iField]] = '\0';
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ szSField, strlen(szSField) );
+ }
+ else
+ {
+ int nWidth = psDBF->panFieldSize[iField];
+
+ if( sizeof(szSField)-2 < nWidth )
+ nWidth = sizeof(szSField)-2;
+
+ sprintf( szFormat, "%%%d.%df",
+ nWidth, psDBF->panFieldDecimals[iField] );
+ sprintf(szSField, szFormat, *((double *) pValue) );
+ if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
+ szSField[psDBF->panFieldSize[iField]] = '\0';
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ szSField, strlen(szSField) );
+ }
+ break;
+
+ default:
+ if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+ j = psDBF->panFieldSize[iField];
+ else
+ {
+ memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField] );
+ j = strlen((char *) pValue);
+ }
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ (char *) pValue, j );
+ break;
+ }
+
+ return( TRUE );
+}
+
+/************************************************************************/
+/* DBFWriteAttributeDirectly() */
+/* */
+/* Write an attribute record to the file, but without any */
+/* reformatting based on type. The provided buffer is written */
+/* as is to the field position in the record. */
+/************************************************************************/
+
+int DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue )
+
+{
+ int nRecordOffset, i, j;
+ unsigned char *pabyRec;
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/* Assign all the record fields. */
+/* -------------------------------------------------------------------- */
+ if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+ j = psDBF->panFieldSize[iField];
+ else
+ {
+ memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField] );
+ j = strlen((char *) pValue);
+ }
+
+ strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+ (char *) pValue, j );
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+ return( TRUE );
+}
+
+/************************************************************************/
+/* DBFWriteDoubleAttribute() */
+/* */
+/* Write a double attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
+ double dValue )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteIntegerAttribute() */
+/* */
+/* Write a integer attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
+ int nValue )
+
+{
+ double dValue = nValue;
+
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteStringAttribute() */
+/* */
+/* Write a string attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
+ const char * pszValue )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
+}
+
+/************************************************************************/
+/* DBFWriteNULLAttribute() */
+/* */
+/* Write a string attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+ return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
+}
+
+/************************************************************************/
+/* DBFWriteTuple() */
+/* */
+/* Write an attribute record to the file. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
+
+{
+ int nRecordOffset, i;
+ unsigned char *pabyRec;
+
+/* -------------------------------------------------------------------- */
+/* Is this a valid record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity > psDBF->nRecords )
+ return( FALSE );
+
+ if( psDBF->bNoHeader )
+ DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/* Is this a brand new record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity == psDBF->nRecords )
+ {
+ DBFFlushRecord( psDBF );
+
+ psDBF->nRecords++;
+ for( i = 0; i < psDBF->nRecordLength; i++ )
+ psDBF->pszCurrentRecord[i] = ' ';
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Is this an existing record, but different than the last one */
+/* we accessed? */
+/* -------------------------------------------------------------------- */
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
+
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = TRUE;
+
+ return( TRUE );
+}
+
+/************************************************************************/
+/* DBFReadTuple() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadTuple(DBFHandle psDBF, int hEntity )
+
+{
+ int nRecordOffset;
+ unsigned char *pabyRec;
+ static char *pReturnTuple = NULL;
+
+ static int nTupleLen = 0;
+
+/* -------------------------------------------------------------------- */
+/* Have we read the record? */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ return( NULL );
+
+ if( psDBF->nCurrentRecord != hEntity )
+ {
+ DBFFlushRecord( psDBF );
+
+ nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+ fseek( psDBF->fp, nRecordOffset, 0 );
+ fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+ psDBF->nCurrentRecord = hEntity;
+ }
+
+ pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+ if ( nTupleLen < psDBF->nRecordLength) {
+ nTupleLen = psDBF->nRecordLength;
+ pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
+ }
+
+ memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
+
+ return( pReturnTuple );
+}
+
+/************************************************************************/
+/* DBFCloneEmpty() */
+/* */
+/* Read one of the attribute fields of a record. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
+{
+ DBFHandle newDBF;
+
+ newDBF = DBFCreate ( pszFilename );
+ if ( newDBF == NULL ) return ( NULL );
+
+ newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
+ memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
+
+ newDBF->nFields = psDBF->nFields;
+ newDBF->nRecordLength = psDBF->nRecordLength;
+ newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
+
+ newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+ newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+ newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+ newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
+ memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
+
+ newDBF->bNoHeader = TRUE;
+ newDBF->bUpdated = TRUE;
+
+ DBFWriteHeader ( newDBF );
+ DBFClose ( newDBF );
+
+ newDBF = DBFOpen ( pszFilename, "rb+" );
+
+ return ( newDBF );
+}
+
+/************************************************************************/
+/* DBFGetNativeFieldType() */
+/* */
+/* Return the DBase field type for the specified field. */
+/* */
+/* Value can be one of: 'C' (String), 'D' (Date), 'F' (Float), */
+/* 'N' (Numeric, with or without decimal), */
+/* 'L' (Logical), */
+/* 'M' (Memo: 10 digits .DBT block ptr) */
+/************************************************************************/
+
+char SHPAPI_CALL
+DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+
+{
+ if( iField >=0 && iField < psDBF->nFields )
+ return psDBF->pachFieldType[iField];
+
+ return ' ';
+}
+
+/************************************************************************/
+/* str_to_upper() */
+/************************************************************************/
+
+static void str_to_upper (char *string)
+{
+ int len;
+ short i = -1;
+
+ len = strlen (string);
+
+ while (++i < len)
+ if (isalpha(string[i]) && islower(string[i]))
+ string[i] = toupper ((int)string[i]);
+}
+
+/************************************************************************/
+/* DBFGetFieldIndex() */
+/* */
+/* Get the index number for a field in a .dbf file. */
+/* */
+/* Contributed by Jim Matthews. */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
+
+{
+ char name[12], name1[12], name2[12];
+ int i;
+
+ strncpy(name1, pszFieldName,11);
+ str_to_upper(name1);
+
+ for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+ {
+ DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
+ strncpy(name2,name,11);
+ str_to_upper(name2);
+
+ if(!strncmp(name1,name2,10))
+ return(i);
+ }
+ return(-1);
+}
Added: packages/openev/branches/upstream/current/delivery/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/delivery/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/delivery/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+/INSTALL.TXT/1.3/Fri Aug 25 19:50:28 2000//
+/install/1.9/Mon Jun 25 19:25:06 2001//
+/license.txt/1.1/Tue Aug 22 18:02:54 2000//
+/mkdist/1.9/Thu Sep 12 13:08:14 2002//
+/mksrcdist.sh/1.1/Thu Jan 24 15:15:54 2002//
+/package/1.4/Mon Jun 25 19:25:06 2001//
+/setup_openev/1.6/Thu Feb 1 03:27:23 2001//
+D
Added: packages/openev/branches/upstream/current/delivery/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/delivery/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/delivery/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/delivery
Added: packages/openev/branches/upstream/current/delivery/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/delivery/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/delivery/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/delivery/INSTALL.TXT
===================================================================
--- packages/openev/branches/upstream/current/delivery/INSTALL.TXT (rev 0)
+++ packages/openev/branches/upstream/current/delivery/INSTALL.TXT 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,9 @@
+OpenEV UNIX Installation
+
+To Install:
+ - go into the unix directory on the CD by typing "cd unix" from the CD root
+ - execute "./install [linux|solaris|irix|nt] [location]" ensuring you have write permission
+ to the location you specify
+
+To Run:
+- execute "[location]/bin/openev"
Added: packages/openev/branches/upstream/current/delivery/install
===================================================================
--- packages/openev/branches/upstream/current/delivery/install (rev 0)
+++ packages/openev/branches/upstream/current/delivery/install 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+#
+# echo with no linefeed at end of line (system dependent)
+#
+echo_no_lf()
+{
+ case `uname -a` in
+ Linux*) echo -n "${1}";;
+ *) echo "${1}\c";;
+ esac
+}
+
+#
+# Check the command line parameters
+#
+if [ -z "${2}" ];
+then
+ echo "usage: $0 [linux|solaris|irix|nt] [location]"
+ exit 1
+fi
+
+#
+# Check parameter 1: platform
+#
+case "${1}" in
+ linux) ARCHPATH=Linux;;
+ solaris) ARCHPATH=SunOS;;
+ irix) ARCHPATH=IRIX64;;
+ nt) ARCHPATH=nt;;
+ *)
+ echo "Platform must be one of linux, solaris, irix, or nt."
+ exit 1;;
+esac
+
+#
+# Check parameter 1: insar directory
+#
+if [ "${1}" = "nt" ]; then
+ case "${2}" in
+ [A-Za-z][:=]/*);;
+ *) echo "Input parameter must be a full path."; exit 1;;
+ esac
+else
+ case "${2}" in
+ /*);;
+ *) echo "Input parameter must be a full path."; exit 1;;
+ esac
+fi
+INSTALLDIR=${2}
+
+
+#
+# Check OpenEV directory doesn't already exist
+#
+if [ -d ${2} ]; then
+ echo_no_lf "OpenEV already exists in the directory ${2}, do you want to overwrite it [Y/n]?"
+ read OVERWRITE
+ if [ "${OVERWRITE}" = "n" -o "${OVERWRITE}" = "N" ]; then
+ echo "Installation aborted. No action taken."
+ exit 1
+ fi
+fi
+
+# Try to make the directory
+mkdir -p ${INSTALLDIR}
+
+#
+# Check for Write permission in directory
+#
+if ! [ -w ${2} ]; then
+ echo "Installation failed. You need to have write permission in ${2}."
+ exit 1
+fi
+
+# --------------------- Real Work Below --------------------
+echo "--Starting OpenEV Installation--"
+
+# Copy OS specific files
+echo "Copying platform dependent file - OpenEV, Python, GTK, Mesa etc."
+
+if [ "${ARCHPATH}" = "Linux" ]; then
+ cp -rf Linux/* ${INSTALLDIR}
+fi
+
+if [ "${ARCHPATH}" = "IRIX64" ]; then
+ cp -rf IRIX64/* ${INSTALLDIR}
+fi
+
+if [ "${ARCHPATH}" = "SunOS" ]; then
+ cp -rf SunOS/* ${INSTALLDIR}
+fi
+
+# Copy OS independent files
+echo "Copying platform independent file"
+cp -rf common/* ${INSTALLDIR}
+
+#setup a link to openev in bin directory
+#ln -s ${INSTALLDIR}/pymod/openev.py ${INSTALLDIR}/bin/openev
+
+# Byte compile Python and OpenEV directories recursively
+echo "Compiling Python Code"
+`${INSTALLDIR}/bin/python -O ${INSTALLDIR}/lib/python2.1/compileall.py ${INSTALLDIR} > /dev/null`
+
+# Create run scripts, to set environment variables and execute openev
+chmod -R u+rw ${INSTALLDIR}
+echo '#!/bin/sh' > ${INSTALLDIR}/first_lines
+echo "OPENEVHOME=$2" >> ${INSTALLDIR}/first_lines
+cat ${INSTALLDIR}/first_lines setup_openev > ${INSTALLDIR}/bin/openev
+rm -f ${INSTALLDIR}/first_lines
+
+chmod a+rx ${INSTALLDIR}/bin/openev
+
+# Done
+echo "Done. OpenEV Installed Successfully in ${2}."
+echo "Run ${2}/bin/openev to start OpenEV."
Property changes on: packages/openev/branches/upstream/current/delivery/install
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/delivery/license.txt
===================================================================
--- packages/openev/branches/upstream/current/delivery/license.txt (rev 0)
+++ packages/openev/branches/upstream/current/delivery/license.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Added: packages/openev/branches/upstream/current/delivery/mkdist
===================================================================
--- packages/openev/branches/upstream/current/delivery/mkdist (rev 0)
+++ packages/openev/branches/upstream/current/delivery/mkdist 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,172 @@
+#!/bin/sh
+
+INSTALLDIR=../delivery
+OSTYPE=`uname`
+GDAL=../../gdal
+
+
+# ---- Work - Platform Independent ---
+
+# Create all directories
+echo "Creating delivery Directory"
+mkdir -p ${INSTALLDIR}/${OSTYPE}/bin
+mkdir -p ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+mkdir -p ${INSTALLDIR}/${OSTYPE}/pymod
+mkdir -p ${INSTALLDIR}/${OSTYPE}/tools
+# include python headers for building tools
+mkdir -p ${INSTALLDIR}/${OSTYPE}/include
+mkdir -p ${INSTALLDIR}/common
+
+# Copy OpenEV specific things
+echo "Copying OpenEV"
+cp ../gvtest ${INSTALLDIR}/${OSTYPE}/bin
+cp -r ../html ${INSTALLDIR}/common
+cp -r ../pics ${INSTALLDIR}/common
+cp -r ../ramps ${INSTALLDIR}/common
+
+# Copy OpenEV pymod directory
+cp ../pymod/*.so ../pymod/*.py ${INSTALLDIR}/${OSTYPE}/pymod
+
+# Don't copy tools- not stable yet. Directory is expected though
+# cp ../tools/*.py ${INSTALLDIR}/${OSTYPE}/tools
+
+# Copy libraries other than Python, NumPy and GTK
+echo "Copying GDAL"
+cp ${GDAL}/libgdal.1.1.so ${INSTALLDIR}/${OSTYPE}/lib
+cp ${GDAL}/apps/gdaladdo ${INSTALLDIR}/${OSTYPE}/bin
+cp ${GDAL}/apps/gdalinfo ${INSTALLDIR}/${OSTYPE}/bin
+cp ${GDAL}/apps/gdal_translate ${INSTALLDIR}/${OSTYPE}/bin
+cp ${GDAL}/pymod/*.py ${GDAL}/pymod/*.so ${INSTALLDIR}/${OSTYPE}/pymod
+
+# ---- Work - Platform Independent ---
+
+if [ "${OSTYPE}" = "Linux" ]; then
+ PYTHON=/data/local_installations/lib/python2.1
+ PYTHONBIN=/data/local_installations/bin/python
+ GTKLIB=/data/local_installations/lib
+ PYTHONINC=/data/local_installations/include/python2.1
+ GNUPLOT_BIN=/home/gwalter/bin
+
+ # Copy Python, NumPy and PyGTK
+ echo "Copying Python and Site-Packages"
+ cp -r ${PYTHON} ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${PYTHONBIN} ${INSTALLDIR}/${OSTYPE}/bin
+ cp -r ${PYTHONINC} ${INSTALLDIR}/${OSTYPE}/include
+
+ echo "Copying GTK"
+ cp ${GTKLIB}/libgtkgl.so.5.0.0 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgtk-1.2.so.0.9.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgdk-1.2.so.0.9.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgmodule-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgthread-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libglib-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+
+ # GL Stuff
+ echo "Copying Mesa GL libraries and other supporting libraries"
+ # cp /usr/lib/libGLcore.so.1 ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+ cp /data/local_installations/lib/libGL.so.1.2.030402 ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+ cp /data/local_installations/lib/libGLU.so.1.1.030402 ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+
+ # Gnuplot stuff
+ cp ${GNUPLOT_BIN}/gnuplot ${INSTALLDIR}/${OSTYPE}/bin
+ cp ${GNUPLOT_BIN}/gnuplot_x11 ${INSTALLDIR}/${OSTYPE}/bin
+
+ # Other libs
+ cp /usr/lib/libjpeg.so.62 ${INSTALLDIR}/${OSTYPE}/lib
+ cp /usr/lib/libpng.so.2 ${INSTALLDIR}/${OSTYPE}/lib
+ cp /lib/libpthread.so.0 ${INSTALLDIR}/${OSTYPE}/lib
+ cp /usr/lib/libvga.so.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp /data/local_installations/lib/libproj.so.0.2.0 ${INSTALLDIR}/${OSTYPE}/lib
+fi
+
+
+if [ "${OSTYPE}" = "IRIX64" ]; then
+ PYTHON=/esa2/temp_gwalter/local_installations/lib/python2.1
+ PYTHONBIN=/esa2/temp_gwalter/local_installations/bin/python
+ GTKLIB=/esa2/temp_gwalter/local_installations/lib
+ PYTHONINC=/esa2/temp_gwalter/local_installations/include/python2.1
+ GNUPLOT_BIN=/usr/local/bin
+
+ # Copy Python, NumPy and PyGTK
+ echo "Copying Python and Site-Packages"
+ cp -r ${PYTHON} ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${PYTHONBIN} ${INSTALLDIR}/${OSTYPE}/bin
+ cp -r ${PYTHONINC} ${INSTALLDIR}/${OSTYPE}/include
+
+ # Copy GTK libraries
+ echo "Copying GTK"
+ cp ${GTKLIB}/libgtkgl.so.6.0 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgtk-1.2.so.1.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgdk-1.2.so.1.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgmodule-1.2.so.1.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgthread-1.2.so.1.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libglib-1.2.so.1.10 ${INSTALLDIR}/${OSTYPE}/lib
+
+ # GL Stuff
+ echo "Copying Mesa GL libraries and other supporting libraries"
+ cp /esa2/temp_gwalter/local_installations/lib/libGL.so ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+ cp /esa2/temp_gwalter/local_installations/lib/libGLU.so ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+
+ # Gnuplot stuff
+ cp ${GNUPLOT_BIN}/gnuplot ${INSTALLDIR}/${OSTYPE}/bin
+ cp ${GNUPLOT_BIN}/gnuplot_x11 ${INSTALLDIR}/${OSTYPE}/bin
+
+ # Other libs
+ cp /usr/lib/libjpeg.so ${INSTALLDIR}/${OSTYPE}/lib
+ cp /usr/lib/libpng.so ${INSTALLDIR}/${OSTYPE}/lib
+ cp /usr/lib/libpthread.so ${INSTALLDIR}/${OSTYPE}/lib
+ cp /esa2/temp_gwalter/local_installations/lib/libproj.so.1.0 ${INSTALLDIR}/${OSTYPE}/lib
+fi
+
+if [ "${OSTYPE}" = "SunOS" ]; then
+ PYTHON=/stripe2/temp_gwalter/local_installations/lib/python2.1
+ PYTHONBIN=/stripe2/temp_gwalter/local_installations/bin/python
+ GTKLIB=/stripe2/temp_gwalter/local_installations/lib
+ PYTHONINC=/stripe2/temp_gwalter/local_installations/include/python2.1
+ GNUPLOT_BIN=/opt/sfw/bin
+
+ # Copy Python, NumPy and PyGTK
+ echo "Copying Python and Site-Packages"
+ cp -r ${PYTHON} ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${PYTHONBIN} ${INSTALLDIR}/${OSTYPE}/bin
+ cp -r ${PYTHONINC} ${INSTALLDIR}/${OSTYPE}/include
+
+ # Copy GTK libraries
+ echo "Copying GTK"
+ cp ${GTKLIB}/libgtkgl.so.5.0.0 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgtk-1.2.so.0.9.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgdk-1.2.so.0.9.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgmodule-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libgthread-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+ cp ${GTKLIB}/libglib-1.2.so.0.0.10 ${INSTALLDIR}/${OSTYPE}/lib
+
+ # GL Stuff
+ echo "Copying Mesa GL libraries and other supporting libraries"
+ cp /stripe2/temp_gwalter/local_installations/lib/libGL.so.1.2.030402 ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+ cp /stripe2/temp_gwalter/local_installations/lib/libGLU.so.1.1.030402 ${INSTALLDIR}/${OSTYPE}/lib/Mesa
+
+ # Gnuplot stuff
+ cp ${GNUPLOT_BIN}/gnuplot ${INSTALLDIR}/${OSTYPE}/bin
+ cp ${GNUPLOT_BIN}/gnuplot_x11 ${INSTALLDIR}/${OSTYPE}/bin
+ cp ${GNUPLOT_BIN}/../lib/libpng.so.2 ${INSTALLDIR}/${OSTYPE}/lib
+
+ # Other libs
+ #cp /usr/lib/libjpeg.so ${INSTALLDIR}/${OSTYPE}/lib
+ #cp /usr/lib/libpng.so ${INSTALLDIR}/${OSTYPE}/lib
+ cp /usr/lib/libpthread.so.1 ${INSTALLDIR}/${OSTYPE}/lib
+ cp /stripe2/temp_gwalter/local_installations/lib/libproj.so.0.2.0 ${INSTALLDIR}/${OSTYPE}/lib
+ # libstdc++.so is linked to in gdal/openev. Later should
+ # try to get rid of this dependency...
+ cp /opt/sfw/lib/libstdc++.so.2.10.0 ${INSTALLDIR}/${OSTYPE}/lib
+
+fi
+
+
+# Remove Unnecessary Python stuff to save space
+rm -r ${INSTALLDIR}/${OSTYPE}/lib/python2.1/test
+rm -r ${INSTALLDIR}/${OSTYPE}/lib/python2.1/*.pyc
+rm -r ${INSTALLDIR}/${OSTYPE}/lib/python2.1/*.pyo
+rm -r ${INSTALLDIR}/${OSTYPE}/lib/python2.1/site-packages/*.pyc
+rm -r ${INSTALLDIR}/${OSTYPE}/lib/python2.1/site-packages/*.pyo
+
+echo "Done"
Property changes on: packages/openev/branches/upstream/current/delivery/mkdist
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/delivery/mksrcdist.sh
===================================================================
--- packages/openev/branches/upstream/current/delivery/mksrcdist.sh (rev 0)
+++ packages/openev/branches/upstream/current/delivery/mksrcdist.sh 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+if [ $# -lt 1 ] ; then
+ echo "Usage: mksrcdist version"
+ echo
+ echo "Example: mksrcdist.sh 1.1.4"
+ exit
+fi
+
+SRC_VERSION=$1
+COMPRESSED_VERSION=`echo $SRC_VERSION | tr -d .`
+
+rm -rf dist_wrk
+mkdir dist_wrk
+cd dist_wrk
+
+export CVSROOT=:pserver:anonymous at cvs.openev.sf.net:/cvsroot/openev
+
+echo "Please type [ENTER] if prompted for a password."
+cvs login
+
+cvs checkout openev
+
+if [ \! -d openev ] ; then
+ echo "cvs checkout reported an error ... abandoning mksrcdist"
+ cd ..
+ rm -rf dist_wrk
+ exit
+fi
+
+find openev -name CVS -exec rm -rf {} \;
+
+mv openev openev-${SRC_VERSION}
+
+rm -f ../openev-${SRC_VERSION}.tar.gz ../openev${COMPRESSED_VERSION}.zip
+
+tar cf ../openev-${SRC_VERSION}.tar openev-${SRC_VERSION}
+gzip -9 ../openev-${SRC_VERSION}.tar
+zip -r ../openev${COMPRESSED_VERSION}.zip openev-${SRC_VERSION}
+
+cd ..
+rm -rf dist_wrk
Property changes on: packages/openev/branches/upstream/current/delivery/mksrcdist.sh
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/delivery/package
===================================================================
--- packages/openev/branches/upstream/current/delivery/package (rev 0)
+++ packages/openev/branches/upstream/current/delivery/package 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+#
+# Check parameter 1: platform
+#
+case "${1}" in
+ linux) ARCHPATH=openev/Linux;;
+ solaris) ARCHPATH=openev/SunOS;;
+ irix) ARCHPATH=openev/IRIX64;;
+ all) ARCHPATH=openev/Linux openev/IRIX64 openev/SunOS;;
+ *)
+ echo "Platform must be one of linux, solaris, irix."
+ exit 1;;
+esac
+
+
+# Create a tar file, from delivery directory
+
+cd ..
+mv delivery openev
+tar -cvf openev.tar openev/INSTALL.TXT openev/license.txt openev/install openev/setup_openev openev/common ${ARCHPATH}
+mv openev delivery
+cd delivery
Property changes on: packages/openev/branches/upstream/current/delivery/package
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/delivery/setup_openev
===================================================================
--- packages/openev/branches/upstream/current/delivery/setup_openev (rev 0)
+++ packages/openev/branches/upstream/current/delivery/setup_openev 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,22 @@
+
+# Setup Environment Variables for OpenEV
+
+PYTHONHOME=${OPENEVHOME}
+PYTHONPATH=${OPENEVHOME}/pymod:${PYTHONPATH}
+LD_LIBRARY_PATH=${OPENEVHOME}/lib:${LD_LIBRARY_PATH}
+PATH=${OPENEVHOME}/bin:${PATH}
+
+# check for accelerated hardware flag
+if [ "${1}" = "-h" ]; then
+ shift
+ echo "Setup for user installed hardware acceleration"
+else
+ echo "Default software rendering mode (use -h if accelerated video card installed)."
+ LD_LIBRARY_PATH=${OPENEVHOME}/lib/Mesa:${LD_LIBRARY_PATH}
+fi
+
+export PYTHONHOME PYTHONPATH LD_LIBRARY_PATH PATH
+
+
+# Run OpenEV
+${OPENEVHOME}/pymod/openev.py "$@"
Property changes on: packages/openev/branches/upstream/current/delivery/setup_openev
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/doc/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/doc/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/doc/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,16 @@
+/Makefile/1.5/Fri Jul 14 16:05:48 2000//
+/asilogo.eps/1.1/Tue Jun 20 14:33:16 2000//
+/future.tex/1.1/Tue Jun 20 15:34:18 2000//
+/gvclass.fig/1.1/Tue Jun 20 14:33:16 2000//
+/gvdata.fig/1.1/Tue Jun 20 14:33:16 2000//
+/l2h-init.perl/1.1/Fri Jul 14 16:04:28 2000//
+/layerdlg.eps/1.1/Tue Jun 20 14:33:16 2000//
+/lodgen.fig/1.1/Tue Jun 20 14:33:16 2000//
+/openev.tex/1.1/Tue Jun 20 14:33:16 2000//
+/openev_bigpicture.fig/1.1/Tue Jun 20 14:33:16 2000//
+/openevlogo.eps/1.1/Tue Jun 20 14:33:16 2000//
+/openevreport.cls/1.1/Tue Jun 20 14:33:16 2000//
+/openevreport.perl/1.1/Fri Jul 14 15:50:33 2000//
+/phaseclip.fig/1.1/Tue Jun 20 14:33:16 2000//
+/toolbar.eps/1.1/Tue Jun 20 14:33:16 2000//
+D
Added: packages/openev/branches/upstream/current/doc/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/doc/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/doc/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/doc
Added: packages/openev/branches/upstream/current/doc/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/doc/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/doc/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/doc/Makefile
===================================================================
--- packages/openev/branches/upstream/current/doc/Makefile (rev 0)
+++ packages/openev/branches/upstream/current/doc/Makefile 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,42 @@
+DOC = openev
+FUTURE = future
+L2H_OPT = -show_section_numbers -no_navigation
+L2H_INC = l2h-init.perl
+SPLIT = 0
+L2H_FLAGS = $(L2H_OPT) -split $(SPLIT) -init_file $(L2H_INC)
+
+FIGS = openev_bigpicture.eps gvclass.eps gvdata.eps lodgen.eps phaseclip.eps
+
+default: all
+
+%.eps : %.fig
+ fig2dev -L ps $< $@
+
+$(FUTURE).dvi : $(FUTURE).tex
+ latex $*
+# - at grep 'Rerun to get cross-references right' $*.log && latex $*
+
+$(DOC).dvi : $(DOC).tex $(FIGS)
+ latex $*
+ - at grep 'Rerun to get cross-references right' $*.log && latex $*
+
+$(DOC)/%.html : %.tex $(FIGS) $(L2H_INC)
+ latex2html $(L2H_FLAGS) $*
+
+all: $(DOC).dvi $(FUTURE).dvi
+
+print: $(DOC).dvi
+ dvips $*
+
+html: $(DOC)/$(DOC).html
+
+html-force: $(FIGS)
+ latex2html $(L2H_FLAGS)
+
+html-clean:
+ rm -rf $(DOC)
+
+clean:
+ rm -f $(DOC).aux $(DOC).dvi $(DOC).log $(DOC).toc $(FIGS)
+ rm -f $(FUTURE).aux $(FUTURE).dvi $(FUTURE).log
+ rm -rf $(DOC) $(FUTURE)
Added: packages/openev/branches/upstream/current/doc/asilogo.eps
===================================================================
--- packages/openev/branches/upstream/current/doc/asilogo.eps (rev 0)
+++ packages/openev/branches/upstream/current/doc/asilogo.eps 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,344 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: (ImageMagick)
+%%Title: (asilogo.eps)
+%%CreationDate: (Fri Feb 25 14:25:33 2000)
+%%BoundingBox: 0 0 251 46
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 1
+%%Pages: 0
+%%EndComments
+
+%%BeginDefaults
+%%PageOrientation: Portrait
+%%EndDefaults
+
+%%BeginProlog
+%
+% Display a color image. The image is displayed in color on
+% Postscript viewers or printers that support color, otherwise
+% it is displayed as grayscale.
+%
+/buffer 512 string def
+/byte 1 string def
+/color_packet 3 string def
+/pixels 768 string def
+
+/DirectClassPacket
+{
+ %
+ % Get a DirectClass packet.
+ %
+ % Parameters:
+ % red.
+ % green.
+ % blue.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/DirectClassImage
+{
+ %
+ % Display a DirectClass image.
+ %
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { DirectClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayDirectClassPacket } image
+ } ifelse
+} bind def
+
+/GrayDirectClassPacket
+{
+ %
+ % Get a DirectClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % red
+ % green
+ % blue
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/GrayPseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassImage
+{
+ %
+ % Display a PseudoClass image.
+ %
+ % Parameters:
+ % class: 0-PseudoClass or 1-Grayscale.
+ %
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ class 0 gt
+ {
+ currentfile buffer readline pop
+ token pop /depth exch def pop
+ /grays columns 8 add depth sub depth mul 8 idiv string def
+ columns rows depth
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { currentfile grays readhexstring pop } image
+ }
+ {
+ %
+ % Parameters:
+ % colors: number of colors in the colormap.
+ % colormap: red, green, blue color packets.
+ %
+ currentfile buffer readline pop
+ token pop /colors exch def pop
+ /colors colors 3 mul def
+ /colormap colors string def
+ currentfile colormap readhexstring pop pop
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { PseudoClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayPseudoClassPacket } image
+ } ifelse
+ } ifelse
+} bind def
+
+/DisplayImage
+{
+ %
+ % Display a DirectClass or PseudoClass image.
+ %
+ % Parameters:
+ % x & y translation.
+ % x & y scale.
+ % label pointsize.
+ % image label.
+ % image columns & rows.
+ % class: 0-DirectClass or 1-PseudoClass.
+ % compression: 0-RunlengthEncodedCompression or 1-NoCompression.
+ % hex color packets.
+ %
+ gsave
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ x y translate
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ currentfile buffer readline pop
+ token pop /pointsize exch def pop
+ /Helvetica findfont pointsize scalefont setfont
+ x y scale
+ currentfile buffer readline pop
+ token pop /columns exch def
+ token pop /rows exch def pop
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ currentfile buffer readline pop
+ token pop /compression exch def pop
+ class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
+ grestore
+} bind def
+%%EndProlog
+%%Page: 1 1
+%%PageBoundingBox: 0 0 251 46
+userdict begin
+%%BeginData:
+DisplayImage
+0 0
+251.000000 46.000000
+12
+251 46
+1
+0
+0
+26
+000000
+040404
+0c0c0c
+111111
+161616
+1c1c1c
+222222
+292929
+393939
+4d4d4d
+666666
+777777
+808080
+868686
+969696
+999999
+a0a0a4
+b2b2b2
+c0c0c0
+cbcbcb
+d7d7d7
+dddddd
+e3e3e3
+f1f1f1
+f8f8f8
+ffffff
+19880c0619f10c0819ef0c0a19ed11000c0119050c0319ec0c01190618000c0219f60c03
+19f60c0219f60c0219f70c02195f12000006110019130000191400181909000719240000
+19120c0219030000190f00071908001819090006190d1200000d190f0b00000119130018
+190900071923000219100c0219040002190d00071908001819090006190c0011190d0003
+1912001819090007192300020a00190e0c0219050004190b00071908001819090006190b
+0012190c00040e00191100181909000719220004190d0c02190600061909000719080018
+19090006190a0012190c0006191100181909000719210006190b0d000c01190700081907
+00071908001819090006190a0006190600031200190b1700000719100018190900071920
+000819090c021908000a190500071908001819090006190a000519180009190f00181909
+0007191f0c000008020019070c021909000c190300071908001819090006190a00051917
+000b190e001819090007191e0c00000a19060c01190b000e190100071908001819090006
+190a00071914000c1917000719110007191c0c01000c19040c01190c0018191100071911
+0006190a000a19101400000d1916000719110007191b0c01000e190112000c01190d0018
+1911000719110006190b000c190d000f1915000719110007191a0c011800000f0c01190f
+00181911000719110006190c0c00000d1909000719000008191400071911000719181300
+0c000d0019000007190000070c00191000181911000719110006190f000c090019060008
+19010007191400071911000719170c011000190000070100190100071910001819110007
+1911000619110300000a170019040f00000719030007191300071911000719160c011901
+000819020c000007190f0006190000101911000719110006191500081904000719040008
+191200071911000719150c0119011600000719040008190e00061902000e191100071911
+0006191700061903000719010c0219010008191100071911001319080c01190200071901
+0c0219000c000007190e00061904000c1911000719110006191800051902000819000f00
+0c03190100071911000719110013190612000c01190200070e0019000c0419010007190d
+00061906000a1911000719110006190c0700190a000519010a00000719010c040d001901
+00071910000719110013190514000c011902000819010c04190115000007190c00061908
+00081911000719110006190c000508001902050000061901000719020c04130019010100
+0007190f00071911001319040c0219020b00000719020c0419020008190b0006190a0006
+1911000719110006190b00121900000719040c0319030008190e00071911001319030c02
+1903000719030c0419030007190b0006190c00041911000719110006190b001104000008
+19050c01190500071700190d00071911001319020e000c011903000719060c0019060007
+190a0006190e00021911000719110006190a001219000007190f0007190d000719110013
+19010c0219030008190f000719090006191000001911000719110006190c0600000d195f
+18000c01180019f60c0219f60c0219f60c0219f60c0219f70c0219f60c0219f60d000c02
+19f60c0319090c02120019e80c0319050e000c030d0019e90c0e19eb0c0c19ed0c0919f0
+0c060d0019f30c010d00199f
+%%EndData
+end
+%%PageTrailer
+%%Trailer
+%%BoundingBox: 0 0 251 46
+%%EOF
Added: packages/openev/branches/upstream/current/doc/future.tex
===================================================================
--- packages/openev/branches/upstream/current/doc/future.tex (rev 0)
+++ packages/openev/branches/upstream/current/doc/future.tex 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,48 @@
+\documentclass{article}
+
+\begin{document}
+
+\title{Improvements to OpenEV}
+\date{2000-06-20}
+\author{OpenEV Project}
+\maketitle
+
+\section{Future Directions}
+
+As OpenEV matures, new tools and layer classes, and common UI elements
+will be added to enhance its capabilities. The object oriented
+structure ensures that this growth is possible.
+
+The follow sections list ideas that could be added to OpenEV.
+
+\subsection{3D}
+
+One particular area for improvement in OpenEV is in its handling of 3D imagery.
+
+\begin{itemize}
+\item continuous LOD approach to rendering the 3D mesh is required to allow for
+interactive frame rates when dealing with large elevation datasets.
+\item intellegent tesselation of mesh
+\item 3D datasets, such as scene graph elements (e.g. city buildings) could be added.
+\item LUT for mesh would allow elevation data to be visualized without a drape
+\item lighting could be added for more realistic view, this would also facilitate viewing
+elevation data without a drape.
+\end{itemize}
+
+
+\subsection{R\&D Tools}
+
+From its conception OpenEV has been designed to be a R\&D tool.
+
+\begin{itemize}
+\item Another important direction is coupling the display capabilities with
+a Python shell window, to create an interactive numerical analysis and
+image manipulation environment in the vein of Research Systems's IDL,
+or The Mathwork's MATLAB. This will eventually become an integrated
+environment where the user is able to combine plug-in processing and
+analysis functions, plotting capabilities, image display, point and
+vector marking, and a powerful scripting language. The goal is to
+build a platform for image processing R\&D.
+\end{itemize}
+
+\end{document}
\ No newline at end of file
Added: packages/openev/branches/upstream/current/doc/gvclass.fig
===================================================================
--- packages/openev/branches/upstream/current/doc/gvclass.fig (rev 0)
+++ packages/openev/branches/upstream/current/doc/gvclass.fig 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,101 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4200 600 5400 600 5400 900 4200 900 4200 600
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4200 1500 5400 1500 5400 1800 4200 1800 4200 1500
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4200 2100 5400 2100 5400 2400 4200 2400 4200 2100
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1200 1200 9000 1200
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 600 1500 1800 1500 1800 1800 600 1800 600 1500
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 600 2100 1800 2100 1800 2400 600 2400 600 2100
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1200 1200 1200 1500
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1200 1800 1200 2100
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 2400 3000 3600 3000 3600 3300 2400 3300 2400 3000
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 900 3900 2700 3900 2700 4200 900 4200 900 3900
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4800 900 4800 1500
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4800 1800 4800 2100
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4800 2400 4800 2700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 3000 2700 8100 2700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 3000 2700 3000 3000
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 3000 3300 3000 3600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1800 3600 4200 3600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1800 3600 1800 3900
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 3300 3900 5100 3900 5100 4200 3300 4200 3300 3900
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4200 3600 4200 3900
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 7500 3000 8700 3000 8700 3300 7500 3300 7500 3000
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 8100 2700 8100 3000
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 8400 3900 9600 3900 9600 4200 8400 4200 8400 3900
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9000 1200 9000 3900
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 3900 4800 5700 4800 5700 5100 3900 5100 3900 4800
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 6000 4800 7200 4800 7200 5100 6000 5100 6000 4800
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 7500 4800 8700 4800 8700 5100 7500 5100 7500 4800
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 9000 4800 10200 4800 10200 5100 9000 5100 9000 4800
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9000 4200 9000 4500
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9600 4500 9600 4800
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 8100 4500 8100 4800
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 6600 4500 6600 4800
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4800 4500 4800 4800
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 4800 4500 9600 4500
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 1800 4200 1800 4650
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 4950 3000 6450 3000 6450 3300 4950 3300 4950 3000
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 5700 2700 5700 3000
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 900 4650 2700 4650 2700 4950 900 4950 900 4650
+4 1 0 100 0 20 12 0.0000 4 180 825 4800 825 GtkObject\001
+4 1 0 100 0 20 12 0.0000 4 135 660 4800 1725 GtkData\001
+4 1 0 100 0 20 12 0.0000 4 135 630 4800 2325 GvData\001
+4 1 0 100 0 20 12 0.0000 4 135 915 1200 1725 GtkGLArea\001
+4 1 0 100 0 20 12 0.0000 4 135 1065 1200 2325 GvViewArea\001
+4 1 0 100 0 20 12 0.0000 4 180 720 3000 3225 GvLayer\001
+4 1 0 100 0 20 12 0.0000 4 180 1350 1800 4125 GvShapesLayer\001
+4 1 0 100 0 20 12 0.0000 4 180 1245 4200 4125 GvRasterLayer\001
+4 1 0 100 0 20 12 0.0000 4 135 765 8100 3225 GvRaster\001
+4 1 0 100 0 20 12 0.0000 4 135 600 9000 4125 GvTool\001
+4 1 0 100 0 20 12 0.0000 4 135 1380 4800 5025 GvSelectionTool\001
+4 1 0 100 0 20 12 0.0000 4 135 960 6600 5025 GvLineTool\001
+4 1 0 100 0 20 12 0.0000 4 135 1050 8100 5025 GvNodeTool\001
+4 1 0 100 0 20 12 0.0000 4 135 900 9600 5025 GvToolbox\001
+4 0 0 100 0 0 12 0.0000 4 180 1185 1200 4875 GvPqueryLayer\001
+4 0 0 100 0 0 12 0.0000 4 180 780 5250 3225 GvShapes\001
Added: packages/openev/branches/upstream/current/doc/gvdata.fig
===================================================================
--- packages/openev/branches/upstream/current/doc/gvdata.fig (rev 0)
+++ packages/openev/branches/upstream/current/doc/gvdata.fig 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,40 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 4275 900 5325 1950
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 4800 1425 456 456 4800 1425 5250 1500
+4 1 0 100 0 20 12 0.0000 4 135 510 4800 1500 Points\001
+4 1 0 100 0 20 12 0.0000 4 135 390 4800 1275 UTM\001
+4 1 0 100 0 20 12 0.0000 4 180 480 4800 1725 Layer\001
+-6
+6 1050 1650 1950 2550
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 1500 2100 437 437 1500 2100 1875 2325
+4 1 0 100 0 20 12 0.0000 4 135 375 1500 2025 LCC\001
+4 1 0 100 0 20 12 0.0000 4 135 510 1500 2250 Points\001
+-6
+6 2475 900 3525 1950
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 3000 1425 456 456 3000 1425 3450 1500
+4 1 0 100 0 20 12 0.0000 4 135 390 3000 1350 UTM\001
+4 1 0 100 0 20 12 0.0000 4 135 510 3000 1575 Points\001
+-6
+6 4350 2325 5250 3225
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 4800 2775 450 450 4800 2775 5250 2775
+4 1 0 100 0 20 12 0.0000 4 135 375 4800 2625 LCC\001
+4 1 0 100 0 20 12 0.0000 4 135 510 4800 2850 Points\001
+4 1 0 100 0 20 12 0.0000 4 180 480 4800 3075 Layer\001
+-6
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1875 1875 2550 1575
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 3450 1425 4350 1425
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1950 2250 4350 2700
Added: packages/openev/branches/upstream/current/doc/l2h-init.perl
===================================================================
--- packages/openev/branches/upstream/current/doc/l2h-init.perl (rev 0)
+++ packages/openev/branches/upstream/current/doc/l2h-init.perl 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+# latex2html init file for openev
+
+$BODYTEXT = "bgcolor=white text=black";
+$TITLE = "OpenEV Library Design";
Added: packages/openev/branches/upstream/current/doc/layerdlg.eps
===================================================================
--- packages/openev/branches/upstream/current/doc/layerdlg.eps (rev 0)
+++ packages/openev/branches/upstream/current/doc/layerdlg.eps 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,924 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: (ImageMagick)
+%%Title: (layerdlg.eps)
+%%CreationDate: (Fri Feb 25 14:26:49 2000)
+%%BoundingBox: 0 0 208 223
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 1
+%%Pages: 0
+%%EndComments
+
+%%BeginDefaults
+%%PageOrientation: Portrait
+%%EndDefaults
+
+%%BeginProlog
+%
+% Display a color image. The image is displayed in color on
+% Postscript viewers or printers that support color, otherwise
+% it is displayed as grayscale.
+%
+/buffer 512 string def
+/byte 1 string def
+/color_packet 3 string def
+/pixels 768 string def
+
+/DirectClassPacket
+{
+ %
+ % Get a DirectClass packet.
+ %
+ % Parameters:
+ % red.
+ % green.
+ % blue.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/DirectClassImage
+{
+ %
+ % Display a DirectClass image.
+ %
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { DirectClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayDirectClassPacket } image
+ } ifelse
+} bind def
+
+/GrayDirectClassPacket
+{
+ %
+ % Get a DirectClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % red
+ % green
+ % blue
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/GrayPseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassImage
+{
+ %
+ % Display a PseudoClass image.
+ %
+ % Parameters:
+ % class: 0-PseudoClass or 1-Grayscale.
+ %
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ class 0 gt
+ {
+ currentfile buffer readline pop
+ token pop /depth exch def pop
+ /grays columns 8 add depth sub depth mul 8 idiv string def
+ columns rows depth
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { currentfile grays readhexstring pop } image
+ }
+ {
+ %
+ % Parameters:
+ % colors: number of colors in the colormap.
+ % colormap: red, green, blue color packets.
+ %
+ currentfile buffer readline pop
+ token pop /colors exch def pop
+ /colors colors 3 mul def
+ /colormap colors string def
+ currentfile colormap readhexstring pop pop
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { PseudoClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayPseudoClassPacket } image
+ } ifelse
+ } ifelse
+} bind def
+
+/DisplayImage
+{
+ %
+ % Display a DirectClass or PseudoClass image.
+ %
+ % Parameters:
+ % x & y translation.
+ % x & y scale.
+ % label pointsize.
+ % image label.
+ % image columns & rows.
+ % class: 0-DirectClass or 1-PseudoClass.
+ % compression: 0-RunlengthEncodedCompression or 1-NoCompression.
+ % hex color packets.
+ %
+ gsave
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ x y translate
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ currentfile buffer readline pop
+ token pop /pointsize exch def pop
+ /Helvetica findfont pointsize scalefont setfont
+ x y scale
+ currentfile buffer readline pop
+ token pop /columns exch def
+ token pop /rows exch def pop
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ currentfile buffer readline pop
+ token pop /compression exch def pop
+ class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
+ grestore
+} bind def
+%%EndProlog
+%%Page: 1 1
+%%PageBoundingBox: 0 0 208 223
+userdict begin
+%%BeginData:
+DisplayImage
+0 0
+208.000000 223.000000
+12
+208 223
+1
+0
+0
+174
+b5b6b5
+a5aaa5
+292829
+9c9e94
+949694
+94968c
+949a94
+94928c
+9c9a94
+9c9e9c
+9ca29c
+a5a29c
+a5a69c
+6b6963
+080808
+9c9a9c
+949294
+8c8e8c
+6b6d6b
+393839
+000000
+8c8a8c
+9c9694
+8c928c
+948e8c
+313031
+adaaa5
+b5b2b5
+8c8a84
+7b797b
+5a595a
+424542
+424142
+424139
+394139
+393c39
+525152
+6b716b
+a5a2a5
+5a5d5a
+4a4d4a
+636563
+737173
+7b7973
+737573
+7b7d7b
+737973
+636163
+5a615a
+848684
+7b7573
+63615a
+635d5a
+636963
+293029
+7b7d73
+8c8684
+524d4a
+313029
+848284
+84827b
+313431
+adaead
+73716b
+4a494a
+6b696b
+292c29
+847d73
+4a4942
+312c29
+6b6d63
+5a5952
+847d7b
+736d6b
+4a4542
+52514a
+080c08
+a5a6a5
+292421
+524d42
+84867b
+101010
+635d52
+393431
+212421
+6b6563
+292821
+63655a
+424539
+393831
+adaaad
+5a5552
+6b655a
+dedbde
+b5b2ad
+ffffff
+e7e3e7
+adaeb5
+dedfde
+adb2ad
+d6d7d6
+313831
+d6d3d6
+cecfce
+c6c7c6
+c6c3c6
+bdbebd
+84868c
+adaea5
+8c868c
+181818
+e7e7e7
+efebef
+7b8e9c
+cecbce
+bdbabd
+00ff00
+cecfc6
+b5b6ad
+004d00
+7b827b
+efefef
+848a84
+ffff00
+8c8e84
+7b8284
+84756b
+7b7563
+7b716b
+8c796b
+de9a10
+efbe00
+efb600
+7b717b
+ef9e08
+f7c700
+ffcb08
+f7f7f7
+7b756b
+ffb608
+ffcf00
+f7f3f7
+94aebd
+ffebd6
+f7fbf7
+effbff
+c6c7ce
+cecbd6
+c6c3ce
+313429
+c6c7bd
+bdbeb5
+c6c3bd
+fffbff
+f7f3ef
+fffbf7
+d6d7de
+cecfd6
+7b7d84
+8c8e94
+42454a
+4a454a
+d6d3ce
+b5bab5
+bdc3bd
+bdbab5
+c6cbc6
+4a5152
+bdc7d6
+738e94
+f7fbff
+9cb2ce
+f7f7ff
+525952
+00cd01000200000103000401050104000501040106000402070005000401060004070600
+040006000400060008040600030109000a000b010a0009000a0009010a00090103000903
+0300080003020900030408000301090003000901030209000b010a000900030108010300
+09000a020901030009010a000b010a0209000a0009010a010b010a060b01090003010905
+030006000400060008020306090208000302080006010801060104000600040005000402
+07000501040206000300090203010903030009030301090103030900030109020b000a00
+0c000b000d000e0000000b000400080104020803040c0801040f080004000f0008030400
+08000406080104000800041810000701100104001004070010000701101c070010050700
+10000704110e07041001070010020408080104000f0008000f0a08061000120013001400
+00000700110315001102150011091000110007011001040008020f0008000f0016000407
+1001040b1600040810020700110417000701110517000701100107001000170018011001
+04011000040a0800041910020700100504001001040c1600040710080407100007041800
+1101070111021000120019001400000004001500110318000f001a001b00000007011c00
+10020700100304041d001e001f002000210120022100200f210020022100200f21002003
+210020002101200021022007210420002200210020012100200321002001210023242400
+1200150010030700110318000f001a001b00000007011c0007001100070111020f001a00
+1b00000007011c00070010050f001a001b00000007011500040108011700250019001400
+00000a0010031500260000001a00160011001c021d001002070010010400100327002300
+280029002a002b022c102a042c032b002c0d2b042c062b001d022d031d092d0b1d012d02
+1d002d001d122b002c022e002b002e002c002a002f0030002d000702110207001c002600
+00001a00160011001c022b0011031c00260000001a00160011001c022b00110110011c00
+260000001a00160011001c022b0011010700040012001900140000000900100231000f00
+0000180032060d00110018000700100007031000270023002f002b011d032d011d072d09
+1d002d0d1d022e002c022e011d002e001d112b012c072b002c0d2b032c072b001d042b02
+1d092a003100080004031c000f000000070032060d00100006001c000f0010002c003302
+340232000d0004011c000f00000007003203330132000d00070010000400350036001400
+00001a00040218000000100037070d002c000700100004041d0023002f001d0314011d0a
+2d011d0e2b011d0a2b001d012b011d022b002c0c2b001d042d001d002d0b1d022e012c01
+2e011d002b001d042d011d022d001d002d031d0b2d001100040307000000100037070d00
+2b001000070000001300190638000d002b00100007000000100019011500370039001901
+07000d001d001000040035003a00140000000c0009010f000b0026002b082c0027001000
+04051e0024001d002c022b00140100002c0214022c012b0014012e0114012b0114022c00
+2b002e0014012b0014001d0114022d201d002d021d002d001d032b001d022b001d072b00
+1d002b011d032c062e002b001d042d081d013b00150004030b0026002b082c0027000700
+0b0026003a0731002c00270007000b0026002b003a023c003a013d0018002c0027001001
+0d003a00140000000a0009023e0038003f09400010000905400041002d04140100002d03
+000014012d001d00140100001d00140100001401000014011d0114030000140100022d0c
+3b0231013b003c003b003c042d061d0a2d1a3c002d003c033b013c022d013c002d003c01
+3b0010000f033e0038003f09400018003e0038004200150007001500310038002b004200
+43003f00440011003e0038003f0034004203450007002b003f004400150004000d003a00
+140000000c0007001101000032003f08460020001c000703170123002a002c002b031401
+00002b001d01140300001d0114011d001400000114010000140100001d00140100021402
+1d002b012c002e012c022e012b002e032b002c152b002e002b011d002b001d022d001d00
+2d0b3b053c003b003c002d063c002d0b100004021000000032003f084600210031000000
+3200420007003f03470042004800460021003b00000032003f013400420145001c003f01
+460021003b0008000d003600140000000b0004023e00490934004a001c00110520002a00
+2c022e01140100002b001d0014010000140100002c0114010000140000002c0014040000
+2e00140100002b011d0014022c062a062c072a052c072b001d002b012c002b011d042b01
+2e012c032e002b002e012b032c042e002c001d022d011d002d001d002d0a04000f020400
+3e0049093400440011003e00490042001c004903470042002b0034004a001c003e004901
+4b0042043800490034004a001c000700250013004c0000004d0004020f000d0033043403
+21004b001500080009010b00260130002d003b003103140100003b011401000014010000
+3b0214013c0000002d00140100032d00140100002d03140100002d0c1d032d0a1d0e2b00
+2e002c082a002c002a002c002a002c042e002c002b011d052d001d002d0b310009000401
+080004000f000d0033004e053700340021004b001c000f000d004e002b0039014f012100
+4e00490021004b001c000f000d004a004e01420050004e02480021004b001c0010002500
+13005100000009000f01040015002b0052074400530029003100070004042b0029002c00
+1d0314042d0014011d0014011d012d00140100001d0214032b001d00140100002c011402
+00012b002c052a022c002a042c002a072c032b011d042d181d012d181100260008000f00
+040111002b005200540548004400530055001c0011002b0054073400530055001c001100
+2b004f0054004e003c005201540056003f00530055001500100012001300140000004d00
+0f02040038004b0621003a0044002b000700040641001d002e002c012b0100042c000001
+1d0000011d00140100011d0300032e0100012c002e002c0000021d022d021d062b012c01
+1d012b001d062d011d042b052c072b012c052a002c0d1d022d011d082d011d0031002600
+090004021000170038004b003f0555003a0044002b001100100038005704330121003a00
+440032001500110038004b0046002c004b0233011f004a002c001c00040025003d001400
+000001000f02040015002d0047004b014f00580059003a0044002c001100040008000404
+100004002d001d032d061d05140100001d052d021d022d063c003b013c003b012d1a1d04
+2b011d012c031d032d021d082b011d092d021d09310026005a0004041000310037004700
+4b014f00580059003a001f003f0031001100170031002b005b004b014f00580059003a00
+1f0049003c001c0148002b005b004b014f00580059003a001f0049003c0015000f003500
+3600140000000c0009010f01070031003c0049005c003d005900210047002c001c001005
+170010021700110015001d002c072b022c0300011d002b001d052d0b3b0e2d003b022d01
+3b002d183c003b003c003b012d1f15000f005a0109000f0009030f00100038003c003f00
+55003d0059001f0027002b00110008000f01100031003c003f0055003d00590021004700
+32001c00040211003c002d00490057003d0059002100470032001c00100004000f000d00
+3a001400000001000f0109010f00040007001c003c031c001000040008000f0008000400
+080004030800040109005a001b0000771b005a00260008000f0109050800100015003b00
+3c021c0004000f0009020f00160010001500310311000f00090026000b0009010f000400
+1100310315000400090211002c003d0014000000090004010f0009010f0216020f130908
+0f1904010f02040210030701100504021000041208000f0208010f000801040310000400
+100a11010700170111000700170011010700100017001002040010000400100004031001
+040010020402100004060f0004000f0016020f0009010f0704060f0004012c003d001400
+00000c000f015dc704002b003d00140000005e0009000f005dc704003f00190014000000
+1b0009015dc715002a001900140000001a0004015dc7080012001900140000001a001001
+5d255f9b600014005d0310002c003d00140000000c0004015d255f00609a610014005d03
+04002a003d00140000005a000f015d255f00609a610014005d030f002c003d0014000000
+1a00170011005d255f00629a610014005d0310002b003d001400000001000f015d255f00
+5d0514005d0414015d1214005d78610014005d0304003f003d0014000000630004015d05
+14005d0414015d175f005d0514005d0414005d1214015d78610014005d0304002d001300
+140000001a00040010005d0514005d0414005d185f006406140064021400640014006401
+140164011400640114006401140064051400646a1902640a610014005d0304002d006500
+140000001b0010015d0614005d0214005d0014005d0114015d0114005d0114005d011400
+5d0114005d075f0066061400660214006600140066001400660114006600140066011400
+6601140066051400666a1902660a610014005d0311002d003d0014000000010010015d06
+14005d0214005d0014005d0014005d0114005d0014005d0114005d0114005d0a5f006606
+140066021400660014006600140366011400660014006600140066061400666819066608
+610014005d0310002e003d00140000003e0010015d0614005d0214005d0014005d001403
+5d0114005d0014005d0014005d0b5f006707140067001400670114006700140067041400
+670014006700140067061400676919046709610014005d0310002c003d00140000000100
+15015d0714005d0014005d0114005d0014005d0414005d0014005d0014005d0b5f006807
+140068001400680114006800140068011400680214006800140068071400686a1902680a
+610014005d0315002c003d00140000001b0010015d0714005d0014005d0114005d001400
+5d0114005d0214005d0014005d0c5f006808140068021400680114016803140068001400
+68071400686b1900680b610014005d0310002d003d00140000005e003b015d0814005d02
+14005d0114015d0314005d0014005d0314005d075f00699a610014005d0315002e003d00
+140000003e002c015d255f006a9a610014005d032d013d00140000003e0031015d255f00
+6a9a610014005d031d003f001900140000001b0031006b005d255f00009a610014005d03
+2d003c0013001400000131015d256000619b14005d0331002c003d00140000001b003101
+5d25199c14005d033b011300140000006c0015015dc731002b003d00140000005e003101
+5dc731003c001300140000003e0011015dc731002d003d00140000005a0031003b005dc7
+6b002d001300140000013b015d0214ad280029005d02620e5d023b002e003d0014000000
+1b0031006d005d026e003d0028ab0f0000005d026200190c62005d0231001d0065001400
+0000630048015d023d0029005dab6f005f005d02620019006f0270016f0070026f007000
+190062005d0238002b006500140000001b0015015d023d0029005dab6f005f005d026200
+19007000620060005d02640067005d006701190062005d0215002d003d00140000013800
+31005d023d0029005d015fa75d016f005f005d0262001900700060005d0060005d006200
+64005d0066006701190062005d0231002d00650014000001310038005d023d0029005d01
+71a75d016f005f005d026200190060015d0064005d016700660072006701190062005d02
+3b002d006500140000003e0015001c005d023d0029005d0171a75d016f005f005d026200
+19006f00620164005d0042001900660067007201190062005d022d016500140000001b00
+3b015d023d0029005d0171221417716c5d016f005f005d02620019006f005d0062006600
+130019003d017202190062005d0231001d003d00140000001b00310038005d023d002900
+5d0171221417716c5d016f005f005d026200190060006201670066003d00190067006900
+6801190062005d023b002d006500140000001b003b003c005d023d0029005d0171221417
+716c5d016f005f005d0262001900700067016400660042003d0068007200680069001900
+62005d023c002d005900140000012d015d023d0029005d0171221417716c5d016f005f00
+5d02620019006f0066006400720167007201690072006a00190062005d0231002e003d00
+1400000131015d023d0029005d0171221417716c5d016f005f005d02620019006f006701
+64006701680072006a0073006900190062005d023b002d005900140000012d015d023d00
+29005d017122141274001403716c5d016f005f005d026200190070006600670068007200
+68016903190062005d023c0031002300140000001b0031015d023d0029005d0171221406
+7402140774011403716c5d016f005f005d026200190004006c0075006300760063000600
+0c00760075007600190062005d0231002d006500140000011c0031005d023d0029005d01
+7122140374027702740214047400770074001402716c5d016f005f005d02620019003d00
+19013d0219003d0142002300190062005d0231012300140000012d015d023d0029005d01
+7122140174017708740114017400770174001402716c5d016f005f005d02620019007000
+6f0170006f03600070006900190062005d023c001c002300140000013c0078005d023d00
+29005d01710a1406711014017400770a740014017400770274001401716c5d016f005f00
+5d026200190066007202680372013e00190062005d023101130014000001170007005d02
+3d0029005d017108140a710e140174007709740014037401770074001401716c5d016f00
+5f005d0262001900790070006f0070006f00700179006f017200190062005d022d003c00
+13001400000111015d023d0029005d017106140e710c1401740077027400770674001404
+74021400716c5d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d0231001d0059001400000131003b005d023d0029005d0171051410
+710b14007400770274001400740177057400140574001400710c1402715c5d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d023b00
+310013001400000131007a005d023d0029005d01710414035f0114035f0014015f011403
+710a140074007702740014027401770474001406710b140071021400715b5d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d023100
+15002300140000017a001c005d023d0029005d01710314035f0114085f02140271091400
+74007701740014047400770574001405710b140071051402710114027100140171021401
+710414027101140071001400710114017101140271021401712e5d016f005f005d026200
+19006f00600062005d00640066007200690173003e00190062005d0215002d0013001400
+000115015d023d0029005d01710314015f0314085f041400710914007400770174001405
+7400770574001404710c1402710114007102140071001400710114007101140071001400
+7101140071061400710014017101140071011400710314007100140071011400712d5d01
+6f005f005d02620019007000600062005d006400660072006800690073003e0019006200
+5d02310113001400000131015d023d0029005d01710314015f0314085f03140171091400
+74007701740014057400770674001403710f140071001400710214007100140071011400
+71011400710014037104140271001400710214037101140271011401712e5d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d023100
+2d0059001400000131015d023d0029005d01710414025f0214065f031401710a14007400
+7701740014037401770774011402710b1400710214007100140071021400710014007101
+140071011400710014007106140071011400710014007102140071031400710114007103
+1400712d5d016f005f005d02620019007000600062005d00640066007200680069007300
+3e00190062005d027a001c0023001400000111015d023d0029005d01710514025f011406
+5f011402710b1400740077017404770674021404710b1400710214007100140071021400
+710014007101140071011400710014007101140071031400710114007100140071021400
+7101140071001400710114007100140071011400712d5d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d0231001100230014000001
+15015d023d0029005d01710614035f0014045f001403710c14007400770a74021407710c
+140271021402710114007101140071011400710114017105140171001401710314017102
+14017100140071001401712e5d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d0210003100130014000001310015005d023d002900
+5d017108140a710e1400740077087401140a716c5d016f005f005d026200190070006000
+62005d006400660072006800690073003e00190062005d02110031001300140000011500
+11005d023d0029005d01710a140671101400740077087400140b716c5d016f005f005d02
+620019007000600062005d006400660072006800690073003e00190062005d0207001100
+23001400000115015d023d0029005d0171221401740077087400140a716c5d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d021500
+070020001400000131015d023d0029005d0171221401740077087400140a716c5d016f00
+5f005d02620019007000600062005d006400660072006800690073003e00190062005d02
+10001100230014000001110015005d023d0029005d0171221402740277057400140a716c
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d021500310013001400000110015d023d0029005d01712214057404770174001409
+716c5d016f005f005d02620019007000600062005d006400660072006800690073003e00
+190062005d021100310023001400000115015d023d0029005d017122140a74021409716c
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d0217001500230014000001040010005d023d0029005d0171221417716c5d016f00
+5f005d02620019007000600062005d006400660072006800690073003e00190062005d02
+1000110023001400000111015d023d0029005d0171221417716c5d016f005f005d026200
+19007000600062005d006400660072006800690073003e00190062005d02100017002300
+1400000110015d023d0029005d0171221417716c5d016f005f005d026200190070006000
+62005d006400660072006800690073003e00190062005d02110123001400000104015d02
+3d0029005d0171221417716c5d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d021000110023001400000110015d023d0029005d01
+71221417716c5d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d02110123001400000110015d023d0029005d0171a75d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d020700
+1100230014000001070010005d023d0029005d0171a75d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d0211001500230014000001
+1c015d023d0029005d015fa75d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d020700110023001400000115015d023d0029005d01
+5fa75d016f005f005d02620019007000600062005d006400660072006800690073003e00
+190062005d02150011002300140000011c015d023d0029005d015fa75d016f005f005d02
+620019007000600062005d006400660072006800690073003e00190062005d0211000400
+20001400000111015d023d0029005d015f2214175f6c5d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d0211000700200014000001
+15015d023d0029005d015f22140a7b00140b5f6c5d016f005f005d026200190070006000
+62005d006400660072006800690073003e00190062005d021c0010002000140000011c01
+5d023d0029005d015f2214097b00140c5f6c5d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d021c0011002300140000011c015d02
+3d0029005d015f227b0014077b00140d5f6c5d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d023100110023001400000131015d02
+3d0029005d015f227b0014067b00140e5f6c5d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d02110121001400000131003c005d02
+3d0029005d015f227b0014057b00140f5f6c5d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d02500015002300140000017a015d02
+3d0029005d015f227b0014057b00140f5f6c5d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d02310007002100140000013b003c00
+5d023d0029005d015f227b0014057b00140f5f6c5d016f005f005d026200190070006000
+62005d006400660072006800690073003e00190062005d0231001c002300140000013101
+5d023d0029005d015f2214007b0014047b0014027b00140b5f6c5d016f005f005d026200
+19007000600062005d006400660072006800690073003e00190062005d021c007c002300
+1400000115007a005d023d0029005d015f0a14065f1014007b0014047b0014037b011409
+5f6c5d016f005f005d02620019007000600062005d006400660072006800690073003e00
+190062005d02310007002100140000012d015d023d0029005d015f08140a5f0e14007b00
+14047b0014057b0114075f6c5d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d023c007c002300140000013c015d023d0029005d01
+5f06140e5f0c14007b0014047b0014077b0114055f6c5d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d0231000700200014000001
+31015d023d0029005d015f0514105f0b14007b0014047b0014087b0014055f0c14025f17
+14005f0014005f415d016f005f005d02620019007000600062005d006400660072006800
+690073003e00190062005d0231001100230014000001170007005d023d0029005d015f04
+14035f0114035f0014015f0114035f0a14007b0014047b0014097b0014045f0b14005f02
+14005f1614005f435d016f005f005d02620019007000600062005d006400660072006800
+690073003e00190062005d022d001c0023001400000111015d023d0029005d015f031403
+5f0114085f0214025f0914017b0014037b0014097b0014045f0b14005f0514025f011402
+5f0014015f0214015f0414005f0014005f0014005f0014015f0214015f0214015f325d01
+6f005f005d02620019007000600062005d006400660072006800690073003e0019006200
+5d023100100021001400000131007a005d023d0029005d015f0314015f0314085f041400
+5f0914027b0014037b0014087b0014045f0c14025f0114005f0214005f0014005f011400
+5f0114005f0014005f0114005f0314005f0014005f0014015f0114005f0014005f011400
+5f0014005f0114005f315d016f005f005d02620019007000600062005d00640066007200
+6800690073003e00190062005d02310007002100140000017a001c005d023d0029005d01
+5f0314015f0314085f0314015f0914037b0114017b0014097b0014035f0f14005f001400
+5f0214005f0014005f0114005f0114005f0014035f0314005f0014005f0014005f021400
+5f0014035f0114015f325d016f005f005d02620019007000600062007d007e007f008000
+1b00690073003e00190062005d021500100020001400000115015d023d0029005d015f04
+14025f0214065f0314015f0a14057b0014017b0014087b0014035f0b14005f0214005f00
+14005f0214005f0014005f0114005f0114005f0014005f0614005f0014005f0014005f02
+14005f0014005f0614005f315d016f005f005d0262001900700060006200810082008300
+84007900690073003e00190062005d023100070021001400000131015d023d0029005d01
+5f0514025f0114065f0114025f0b14067b0014017b0014087b0014025f0b14005f021400
+5f0014005f0214005f0014005f0114005f0114005f0014005f0114005f0314005f001400
+5f0014005f0214005f0014005f0114005f0014005f0114005f315d016f005f005d026200
+190070006000620085008600870088008900690073003e00190062005d02310008001f00
+1400000131015d023d0029005d015f0614035f0014045f0014035f0c14057b0014027b00
+14097b0014015f0c14025f0214025f0114005f0114005f0114005f0114015f0414005f00
+14005f0014005f0214005f0114015f0214015f325d016f005f005d026200190070006000
+62008a008b008c018d00690073003e00190062005d027a00070020001400000111015d02
+3d0029005d015f08140a5f0e14057b0014037b0014097b0014005f6c5d016f005f005d02
+620019007000600062008e008f00900091008d00690073003e00190062005d0231001000
+20001400000131015d023d0029005d015f0a14065f1014047b0014057b00140a5f6c5d01
+6f005f005d02620019007000600062005d006400660072006800690073003e0019006200
+5d023100070020001400000115015d023d0029005d015f2214037b0014067b00140a5f6c
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d0210000f001f0014000001150011005d023d0029005d015f2214027b0014087b00
+14095f6c5d016f005f005d02620019007000600062005d00640066007200680069007300
+3e00190062005d02070004001f001400000115015d023d0029005d015f2214027b001408
+7b0014095f6c5d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d02150008001f001400000131015d023d0029005d015f2214017b00
+140a7b0014085f6c5d016f005f005d02620019007000600062005d006400660072006800
+690073003e00190062005d02100009001f0014000001110015005d023d0029005d015f22
+14017b00140a7b0014085f6c5d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d021500040020001400000110015d023d0029005d01
+5f2214017b00140b7b0014075f6c5d016f005f005d02620019007000600062005d006400
+660072006800690073003e00190062005d02110009001f001400000115015d023d002900
+5d015f2214007b0014155f6c5d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d021700040020001400000110015d023d0029005d01
+5f2214007b0014155f6c5d016f005f005d02620019007000600062005d00640066007200
+6800690073003e00190062005d0211001000200014000001040010005d023d0029005d01
+5f2214175f6c5d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d02100009001f001400000110015d023d0029005d015f2214175f6c
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d021100100020001400000104015d023d0029005d015fa75d016f005f005d026200
+19007000600062005d006400660072006800690073003e00190062005d02100009001f00
+1400000110015d023d0029005d015fa75d016f005f005d02620019007000600062005d00
+6400660072006800690073003e00190062005d0211000f001f001400000110015d023d00
+29005d015fa75d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d02070009001f001400000110015d023d0029005d015fa75d016f00
+5f005d02620019007000600062005d006400660072006800690073003e00190062005d02
+110009001f00140000011c015d023d0029005d015fa75d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d02070009001f0014000001
+11015d023d0029005d015fa75d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d02110009001f001400000111015d023d0029005d01
+5fa75d016f005f005d02620019007000600062005d006400660072006800690073003e00
+190062005d02150009001f00140000011c015d023d0029005d015fa75d016f005f005d02
+620019007000600062005d006400660072006800690073003e00190062005d0207000f00
+1f001400000107015d023d0029005d015fa75d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d021100090028004c00000111001500
+5d023d0029005d015fa75d016f005f005d02620019007000600062005d00640066007200
+6800690073003e00190062005d020700090028004c00000107015d023d0029005d015fa7
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d021c00040028005100000111015d023d0029005d015fa75d016f005f005d026200
+19007000600062005d006400660072006800690073003e00190062005d02110009002800
+4c0000011c015d023d0029005d015fa75d016f005f005d02620019007000600062005d00
+6400660072006800690073003e00190062005d021c00090028004c00000107015d023d00
+29005d015fa75d016f005f005d02620019007000600062005d0064006600720068006900
+73003e00190062005d020700090040000e00000107015d023d0029005d015fa75d016f00
+5f005d02620019007000600062005d006400660072006800690073003e00190062005d02
+0700090028004c00000104015d023d0029005d015fa75d016f005f005d02620019007000
+600062005d006400660072006800690073003e00190062005d021100090028000e000001
+07015d023d0029005d015fa75d016f005f005d02620019007000600062005d0064006600
+72006800690073003e00190062005d021000090028004c00000111015d023d0029005d01
+5fa75d016f005f005d02620019007000600062005d006400660072006800690073003e00
+190062005d020400090028004c00000107015d023d0029005d015fa75d016f005f005d02
+620019007000600062005d006400660072006800690073003e00190062005d0207000900
+28004c00000107015d023d0029005d015fa75d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d020700090028004c00000110015d02
+3d0029005d015fa75d016f005f005d02620019007000600062005d006400660072006800
+690073003e00190062005d0204000f0028005100000107015d023d0029005d015fa75d01
+6f005f005d02620019007000600062005d006400660072006800690073003e0019006200
+5d020700090028004c00000104015d023d0029005d015fa75d016f005f005d0262001900
+7000600062005d006400660072006800690073003e00190062005d020400260028000e00
+000109015d023d0029005d015fa75d016f005f005d02620019007000600062005d006400
+660072006800690073003e00190062005d020800260028004c00000104015d023d002900
+5d015fa75d016f005f005d02620019007000600062005d00640066007200680069007300
+3e00190062005d021600090028004c00000110015d023d0029005d015fa75d016f005f00
+5d02620019007000600062005d006400660072006800690073003e00190062005d021000
+090028005100000110015d023d0029005d015fa75d016f005f005d026200190070006000
+62005d006400660072006800690073003e00190062005d0204000f002800510000011101
+5d023d0029005d015fa75d016f005f005d02620019007000600062005d00640066007200
+6800690073003e00190062005d020f00260028000e00000109015d023d0029005d015fa7
+5d016f005f005d02620019007000600062005d006400660072006800690073003e001900
+62005d021000090028004c000001040010005d023d0029005d015fa75d016f005f005d02
+620019007000600062005d006400660072006800690073003e00190062005d0204000900
+28004c00000104015d023d0029005d015fa75d016f005f005d0262001900700060006200
+5d006400660072006800690073003e00190062005d020800090028004c0000010f000800
+5d023d0029005d015fa75d016f005f005d026200190064001b005a003e025a003e011b00
+5a00190062005d020800260028004c00000108000f005d023d0029005d015fa75d016f00
+5f005d0262001900700067006800920072029300940068006100190062005d0204000900
+28004c000001040010005d023d0029005d015fa75d016f005f005d026200190072005a00
+1b013e001b015a0000001b005a00190062005d020400090028000e00000111015d023d00
+29005d015fa75d016f005f005d0262001900650095003d003a0195003d0042003a001900
+3d00190062005d021000090028000e00000110015d023d0029005d015fa75d016f005f00
+5d0262001900050a190062005d0204000900280051000001070010005d023d0029005d01
+5fa75d016f005f005d02620019000500960076006300760003000c009700980097006300
+190062005d0210000f0028005100000104015d023d0029005d015fa75d016f005f005d02
+62001900990079008d019a009b00790089008d0079008900190062005d0211000f004000
+4c00000104015d023d0029005d015fa75d016f005f005d026200190070006f0060005d02
+640066015d007200190062005d0211000f0040004c00000111015d023d0029005d015fa7
+5d016f005f005d02620019008d0062005d006201640066009c009d007200660019006200
+5d021100040040004c00000115015d023d0029005d015fa75d016f005f005d0262001900
+700060005d016200640066037200190062005d021100040040000e00000111015d023d00
+29005d015fa75d016f005f005d0262001900600166005d0066003d004200660068006700
+7200190062005d021c003b0023004c00000131015d023d0029005d015fa75d016f005f00
+5d026200190062015d0167003d01660072016800190062005d0231009e00200051000001
+31015d023d0029005d015fa75d016f005f005d02620019006401660119003d0119007200
+6a007200190062005d027a00310020004c00000111015d023d0029005d015fa75d016f00
+5f005d02620019005d00640066021901680072016a00190062005d023100150020004c00
+000131015d023d0029005d015fa75d016f005f005d026200190067005d00670072006600
+7200670068006902190062005d0231006b001f004c00000115015d023d0029005dab6f00
+5f005d0262001900670066006701720168016a0069006a00190062005d0210009f001f00
+0e000001310015005d023d0029005dab6f005f005d026200190067037201680069006800
+6a007300190062005d0211001500a00051000001150011005d022d001b006fab5f015d02
+6200190c62005d02070015001f004c00000131015d020f0067005fad5d02620e5d021001
+1f004c000001110015005dc71500100040004c00000110015dc711000400a1000e000001
+15015dc7170015001f005100000110015d0262af5d1411014a004c000001040010005d02
+620019ad62005d14100011004a005100000111015d02620019006f0570006f0305006500
+72007000640070866f0070027900660070003d00050008008d02700160005d0167006600
+7200190062005d14100015001f004c00000110015d02620019006f00600162015d006600
+64006600a201960095005a0067001b00608a700072006f00190005004d008d0060006201
+5d016400660064006701190062005d14110015001f004c00000110015d02620019006f00
+62015d036601670176003d005a0068005a00628a6f0072006f0019000500a3008d006000
+5d0062005d0164006600670066006700190062005d14110010004a004c00000110015d02
+62001900700062005d006200640166016701720063003a005a0092003e005d427d007e00
+7f0080001b005d427000720070003d000500a4008d00620060005d016400660272011900
+62005d14070015001f005100000110015d02620019006f00620164011900660167007201
+76003a005a0072003e0064428100820083008400790064426f0068006f003d0005007600
+8d00620064015d0064001900660067017200190062005d14110015001f00510000011c01
+5d02620019006f005d0164003d0019003d01670072006800030095005a0072003e006642
+850086008700880089006642700068006f003d000500a5008d0064005d0119023d007201
+6800190062005d14070010001f000e00000111015d02620019007000640166003d001902
+7200680069000c003d005a0072005a0072428a008b008c018d007242700068006f001900
+050063008d00640066013d0019003d00190072006801190062005d14110015001f004c00
+000111015d02620019006f006400660167003d00670068026900970042005a0093003e00
+68428e008f00900091008d00683e69006802790068006f003d00050006008d0066006400
+660067011900720068016900190062005d14150011001f004c0000011c015d0262001900
+7000660167026802690198003a005a0094003e00698a6f00720060003d0005004d008d00
+6600670172006700680072006902190062005d14070015001f005100000107015d026200
+19006f0066016700720067007200680069016a00970019005a0068001b00738a6f007200
+70004200050076008d00660167007201680269006a00190062005d1407006d001f005100
+0001110015005d02620019006f0067027201680069016a0163003d005a0061005a003e8a
+72003e00690023000500a6008d006700720067007201680069026a00190062005d140700
+3b0020005100000107015d02620019ad62005d141c00310020004c0000001b0011015d02
+62af5d1411003b002000510000011c015dc71c00310020004c00000107015dc707003b00
+20004c00000107015dc707007a0020004c00000104015dc7110078001f00510000011101
+5d031b2b5d021b2b5d021b315d021b2c5d03110031001f005100000107015d031b00a72a
+79005d011b00a72a79005d011b00a73079005d011b00a72b79005d021000310020004c00
+000107015d031b00a700a827a900a700aa005d011b00a700a827a900a700aa005d011b00
+a700a82da900a700aa005d011b00a700a828a900a700aa005d020700310021004c000001
+07015d031b00a700a800ab26a900a700aa005d011b00a700a800ab26a900a700aa005d01
+1b00a700a800ab2ca900a700aa005d011b00a700a800ab27a900a700aa005d0207003c00
+1f005100000110015d031b00a700a800ab111405ab0ea900a700aa005d011b00a700a800
+ab26a900a700aa005d011b00a700a800ab2ca900a700aa005d011b00a700a800ab27a900
+a700aa005d020400500020004c00000107015d031b00a700a800ab1014015f0314002d00
+ab0da900a70089005d011b00a700a800ab26a900a70089005d011b00a700a800ab2ca900
+a70089005d011b00a700a800ab0e14002d00ab0614002d00ab0da900a70089005d020700
+11001f000e00000104015d031b00a700a800ab0f14005f0014005f0314002d00ab0da900
+a7009a005d011b00a700a800ab26a900a7009a005d011b00a700a800ab2ca900a7009a00
+5d011b00a700a800ab0d14022d00ab0414022d00ab0ca900a7009a005d0204007a001f00
+51000000760009015d031b00a700a800ab0e14005f0114005f0314002d00ab0da900a700
+8d005d011b00a700a800ab26a900a7008d005d011b00a700a800ab2ca900a7008d005d01
+1b00a700a800ab0e14022d00ab0214022d00ab0da900a7008d005d020800310020004c00
+000104015d031b00a700a800ab0d14045f0314002d00ab0da900a7008d005d011b00a700
+a800ab111401ab12a900a7008d005d011b00a700a800ab0e140dab0fa900a7008d005d01
+1b00a700a800ab0f14022d00ab0014022d00ab0ea900a7008d005d02080031001f005100
+0000760004015d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00
+a700a800ab1014032d00ab10a900a7008d005d011b00a700a800ab0f140b2d00ab0fa900
+a7008d005d011b00a700a800ab1014052d00ab0fa900a7008d005d0216001c001f004c00
+000110015d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00a700
+a800ab0f14052d00ab0fa900a7008d005d011b00a700a800ab1014092d00ab10a900a700
+8d005d011b00a700a800ab1114032d00ab10a900a7008d005d020400500020004c000001
+11015d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00a700a800
+ab0e14072d00ab0ea900a7008d005d011b00a700a800ab1114072d00ab11a900a7008d00
+5d011b00a700a800ab1114032d00ab10a900a7008d005d020f003c0022004c0000010901
+5d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00a700a800ab0d
+14092d00ab0da900a7008d005d011b00a700a800ab1214052d00ab12a900a7008d005d01
+1b00a700a800ab1014052d00ab0fa900a7008d005d0210002e002300510000000c000400
+10005d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00a700a800
+ab0c140b2d00ab0ca900a7008d005d011b00a700a800ab1314032d00ab13a900a7008d00
+5d011b00a700a800ab0f14022d0114022d00ab0ea900a7008d005d0204002e0023004c00
+00000a0004015d031b00a700a800ab0d14005f0714002d00ab0da900a7008d005d011b00
+a700a800ab0d2d0bab0ca900a7008d005d011b00a700a800ab1414012d00ab14a900a700
+8d005d011b00a700a800ab0e14022d00ab0214022d00ab0da900a7008d005d020f002e00
+23004c00000001000f015d031b00a700a800ab0d14005f0714002d00ab0da900a7008d00
+5d011b00a700a800ab26a900a7008d005d011b00a700a800ab152d00ab15a900a7008d00
+5d011b00a700a800ab0d14022d00ab0414022d00ab0ca900a7008d005d020f002c002300
+51000000090004015d031b00a700a800ab0d14092d00ab0da900a7008d005d011b00a700
+a800ab26a900a7008d005d011b00a700a800ab2ca900a7008d005d011b00a700a800ab0e
+14002d00ab0614002d00ab0da900a7008d005d0204002c0023004c0000001a0009015d03
+1b00a700a800ab0e2d09ab0da900a70089005d011b00a700a800ab26a900a70089005d01
+1b00a700a800ab2ca900a70089005d011b00a700a800ab27a900a70089005d0204002c00
+13004c0000000100100004005d031b00a700a800ab26a900a70089005d011b00a700a800
+ab26a900a70089005d011b00a700a800ab2ca900a70089005d011b00a700a800ab27a900
+a70089005d0204002a0013004c0000000100080004005d031b00a700a800ab26a900a700
+8d005d011b00a700a800ab26a900a7008d005d011b00a700a800ab2ca900a7008d005d01
+1b00a700a800ab27a900a7008d005d020f002c0023004c0000000900040008005d031b00
+a700a928a7008d005d011b00a700a928a7008d005d011b00a700a92ea7008d005d011b00
+a700a929a7008d005d020800250023005100000004000f015d031b00a72a70005d011b00
+a72a70005d011b00a73070005d011b00a72b70005d020f00120013005100000006000901
+5d047900ac008902790189048d04ac0189167000aa005d027900ac008902790189048d04
+ac0189167000aa005d027900ac008902790289058d04ac0289197000aa005d027900ac00
+8902790189048d04ac0289167000aa005d02080025001300510000003e000b015dc70900
+3f0013004c00000004025dc70900410013004c00000007000f015dc708002c0013004c00
+00000900070011020702110007011800111a070118001004070110050700180107001015
+0700100a040408010f0209190f0009000f0604000802040210010703110f150011001503
+1c0015061105070010010700100304001002040010020800290013005100000011002900
+2f0129002f0033002f00290033062f003302300027111e0647031e062717300233012f01
+29002f0229052f0033052f0033002f0033042f0129042f0033012f0029002f0133013000
+27013000270930013307300027083000270530023302271c42004c000a00ad003d001901
+3d0019003d0265003d6365003d0059013d00650059011300590365013d0165003d0e5901
+650059013d1d19003d0119003d0119073d0019013d075600420051004c00540051054c0a
+51044c1051024c0d51024c0651004c0151054c0851014c0151044c1d0e014c000e1d4c01
+0e014c010e004c000e0c4c030e1514004c02
+%%EndData
+end
+%%PageTrailer
+%%Trailer
+%%BoundingBox: 0 0 208 223
+%%EOF
Added: packages/openev/branches/upstream/current/doc/lodgen.fig
===================================================================
--- packages/openev/branches/upstream/current/doc/lodgen.fig (rev 0)
+++ packages/openev/branches/upstream/current/doc/lodgen.fig 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,117 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+5 1 0 1 0 7 100 0 -1 0.000 0 1 0 0 8850.000 5287.500 8400 6600 8850 6675 9300 6600
+6 1200 2700 2100 3600
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 1200 2700 2100 2700 2100 3600 1200 3600 1200 2700
+4 1 0 100 0 20 10 0.0000 4 120 420 1650 3075 LOD0\001
+4 1 0 100 0 20 10 0.0000 4 120 390 1650 3270 cache\001
+-6
+6 2400 4200 3300 5100
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 2850 4650 424 424 2850 4650 3150 4950
+4 1 0 100 0 20 10 0.0000 4 120 540 2850 4845 average\001
+4 1 0 100 0 20 10 0.0000 4 150 450 2850 4650 4 pixel\001
+-6
+6 4800 4200 5700 5100
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 5250 4650 424 424 5250 4650 5550 4950
+4 1 0 100 0 20 10 0.0000 4 120 540 5250 4845 average\001
+4 1 0 100 0 20 10 0.0000 4 150 450 5250 4650 4 pixel\001
+-6
+6 7200 4200 8100 5100
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 7650 4650 424 424 7650 4650 7950 4950
+4 1 0 100 0 20 10 0.0000 4 120 540 7650 4845 average\001
+4 1 0 100 0 20 10 0.0000 4 150 450 7650 4650 4 pixel\001
+-6
+6 9600 4200 10500 5100
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 10050 4650 424 424 10050 4650 10350 4950
+4 1 0 100 0 20 10 0.0000 4 120 540 10050 4845 average\001
+4 1 0 100 0 20 10 0.0000 4 150 450 10050 4650 4 pixel\001
+-6
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 1650 4650 40 40 1650 4650 1690 4650
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 4050 4650 40 40 4050 4650 4090 4650
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 6450 4650 40 40 6450 4650 6490 4650
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 8850 4650 40 40 8850 4650 8890 4650
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 8850 5700 450 75 8850 5700 9300 5775
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 300 4650 2325 4650
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 3375 4650 4725 4650
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 5775 4650 7125 4650
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 8175 4650 9525 4650
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 3
+ 0 0 1.00 60.00 120.00
+ 10575 4650 11250 4650 11250 3675
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1650 4650 1650 3675
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4050 4650 4050 3675
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 6450 4650 6450 3675
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 8850 4650 8850 3675
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 3600 2700 4500 2700 4500 3600 3600 3600 3600 2700
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 6000 2700 6900 2700 6900 3600 6000 3600 6000 2700
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 8400 2700 9300 2700 9300 3600 8400 3600 8400 2700
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 10800 2700 11700 2700 11700 3600 10800 3600 10800 2700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1650 2625 1650 1725
+2 4 0 1 0 7 100 0 -1 0.000 0 0 15 0 0 5
+ 11700 1200 1200 1200 1200 1650 11700 1650 11700 1200
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4050 2625 4050 1725
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 6450 2625 6450 1725
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 8850 2625 8850 1725
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 11250 2625 11250 1725
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 11775 1425 12900 1425
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 8400 5700 8400 6600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 9300 5700 9300 6600
+2 1 1 1 0 7 100 0 -1 4.000 0 0 -1 1 1 2
+ 0 0 1.00 60.00 120.00
+ 0 0 1.00 60.00 120.00
+ 8850 4725 8850 5550
+4 1 0 100 0 20 10 0.0000 4 120 420 4050 3075 LOD1\001
+4 1 0 100 0 20 10 0.0000 4 120 390 4050 3270 cache\001
+4 1 0 100 0 20 10 0.0000 4 120 420 6450 3075 LOD2\001
+4 1 0 100 0 20 10 0.0000 4 120 390 6450 3270 cache\001
+4 1 0 100 0 20 10 0.0000 4 120 420 8850 3075 LOD3\001
+4 1 0 100 0 20 10 0.0000 4 120 390 8850 3270 cache\001
+4 1 0 100 0 20 10 0.0000 4 120 420 11250 3075 LOD4\001
+4 1 0 100 0 20 10 0.0000 4 120 390 11250 3270 cache\001
+4 1 0 100 0 20 12 0.0000 4 135 975 6450 1500 LOD Select\001
+4 1 0 100 0 20 10 0.0000 4 150 450 12300 1350 output\001
+4 1 0 100 0 20 10 0.0000 4 150 345 750 4575 input\001
+4 1 0 100 0 20 10 0.0000 4 120 420 8850 6150 LOD3\001
+4 1 0 100 0 20 10 0.0000 4 120 195 8850 6345 file\001
Added: packages/openev/branches/upstream/current/doc/openev.tex
===================================================================
--- packages/openev/branches/upstream/current/doc/openev.tex (rev 0)
+++ packages/openev/branches/upstream/current/doc/openev.tex 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1039 @@
+\documentclass{openevreport}
+
+\renewcommand{\bibname}{References}
+\foottext{Version 1.1, 2000-06-19 \newline\scriptsize
+Use and duplication of this document or any information
+contained herein is subject to the notice on the front of this
+document.}
+
+\begin{document}
+
+\begin{titlepage}
+\pagestyle{empty}
+\centering
+\vspace*{0.75in}
+
+\includegraphics[width=2.5in]{openevlogo.eps} \\
+\vspace{0.2in}
+{\bf\Large
+Library Design\\
+}
+\vspace{0.5in}
+{\large
+Revision 1.1
+\\
+June 19, 2000 \\
+\vspace{0.2in}
+\copyright Atlantis Scientific Inc.
+}
+
+GeoInnovations 1999 \\
+
+\vspace{0.5in}
+\includegraphics[width=2.5in]{asilogo.eps} \\
+Scientific Inc. \\
+20 Colonade Road, Suite 110 \\
+Nepean, Ontario K2E 7M6 \\
+email: openev at atlsci.com \\
+\vspace{0.7in}
+
+\framebox{
+\begin{minipage}[t]{6in}
+Copyright \copyright 2000, Atlantis Scientific Inc. (www.atlsci.com)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+\end{minipage}
+}
+
+\end{titlepage}
+
+\pagenumbering{roman}
+
+\setlength{\parskip}{1.0ex}
+\tableofcontents
+\setlength{\parskip}{3.0ex}
+\clearpage
+\pagenumbering{arabic}
+\setcounter{page}{1}
+
+\chapter{Introduction}
+
+This document describes the ``OpenEV'' library, which is a tool for
+interactive visualization of raster and vector data, with a particular
+emphasis on remotely sensed data and geographic datasets.
+
+In summary, OpenEV is targeted at the following feature set:
+\begin{itemize}
+\item Run on popular platforms.
+\item Handle 2D/3D raster and vector data.
+\item Gracefully handle very large (gigabyte) raster datasets.
+\item Display real and complex raster data.
+\item Handle multi-channel data.
+\item Represent multi-channel data in a number of ways (RGB, HSV).
+\item Provide multiple views of a single dataset with different
+interpretations.
+\item Display multiple datasets within a single view.
+\item Understand and interpret georeferencing information, and provide
+on-the-fly reprojection of datasets as necessary.
+\item Provide printed output.
+\item Provide view manipulation function (pan, zoom, rotate) at
+interactive frame rates.
+\item Be able to play a role in a larger tool development or image
+analysis environment.
+\item Take advantage of commodity hardware for 2D/3D acceleration, if
+present.
+\end{itemize}
+
+The discussion begins with a description of how OpenEV fits in a
+broader environment, including third party
+libraries it relies on. The OpenEV architecture and class hierarchy is
+then summarized. This is followed by a more detailed description of
+the OpenEV undo system, data model and layer drawing model.
+Interactive systems, such as OpenEV tools and common user interface
+elements are described.
+
+A familiarity with the concepts of computer graphics, and with OpenGL
+in particular, is assumed. The reader is referred to \cite{woo:opengl}
+for a general background of this subject.
+
+\chapter{The Broad Environment}
+
+The OpenEV library provides both C and Python language bindings. While
+the OpenEV C level library can be used as part of other specialized
+applications, it's main function is to participate in a broader
+environment of ``pluggable'' models. Python provides the glue to tie
+these modules together.
+
+\begin{figure}
+\centering
+\includegraphics[width=6in]{openev_bigpicture.eps}
+\caption{The Broad Environment}
+\label{fig:bigpicture}
+\end{figure}
+
+Figure \ref{fig:bigpicture} shows the OpenEV C library and PyOpenEV
+Python bindings in the broader context. The other pieces in this
+context are as follows:
+\begin{description}
+\item[OpenGL] The portable graphics library.
+\item[Gtk+] The portable user interface components library.
+\item[PyGtk] Python bindings for Gtk+.
+\item[Basic Viewer UI] Simple dialogs that are common to most OpenEV
+based applications.
+\item[GDAL I/O Lib] The geospatial raster data I/O formats library.
+\item[PyGDAL I/O] Python bindings for the GDAL I/O Lib.
+\item[Proj.4] The C level cartographic projections library.
+\item[NumPy] The Numerical Python library, which provides Python
+access to array objects.
+\item[Numerical Analysis] Standard numerical analysis libraries.
+\end{description}
+
+\chapter{Architecture}
+
+OpenEV makes use of the GtkObjects hierarchy which provides a degree of
+object-orientation to the C language. The OpenEV classes are exposed
+to Python using a C to Python wrapper layer in a manner similar to the
+Gtk Python bindings (PyGtk)\cite{gtk.org}. Figure \ref{fig:gvclass}
+shows the highlights of the OpenEV class structure. The list of
+classes in the figure is representative, not exhaustive.
+
+\begin{figure}
+\centering
+\includegraphics[width=6in]{gvclass.eps}
+\caption{OpenEV Class Hierarchy}
+\label{fig:gvclass}
+\end{figure}
+
+\section{GvViewArea}
+
+The GvViewArea is the principle drawing area widget exposed by the
+OpenEV library. This widget is typically embedded in a top level
+window. Any number of view areas may be active concurrently. Each
+view area normally has its own OpenGL context, and a set of GvLayers.
+When the view area receives an expose event, it activates its context
+and commands each layer to draw in turn. The set of layers are
+assigned a changeable drawing order, so that one layer may partially
+obscure another (i.e. it is drawn ``on top''). The view also
+maintains an ``active'' layer, which is the layer currently under edit
+by a tool.
+
+The view area has a current transformation state (camera position and
+orientation), which it sets before drawing. In 2D mode the transformation
+state describes a top down orthographic view of the data, while in 3D
+the transformation state describes a perspective view with arbitrary
+orientation. The 3D view mode can be used to view either 3D or 2D data.
+Keyboard and mouse events are
+trapped by the view area which allow the user to modify the
+transformation state (e.g. pan, zoom, rotate).
+
+Because each view area is provided with its own set of layers, two views
+can display a different ``interpretation'' of the same dataset. For
+instance, one view might display the magnitude of a complex
+interferogram, and another the phase of the same image. It is also
+possible that multiple views may share the same set of layers (and
+the same OpenGL context). These views always provide the same
+interpretation of the data, but may be displaying different parts of
+it.
+
+A GvViewArea publishes the following signals (events):
+\begin{itemize}
+\item {\bf active-changed}: The ``active layer'' for editing and
+interpretation purposes has changed. This signal is also emitted when
+new layers are added or removed, even if the active layer does not change.
+
+\item {\bf view-state-changed}: This signal is emitted after the view state
+changes.
+This includes flipping, zooming and roaming. It does not include mouse
+position changes, or changes to display characteristics of layers in the
+view.
+
+\item {\bf gldraw}: Generated after layer drawing to give other application
+components (such as the GvTool) the opportunity to overlay additional
+drawing on the view for each refresh.
+
+\end{itemize}
+
+\section{GvData}
+
+GvData is an abstract class that provides some essential event
+handling and generic property
+mechanisms to data containers and layers. GvData instances
+are connected in a hierarchical parent-child relationship. These
+relationships are used to propagate data change events through the
+OpenEV system. Two signals, ``changing'' and ``changed'', are exposed
+by GvData to facilitate this propagation. Rules for state changes are
+as follows:
+
+\begin{enumerate}
+\item If a GvData instance is about to change state, it first sends a
+``changing'' event to its parent. The event propagates up the
+ancestor tree to the top node (parentless) GvData which emits a
+``changing'' signal. Only the top node emits this signal.
+\item Once the state change is affected, the GvData instance sends a
+``changed'' event to its parent. If the parent has a
+``child-changed'' handler, it is called. The event propagates up the
+ancestor tree to the top node GvData which emits a ``changed''
+signal.
+\item Each child of the top node GvData traps the ``changed'' signal
+and re-emits the signal. If the child has a ``changed'' handler, it
+is called. The event propagates down the ancestor tree, fanning out
+across all descendants.
+\end{enumerate}
+
+A GvData subclass can use the ``changed'' and ``child-changed'' event
+handlers to adjust their state to reflect the change that has
+occurred. Normally, the ``child-changed'' handler would pull state
+information from the child, and the ``changed'' handler would pull
+state information from the parent.
+
+\begin{figure}
+\centering
+\includegraphics{gvdata.eps}
+\caption{GvData Hierarchy Example}
+\label{fig:gvdata}
+\end{figure}
+
+To illustrate change event handling, consider the example GvData
+hierarchy in figure \ref{fig:gvdata}. Here we have two layers showing
+different representations of the same set of points, one in UTM (Universal Transverse Mercator)
+projection and one in LCC projection. The original dataset is in an
+LCC projection. An intermediate data set (UTM points) is created to
+cache the points after transformation to UTM.
+
+Now consider the effect of a tool applied to the UTM points
+representation, which moves a point in UTM space. Prior to
+affecting the translation, the UTM points object sends a ``changing''
+event to the LCC (Lambert Conformed Conic) point object, which emits a ``changing'' signal.
+This signal is trapped by the undo mechanism (see Chapter 4). After the
+change, a ``changed'' event is sent to the LCC points object. The
+``child-changed'' handler of this object pulls the new location of the
+translated point from the UTM points object. The LCC points object
+repositions the point in LCC space and emits a ``changed'' signal.
+Both layers eventually trap this signal and force a redraw to display
+the change.
+
+The GvData class also provides a mechanism to get and set state
+``mementos'', which are used to facilitate undo and redo capabilities
+(see below).
+
+\section{GvLayer}
+
+GvLayer is an abstract class whose subclasses know how to draw a
+representation of a dataset using OpenGL commands. Most layers
+provide an adjustable internal state which effects the representation
+(e.g. colour of the lines in a line layer). The GvLayer class
+provides facilities to get the extents (bounding region) of the layer
+and change the visibility of the layer.
+
+The GvLayer publishes the following signals:
+\begin{itemize}
+\item {\bf setup}: Generated when a layer is attached to a GvViewArea,
+and normally trapped by the specific layer class (ie. GvRasterLayer) to
+perform view specific setup operations. Note that technically a GvLayer
+can be attached to more than one GvViewArea though this is not being
+utilized, and may be specifically forbidden in the future.
+
+\item {\bf teardown}: Generated when a layer is removed from a GvViewArea,
+and normally trapped by the specific layer class to perform disconnect
+operations.
+
+\item {\bf draw}: Generated by the GvViewArea on the layer to trigger
+it to draw itself.
+
+\item {\bf get-extents}: Used to fetch the layer extents.
+
+\item {\bf display-change}: Notification that some aspect of the display
+characteristics has changed, and that a redraw will be necessary. Normally
+trapped by GvViewArea to trigger a redraw. Note that it is intended to
+be distinct from a data-change signal which indicates that the underlying
+raster or vector data (normally from a parent GvData) has changed.
+
+\end{itemize}
+
+\section{GvShapeLayer}
+
+The GvShapeLayer class provides a layer of abstraction to datasets
+containing shapes (vector data). This abstraction is used by certain
+tools which can operate on any kind of shape (such as the node editing
+tool).
+
+The GvShapeLayer maintains a list of ``selected'' shapes and permits
+translate and delete operations on the currently selected shapes.
+Facilities for node manipulation (move, insert, delete) are provided.
+Functions to ``pick'' a shape or a node (determine which shape/node
+the mouse cursor is over) are provided.
+
+The GvShapeLayer publishes the following signals, many of which are
+just intended to be caught by the derived layer to trigger an operation:
+
+\begin{itemize}
+
+\item {\bf draw-selected}: Cause the layer to draw the selected shape(s) in
+a special manner indicating their selection.
+
+\item {\bf delete-selected}: Cause the layer to delete the currently selected
+shape(s).
+
+\item {\bf translate-selected}: Cause the layer to
+translate the selected objects by the specified amount.
+
+\item {\bf pick-shape}: Cause the layer to draw all shapes in picking mode
+(with their identifier as the GL name.
+
+\item {\bf pick-node}: Cause the layer to draw all nodes of the selected
+shapes in picking mode.
+
+\item {\bf get-node}: Cause the layer to return the position of the indicated
+node.
+
+\item {\bf move-node}: Cause the layer to move the indicated node by the
+indicated amount.
+
+\item {\bf insert-node}: Cause the layer to insert a node at the indication
+position.
+
+\item {\bf delete-node}: Cause the layer to delete the indicated node.
+
+\item {\bf node-motion}: Indicate that a node has moved.
+
+\item {\bf selection-changed}: Indicate that the selection list has
+changed. Used by other application components wanting to act on, or report
+information about the current selection.
+
+\end{itemize}
+
+\section{Data Containers}
+
+The classes GvShapes, and GvRaster (see \ref{fig:gvclass}) are examples of OpenEV
+data containers. These classes provide access to the data they
+contain, and may expose methods for modifying the data. Normally a
+GvLayer subclass points to a corresponding data container
+(e.g. GvRasterLayer points to a GvRaster instance).
+
+\section{GvTool}
+
+The GvTool class is an abstract base class for OpenEV tools. Tools are
+used to interact with the user for the purpose of querying or
+manipulating datasets. When a tool is ``activated'' on a particular
+view area, it captures certain mouse and keyboard events that occur in
+the view window to provide this interaction. If a tool needs to draw
+in the view window, it traps the ``draw'' signal from a layer or from
+the view to trigger drawing.
+
+\chapter{Undo/Redo System}
+
+OpenEV provides a flexible system for recording user interactions with
+datasets in order to provide undoable and redoable operations. For
+instance, if a user deletes a shape from a shape layer, an undo
+function is available to restore the shape. If an undo is performed,
+a redo function is available to delete the shape again.
+
+The undo system (called GvUndo) maintains a stack of so-called data
+state ``mementos'', which contain enough information to reverse an
+operation on a dataset (a GvData object). Each GvData object wishing
+to employ the GvUndo must be registered with the system. GvUndo
+connects to the objects ``changing'' signal (thus only root level
+GvData objects should be registered). When this signal is received,
+GvUndo asks the GvData for a memento describing the change about to
+take place (essentially a snapshot of the current state), and pushes
+the memento onto the undo stack.
+
+Mementos are opaque to GvUndo. Only the originating GvData object
+can interpret them. If an undo request is issued, a memento is popped
+off the stack and the memento is handed back to the GvData object to be
+used. The originating GvData object is also responsible for deleting
+the memento when the undo stack is cleared.
+
+In some cases a tool may perform a function which is not undoable.
+The undo system may be temporarily ``closed'' for this purpose. When
+closed, GvUndo will ignore ``changing'' signals. Undoing may also be
+temporarily disabled by a tool in the middle of a complex operation.
+When disabled, GvUndo will ignore events that would pop mementos off the
+stack.
+
+A separate redo stack is maintained by GvUndo. Before a memento is
+popped off the undo stack, a flag is set which temporarily puts GvUndo
+in ``redo mode''. When the GvData object makes a change as the result
+of the undo, it emits a ``changing'' signal which is trapped by
+GvUndo. A new memento is created, and since the redo mode flag is
+set, it is pushed onto the redo stack. If the user requests a redo
+operation, the memento at the top of the redo stack is used. Finally,
+once a new undoable operation is pushed onto the undo stack, the redo
+stack is cleared.
+
+\chapter{Data Model}
+
+OpenEV is able to display a fairly diverse array of geographic
+datasets. The primitives in OpenEV are:
+point, polyline, area, and raster. Other primitives may be added in the
+future.
+
+Geographic primitives have no knowledge of the coordinate system,
+projection or geographic datum to which their data is referenced.
+Such information is instead associated with the GvData container class in
+the from of an OpenGIS ``Well Known Text'' coordinate system descriptions.
+
+The model used in OpenEV for vector data is based on the OGDI data model
+\cite{mor:ogdi}, and the OpenGIS ``Simple Features'' specification.
+The current data model is explicitly three dimensional.
+
+\section{Shapes}
+
+Point, polylines are areas are all managed internally as GvShape objects,
+and held in a GvShapes container class.
+
+All shapes have a properties list
+(GvProperties) which can be used to hold per-shape attributes useful for GIS
+applications. Drawing
+override information or other application or user specific data. There is
+no concept of a fixed container wide schema (set of attributes) applied for
+all shapes ... each shape can have an independent list of properties.
+
+\begin{itemize}
+
+\item {\bf Points} - A point GvShape has one 3D vertex.
+
+\item {\bf Polylines} - A polyline GvShape
+contains a list of points forming one contiguous line.
+
+\item {\bf Areas} - A GvShape area which consists of one outer ring, and zero
+or more inner rings, each consisting of 3 or more points which implicitly
+forms a ring (the last point does not need to match the first ... it is
+assumed the ring should be closed). The inner rings represent ``holes''
+in the area. Inner rings are constrained to be within the outer ring,
+non-intersecting with other rings, and to not be nested.
+
+\end{itemize}
+
+The GvShape object provides a unified interface to the points and rings
+in a shape for points, line and areas. Thus a point GvShape can be
+accessed as if it were an area with one ring containing only one point.
+The only way to determine the underlying type is to explicitly query it.
+
+Note that currently GvShape's are not GtkObjects, in order to keep them
+as lightweight as possible. The following definitions are used internally
+for shape objects. The flags field is used to keep track of some display
+related information, and the GvAreaShape also contains a tesselated
+``OpenGL ready'' form of the area for rapid display.
+
+\begin{verbatim}
+#define GVSHAPE_POINT 1
+#define GVSHAPE_LINE 2
+#define GVSHAPE_AREA 3
+
+typedef struct
+{
+ gint type;
+ guint flags;
+ GvProperties properties;
+} GvShape;
+
+typedef struct
+{
+ gint type;
+ guint flags;
+ GvProperties properties;
+ float x;
+ float y;
+ float z;
+} GvPointShape;
+
+typedef struct
+{
+ gint type;
+ guint flags;
+ GvProperties properties;
+ int num_nodes;
+ float *xyz_nodes;
+} GvLineShape;
+
+typedef struct
+{
+ gint type;
+ guint flags;
+ GvProperties properties;
+ int num_rings;
+ int *num_ring_nodes;
+ float **xyz_ring_nodes;
+
+ /* tesselation information */
+ gint fill_objects; /* -1 is untesselated, -2 is `do not tesselate' */
+ GArray *mode_offset;
+ GArray *fill;
+} GvAreaShape;
+\end{verbatim}
+
+\section{Raster}
+
+The GvRaster class provides access to image data in tiles. Because
+image data size is potentially very large, GvRaster does not store the
+entire image in memory. Instead, it connects to a data input
+abstraction object provided by the GDAL Data I/O Library. This abstraction
+object may be connected to a memory buffer (in the case of an image in
+virtual memory) or to an image file, socket, etc. Since reading data
+from this object is potentially slow, GvRaster maintains a local cache
+of the image tiles. The maximum cache size is a parameter of
+GvRaster. When the cache size limit is reached, tiles in the cache
+are discarded on a least recently used (LRU) basis. The exact
+strategy for determining which tiles to discard will be tuned during
+the testing phase of the project.
+
+GvRaster is also responsible for level of detail (LOD) reduction of
+image tiles, also known as \emph{pyramiding}. The LOD reduction
+process is performed ``on-the-fly'' as each tile is loaded. LOD0 is
+the full resolution data, with nominal tile dimensions (adjustable) of
+$256\times 256$ pixels (maximum 512KB/tile). LOD1 through LODN are
+generated by recursively applying a $2\times 2$ box filter (4 pixel
+average) and decimating by 2 in rows and columns. For example,
+nominal tile dimensions for LOD1 through LOD3 are $128\times 128$
+(128KB), $64\times 64$ (32kB), and $32\times 32$ (8kB),
+respectively. The process is stopped if the LOD being generated
+already exists in the cache. Figure \ref{fig:lodgen} illustrates the
+LOD reduction process. The number of levels generated will be tuned during the
+testing phase of the project.
+
+Since the data contained in a GvRaster can take on a number of
+different types (integer or floating point, real or complex, different
+bit depth), and since either averaging, or decimation may be desired, there are
+a number of reduction kernels required. GvRaster
+switches to the right kernel at run time. Currently, an averaging algorithm
+is employed in computing LOD1 through LODN
+
+In order to accelerate initial overview display, GDAL provides for access
+to pre-built levels of detail in source data files when available.
+A pyramid level can be attached to one or more LOD stages (see LOD3
+in the figure). If the LOD3 file existed when the pipeline was constructed,
+it would be used to fill in the LOD3 and LOD4 caches without needing
+to read the full resolution image. Such persistent caches are only
+attached to lower LODs, where the total data size is relatively small
+(a few megabytes). Addition of a LOD file to the raster cache is the
+responsibility of the application, and can be either automatic, or
+triggered by user request.
+
+\begin{figure}
+\centering
+\includegraphics[width=6in]{lodgen.eps}
+\caption{LOD Reduction and Cache}
+\label{fig:lodgen}
+\end{figure}
+
+The total available cache size is split evenly across each LOD, except
+the lowest LOD cache which should handle every tile in the image.
+Each LOD cache has a separate LRU list. Requests for a tile/LOD
+combination can be made in either blocking or non-blocking mode. In
+blocking mode, the tile/LOD will be loaded if it is not in the cache
+before the request completes. In non-blocking mode, the request always
+returns immediately to the calling function with one of the following
+status codes:
+\begin{description}
+\item[hit] The tile/LOD was found in the cache. The tile is
+returned.
+\item[suboptimal] The tile/LOD was not found, but a lower LOD is
+available. The lower LOD tile is returned.
+\item[miss] No tile was found to match the request.
+\end{description}
+The GvRasterLayer class uses the non-blocking mode to implement
+asynchronous tile loading.
+
+\section{Mesh}
+
+A GvMesh is a collection of points mapping a regular grid to
+arbitrary points in 2D or 3D space. It is used to guide a spatial warp
+for raster data. For instance, a slant-range SAR image may be
+projected ``on-the-fly'' to UTM space by precomputing the UTM
+coordinates of a sparse mesh of points, spaced regularly in image
+(slant-range) space. The mesh is used to generate triangle strips
+when texture mapping the image into place in UTM space.
+
+Currently GvMesh objects are only used as a component of a GvRasterLayer.
+When a new GvRasterLayer is created (related to a particular GvRaster), a
+corresponding GvMesh is created. The output coordinates of the mesh are
+view georeferenced coordinates.
+
+Initially the GvMesh is setup in identity form, mapping coordinates on the
+GvRaster to the pixel/line locations. Subsequently this may be transformed
+into georeferenced coordinates using an affine geotransform, or using a
+polynomial warp based on GCPs. If the GvViewArea is utilizing a different
+coordinate system (projection) than the GvRaster, then an additional pass
+is made to reproject the mesh coordinates into the desired projection.
+
+In the 2D case, the mesh is a regular grid of vertex points which lie
+in a plane. By associating a third dimension to each vertex a 3D surface is
+created. The raster data is then ``projected'' onto the mesh surface using
+the same warping technique as was used to accomplish the 2D projection. The
+resulting mesh provides a correct warping of the raster data in all three
+dimensions.
+
+Information for the third dimension is derived
+from a GvRaster layer which is coregistered with the reference space.
+Nominally such a layer contains elevation data, so the result is
+a tessellated, multi-resolution terrain model. The resulting mesh
+can be used for 3D visualization of terrain data in
+conjunction with a coregistered ``drape'' image.
+
+\chapter{Layer Drawing}
+
+Static content in the view window (i.e. not tool related as in Section
+\ref{sec:tools}) is drawn by layer objects. Normally layers draw a
+representation of a data container, but are not limited to this
+purpose. Other layer functions include such things as drawing grid
+lines, or displaying user provided annotation, such as text or
+legends.
+
+\section{Raster}
+
+Rasters are drawn using OpenGL's texture mapping capabilities.
+While not strictly required for 2D image drawing, texture mapping
+allows OpenEV to take advantage of the automatic warping, and
+interpolation features
+of OpenGL in order to provide continuous zoom levels, image rotation
+and reprojection, and extensions to 3D (e.g. draping over height
+fields).
+
+Each GvRasterLayer connects to one or more GvRaster objects and a
+GvMesh object. The GvMesh is used to map image coordinates to the
+view space (see below). The GvRaster objects provide image data which
+is used to generate textures one tile at a time.
+
+The GvRasterLayer maintains an internal cache of which textures are
+available. When a draw event is received, it computes which textures
+are required to draw the scene (a tile/LOD combination) and compares
+this to what is available in the cache. If the appropriate texture is
+not available, it attempts to find a lower resolution texture that
+covers the tile. If no other texture is found, the tile is not
+drawn.
+
+Texture generation is driven asynchronously from the draw event
+(e.g. by an input idle event). A texture miss during a draw will
+schedule an asynchronous update. The update begins by generating a
+list of textures required for the current view and comparing this
+against the tile cache. Of the missing tile/LOD combinations, the
+``best'' one to generate is chosen according to the following order of
+preference:
+\begin{enumerate}
+\item The tile/LOD is in the GvRaster cache (highest preference).
+\item A lower LOD of the same tile is in the cache.
+\item The tile/LOD must be loaded to the cache (lowest preference).
+\end{enumerate}
+Non-blocking GvRaster tile loading is used to query the raw cache
+state. Once a few tiles/LODs have been generated, a view refresh is
+forced. This will display the new tiles and reschedule an asynchronous
+update if required.
+
+The texture generation method depends on the data type of the GvRaster
+layer. The layer switches to the appropriate method at run time.
+
+\subsection{Real Data}
+
+User adjustable minimum and maximum values are used to scale and clamp
+each input value to an integer in the range 0-255. In the case of
+floating point data, values are first scaled and clamped from 0-1 and
+then passed through a fast float to int conversion function. In
+either case, the scaled values are used as unsigned bytes to create a
+\texttt{GL\_LUMINANCE} texture.
+
+Real data textures can be rendered in a variety of ways to achieve
+various effects. For example:
+\begin{itemize}
+\item The texture can be modulated with an arbitrary fragment
+colour to map value to shades of that colour (e.g. gray scale or
+aqua-marine scale, etc.).
+\item An alpha value can be set for the fragment colour. The texture
+can then be filter (alpha) blended with the background to achieve a
+constant transparency for the image.
+\item A 256 colour look up table (LUT) can be applied as the texture
+is loaded. The colours in the table can be used directly, or can be
+modulated by the fragment colour/alpha.
+\end{itemize}
+
+\subsection{Complex Data}
+
+To translate complex (I\&Q) values to an RGB tuple, a two dimensional
+look up table (LUT) is used. A user adjustable maximum magnitude
+parameter is used to determine a scaling factor:
+\begin{quote}\begin{verbatim}
+scale = 0.5 / max_mag;
+\end{verbatim}\end{quote}
+The scaled sample cannot be clamped independently in I and Q, since
+this would modify the sample phase. A \emph{phase preserving}
+clamping is performed to clip the sample to the LUT boundary (see
+figure \ref{fig:phaseclip}):
+\begin{quote}\begin{verbatim}
+I *= scale;
+Q *= scale;
+if (fabs(I) > 0.5)
+{
+ Q *= 0.5 / fabs(I);
+ I = 0.5 * sign(I);
+}
+if (fabs(Q) > 0.5)
+{
+ I *= 0.5 / fabs(Q);
+ Q = 0.5 * sign(Q);
+}
+I += 0.5;
+Q += 0.5;
+\end{verbatim}\end{quote}
+The resulting I and Q are in the range $[0,1]$, with phase preserved.
+
+\begin{figure}
+\centering
+\includegraphics[scale=0.9]{phaseclip.eps}
+\caption{Phase Preserving Clamping}
+\label{fig:phaseclip}
+\end{figure}
+
+After scaling, I and Q are converted to integers in the range
+$[0,255]$ using a fast float to integer conversion. They are then
+applied as two indices to a 2D LUT. This can either be a $256\times
+256$ LUT, or a $64\times 64$ LUT with bilinear interpolation over the
+2 lowest order bits.
+
+The LUT is generated to map I\&Q into RGB by way of an HSV transform.
+At startup, the LUT maps phase angle into hue and complex magnitude
+into value (brightness). This mapping is adjustable by the user. For
+instance, phase can be mapped to value, with hue and saturation set to
+zero, to produce a gray scale phase image.
+
+For each entry in the table, a floating point I and Q index is
+generated in the range $[-1,1]$. A phase angle from $[0,1]$ is
+calculated using (atan2(Q,I) + PI) / (2*PI). A magnitude is
+calculated using sqrt(I*I + Q*Q) with values clamped to $[0,1]$.
+Floating point RGB is computed using an HSV to RGB transform. These
+are converted to integer $[0,255]$ and placed in the LUT.
+
+\section{GvShapesLayer}
+
+The GvShape objects are drawn using GL primitives suitable to the type
+of geometry. Various style parameters (colour, width, etc) are controlled
+by layer wide defaults stored as properties on the GvShapesLayer, and can
+be override on a per-shape basis by properties of the shapes.
+
+\subsection{Points}
+
+GvPointShapes are drawn using a small cross symbol. The point cross size,
+and color are properties that can be specified at the layer, or shape level.
+Note that per-shape drawing overrides can incur substantial performance
+overhead.
+
+Different symbols are drawn for points marked as ``selected''. The
+default symbol is a cross with a square around it.
+
+\subsection{Polylines}
+
+Polylines are drawn using a \texttt{GL\_LINE\_STRIP} in a user
+selectable colour and line width. Selected lines have small squares drawn at
+each vertex (node) in the same colour (using \texttt{GL\_POINTS}).
+
+\subsection{Areas}
+
+Since OpenGL cannot draw non-convex polygons, or polygons with holes,
+each GvAreaShape must be ``tessellated'' prior to drawing. That is, a set
+of triangles must be constructed that, when drawn together, make up
+the region described by the GvArea. The OpenGL GLU library
+tessellation routines are used for this purpose. When a new GvAreaShape is
+created, it is first checked for proper ring winding (clockwise or
+counterclockwise ordering of nodes), and then tessellated. The
+resulting triangles are stored with the GvAreaShape, in the fill\_objects,
+mode\_offset, and fill fields. Any modifications to
+the area result in a re-tessellation. An error encountered during
+tessellation indicates that GvArea is invalid (e.g. crossing or
+self-intersecting rings) and it is drawn without fill.
+
+Areas are drawn using the filled triangles for the interior and a
+\texttt{GL\_LINE\_LOOP} for each ring (the region boundaries).
+Selected areas have an additional \texttt{GL\_POINTS} drawn at each
+vertex. Edges, and fill can be different colors. In most cases
+the interior fill have a non-opaque alpha value
+applied, so that it does not completely obscure the layers below it.
+
+\chapter{Tools}
+\label{sec:tools}
+
+Tools provide interactive dataset querying and editing capabilities to
+OpenEV. OpenEV's object oriented architecture makes it reasonably easy
+to add additional tools to OpenEV to support specific application
+requirements. This section describes some common tools.
+
+\section{Toolbox}
+
+The GvToolbox class provides a means of multiplexing several tools
+across multiple view areas. The toolbox maintains a list of
+registered view areas and tools. A particular tool can be
+``activated'' by name. The toolbox traps pointer enter and pointer
+leave notification messages from the view areas. When the pointer
+enters a view window, the current tool is activated on that view. When
+it leaves, the tool is deactivated. The tool therefore needs only to
+know about one view at a time.
+
+The toolbox is normally connected to a toolbar widget containing icons
+for all available tools.
+
+\section{Selection Tool}
+
+The selection tool allows the user to change the current ``selected''
+shape (point, line, area). Multiple shapes can be selected by
+dragging out a region (rubber-banding), or shift-clicking. Only
+shapes within the same layer can be selected this way.
+
+Once selected, two operations can be performed on the shapes: delete
+and move (translate). The user deletes the selected shapes by
+pressing the delete key. Shapes are moved by clicking and dragging
+the mouse over one of the selected shapes.
+
+\section{Line Tool}
+
+The line tool is used to draw new lines or append to an existing
+line. The user clicks to start a new line, moves the mouse to the
+next node in the line, and clicks again to insert a node. The view
+state (pan, zoom, etc.) may be changed between clicks. After drawing
+the final node, the user right clicks to finish the line. While
+drawing, the delete key can be pressed to remove the last node drawn.
+
+Existing lines can be extended by clicking on one of the end nodes of
+a line, and proceeding as above.
+
+\section{Area Tool}
+
+The area tool is used to draw new areas, or to insert holes in an
+existing area. To start a new area, the user proceeds in the same
+manner as drawing a line. Once the right mouse button is pressed, the
+area tool closes the loop (connects the last node to the first) and
+fills in the area.
+
+To insert a hole in an existing area, the user clicks somewhere in the
+area's interior to insert the first node, and proceeds as above. The
+area's interior fill is disabled during hole drawing to aid in viewing
+layers under the area layer.
+
+\section{Node Tool}
+
+The node tool is used to add, delete or move nodes in an existing
+shape (line or area). The user first clicks on a shape to select it.
+To delete a node, the user clicks on the node to highlight it (denoted
+by an oversized vertex marker), and presses the delete button. Nodes
+are moved by clicking and dragging them. New nodes are inserted by
+clicking on a line segment between two nodes.
+
+When moving a node belonging to an area, the area's interior fill is
+disabled to aid in viewing layers under the area layer.
+
+\section{Point Query Tool}
+
+The point query tool is used to identify the view space coordinates of
+locations in the view, to query the value of a raster layer, and to
+measure distances between locations in a view. Optionally, raster
+layer ``row and column'' coordinates can be displayed. When first
+invoked, the point query tool creates a temporary point query layer
+and attaches it to the view area. Subsequent invocations will use the
+same layer.
+
+The user clicks to insert a new query point in the layer. The point
+is marked with an identifying symbol, accompanied by a small amount of
+text which gives the coordinates of the point. If a raster layer is
+currently selected in the view area, the value of the raster at that
+point is also displayed. The point can be moved by clicking and
+dragging. The coordinates and raster value are updated as the point
+is moved.
+
+The user can Ctrl-click over a query point to begin dragging out a
+query second point. A line is drawn between the two points. Text
+near the center of the line gives the line length in view
+coordinates.
+
+Query points are removed by clicking to select them, and pressing
+delete. It is also possible to clear all query points (through a
+separate menu function).
+
+\section{Other Tools}
+
+Briefly, other tools planned for future incorporation into OpenEV are:
+\begin{itemize}
+\item A generic control point marking tool, which can be extended for
+application specific uses.
+\item An general region-of-interest (ROI) marking tool, which can be
+used for sub-image extraction, for example.
+\item A grid overlay tool.
+\end{itemize}
+
+\chapter{Common UI Elements}
+
+The OpenEV facilities can be used in a variety of applications. Most of
+these share some functionality, and therefore can benefit from a
+library of common user interface elements. This section describes
+sample elements, written largely in Python, which interact with OpenEV.
+
+\section{Icon Bar}
+The Icon Bar (see \ref{fig:iconbar} for prototype) provides a top level
+user interface. It provides access to many of the commonly used features
+OpenEV provides through menus and icons. From the File menu the user can
+create new views, open files (raster or vector) into the current view, print
+or close down the application. The Edit menu provides access to the toolbox
+(for vector type operation described above), layer control (see \ref{sec:layer-control}) and
+preferences. The Help menu launches the online help (see \ref{sec:online-help}). The row
+of icons provide quick access the following (from left
+to right): open new file, print view, linear scaling of view, equalization
+enhancement of view, fit all layer in view, zoom to 1:1, zoom in by factor of two,
+zoom out by factor of two, launch online help.
+
+\begin{figure}
+\centering
+\includegraphics{toolbar.eps}
+\caption{Basic Icon Bar}
+\label{fig:iconbar}
+\end{figure}
+
+\section{Layer Control}
+\label{sec:layer-control}
+
+The layer control dialog provides the user with a list of layers
+associated with a view area, and provides some controls to manipulate
+the layers, and the ability to launch layer-specific properties panels.
+Layer manipulation functions accessible via the layer control dialog, or
+layer-specific properties panels include:
+
+\begin{itemize}
+\item Change the active (selected) layer.
+\item Raise or lower a layer.
+\item Delete a layer.
+\item Change the name of a layer.
+\item Change the visibility of a layer.
+\item Change the opacity of a layer.
+\item Change the default color of a layer.
+\item Change the raster scaling parameters of a layer.
+\item Change the raster interpolation schema for a layer.
+\item Change the raster bands used for a layer.
+\end{itemize}
+Layers are identified by name, and by a thumbnail image. Figure
+\ref{fig:layerdlg} shows a conceptual layer dialog.
+
+\begin{figure}
+\centering
+\includegraphics{layerdlg.eps}
+\caption{Conceptual Layer Dialog}
+\label{fig:layerdlg}
+\end{figure}
+
+\section{Toolbar}
+
+The toolbar dialog is a simple button box widget connected to a OpenEV
+toolbox tool. The user changes the currently active tool with this
+dialog.
+
+\section{On-Line Help}
+\label{sec:online-help}
+
+A general on-line help system, based on HTML formatted help pages, is
+available for OpenEV application development. Providing access to help
+is the responsibility of the application, but is normally provided in
+a drop down menu. Help pages are viewed through a user configurable
+external web browser.
+
+Applications use the python {\tt gvhtml.LaunchHTML()} to display help or
+other web pages.
+
+\section{Printing}
+
+In order to enable printing, the GvViewArea has the ability to render
+its contents at an arbitrary resolution, providing the resulting raster
+RGB data to application callbacks. Particular mechanisms are built on
+this to write the result to PostScript, or any GDAL supported raster format.
+
+The rendering mechanism is invoked by the
+{\tt gv\_view\_area\_render\_to\_func() }
+function, which takes a view to render, a resolution and a callback to
+provide the data to. The rendering is accomplished by altering the view port
+and rendering into the backbuffer of the GvViewArea. This is fetched
+by using the glReadPixels() call to fetch the result back from the
+back buffer.
+
+One downside to this approach is that on eight or sixteen bit
+display systems, the resulting rendering is normally done at the
+color resolution of the visual. Also, it appears some GL implementations
+(such as the 1999 Linux NVidia drivers) don't support glReadPixels().
+However, the greatest limitation with this architecture is that text, and
+vector graphics are rendered at the same resolution as the raster data
+rather than being transported in descriptive form to be rendered by the
+printer at it's best resolution.
+
+For higher resolution renderings the region to render is split into smaller
+tiles matching the size of the viewport, and the result reassembled for
+output.
+
+Currently output drivers exist for PostScript
+({\tt gv\_view\_area\_print\_postscript\_to\_file()}) and GDAL supported raster
+formats such as TIFF and PNG
+({\tt gv\_view\_area\_print\_to\_file()}). In time it is expected to implement
+support for a few other common outputs such as HPGL and writing directly to
+MS Windows printer drivers.
+
+
+\begin{thebibliography}{9}
+
+\bibitem{woo:opengl} M.Woo, J.Neider, T.Davis, D.Schreiner, OpenGL
+Architecture Review Board, \emph{OpenGL Programming Guide: The
+Official Guide to Learning OpenGL, Version 1.2}, 3rd ed.,
+Addison-Wesley, 1999.
+
+\bibitem{gtk.org} The GIMP Toolkit homepage. http://www.gtk.org
+
+\bibitem{mor:ogdi} P.Morin, \emph{OGDI: Programmer Reference},
+ver. 3.0, OGDI Research Institute, OGDI-RI-98001, May 1998.\\
+http://132.156.30.81/iii/docs/programmers\_guide/ogdi.pdf
+
+\end{thebibliography}
+
+\end{document}
Added: packages/openev/branches/upstream/current/doc/openev_bigpicture.fig
===================================================================
--- packages/openev/branches/upstream/current/doc/openev_bigpicture.fig (rev 0)
+++ packages/openev/branches/upstream/current/doc/openev_bigpicture.fig 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,108 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 2639 3923 3764 4627
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 3201 4275 562 352 3201 4275 3764 4627
+4 1 0 100 0 20 11 0.0000 4 120 660 3201 4275 Numerical\001
+4 1 0 100 0 20 11 0.0000 4 150 555 3201 4486 Analysis\001
+-6
+6 9600 4838 10725 5259
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 10162 5048 562 211 10162 5048 10725 5259
+4 1 0 100 0 20 11 0.0000 4 150 585 10162 5119 OpenGL\001
+-6
+6 6365 3713 7350 4275
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 6858 3994 492 281 6858 3994 7350 4275
+4 1 0 100 0 20 11 0.0000 4 120 690 6858 3994 GDAL I/O\001
+4 1 0 100 0 20 11 0.0000 4 120 210 6858 4205 Lib\001
+-6
+6 4819 1041 5944 1463
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 5381 1252 562 211 5381 1252 5944 1463
+4 1 0 100 0 20 11 0.0000 4 150 765 5381 1322 Application\001
+-6
+6 9881 3713 10725 4134
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 10303 3923 422 211 10303 3923 10725 4134
+4 1 0 100 0 20 11 0.0000 4 120 345 10303 3994 Gtk+\001
+-6
+6 2850 2728 3694 3150
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 3272 2939 422 211 3272 2939 3694 3150
+4 1 0 100 0 20 11 0.0000 4 150 495 3272 3009 NumPy\001
+-6
+6 9881 2025 10725 2447
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 10303 2236 422 211 10303 2236 10725 2447
+4 1 0 100 0 20 11 0.0000 4 150 435 10303 2306 PyGtk\001
+-6
+6 7350 2025 8756 2447
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 8053 2236 703 211 8053 2236 8756 2447
+4 0 0 100 0 20 9 0.0000 4 105 855 7561 2306 Basic Viewer UI\001
+-6
+6 4748 4205 5733 4627
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 5275 4416 457 211 5275 4416 5733 4627
+4 1 0 100 0 20 12 0.0000 4 135 645 5275 4486 PROJ.4\001
+-6
+6 5451 2517 6717 2939
+1 1 0 1 0 7 50 0 -1 0.000 1 0.0000 6050 2728 598 211 6050 2728 6647 2939
+4 0 0 50 0 0 11 0.0000 4 135 825 5592 2798 PyGDAL I/O\001
+-6
+6 7875 4275 9075 4800
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 8464 4553 562 211 8464 4553 9027 4763
+4 1 0 100 0 20 11 0.0000 4 150 585 8475 4627 OpenEV\001
+-6
+6 7875 2700 9075 3225
+1 1 0 1 0 7 100 0 -1 0.000 1 0.0000 8476 2941 562 211 8476 2941 9038 3152
+4 1 0 100 0 20 11 0.0000 4 150 810 8475 3009 Py OpenEV\001
+-6
+2 1 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 2
+ 600 3450 11700 3450
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 5944 1322 9951 2095
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 5873 1392 7631 2025
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 8123 2447 8334 2728
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 10303 2447 10303 3713
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 8475 3150 8475 4275
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 9037 4627 9600 4908
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 9037 4486 9881 4064
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 7983 4416 7280 4134
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 6155 2939 6858 3713
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 5733 1463 6084 2517
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 3272 3150 3272 3923
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 5030 1463 3553 2728
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 4819 4416 3764 4345
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 6365 4134 5733 4416
+2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 56.25 112.50
+ 7912 4556 5733 4486
+4 0 0 100 0 22 11 0.0000 4 150 525 600 3361 Python\001
+4 0 0 100 0 22 11 0.0000 4 120 120 600 3642 C\001
Added: packages/openev/branches/upstream/current/doc/openevlogo.eps
===================================================================
--- packages/openev/branches/upstream/current/doc/openevlogo.eps (rev 0)
+++ packages/openev/branches/upstream/current/doc/openevlogo.eps 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1756 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.06 by Peter Kirchgessner
+%%Title: /home/srawlin/openev/logo.eps
+%%CreationDate: Mon Jun 19 06:20:23 2000
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 828 225
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+5 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.173228 14.173228 translate
+% Translate to begin of first scanline
+0.000000 210.399131 translate
+813.543307 -210.399131 scale
+% Variable to keep one line of raster data
+/scanline 290 3 mul string def
+% Image geometry
+290 75 8
+% Transformation matrix
+[ 290 0 0 75 0 0 ]
+{ currentfile scanline readhexstring pop } false 3
+colorimage
+fefff8fefff8fefffafefffbfcfffdfcfffffcfffffcfffffcfffffcfffffefffffefffffeffff
+fefffffffffdfefefcf8faf9fafcfbfcfcfafefefcfffffdfffffdfffefbfffefbfffefbfefaf7
+faf6f3faf6f3fbf7f4fbf7f4fcf8f5fffbfafff8fbfff8fdfff9fdfdf7fbfaf6f7f8f4f5f4f2f3
+f3f1f2fffefffffefffffcfcfffbfbfff8f9f8eff0fcf2f3fffefbfdfcf7fbfef5fcfef9fdfffa
+fbfffefcfffffcfffffcfffffcfffffcfffffffffffffffffffffdfffefafffef9fffdfafffeff
+fffdfffffdfffffdfffffefffffefffffffffffffffffffffffffffefffffefffffcfffffcffff
+fcfffffefffffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffdfffffdfffffdfffffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffefffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffefffffefffffefffffefffffefffffefffffffffffffffffffffffffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefffbfafffaf9fffcfbfffcfd
+f8f7fcf8fbfff0f5fbf1f4f9fefffffffefcfffef9fffcf9fffdf7fffcf9fffdf9fffdfcfefffa
+fbfff9fafff7fafff7fafff7fafff7f9fff6f9fff6f9fff6fafff7fbfff8fbfff8fbfff8fbfff8
+fbfff8fbfff8fbfff9fefffbfcfcfafcfbf9fffffdfffefbfefaf7fefaf7fffefbfffefdfffefd
+fffefffffefffffefffffefffefffffdfefff8fcfffefffffffffff9f7f8fffdfdfffefdfaf6f3
+fffffbfbfdf8fafff9f9fffbfbfffcfdfefffffdfffffafffffbfffbf9fafbfbf9fffffdfffffd
+fdfdfbf7f7f5f8f8f6fefefcfdfdfbfcfcfafbfbf9fcfcfafdfdfbfdfdfbfcfcfaf9fbfafbfcfe
+f9fdffeff3f4f8fcfdf8faf9fdfffefffffdfffffdfffefafffefafefefcfefefcfefefffefeff
+fefdfffefeffffffffffffff
+fefff8fefffafefffafefffbfcfffdfcfffffcfffffcfffffcfffffcfffffefffffefffffeffff
+fffffdfffffdfefefcfffffdfffffdfefefcfffffdfffffdf7f6f4faf9f7fffffdf8f7f5f9f8f6
+fefefcfffffdfffffdfffffdfbfbfbf8f8f8fcfafffcfafffefcfffffefffffffffffffffefeff
+fcfcfef5f5f7fcfcfcfbf9fafbf7f6fffdfdfffdfdfff8f9fdf7f7fdfef8fcfff8fdfffafdfffc
+fcfffffcfffffcfffffcfffffcfffffefffffffffffffffffffffdfffefafffef9fffdfafffeff
+fffdfffffdfffffdfffffefffffefffffffffffffffffffffffffffefffffefffffefffffcffff
+fcfffffefffffffefffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffdfffffdfffffdfffffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffefffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdff
+fffdfffffdfffffefffffefffffefffffefffffefffffefffffffffffffffffffffffffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefffbfafcf4f2fff9fafffbff
+fefffffbfffff7feffeef5fbf4f9fdfbfcfefdfcfafffbf8fffbf8fffbfafdfbfcfcfcfefbfdfc
+fcfefbfcfef9fcfef9fcfef9fcfef9fcfef9fcfef9fcfef9fbfdf8fcfef9fcfef9fcfef9fcfef9
+fcfef9fcfef9fcfefbfbfffcf9fefafbfdfcfdfffcfefefcfcfdf8fcfcfafefefcf9f9f7f9f9f9
+fafafafafafcf9fafcf8f9fdf5f9fcf4f8fbf8fcfdfafefffbfbfbf8f6f7fffdfcfffdfdfdf9f6
+fffffbfbfdf8fafff9f9fffbfbfffcfdfefffffdfffffafffffbfff9f7f8fffffdfefefcfafaf8
+fefefcfefffffefffff6f8f7fbfffefafefff9fdfef9fdfefafefffafefff9fdfef7fdfdfbffff
+f9fffffbfffffbfffff6fafbfafcfbf8f8f8f9f9f7fffefcfffefafffefcfefefefefefefefeff
+fefdfffefeffffffffffffff
+fefffafefffafefffbfefffdfefffffefffffefffffefffffefffffeffffffffffffffffffffff
+fffffdfffefcfffefafffefafdfcf8f8f7f3f7f6f2fdfef9fffffdfefffdf6f8f7fcfffffbfffe
+f1f7f7eff5f5eef6f8f1f9fbf7fffff9fffffafffff9fdfff8fdfff7fefff9fffff7fffff3fbfd
+f1f6f9f3f8fbfcfffffefffffbfbfbfaf8f9fbf7f8fffafcfffefdfffffbfefffbfefffbfefffd
+fefffffefffffefffffefffffefffffefffffffffffffffffffffdfffefafffef9fffefafffeff
+fffdfffffdfffffdfffffefffffefffffefffffefffffffffffffffffffffefffffefffffeffff
+fefffffefffffffffffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffeffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffdff
+fffefffffefffffefffffefffffefffffefffffefffffefffffffffffffffffffffffffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffff
+fefffffefffffefffffefffffefffffefffffefffffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefffbfcfffcfdfffcfefaf8fd
+f5f8fff1fafff1fbfff5fffff7fffff8fffffafffffbfffffafefffafdfff9fefff7fefff8fcff
+fdfcfffffbfffffbfffffbfffffcfffffcfffffcfffffcfffffbfffffbfffffbfffffbfffffbff
+fffbfffffcfffefdfff9fffff8fffff9fffff9fffffbfffffbfffdfbfffffafffefbfffffbffff
+fbfffffbfffffbfffffbfffffbfffffbfffffbfffffafefffafafafbf9fafffbfafffcfcfffefb
+fffffbfcfef9fafff9fafffcfbfffcfdfefffffdfffffafffffbfffffdfefffffdfdfdfdf7f7f7
+f7f9f8fbfffff7fcffecf4f6f8fffff8fffff5fffff5fffff4fffff4fffff3fffff3ffffe3f1f4
+e9f7f8f4fffff0fafbf0f6f6f9fdfcfbfdfcfffffdfffefcfffefcfffdfefefefefefefefdfffe
+fdfefffdfeffffffffffffff
+fefffbfefffbfefffdfefffdfefffffefffffefffffefffffefffffffffffffffffffefffffffd
+fffffdfffefafffefafdfcf7fffef9fffefafdfef9fefffdfcfffdfbfffff2fafcf2fcfef0fbfd
+effefff2fffff2ffffedffffe9fcffe8fbffecfdffeafbffe9faffecfdfff0fffff2fffff3ffff
+f1fffff0fefff0fbfdeef8faf5fdfffcfffffbfcfef5f5f7fafafafefffdfefffdfefffdfeffff
+fefffffefffffefffffefffffffefffffffffffffffffffffffffdfffffbfffffbfffefafffeff
+fffdfffffdfffffdfffffefffffefffffefffffefffffffffffffffffffffffffffffffffeffff
+fefffffefffffefffffefffffffffffefffffffffffefffffffffffefffffffffffeffffffffff
+fefffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffeffffffffff
+fefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffffffffffefffffdff
+fffefffffefffffefffffefffffefffffefffffefffffefffffffffffffffffffffffffffeffff
+fefffffefffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffeffff
+fffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffeffffffffff
+fefffffffffffefffffffffffefffffffffffffffffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefdfbfcf9f7faf7f6fbf6fbff
+f4feffeefeffebfeffeaffffe9ffffebffffecffffedfeffedfeffebfdffeafeffe7fdffeafcff
+eff6fff3f6fff4f6fff4f7fff5f7fff5f8fff6f8fff6f9fff8fafff6f9fff6f8fff4f7fff5f7ff
+f5f8fff7f9fff4fcffebfdffebffffeeffffebffffedfffff0ffffefffffebfffeebfdfdebfdfd
+eefefeeefefeeefefeefffffeffffff0fefff7fffffbfffffdfefffffffffffbfcfff9f9fffefd
+fdfcf8fcfef9fafff9fafffcfbfffcfdfefffefcfffffafffffafefffbfcf8f7f5fbfbfbfeffff
+fcfffff2fafdf3fefff4ffffefffffecffffe9fdffe6fdffe6fdffe6fdffe6fdffe5fcfff0ffff
+effffff2fffff5fffff5fffffbfffffbfcfefffefffffdfefffdfcfffdfefffdfefdfffefbfffe
+fbfffffbfffffeffffffffff
+fcfffdfcfffdfefffffefffffffffffffffffffefffffefffffffffffefffffefffffefffffefd
+fffdfcfffdfafffcf9fbfaf5fcfbf6fffffbfefffdf7fdfbe7f1f0e7f2f4f0ffffedffffe8ffff
+e6ffffe6ffffdefeffd1f3ffc6e8f4c1e3efc1e1f0c2dfedc3e0eec8e6f1d1eff9daf6ffe1fcff
+e3feffe2fbfff0fffff1fffff0fffff2fdfff2fbfff4fcfffbfffffcfffffefffffefffffeffff
+fffffffffefffefdfffefdfffffdfffffefffffefffffefffffffdfffffbfffffbfffffbfffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffffffffffffffffffff
+fffffffefffffefffffcfffffefffffcfffffefffffcfffffefffffcfffffefffffcfffffeffff
+fcfffffefffffcfffffefffffeffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefffffcfffffefffffcfffffeffff
+fcfffffefffffcfffffefffffcfffffefffffcfffffefffffcfffffefffffefffffffefffffeff
+fffefffffefffffefffffefffffefffffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffefffffffffffefffffffffffefffffffffffefffffffffffeffffffff
+fffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffeff
+fffffffffefffffffffffefffffffffffefffffefffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefbfcfef7fcffe0eef1c3d6dc
+b4ccd6b6d6e3b9deeeb5dcebb2d9e8bce4f0bde3eebde3eebce2efbbe0f0bae1f2b7e0f4b9dff4
+bddcf1c0dcf1c1dcf1c1ddf2c3def3c3dff4c5e0f5c4e0f5c6e1f6c5e1f6c4dff4c2def3c3def3
+c2def3c4dff4c2e1f3bbe1ecbce4ecbde5efbbe3ebbbe3ebbde5edbee4edbce3eabce1e9bddfe8
+bedfe6c0dee6c0dfe4c2dfe5c4e1e7c9e1e5deecedf9fffffcfffffefefefffcfdfdf9f8fffefd
+fcfbf9fefefcfbfffcfafffcfbfffcfdfefffefcfffff9fffffafefffbfafbfaf8fdfdfdfcffff
+f5fdffddeaf0c7dae1bdd3dec8e2efc4e1efbfdfeebddeedbddeedbadeecb8dceab9dbe5bcdbe0
+bcdadcbad3d7e8fbfff4fffff9fffffafbfdfcfafbfffdfefffdfefffdfefffdfefdfffefbfffe
+f8fffffafffffeffffffffff
+fcfffffcfffffefffffefffffffffffffffffffefffffefffffdfffffdfffffefffffefffffefd
+fffdfcfffcf9fefdf9f6f7f2fefffdfafffbeef7f4f2fefef4fffff0ffffd8f1f8dbf9ffbfe1ed
+99bece759faf5987974776884271854473874b788d4976894974874873844974844c7684527a86
+557b8670959ea1c2cbc5e1ecd2eaf4e4fbfff1fffff2fffff1fcfffafffffbfffffdfefffdfeff
+fefdfffefdfffffdfffffdfffffdfffffdfefffdfefffefffffffdfffffdfffffbfffffdfffffd
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeffffffffffffff
+fffffffffffffefffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffcffff
+fcfffffcfffffcfffffcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefffffcfffffcfffffcfffffcffff
+fcfffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffcfffffefffffffefffffeff
+fffefffffefffffefffffefffffefffffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfef9fdfeecfcfcbad3d76b8c93
+3f6771487886508595467f90468193397484397482397381397283387185367086336f89336f87
+3a70883d71873d71873f738940748a41758b42768c43778d42768c41758b40748a3f73893e7288
+3e72883e72883c73883c75893972853871843974863972863770833871843b73843f7486407384
+42738443728244728145717e456f7d4b6d77b3c6caf4fcfefafefffafafcfffdfefdf9fafffefd
+fdfcfafefefcfdfffcfbfffcfbfffcfdfefffefcfffff9fffff9fdfefaf9fffffdfefffff3f8fb
+eaf7fdd7e9f39fb6c46282915073864d7386487386447184437085406d803d6a7d3c68754b7279
+56797b526f73c9e1e5ecfbfff9fffffbfcfffffcfffffcfffffcfefffdfefffdfefdfffefafffe
+f8fffff8fffffeffffffffff
+fcfffffcfffffefffffefffffffefffffefffffefffffdfffffcfffffcfffffdfffffdfffffefd
+fffdfcfffcfbfdfdfbfafffef8fffff7ffffeaf9fcebffffedffffcbe9f49abecc628c9c558496
+487b9041778f3e78903d7993417d9946829e48819c48829a477f9840788f387185336a7e356a7c
+376a7b477686436e7e39606f476b797c9eaab7d4e2d9f5ffecfffff4fefff8fdfff9fcfffcfdff
+fdfcfffefdfffffdfffffcfffffcfffffdfefffdfefffffdfffffdfffffdfefffdfffffdfffffd
+fffefdfffefdfffefdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffd
+fefffdfefffdfefffdfefffdfefffdffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefffdfefffdfefffdfefffdfefffd
+fefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfefffdfffefffffeff
+fffefffffefffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefefef6fffeedffffcbf3f57aa9af
+477d874e8d9c438b9a2974872d7a8e307d8f2f7c8e307b8e2e7b8d2d79902b7990287893287893
+2f7c96317d95327e96337f9735819936829a37839b38849c37839b37839b36829a358199348098
+327e96307c942f7b9338829f2f78982d7696317c9b317a9b2a73932b7494347d9d2d7494327494
+35769239769237738d346e862f677e3462728ea5abf1fbfcfbfffff6f7f9fffefffdf9fafffefd
+fefdfbfefefcfdfffcfcfffdfbfffcfdfefffefcfffffafefff9fbf7f3f2fffffdfdfefff2fcfe
+f2ffffe9ffffa7c6d85b8196507d944d7d94497d95467c964379913f758d3a7088396c7d2c5861
+396065214247cbe7ebedfffff4fdfff6f7fcfffafffffcfffffcfffffdfefffdfefdfffefafffe
+f7fffef8fffefeffffffffff
+fcfffffcfffffefffffefffffffefffffefffffdfffffdfffffcfffffcfffffdfffffefffffdfe
+fffefcfefcfdfcfdfff6ffffe2f4f8e6fbffedffffcae6f180a1b04e788849788c43778d3f7790
+407c984585a14789a94388a94186a74186a73e80a04485a34889a74687a340829c3e7e97417f96
+45829740788f40748a4272884473873d687b39627462889ba6c3d5edfdfff4fdfff5fcfff8fdff
+fcfcfffdfcfffffdfffffcfffffdfefffdfefffdfcfffffdfffffdfffffdfefffdfefffdfffffd
+fffffdfffefdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdffffffffffff
+fffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefefef5ffffdffdffd0fbff88bac3
+4c87954f94a44391a535879d4fa3bb2d82972d82972e80962d7f952c7d98297d99287d9c287b99
+2f809d31819c32829d34849f3686a13787a23888a33989a43a8aa53a8aa53a8aa53989a43787a2
+34849f32829d307f9d3f8bad2f7da12c7aa03482a83281a827769d29789f3685ac2f7da43680a5
+3d83a74183a53e7f9f3875922f6b873161777a959cf3fefff9fffff7f8fcfffefffefafbfffdfe
+fdfcfafffffdfefffdfcfffdfbfffefefefefdfbfefef9fdfefafbfffdfcfffffdf9fdfff2fdff
+edffffd4f1ff94bacf54829a50839e4d84a24b84a14884a045819d3f7b953b758d386f8333636d
+40696d13363cd6f2f6f0ffffeff8fdf5f5fdfffefffffbfffffcfffffdfefffdfefdfffefafffe
+f7fffef8fffefeffffffffff
+fcfffffcfffffefffffefffffffffffffefffffcfffffbfffff9fdfffdfffbf6fafffbfffffeff
+ffffffffffffedf5f8e6f9ffebffffd2f0fb94b5c4688d9f5882984e7e95447a964c87a55897b6
+4d8fb14286a9387ea2367ea4438bb13d86a93f85a73e84a64086a83a81a1367d9d498ead4b90ad
+3578933979953b78943b748f39718a3d708b41738c41708a416a808299a7c1cfdaf7fffff4fdff
+ecf1f7fefffff1eff4fffdfffffcfefffbfbfffcfbfefdfbfffdfefffffffefffffefffffefefc
+fefefcfffefcfefefcfefefcfefefcfefefcfefefcfffffdfffffdfffffdfffffdfffffdfffffd
+fffefcfdfcfafffefcfffffdfffffdfffffdfffffdfffffdfffffdfffefcfffffdfffffdfffffd
+fffffdfffefcfffffdfffffdfffffdffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffefcfffefcfffefcfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffefcfffefcfffefcfffefcfffefcfefefefdfffe
+fefefefffffffffffffffffffffffffffffffffffffffffffdfdfdfdfdfdfefefeffffffffffff
+fffffffffffdfffffdfffefcfffffdfffffdfefdfbfffefcfffffdfffffdfffffdfffffdfffefc
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfefdfbfdfcfafefdfbfffffdfffefc
+fffefcfffefcfffefcfffefcfffefcfffefcfffefcfffffffefefefefefefffffffffffffdfdfd
+fafafafbfbfbfffffffffffffffffffffffffffffffffffffffffff7ffffedffffcff3ff6d9baa
+578fa04e90a6438da63787a22778952b7c973a8aa52f7c9635829e4994b1327d9c337fa13b84a7
+3c7ea03e7f9f3e7f9f3f80a04081a14182a24283a34283a33f80a04182a24485a54283a33e7f9f
+3b7c9c3d7e9e3e80a033779a468cae11577b377fa5246e953f8ab22e7ca3347fa72d769f3b83ab
+3b7fa63d7da1427f9e2c6583205775416e835a757ef5ffffebf5f7fafefffffffffcfafbfdf9fa
+fffefffffffdfdfffcfbfffefbfffefffffffffefffffbfffffbfcfffdfcfffffff6feffe7f5fe
+ebffffbcdcf16793ac6396b35992b0518ead4382a141809f44819d437f99336d850e465726555f
+042b3084a5ace6ffffe0f1f8f8fffffcfffff8f6fbfffbfffffcfffffdfefffdfefdfffefafffe
+f8fffef8fffefeffffffffff
+fcfffffcfffffefffffffffffffefffffdfffffcfffffbfffff9fdfffbfffdf8fcfffefffbfbfd
+f7f8fcfcfffff5ffffebffffc2e6f68eb3c560899d4b788f4b7d985085a44c87a73f7e9f3c7ca0
+36789b367a9f377ba0367ba23a80a43a80a43a7ea12e72953a7ea14f93b6458aab2d7293296e8f
+3479984082a24384a241809f3c799838739138718f366d8b396781506d7f758994c8d9e3f1feff
+edf4fcf7fafffffefff7f3f4fffdfdfffdfdfffefdfffefcfffdfefcfefdfafefdfafefdfeffff
+fefffdfefffffefffdfffffffefffdfffffffffffdfefefefdfdfbfbfbfbfbfbf9fefcfdfffffd
+fffefffffffdfffefffffefdfffefffffefdfffefffffefdfffefffffefdfefafbfffbfafffcfd
+fffdfcfffefffffefdfffefffffefffffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffefffffefdfffefffffefdfffeff
+fffefdfffdfefffcfbfffefffffefdfffefffffefdfffefffffefdfffefffffefffffffffeffff
+fefffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffafafafefefcfffefffefefcfffefffffffdfffefffdfdfbfbf9fafcfcfafefcfdfefefc
+fefcfdfdfdfbfefcfdfefefcfcfafbfcfcfafffdfefffffdfffefffffffdfffefffffffdfffeff
+fffffdfffefffffffdfffefffffffdfffefffffffffffffffcfcfcfcfcfcfefefefefefefcfcfc
+fffffffffffffffffffffffffffffffffffffffffffffffffffffff9feffebfbffd5f0ff65889c
+59879f4e86a15293b1377e9e357e9e4188a82b708f38799731708f1754732c6789246084255d82
+2f61843061822f60812f60812e5f802d5e7f2d5e7f2d5e7f36678837688938698a366788336485
+326384366788386b8a245a761d5570245d7b134e6e4c8bac3373972d6e943b7ca23172983f7da2
+3e789d3f7597417491295b7622506843697c3f585ff3fffff0fbfff8fdfffffefffefcfffffcfd
+fffefffffffdfdfffcfdfffefbfffefffffffffffffffbfffffafefcfafbf5f9faf5feffe7f9ff
+e2fdff8cb2c9608fab538aa9538fb15291b43877983776954a86a2306a8212495e1a4b5c143c46
+2c4d54d3f0f6e0f7fdeaf9fef8ffffe9ecf1fffefffffcfffffcfffffdfefffdfefdfffefbfffe
+f8fffefafffefeffffffffff
+fefffffefffffffffffffffffffefffffefffffcfefffbfdfffafefffafefcfbfffefffff3f7fa
+f2f7fbf9ffffebfcffa6c7d8729cb25b889f608fa95e91ae588dac528aab4581a34887aa347297
+3a789d4685a83e7a9e2460841b5779316d8f2c67893671932d698b235f812d6c8d3f80a04182a2
+397b9b347595397a9a3b7c9c3a799a3b77993e7a9c417c9e477a97395c7047616e6f8592f1ffff
+f1feffedf4fafdfefffefcfdfffefdfffefbfffefbfffffdfffefffefffffcfffffbfffffafeff
+fafefdfafefffafefdfcfdfffafefdfcfdfffcfefdfefffffefffffefffffdfffefefeffffffff
+fffffffffefffffdfffffdfefffbfffffbfcfffafefffcfdfffcfffffefffffcfffffdfefffdff
+fffefffffdfffffefffffbfffefcfdfffeffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffcfdfffbfcfef9fdfefafbfef9fd
+fffbfcfffbfffffdfefef9fdfefafbfffafefffcfdfffcfffffdfefffbfffefcfdfefffffcffff
+fcfffffcfffffefffffefffffefffffefffffefefeffffffffffffffffffffffffffffffffffff
+fefefefffffffefffffffffffcfefdfbfbfdfefffffdfdfff6f8f7fffffffefffffffffffeffff
+fffffffefffffffffffefffffffffffefffffffffffdfffefdfdfffafcfbf9f9fbf5f7f6ffffff
+fefffffffffffefffffffffffefffffffffffefffffefffffefffffefffffefffffdfffefbfdfc
+fefffffefffffefffffefffffefffffefffffefffffefffffefffffafdfff2f8ffd0dcf46d809e
+5f7e9d6189ac5688ab3e749a3d759a487ea037698a4d7a9b4e7797305778385c7e35577c2e5073
+2c4d6e2e4d6c2d4c6b2d4c6b2c4b6a2b4a692a49682a496825446326456426456423426121405f
+2241602746652b4a663354653357653f6476224b5f84b1c84978924c7d9b4477963d708f497a98
+48759248728b496f863154682c4b5d4d69751f363ce9fbfdf7fffff7fcfffaf9fefffdfffffeff
+fdf9fafffffdfdfffcfdfffefbfffefffffffffffffffbfffdfbfefafafcfbffffe6f3fbeeffff
+b4d3e7729cb4578aa9578fb24d8caf4887aa3a76983a759341799226596e0c3b4d1b45530d2e37
+9db6bbeefffff0fffff7ffffedf4fafafbfffffdfffffcfffffdfefffdfefffdfefdfffefbfffe
+fafffffafffffeffffffffff
+fefffffefffffffffffffefffffefffffefffffcfefffcfdfffcfffefcfffcfdfffbfffff4fcff
+f3feffeffcffc4dae581a7bc5988a2598ba66699b65287a643799b457da0407b9d336e903c7497
+3f7597255a7a235474376684325f7c2b58752b58773a69873b6a88356684356a892f6684306987
+3e79973e7b9a407d9c3f7b9d3b77993a76983d799d3f7b9f437897355e72496a79425e6aadc3ce
+f2fffff0f9fee6eaebfffffdfffdfafffcf9fffcf9fffcf9fefcfdfefffffcfffffbfffffbffff
+fbfffffbfffffbfffffbfffffbfffffbfffffcfffffbfffffcfffffefffffefffffefffffdfeff
+fcfdfffcfcfefffefffffefffffefffffefffffefffffefffffefffffefffffdfffffdfffffeff
+fffefffffefffffefffffefffffeffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffefffffefffffefffffefffffeff
+fffefffffefffffefffffefffffefffffefffffefffffefffffefffffefffffffffefffffbfffe
+fbfffefbfffefdfffefcfefdfcfefdfcfefdfdfdfdfefefefffffffefefefefefefdfdfdfefefe
+fefefefdfefffbfffffcfdfffafefffefffffcfffffefffffcfffffefffffafefffafbfff6fafb
+f8f9fdf7fbfcfbfcfffbfffffefffffcfffffdfefffcfffffefffffcfffffefffffcfffffcfdff
+fafefffcfdfffafefffcfdfffafefffcfdfffcfdfffefffffefffffefffffefffffefffffeffff
+fcfefdfbfdfcfefffffefffffefffffefffffefffffefffffdfffefcfdfff9faffaeb3d07986a6
+687fa1799bc14c769c4e7ea43f6f954470935077983c5d7c3e59773e5574263959415172465977
+485d78485e76495f774a60784b61794b61794c627a4c627a50667e51677f51677f4f657d4e647c
+4e647c51677f54697c4b5d676073790e252d728d987797a66186994e778d5c869f46728b537d96
+53789253778d5574883c5768354f5c576f79152c32e4f7fbf5fffff5fcfff7f8fdfefcfffffdff
+fdf9fafffefffefefcfdfffefdfffefefffffffffffefcfffdfbfef8fcfdf8ffffe6f7ffe3faff
+83a6ba6793ae5f94b4629cc14c88ac3a769a4981a2487e9a3060762853642349561a3842485c65
+f4ffffdce9f1f7fffff9ffffe8edf1fefffff7f7f7fffdfefffdfefffdfefefefefefefefdfffe
+fbfffffbfffffeffffffffff
+fefffffefffffffffffffefffffefffffefdfffdfcfffcfdfffefffffffff8fcfff9fffff5ffff
+f1ffffd1e4eb8fabb76e98ae598aa85f92af5d90af3d7292356a8a457a9c497e9e4c7d9e3f6e8c
+2f58761e435e2648613d5b73415d723e596e4c687e48667e40607944667f4f748e446e873d6b85
+4a7c974a7d9a477c9b4279983d76943f7798447c9f467ea1467b9a2b5a6e436a794f717d3c5863
+d7eaf1f3fefffbfffffefefcfffefbfffefafffcf9fefaf7fbf9faf9fbfaf9fdfff9fefff9ffff
+f9fffff9fffff9fffff9fffff9fffff9fffffbfffff5fafef8fdfffcfffffcfffffcfffffbffff
+fcfffffcfffffafdfffbfffffcfffffcfffffcfffffcfffffbfefffafefffbfefffafefffafdff
+fafefffbfefffcfffffcfffffeffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffcfdfffcfffffcfffffcfffffcffff
+f9fdfff9fcfff9fdfffcfffffcfffffcfffffbfffffbfefffafefffafdfff9fdfffcfffffbffff
+fbfffefbfffefbfffefbfffefdfffefdfffefefffffefffffffffffefefefcfcfcfcfcfcfffeff
+fffffffbfffff4f9fcf6f9fefbfffffcfffff4f9fcf4f7fcf8fdfffcfffffafffffafdfffbffff
+fcfffffbfffffcfffffbfffffcfffffbfffffafdfff8fdfffbfefffbfffffcfffffbfffffcffff
+fbfffffcfffffbfffffcfffffbfffffcfffffcfffffbfcfefafcfbf9fbfafbfdfcfefffffeffff
+fefffffcfefdfefffffefffffdfffefefffffefffffefffffdfffef9fcfff9fbff8c93b07584a5
+7890b2789ac04872985f8db14c7a9c4871915d809c3d5971344a6117273e2d384e353d54354054
+293a4a263c49273d4a293f4c2b414e2c424f2e44512e4451334956354b58364c59364c59344a57
+334956324855344650303b3d364240303f42c4d8dfbad5e05e7f904b7083527b9149738c547e97
+557a945a7d935c7b8f425d6e3953625a727c1f363ce5f8fcf3fffff5fcfff8f9fefcfafffffdff
+fffdfefffefffefefefdfffefdfffefefffffffffffefcfffcfcfef7fcffebf6faf1ffffa3bfcd
+7599af5b88a56da2c45e96bb4f89ae3d75984f84a34d7b9332596a28485326414833464cacb5bc
+fbfffff1f4fbfafdfff0f4f7fcfffff8f9fbfefffffefefefefefcfefefefefefefefefefefefe
+fdfefffdfeffffffffffffff
+fefffffffffffffefffffffdfffefdfffefdfffdfcfefdfbfffffffefffff4f9fdf5fffff4ffff
+daeef5aac1c96e8e9b618ea5588ba85c8fae578aa9477a99487b9a5081a14b78973c6583375c77
+2f4d653e596e44596a3c4c5b4652604854623c495939485b3647593b50634861754e6a7f4e7187
+557b924b758e4a78924a7995457895477a994b80a05085a75085a439697f32606f49717d294a53
+95acb2f3fffff9fffff6f6f4fffefbfffefafffefbfffefbfffffdfefffffcfffff9fffff8ffff
+f7fffff8fffff8fffff8fffff8fffff9fffff9fffff9fffffbfffffbfffffbfffffbfefffafdff
+fcfffffbfffff8fffff8fffff9fffff9fffff9fffff9fffff8fffff8fffff9fffff9fffff9ffff
+f9fffff9fffff9fffff8fffffbfffffeffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffefffff6fbfef7fffff9fffff9fffff8ffff
+f7fffff9fffff9fffff9fffff9fffff8fffff7fffff7fffff7fffff8fffff8fffffafffffbffff
+fcfffffcfffffcfffffcfffffefffffefffffefffffefffffffffffffffffdfdfdfdfdfdfffeff
+fffffffcfffffafffffbfffffbfffffbfffffbfffff9fefffbfffffafffffafffffbfffffbffff
+fbfffffbfffff7fcfff3f8fcfbfffffbfffffbfffffbfffffafffffafffffbfffffbfffff9feff
+f9fefff9fefff9fefff9fefff9fefff9fefff9fefffcfffffefffffefffffbfdfcfcfefdfeffff
+fefffffefffffefffffdfffefdfffefdfffefefffffefffffdfffef8fdfff2faff8494ae6a81a0
+83a4c35f8aac49799d5489a94f82a1416f89426b7f4a697b4b6272182837bfcbd9bbc1cfbec6d1
+c2d1d8c1d3d7c1d3d7c1d3d7c2d4d8c2d4d8c3d5d9c3d5d9bcced2bdcfd3bfd1d5c0d2d6bfd1d5
+bcced2b9cbcfb9c8cbdbe5e4b8c2c1dfefefe1f5fcc8e4f05478885982985d89a2497693517e9b
+4f7b96577f995c80983e617534536755717f284148e7fcffeffefff3fcfffafafffcfafffffcff
+fffdfffffefffefefefefefefdfffefefffffefffffefcfffbfcfff4fcffe8f5fbe3f7ff88a5b5
+6d93aa6c99b6669bbd558db2538bb04d83a54b7a963f687c3f5f6c2239411d2f31757f81efeef4
+f1ecf3fffdfff7f5fafafafcfefefef4f6f5fefffdfdfffcfdfffcfefefefefefefefefefefefe
+fffdfffffdffffffffffffff
+fffffdfffffdfffffdfffffbfffefbfffefbfffdfcfefdfbfcfcfefcfffff0f8fbf3ffffeafdff
+b3cad2859da76e8f9e7aa8c0699cb95586a6477898477898507f9d4d79964269863759743b576d
+12273a1f2c3c474f5a7b7e87c2c0c5c4c2c7c7c5d0c1c1cdccd0dccdd5e29ca9b95e6f7f445b6d
+486479507389587e955a849d54809b4a7995477896497a9a4b7c9a497d92356675305c694f747d
+58737aedfffff1fbfafefffdfdfcf8fffef9fffefafffefbfffffdfefffff8fcfff3fbfef4ffff
+f2fffff4fffff4fffff4fffff4fffff5fefff5feffeff8fdf5fcfff9fffff9fffffbfffff9feff
+f8fdfff7fefff6fffff3fffff1fffff0fefff0fefff1fffff3fffff4ffffeefcfff0fefff2ffff
+f3fffff4fffff3fffff2fffff4fefffbfffffefefefefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefbfffff8fffff5fffff5fffff5fffff1ffff
+f1fffff4fffff5fffff2fffff1fffff0feffeffdfff0fefff2fffff4fffff7fffff5fefdf7fdfb
+f8fefcf9fffdfbfffefbfffefcfffffcfffff8faf9fcfefdfffffffffffffefefefbfbfbfdfbfc
+fefefff8fdfff9fffff8fffff0f7fdf1f8fef9fffff9fffff9fffff3fafff4fbfff5fcfff2f9ff
+f1f8fef3fafff9fffff9fffff0f7fdf7fefff9fffff9fffff9fffff5fcfff4fbfff5fcfff8ffff
+f8fffff8fffff8fffff8fffff8fffff8fffffafffff2f6f7fcfefdfefffffefffffbfdfcfcfefd
+fefffffdfffefefffffdfffefdfffefdfffefefffffefffffcfefdf6fdffcfe2f17f9eb3678ca6
+76a5bf568fac4585a142849e44859b5590a233677437626924454a0d262ae2f5f9e7f5f8f7ffff
+f5fffff5fffef5fffef5fffef4fefdf4fefdf4fefdf3fdfcf8fffff8fffff8fffff8fffff8ffff
+f8fffff6fffff4fffeebf9f9f1ffffeeffffe7ffff9abece719bb14a7c975e93b34a82a54d85a8
+487ea24e83a35485a33866802d57704e7386223e49e7fcfff1fffff2fbfff9f9fffefcfffffdff
+fffafefffefffefefefefefefdfffefefffffefffffefcfffbfcfff2fcfeeaf9ffa9bfcc829fb1
+6d93aa79a8c6568bad538bb0548aae5588a74a768f32556839515b2a393e434c4bcbcbcbfffaff
+fdf0f9fffbfffffafffffdfff1eff0fffffffcfefbfbfffcfbfffafdfffcfefefefefefefffdff
+fffcfffffcfffffeffffffff
+fffffffffffdfffffdfffffbfffffbfffefbfffdfcfefdfbf8f9fbfbffffedf8fcf0ffffdef4ff
+90acb8688897799eb16595ac598ca748799746759157859f5e88a14c72893d5d72344f62132635
+0e1c27a2a9b3fefefff4eff5fffcfffffafbfffcfffffdfffffdfff5f5fdf2f9fff7ffffcfdfec
+8399a73f5a6d4f6e835b7f9559819a4f7b964d7a995381a25889a743768b437483305c694d727b
+425d64e3f5f7f2fcfbfefffdfefdf9fffffafffefbfffffdf9f9f9ebeff2dde5e8d4dfe5cee1e8
+cbe2eacde1eacde1eacee1e8cfe0e8d1dfe8d1dfe8c9d6ded6e3ebe9f3fcf5fffff8fffff6ffff
+f2fbffedfaffd6e9f0d2e6efcee2ebc9e0e8c9e0e8cce3ebd0e7efd3eaf2c3dae2cbdfe8d5e9f0
+e1f4fbe9fcffeffffff1fffff4fffff8fdfffbfdfcfcfcfcfcfcfafdfcfafdfcf8fdfcf8fdfcfa
+fcfcfcfbfdfcf9fdfef8fdfff6fefff6fefff6fefff4ffffeafdffe5fcffdff6fed5ecf4cee2e9
+cadee5cce0e7d0e4ebcee2e9cde1e8cce0e7cbdfe6cbe2e8cfe6ecd3eaf0d7ebf2ebfaffedfbfe
+eefcfdf1fcfef3fdfff4fefff6fefff9ffffeff3f4f7f8fafffffffffffffdfdfdfaf9f7f8f7f5
+f8f6f7fcfffffbffffe4ebf1b9c2c9a8b2bbb1bec6b1bfc8a1b2bca8b9c3aabac7aabac7a7b7c4
+aab8c3bac8d3d6e2eeedf7fff2fcfff8fffff7ffffebf5fed4e1eabfccd5b1bdc9abb9c4acbac5
+acbac5aabbc5aabbc5aabbc5aabbc5acbac5acbac3c7d2d8dce6e8f1f9fcf8fdfff7fbfef9fafc
+fcfcfefdfdfdfffffffefefefdfdfdfdfffefcfffffbfffff9fffff2ffffa2becc7298ab6b98af
+6296ac69a3bb4c8ca546879d488799477f8e34646e3c636a325154607878f1fffff3fffdf8ffff
+fbfffffbfffdfcfffffbfffdfcfffffcfffdfcfffdfcfffdfcfffdfbfffcfafffbfafffbfcfffd
+fcfffdfcfffdfbfffff5fffff4ffffe3f8fde3ffffc4e8f8658fa552849d639ab8558dae548caf
+4a82a35085a55788a63c69862f5b7451758b193541e8fbfff3fffff2fbfff6f9fefffefffffdff
+fcf6f8fffefdfffefcfefefcfdfffcfefffffefffffcfdfff8fdfff0fdffd8ecf7819baa68879b
+7da2bc6895b25588a75486a75687a7537f9a567a90324f5f2537413b45477e8281fffffdfffbff
+fff5fcfff7fdfffcfffffdfefffefffffffdfcfefbfdfffcfdfffcfdfffcfefefefefefefffdff
+fffcfffffcfffffeffffffff
+fefffffefffffefffffefefcfffefafffffbfffffbfffffdfcfffff0fafcf0ffffebffff9fbccc
+7fa2b678a0b975a3bb679bb3598fa74072896291a55d8698385c6c425f6d2f475122333b0a171d
+dde4eaeceff4edeef2fffefffaf8fbfffefffefcfdfffdfefffffffefffffcfffff8fdffe3edf6
+d0dee9879aa9617b8c5b7a8f587e954d76925e8dab4677975a8daa4f7f95507e8d28505c53747d
+485f65c3d2d5f5fefdfefffdfcfbf7fffefbfffefcfefefefaffffe8f1f6deebf1879ba47192a3
+7197aa6d92a4698c9f7493a57895a56f8a9b6a81918ea4b26a7d8bc8dae6e9fbfff2ffffeeffff
+d5e6ed899da67a97a77293a67494a97194a86a8ea46d91a76f93a9678ba16c8fa37293a6728fa1
+65818f8097a5b2c8d5d4e8f3f0fffff7ffffe8eeeefefffdf8f7f3fffef8fbf4ecfffff6fffdf8
+fafcf9eff8f7f4fffff1ffffe4fcffd5eef3c0d9de9ebbc388acbc658a9d6c91a37598ab799aab
+6382946e8e9d728f9f7592a06f8f9c7393a27697a67498a8779cac7499a9678b9b708d9b7b97a3
+86a1ac91a9b3b7cbd4d7eaf1e6f5fcf7fffff9ffffecf0f3fefffffffffffaf9f7f2eeebfffefb
+fdf9f8fefcfffdfeffeef5fbd3e0e891a3af708a9781a1b07295a87094aa779bb37395ae6989a2
+708ca4668099849ab296a8bedfeffef4ffffe4f4ffa9bccb8ea3b47c93a5728ba17894aa728ea4
+7593ab7696ad7191a86f8fa67191a87291a6718da2728c9b778d9a8fa1add2e0e9f8fffffdfdff
+fefcfffffdfefffafcfffefffdfbfcfefffff9fffff1fcfeecfbfeedffff92b1c37197ac739cb2
+6f9cb36896ad5383995c8aa15b86995a819231515e4b666f3649508e999df8fffffbfdfcfafcf9
+fefffffcfffffefffffcfffffefffffefffffefffffefffffefffffefffffcfefdfbfdfcfcfefd
+fdfffefdfffefdfffefcfdfffbfffff7ffffecffffc5e0eb7293a25e87996594a85f8fa654869d
+56869d58859c59829845697f3a5a6f5d788b203341f4fffff3fdfff4fbfffefffffefcfffefaf9
+fffefbfffbf7fffffafffffbf9faf5fcfffdfafffff0f8faf2ffffeaffff9fbacd7b9aae7fa2b6
+769cb36993ab628ea755819a658ea44f7487395666324a563947503e454bd6d7dbfffffffffdff
+fffefffffefffffefffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffefffffeffffffffffffff
+fcfffffcfffffefffffdfffcfffefcfffffbfffffbfefffdf5fbfbf7ffffe6f8ffc6e0ed7fa0b3
+85abc26c98b36b9db86b9fb7497d935b8ba15d8b9b6086933c5d663d565d31444a111c20bcc4c6
+f3f7f8fefffffffffff0f0f2f5f5f7fffffffdfdfbfdfef9fbfbf9fbfbf9fefffffcfffff7feff
+eef8ffc2d2df6c839367839861859b527c955584a05386a5578aa758879b557f8f375b694b6973
+50646ba7b5b8fafffffefefcfdfcfafffffbfdfdfdfafefff9fffff0fbffeaf8ff96aeba719aae
+709eb5709db46d97ad6f95aa7497ab7292a76c899b6e899a627c8b5d7381ebffffe2f6ffd4e8f1
+97abb4809ba67a9aaf7196b0759ab5779fb9729bb7719db8729ebb6e97b36f96b3698ea865889e
+59788c5a7586688291859caab6cad3eaf9fef6fffffefffdfaf9f4fffef6fbf4eafffbf1fffff8
+f5faf6effbfbeeffffdefafeb9d7df90b2bb7c9ea77197a26b95ab6593ab6f99b26d95ae6e94ab
+6c90a67497ad7194a87497ab789bae7da2b5779db06790a46491a46b98ad6b98ab688ea164879a
+648596678492748e9b7e949f91a3adc3d2d9f7fffff4fcfef9fafcfbfbfbfaf9f7fffcf9fffdfa
+fffbf8fffbfcfdfefff4fbffdeecf58fa7b37191a080a6bb73a0b76b99b36c99b66e9ab76e97b5
+7699b7607f9c5b7694435b75d4e6fadceffeb4c9da8ba5b6809bae809fb47597b07ca0ba7297b2
+739ab7739cb8729bb7729bb7739db66e96b0698fa66184975d7a8a5f76868b9dabacb4bff4f7ff
+fffdfffffdfffff9fcfffdfffdfbfefefffff9fffff1ffffeeffffdff7ff8aabbc7399ae769fb5
+7099af6992a85c8299678ba163869a5875873d5464596b7725323ac1c9ccfcfdfffffefcfffefc
+fffffffefffffefffffefffffefffffefffffffffffffffffffffffffffffdfdfdfdfdfdfefefe
+fefefefefefefefcfdfffbfcfdfdfffbffffeffdffc7dee675939d6288956994a46492a25b889b
+5d889b5e87996083964c6b7d405b6c637889273746f2fefff5fefff5fcfffefffffefcfdfffcf9
+fffefafcf7f1fefbf4fbfaf5fbfcf7fcfffff9fffff3fdffefffffc2dced8aaabf7a9db385a9bf
+749ab1618aa06790a66b94a8567b8e4b6b7a334d5a42565f212e36969da3fefffffbfbfdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fcfffffcfffffdfffefdfffcfffefcfffefafffffdfefffff3f8fbf5ffffebfdff8fa9b887a8bb
+7ea4bb74a0bb608fab5f91aa5d8da36594a84e77894566753f5b66384c551e2d329faaacf9ffff
+e4e8e9fbfcfef7f7f9fffffffcfcfefffffffffffdfffffbfffffdfbfbf9fbfcfefcfffff9ffff
+f7ffffe3f3ff6c81926e899e7497ad648ca65986a36293b350829d608da2568090436773415d68
+586b72869195fbfffffdfdfbfffffdfffffbfdfdfdf8fcfdf9fffff4fffff1ffffa4becb7399ac
+6b99b0729fb6729bb1678da26e91a57493a86885975f7a8b647e8d384e5cecffffeeffffb7cdd8
+879da894aebb7b9bb06d93aa6f94ae739bb56e97b36c95b16f98b66e97b36990ad658aa47094ac
+7898ad7996a86983925b7280718590bbcacff8fffff8faf9fbfaf6fffef8fef7effcf7f1fffffb
+fbfffff4ffffd9edf4afccd48babb671939d6b8d977298a5709ab06e9cb4648ea7638ba46b91a8
+799db3779ab0779aae7598ac7497ab789cb2799fb4749db374a1b673a0b76996ab7ea4b97b9eb1
+7a9bac7191a06e8a986179855e727d83949cccd9dff8fffff7fbfef9fbfaf8f7f5fffefbf6f1ee
+fffefdfcfafbfafbfff8ffffe9f7ff8ea6b27797a685a9bf7ba5bd7da9c272a0ba739fba749bb8
+7899b86784a2607997354d67d6edffcae1ef92acbb7f9aab7996a884a4b96d91a77095af769eb8
+749eb7729cb5709cb5739fb874a0b96f99b26891a781a4b77693a35b7282687a88747e88e8ebf4
+fffefffef8fcfff9fcfffcfefffafefefffff6fefff7fffff4ffffcfe5f081a2b5779db47ca5bb
+6d96ac698ea85e849b6a8ea466869b4d6a7c465d6d5c6e7a1a272ff5fdfffafcfbfffffdfffffd
+fffffffefffffefffffefffffefffffefffffffffffffffffffffffefefefefefefefefefffffd
+fffffdfefdfbfdfcfafffcfbfdfdfdfbffffeefcffc8dfe77896a0668a986e98a86994a5608da0
+628da0648a9d64879a517082445f70647a882e3e4bedfafff6fffff7fcfffefffffcfbf9fffdfa
+fffefafffbf5fbf8f3fcfbf7fefffdfbfffff8fffff5ffffe2f5fca0bbcc7e9eb37b9eb486aac0
+7298af61879e688ea37197aa5a7d902c4c5b49606e31434d414b54f8fdfffffffffefcfdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fbfffffbfffffdfffefffffffffffdfefffafefefcfbfffef1f9fbf3ffffd4e6f07b95a498b9cc
+799fb678a2bb57859f6591aa618ea56790a4496e802d4a585169731f32394f5c62f5ffffe6ebee
+fbfffffefffff4f4f6fffffff8f8fafffffffffffdfffffbfffffdfffffdfbfcfef9fdfff5fcff
+f1fbffedfbff788e9c6b8699779ab06991aa5f8da76293b152819d6390a55980914668743e5b63
+5b6e75758084fbfffffcfcfafffffbfefdfbfefefef7fbfcf8fffff5ffffedfeffa5bfcc81a7ba
+74a1b67fa9bf7ea7bb7094aa7598ac7b9aae6784965972865a7485657c8ce4faffd4eaf7a0b6c1
+8ba1ac96b0bd8eafc27ca0b8789cb47a9fb9729ab46e97b3749dbb769fbb6a92ac678ca66b8fa7
+6a8a9f718ea06d88995c7685677b867b8a8ff6fefff3f7f6fdfcfafffefafffcf6fbf8f3fafcfb
+f9ffffecfbffb7cdd887a5b080a0ad83a7b580a4b07fa6b5729cb477a3bc6f99b27ea6bf80a4bc
+7a9db365859c7090a57797ac6f8fa46f92a87599af7ba1b882acc27eabc0719bb16d93a8779caf
+7d9eb17493a57c98a677919e647883697c83839098f8fffffafffffcfffff5f5f5fffffdf3efee
+fffefdfdfbfcf4f8fbf5feffe8f6ff8da5b17d9dac84a9bc7aa3b96f9bb4638faa668fab6186a1
+5c7e9a5977936b839f496179b5ccdea8c2d17b96a77f9cac7594a883a6ba6b8fa57197ae739bb4
+6f99b16b95ae6996ad6b97b06c99b06a97ae6a93a96e93a56c8c9b4d67765b6d79636d77c1c5ce
+fffefffffafefffbfdfff9fbfffbfffffefff4f9fdf7fffff4ffffbdd3de799aad7da3ba84adc3
+6d96ac698ea863879f6b8ea463839848657750677553656f354248fbfffffafcfbfefdfbfffffd
+fffffffefffffefffffefffffefffffefffffffffffffffffefefefefefefefefefffffffffffd
+fffffdfefdfbfcfbf9fffefdfefefefcfffff1fcffcce0e97b99a36b8f9d729cac6c97a86691a4
+6790a4678da0688b9e557584466270647a87374550e5eff8f6fffff7fcfffdfefffaf9f7fffefb
+fffdf9fffefafefbf6fffffdfcfffffafffff8ffffeaf7ffc0d2de95b2c481a1b67c9fb57ea1b7
+7296ae698fa4668aa05f829658798a223e4c405663293a42acb5bcfcffffefeff1fffeffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fcfdfffcfdfffefefefffffffffffdfefefcfcfefdf9fffff1fbfdf1feff9badb790aab990afc3
+81a5bb6c94ad5d87a0779fb84e748b6a8da1506f813751604f636e202e37c6d1d5e6eef1fbffff
+fefffffcfefdfeffffeeeff1fdfefff7f9f8f8f8f6fdfef9fffffdfefefcfbfcfefafefff9feff
+f3fefff4ffffa0b3c26e88997090a562889f628ea75a89a55d8ba56691a45d829242647047626b
+5c6f767d888cfbfffffefefcfffffbfbfaf8fffffff9fdfff8fffff4ffffe5f6fea2b9c77a9fb2
+6b95ab719ab07096ab5f8399638398607f93476476688195455f70a2b9c9e0f7ff9fb6c49eb6c2
+88a0ac8aa4b17c9baf6c8fa56a8ca56c90aa658aa56088a2638aa7638aa7678fa9678ca66a8ea6
+6181965b7a8e587384556f7e6d839058656ddae2e5fafefffbfbfbfcf8f5fffefbfefefcf8fcff
+edf6fdcedfe99eb5c384a4b38fb0c189aec0769bab6d93a6638ba46b93ad5c819c5c809a4d6d86
+45637b3c586e5470854e6a7f4c687d4d6c814b6e82496d83557b9060899d5f889c6a90a36f94a7
+7091a46685976e8b9b6b8795576d7a5c707953616ae3eef4f5fdfffcfffff4f4f4fbfaf8fdf9f8
+fbfaf8fffffff3f7faf2fbffdae8f190a6b386a3b385a8bc759eb46d97b0658fa86e96b06e92ac
+6a8aa366829a7b91a95e748b9db7c899b5c37f9aab86a6b57091a4789baf668aa07197ae6790a6
+6690a66892aa6993a96993ab6791a76791a76992a65c8193638392435d6a546873616e777c8187
+fffefffffafefffdfffef8fafffcfffffefff3f8fcf8fffff3ffffaec1cf7797ac84a9c38bb0ca
+7095af6e94ab688ca46a8da35f7e924e697a59707e43555f768389f8fdfffdfffefcfcfafefdfb
+fffffffefffffefffffefffffefffffefffffffffffffffffefefefefefefffefcfffffdfffffd
+fffffdfefdfbfcfbf9fffcfbfcfcfcfbfffff1fcffcee2eb7f9ba67091a0779eaf6f98aa6893a4
+6992a46a8fa16c8d9e5a77874963726379863b4952d8e3e9f5fffff7fcfffbfdfcf7f6f4fffefb
+fefbf6fffef9fefdf9fefffff6fbfef2f9fff6ffffd6e4ef9ab0be8eaabf87aac080a3b97497ad
+6f93a97397ad678a9e507184415e6e3b52601628346c7981f9ffffe6e7e9fffdfefffefdfffeff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fbfcfefcfdfffefefefffffffffffdfdfffefafefdf8fefef6ffffd8e7ee889ca794aebb92b1c3
+7ca0b67297b1678fa86b8da667879c5a768b4c6677465968253640727c85f9fffffafefffeffff
+e9ebeaeef0eff6f7f9f7f8fafefffffcfefdfdfdfbfffffbfffffdfbfbf9f9fafcfafefffbffff
+f8ffffeefcffb9cbd97993a47897ab6d93a86d97af5987a16591aa6992a66185954363704e6972
+596c728e999bfafffefefffdfffffbf6f6f4fefffffcfffff8fffff4ffffdeeff99cb3c18baec1
+7da6ba7da3b8779caf6a8da1698a9d637f944b6679758fa026404fcae1f1bdd4e295acba92a9b7
+8da5b17e98a56e8b9d69889d6e8ea57193ac6d91ab6d92ad6d92ad658da7678ca75c819b698ba4
+7696ab7594a85d7a8c4963745d73805d6a72aeb6b9fcfffff9fafcf6f5f3fffefffefffff8ffff
+d6e3ecadc0ce8ca7ba8faec28eb1c57499ac608699668c9f7b9fb77296ae55779044647b405c72
+4b667b4c657952687d4e64794d667a5671845c788d5d7c9065889b6c91a4678c9f769bae7194a8
+7495a87293a47190a25c7886465d6b596f7a53646cb3c0c8eef7fcf9fefff6f7f9fefefefffeff
+f7f5f6fffffff5fafdf3fcffc5d4db94aab78daab887aabd769cb1648ca55c849d6388a2698ba4
+718da5667f9570849c566b7e758f9e74909e65809166839349687a4a6b7e44677b52778a63879d
+658ba06c92a76f98ac6e97ab6992a66790a66a90a57196a87495a44c66734f636e65727a474e54
+f6f7fbfcfafdfffdfffff9fbfffcfffffefff4f9fff8ffffeaf4fda2b4c27e9db289aec88bb0ca
+6f94ae7399b06d91a76b8ba05e7d915570815f7583364751bac7cfe6eef1fcfffffffffdfefefc
+fdfefffbfffffdfefffdfefffdfefffdfefffefefffefefefffffffefefefffdfefffefcfffffd
+fffffdfefdfbfdfcfafefaf9fafafaf8fdfff0fbffd0e3ea829da87192a1799eae719bab6c95a7
+6e94a76d90a370909f5e7a884c6371647883404d55cdd6dbf6fefff9fffffcfefbf5f6f1fffffa
+fcf9f4fffdfafffffdfefffff6fdfff1fbffe8f6ffc1d3e18ea5b581a0b58aadc383a6bc7093a9
+6c8fa57396aa66879a4e6b7d3a54633f556234454fcbd6dcfafffff4f4f6fffefdfffbf8fffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fbfbfbfdfdfdfefefefffffffefffffdfffefafefff5fdffeef9fdb2c1c89bafba8ea8b595b2c4
+7c9fb3779bb3698da567869b829db2465c71485b6c4151602e3b44cfd8dfeff4f8fdfefff1f1f1
+fffffffffffff5f6f8f7f8faf7fbfefcfffffefffffefffdfefffdfbfdfafafbfdfafefffaffff
+f4fdffe7f4fdb5c7d3879eae86a3b581a4b87099af6490a96a94ac6d93a66182934967724e6670
+53646b95a0a2f3f9f7fdfffcfffffbf5f5f3fefffffbfffff8fffff1feffd4e5ef93aab885a8bb
+80a6bb789eb36d92a569899e67869a627d925770846882932d4454cbe0f18ea4b292a8b6758b98
+7a909d687f8d567081587386607c916180956282996a8ca56d91ab6287a17195af5e829c5f819a
+6a8a9f7392a66582944d6778586e7c6e7b8471787efbfffffafbfdf8f8fafafafcfafdfff2fbff
+bdcdda9cb3c38ca8be8babc27b9fb5698fa4678ba16f92a667879c5773884e697e465f734c6174
+4f627357687a5162725f7080607181687b8a6b82926983926f8b99718e9e68889766899c638699
+6c8da07596a77d9cae6885934c66735a727e657781717f88f0fbfff6fdfff9fdfffffffffcfafb
+fcfcfcfefffff7fcfff5feffadbec596acb98fabb98bacbd7a9fb27399ae6d93a86d90a67292a7
+7c97ac687f916d7f936174856278866077855f76865f798a546f805b788a6382946b8c9f7090a5
+6c8fa36e91a57396aa7499ac7095a86e92a86f94a7698d9d6d8f9b455f6c3d515c67767d484f55
+f7f8fcfffefffffcfefffafcfffafefffefff6f9fff2f9ffdde6ef98aab887a6bb8db1cb87abc5
+6b8fa9779bb37396ac6d8da26380925670815b717f2c3d47e3f0f8e7eff2fcfffffefffffcfefd
+fbfffffafffffbfefffbfffffbfffffbfffffdfefffdfefffefffffefffffdfdfdfdfdfdfffefc
+fffefcfffefcfefdfbfdfcfafbfbfbfafffff4ffffd5e8ef89a1ab7696a37da1b1769bad7297a9
+7297a97293a47491a1627e8c4e6573637780435056c5cfd0f7fffffcfffffdfffcf6f7f2fffffa
+fcf9f4fffffbfefffffbfffff8fffff0fcffcfdfeea9bccd93acc083a2b787aac07f9fb47191a6
+7292a77291a55d7a8c445f7042586630424c9ba8b0f9ffffe5e6eafffefff7f2effffcf9fffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fbfbfbfcfcfcfefefefffffffefffffbfffff8fdfff4feffd8e3e99aabb39eb4bf98b2bf7d9aaa
+8fb0c3698ca264849989a4b96b8093495c6d4f5f6e404c58778089f0f5fbfcfffffefefeffffff
+fefefef8f8f8fefffff8f9fbfcfffff2f6f7fdfffefefffdfefffdfefffffefffffcfffffbffff
+f3fcfff5ffffb2c2cf8ba1af839eaf82a2b7658ba07098b16e97ad6e93a65f7e904f6b77475e66
+4f5e65939d9fedf1f0f9fbf8fffffbf5f5f3fefffff9fefff4fdffebf8ffcbdce68ba2b083a4b7
+84a9bc7ba0b36d90a36e8da1708d9f6e879b6f8698637a8a697f8dc2d5e491a4b28093a1748893
+5c707b596f7c596f7d5c73835f798a5c778a5f7b917090a7789ab36f91aa6c8ea77395ae7d9db4
+7291a6708ca16b86995872835b717f76838c3f464cf4f9fdfafefffdfefff3f6fbf0f4fde5f2fb
+a5b6c69ab3c794b2ca84a6bf7094ac7397af769ab06a8b9e6781924b60714c5f6e3e505e2f3f4e
+2a384567717d939da97e8892828f9884909c6e7f89536571536772697f8a758f9c7a9aa97497aa
+7091a46a8b9c7999a87390a04c6876435b676c808b3c4d55f7fffff9fffffbfefffeffffefeff1
+fffffff6fafdf5fdfff5ffff9eafb695abb68da9b78dacbe7ea1b46e93a67095a87494a97693a5
+788fa15267785263735163715c6e7c566876576a79576a79566b7c5d7283667d8f627c8d839eb1
+7994a7708d9f708fa17493a77695a97796aa7a9bae698a996f8f9c4b65723b4f58707f865f686d
+f7f8fcfdfbfefffcfdfffbfcfbf9fefffefff6f9ffedf4fed4dce794a4b38fabc190b2cb83a5c0
+688aa37b9bb47797ae7190a4688597536d7e556b79263741f0fdffeff8fdf6fbfefcfffff9fdfe
+fafffff8fffff8fffffafffffafffffbfffffbfffffdfefffefffffefffffdfdfffcfcfcfefcfd
+fffefcfffefcfffefcfffefcfefefefbfffff7ffffdbecf48fa5b07d9aa883a4b3789cac7599a9
+7599a97494a37793a1657f8c516774657781475256c2cbcafafffefcfffdfffffbf8f7f3fffffa
+fbfaf6fdfdfbf8f9fbf3f8fcf7ffffe9f7ffb4c7d890a6bb95b0c58faec386a6bb7595aa7190a4
+7a99ad728fa1516b7c364d5b3d4f5b303e47e0e9f0fbfffff6f6f8fffdfcfffefbfffefbfffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefdfbf8f7f5fffffff8f8f8fcfdfffcffffedf5f8f7ffffc3d0d8a2b5bc9db3be9bb5c2839eaf
+7897a97e9fb27897ab7d93a86677894151615a66742f3742b2b6bffbfefffffffffefefefffefc
+fffefcfefefefdfefffdfefffbfffffbfffffcfefdfcfefbfdfffefefffffefffffbfffff7fcff
+f2f9fff5ffffa4b5bf8ba1ae85a1af84a3b76d92a56c92a77399ae698a9d6481914f6976657982
+536269bec8caf9fdfcf9fbf8fbfcf7fcfefbfbfffef9fffff4ffffeffdffb0c0cd96adbb8bacbd
+88adbf7a9db06d8ea17d99ae809bae6980926176875c6f7e8497a5aabcca8698a46577835a6c76
+6f818b60727c5c6e7a5669777086947289996c85997894a97190a56c8ca37090a77191a87696ad
+7291a67995aa748fa25670815164737c8992383f45f0f5f9fcfffffcfffffafffff6fdffbccad7
+99abbf92adc291afc97fa1bc7799b27fa2b87595aa6580935265735d6b763f4c55000710a9b2bb
+ebf2fafbfefffcfffff9fcfffbfffff8fdfff8fffff4ffffbdcad084939a7488916885937596a7
+7796a86d8c9e7494a37e9bab486472455c6a697f8c40525cf0fdfff7fffffbfffffbfcfefbfbfd
+fffffffcfffff1fbfde2f0f39fb0b797adb88aa4b195b2c27293a665869981a2b57895a77792a3
+6378895d6f7d3a48551a28332d3947535f6d6672807e8a988e9bab8b98a8778796465767647788
+6275868fa4b7889fb17f95aa7a93a77b94a87e99ac7393a264828d546f7a4f636c4f5e658a9496
+fefffffdfbfefefafbfffcfdfcfafffbfcfff9fcfff9ffffbac2cd9aaab993aec38cacc382a2bb
+7797ae7795ad7d99af7894a96f8a9b748b9b748795697b87f1fffff6fffff2fbfff9fffff0f8fb
+f1fafff2fbfff4fdfff6fdfff7fefff9fefff8fdfff8fcfff3f7fafcfffffefffff7f9f8fefefe
+f4f4f4fffffffcfcfcfdfcfafefefefcfffff7ffffebf9ff8da3ae839fab86a6b580a1b27596a7
+7a99ab7d9aaa7b95a2677f8b566a756778804c5759c5cecdfafffefafffbfbfcf7fefdf8fffffa
+fcfbf7fffffff6fafdf4fbffeffbffcfe0f0a2b7ca8da6bc93afc58faec389a8bc708fa37f9cae
+698497546e7f465c6a506270172530b6c0c9eff6fcf4f8fbfffefffcf8f7fffefbfffcf9fffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffffdfcfbf9fffffffafcfbf9fdfefbfffff0f9fee9f6fcb5c3cc9dafb99cb2bf9bb5c284a0ae
+7b98a8809fb17c99ab76899a55657545515f5f69733e454fdee1e8faf9fefffffffffefcfffefc
+fffefcfefefcfefefefdfefffbfffffbfffffdfffefdfffcfdfffefefffffefffffefffff9fdff
+f4fbfff4feffa5b3bc8ea1af8aa4b18ca9bb7596a97297aa7ba0b37190a2627c8d50667461737d
+414e54c3cdcffafefdfdfffcfcfdf8fefffdf9fdfcf9fffff5ffffe7f5fea9b9c697adbb91b0c2
+8aadc07fa0b37695a7809bae7a94a56378895a6d7c495b695e6e7b4e5c672c3a452d3b444a5960
+819097909fa677858e73818a7889936577855b70816e88997792a77f9bb17190a57291a67995ab
+7591a67c97aa7892a35d7486576a7984919a2e373cf9fffff5fafefbfffff2f9ffe7effaaab7c7
+9bb0c399b3ca8fadc77999b27292a97594a9688499586f7f5a6871202930091016dee3e7f9fcff
+f5f6fafdfbfefdfbfefdfbfcf7f7f7f2f2f4f3f7f8fbfffff9ffffd8e2e4a1b0b56e89947b9baa
+7e9ead7393a27595a47c99a949657349606e6c828f3b4d57f5fffff4fdfffafffffdfefffdfbfc
+fffffffbfffff3fdffd1dfe2a3b4bb93a9b495afbc8daaba7897a97493a5809fb17c97a85f7684
+55677551626c1c29328d97a0c2c8d4e9effbfbfffff9fffff7fdffeff7fff5fdffe5effbc3cfdd
+7a87977686967d8ea08c9fb0859aad8095a888a2b37793a1637f8b4f67735c6e78465359a9b1b4
+fcfffffffffffffefffffefffaf9fef9fafff8fbffeff5ffb1b9c699a9b89ab3c78faec385a1b7
+7c98ae7a94ab7a95aa758ea26e88997f94a56e818f758793a9bac4c4d1d9b6c1c7c6d1d5bac5cb
+bec8d1becbd4c1cbd4c3cdd6c4cdd4c3ccd3c2c9cfc1c9ccc5cacebabfc2c5c9ccc0c4c5d0d1d3
+aaabadd8d9dbfdfdfdfdfcfafefefefcfffff7ffffebfaff90a4af859fac8aa7b584a4b37898a7
+7c99a97f9ba97d94a2697f8a5769736a79804d5759c6cccaf8fcfbfefffdfdfef9fdfcf7fdfcf7
+fffffbf6f8f7fbfffff8ffffdeecf9b7cadb97b0c48da9c18dabc38aa9bd708d9f8ba8ba7e99aa
+5e7887495f6d4f616f3947525e6871e3eaf2fcfffffafbfdfaf8f9fcf8f7fffefbfffefbfffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffefbfffffbfefefcfefffff8fcfdf8fffff4ffffd3e2e9a7b8c299adb89cb2bf99b3c084a0ae
+7c99a9809dad7c97a87889994b5966586470545d6672767ffcfffff7f7f9fffefffffdfcfffdfa
+fffefcfefefcfefefefdfefffbfffffbfffffcfffffbfffefdfffefefffffefffffefffffbffff
+f9fefff1faffa2b1b88fa1ad90a8b492adbe7998aa7699ac81a2b57a95a85d748454677564757f
+323f45d2dadcfbfffefefffdfcfef9fefffdf8fcfdf8fffff7ffffdae8f39fafbc99afbd97b6c8
+87aabd7b9aac7794a6748e9f657c8c5467764a5a6919273265727b8a949dcdd7e0f5feffebf4f9
+f2fbfff8fffff3fcfff8fffff7ffffd4e1ea9babb8738695637a8c7790a47590a57692a77c97ac
+7992a67f98ac7d94a662798b5e717f8d9aa2252e33f9fffff4fcfff6fdfff2fbffcdd7e399a9b8
+a0b5c89eb8cf8dabc37d9bb37e9ab07c97aa6e8897667a856a757b1b2024b3b7baf8f9fbf3f3f5
+fffefffffdfdf2ececfffefbfffefbfffefdfcfcfaf2f4f3fcfffff9ffffc6d4d77a929c83a0ae
+89a6b4809dab7b98a67c99a74c68764f66746f859231434df5fffff2fbfffbfffffefffffdfbfc
+fdfdfdf7fffff1fcfebbcacda4b7bd91a7b29fb9c684a0ae7e9bab7a97a77b96a7768d9b556b78
+4f606a435058464f56f3fafff2f5fcfefefffefdfffdfdfffafafff6f9fffbfffff4fbffe9f1fc
+919ba78793a18f9fae9bacbc8699aa788da0849bad7c96a5607b86485e6965767e3b484ec9d1d4
+fafefff8f8fafffefffffefff9f8fdf7fafff9fdffe1e9f4a8b2be9eaebd9bb1c68da8bd829db2
+7f9aaf8099af7e97ab7e95a77d92a3859ba976899780929e7b8c9695a6b0919fa89aa9b093a1aa
+96a4af97a5b09aa8b39ba9b49ca9b29aa7b09aa4ad99a2a9a8afb799a0a69ba0a6a1a6aaa5a8ad
+787c7fc7cbcefefffffcfcfcfefefefbfffff7ffffecfbff92a6af8aa1af8da9b789a6b67c99a9
+7e99aa809aa77f95a26d818c5a6d746d7c814d5758c8ceccf6faf9fefffdfdfef9fffefaf4f3ef
+fffffdeff0f2fbfffff7ffffc4d4e19bb2c494afc492b0ca8aaac186a3b57f9ba97d97a6768d9b
+647a874254604e5c672e3842c7d0d7f7fcfffafbfffffffffffefff9f5f4fffdfafffefbfffffd
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffefbfffffbfdfcfafefffff8fcfdf7fffff6ffffc0ced7a3b5c19cb2bf9eb5c398afbd849ead
+7e9aa87f9ba97a94a170829048566167717b38414ababfc5fefffffafafcfdfcfafffdfafffdfa
+fffefcfffefcfefefefdfffefbfffffbfffffcfffffbfffefdfffefdfffefefffffefffffcffff
+faffffebf4f9a1aeb692a3ad93a9b694aebd7898a77596a77f9eb07b95a6586d7e5b6d7b6c7a83
+384349e5edeffcfffffcfefbfdfffafcfffdf6fcfcf7fffff5ffffc9d7e299a9b69bb1bf99b8ca
+83a4b57794a67893a46c8393596f7d5666754b5964606a74edf6fff3faffeef6f9fafffffbffff
+fbffffeaeeefeff3f6f0f4f7f2f7fbf7ffffecf9ffb6c6d38093a2758c9e7b94a87c95a98099ad
+7c93a58198aa7f94a5667b8c6375838f9ea51f2a2cf8fffff9fffff0f7fdf2fbffb4c0cc99abb9
+a8bfd19eb9ce85a1b77e9ab07d98ab6d84945e74815b6c74333c41767b7ef6fafdf9fafcf6f4f5
+f4f0effffdfdfffcf9fffaf7fbf6f3fffefbfffffbf0f2efeff4f0f8fefcf3feff89a0a889a5b1
+8fabb78aa6b4829eac809caa526c7b526977738694283a44f5fffff3fcfffcfffffdfdfdfcf8f7
+fffffdf6fffee9f7f8aebdc0a1b4ba99afbaa2bac67e9aa8829dae7d98a97b95a46a808d647680
+5c6b722d383caeb6b9fcfffffffefffcfafdf1eff4f7f5fafffefffffefffbfcfff0f3f8f6fbff
+afb8c1a4aeb892a0ad8ea0ae8598a78297a88ca3b37d94a2586e7b4c5e6a64727b4b565ce6eef1
+fbfffff6f7f9fdfdfdfffffff8f9fdfcfffff9ffffd6dee9a5b1bda6b6c59eb3c68fa5ba869cb1
+879eb08a9fb2879caf869bac889dae8093a28a9dac7e919f8a9ca8889aa699abb790a2ac94a6b0
+93a5b195a7b597a9b799abb79aaab79ba9b49aa7b09aa4ada3adb6aab3ba868f968f969c838a90
+6a6f73d3d8dcfcfffffdfdfdfefefefafefff8ffffeffcff96a8b28ea4b291abba8ca7b87e9aa8
+809aa9839aa88498a372848e6071787380864d5557ccd0d1fcfefdfffffdfcfbf9fffffbf2f1ed
+fffffdf6f7f9f9ffffe3f0f9afc1cf91abbc97b6cb98b8d188a8bf7693a394aebb738a98637684
+6274804c5a65353f49778089fbfffff8fbffeeedf2fffffffffefff6f5f3fcfbf9fffefcffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffdf8fffffbfcfbf9fefffff8fdfff6ffffeefbffb2c3cba5b9c4a2b8c59eb5c393aab8859fac
+849eab829ca97c94a05a6c7853616a566069374047eef3f7fbfcfefdfdfdfffffdfffdfafffef9
+fffefafffefcfefefefdfffefbfffffbfffffcfffffbfffefbfffefbfffefefffffefffffcffff
+faffffe6edf3a3b0b899aab296acb793adba7a97a57595a47b9baa7d94a6576a7b5f6f7e68757e
+4b545bf3f8fbfcfffffcfefbfdfffcfcfffff6fcfcf5ffffedfaffbbc9d49aaab99db2c39ab7c7
+81a2b37a97a9859fb07085965c6f7d657380525f68879099f9fefff4f7fcfdfefffdfdfdf0f0ee
+f4f4f2f8f7f3fefdfbfefefef4f5f7fbfffff8ffffe3f0f9a7b7c48093a2859aab859cae879eb0
+8095a68398a98194a3687b8a6577838a999e1c2729f6fffff8fffff6ffffdee9efacbac5a1b3c1
+a4bbcd91aac07792a7829db0839aaa6a7d8b62737b606d73283136d2dadcd7dcdffcfffffeffff
+e7e7e7f7f6f4fffefdfffbfaf9f8f6f0f0eef6f8f5fcfffff9fffdf1faf9f5ffff97abb28ba6af
+8faab590aab786a0ad839daa526c795168767285932c3d47f1fbfff7fefffefffffaf8f9f9f4f1
+fffffdf8ffffddebecadbcbf9eb1b7a8bcc59bb3bf7f99a8849ead88a2b18198a6687c8763747c
+69767c1c2628eef3f6e9ebeafefdfbfcf8f5fffcfbfffffdfffefcfafaf8f7f9f8fcfffff9feff
+bac3c8aebbc398a9b399adb895acba88a2b1819baa798f9d5164725969765a6770778087fbffff
+fcfffffefffffbfbfbfefefff8fcfffbfffff8ffffc7d1dba4b2bda8b8c7a7b8ca98aabe8ea0b4
+8ea1b28ea1b2899cad8699a8879aa98093a296a9b8788b9a9db3c08ca2af9bb1be93a9b699afbc
+99acbb9baebd9db0bf9fb2c1a1b2c2a1b3c1a0b0bda1afbaabb8c1b1bbc479838c757e857f888f
+676e74eff6fcf7fbfefefefefefefefafefff8fffff1feff9aabb593a6b496adbb8fa9b8809aa9
+819baa869eaa899da6798c9367787f79878a50585bc9cdcefefffffcfcfafaf9f7fffffdf6f6f4
+fdfffefcffffedf4fac6d4dda2b5c397b2c39bbbd091b3cc7ea1b76e8a988ca2ad8599a453656f
+4e5c6548525b3b444be6ebf1ededf5fffefffffefffffdfff6f4f5faf9f7fffffdfefefcffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefbf6fffdf8fdfcfafefffff9fefff6ffffe0edf5acbdc7a9bdc8a8becb9db4c28da4b288a2af
+8ca6b3859fac7b919e52646e6d7c83424f55727b80fbfffff8fcfdfbfbfbfffffbfffef9fffef9
+fffefafffefafefefefdfffefdfefffbfffffcfffffbfffefbfffefcfffffefffffefffffbffff
+f9feffdde4eaa9b4baa5b3bc9cb0b994acb87d9ba67a9aa77e9bab7c91a4596a7c5f6c7c59666f
+697277f5fafdfcfffffefffdfdfffcfafefdf8fefef5ffffe3f0f8adbec8a2b2c19fb4c598b5c5
+82a1b37e9bab8ba5b46a808e5264725e6c77414b54a8adb3fcfffffffffff1f0eef7f3f0fffcf7
+fffefaeee9e3f4efebfffefbfffefff6f7f9f4f9fdebf4fbcad6e297a7b48fa2b18da2b390a3b4
+8598a78699a88194a26b7d8b6879837c8b90263435f8ffffebf5f6f8ffffc2cdd3b0bec9a7b9c7
+a2b9cb8da6ba7891a58aa4b5869caa71828c727f85606b6f636e72f4fffff9ffffdde2e5f5f9fc
+f9fafcefefeffefefefefefefffffff8faf9f1f5f4fbfffff8ffffebf5f6e9f9f9a3b8bd8fa8af
+93abb597afbb89a1ad809aa75269774e64716e828d41525ceef8fff9fffffefffffbfaf8faf5f2
+fffffbf8ffffcfdfdfadbfc3a1b4bab1c5ce94acb8859caa88a2af8ea5b37d93a0677983505f66
+687377384042eff3f4f9fbf8fdfcf7fcf9f2fffff8fffff8faf9f4f7f8f2f4f6f1fcfffdecf5f4
+b1bcbeb1c0c5a8bbc2a6bcc794afba819da97b97a57389975466746a78854a5760a7b0b7fbffff
+fcfffffafbfdfcfcfcfafbfdfbfffff9ffffedf7ffb5c1cda4b4c1a6b6c5a4b4c499aaba91a0b3
+8e9faf8fa0b08d9eae899aaa8699a88da0af8fa2b1768c9a92a9b78ba2b0809aa988a2b189a0b0
+8ba2b28ca3b38ea3b68fa4b590a5b692a5b492a4b293a3b09ba9b486939c616e77525c65828c95
+6c757cf8fffffbfffffefefefefefef9fdfef8fffff4feff9daeb896a9b79ab0be94abbb839dac
+869dab8ba1ae8fa1ab7f90976e7d827f8a8e5a5f63bfc0c4fffffff9f9f9fbfaf8fffffdfcfcfa
+fbfdfcfcffffdbe4e9b0bec79fb5c29eb9cc96b6cb84a8c0789baf819ba88da1aa6a7c8651626a
+4e5861333c43989da3fcffffedecf2faf9fefffefffffdfffbf9fafcfcfcfefefefdfdfdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffbf7fdfaf5fffffdfafcfbf9fffff5ffffcedce5aabcc6b0c4cfaec4d19cb3c18aa1af8ea5b3
+94abb9859da971879254676e7382893f4c52bbc6c8f9fffff8fcfbfcfcfafffffbfffef9fffef9
+fffefafffefafefefefdfffefdfefffbfffffafffffafffefbfffefcfffffefffffefffff9fdff
+f6fbffcfd6dcaab5bbacbac39eb2bb93abb7839fab84a1af829fad758a9b5c6d7d606e7b515b65
+929ba0f7fcfffcfffffefffdfbfffcf5f9f8fafffff5ffffdae7efa6b6c3adbdcca0b5c698b5c5
+82a1b37c99a987a1b05f72814959665f6c753a434aeceff4f7f8fcfaf8f9fffefbfffefaf7f3ea
+fff9f1fdf6eefff8f2fffef8f8f4f1f4f4f4fcfffff9ffffdfe9f397a5b097a9b796a9b897a8b8
+8b9cac8a9bab8597a570808f6d7e886c7b804d5b5cf3fdfeeef8f9e8f3f7b8c5cbb1bfc8aabcc8
+aabfd097b1c2849eaf8da4b27a8e996d7c83717c7e3f4a4c909ea1f4fffff0fbfff8fffff5fdff
+fafffff3f7fafdfeffeff0f2fbfffffbfffff3fcfbf5fffff5fffff4ffffebfdffafc4c998afb7
+9db4bca1b9c38ba3af7e96a25068744e6471687a8664727bf4fdfffbfffffbfbfdfffefbfff9f6
+fffefbf5fffec4d4d4acbec2acbfc5b2c6cf92aab68aa1af8da7b489a0ae798d9863747c536066
+5761637e8786ebefeefefffbfffff8f8f8eefefef4f9f9effbfbf1fffff6f5f8eff8fff8ebf6f2
+b1bfbfafc1c39db5b994afb687a5af84a4af90adbb687e8c596978707e8b404a54ced5ddf8fdff
+f3f7f8f6f8f7fefffff4f8f9fbfffff8ffffdfecf4aab8c3afbfccaabac99eaebd9aaab995a2b3
+8f9fae91a1b092a4b28ea0ae8799a78ea1b07487966e8394778e9e6f89986984956c87986a8596
+6d87986c86976e84996d84966d82936f82916f82917082906676834c5a654a5863424f58717b84
+8c969feef8fff6fdfffefffffdfdfbfbfcfef8fffff5ffffa1afba9aacba9cb2c098afbf89a0b0
+8ba1af90a6b194a6b083949b6f7e837f8a8e666b6facadb1fffffff8f8f8fffffdfdfcfafefefc
+fbfdfcf4f9fccad5d9a9bac2a4bcc8a1bed08cafc37da3ba7fa2b690a8b48a9da442535b4e5d64
+545d665a6169eff2f9eff0f5fffefff6f4f9f3f1f4fcfafdfffffffefefff4f4f6feffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffcf8fcf9f4fffffdf5f9f8f9fffff4ffffc1cfd8a9bbc7b6c9d7b4cad79fb5c38ba1af92a8b5
+99acba8397a2697b854c5d645e6d723f4d50e4eef0f7fcfff4f8f7fffffdfefdf9fffef9fffef9
+fffefafffefafefefefdfffefbfffffbfffffafefdfafefdfbfffefefffffefffffbfffff8fcff
+f4f9fdc4cbd1a8b3b9aebcc59eb0ba93a9b489a1ad8aa6b287a1ae6f82915f6f7e66727e525c65
+b4bbc1fbfffffcfffffafcf9fbfffcf1f7f5f9fffff6ffffd3e0e8a2b3bdb3c5d3a1b7c59cb7c8
+86a3b57d97a8869dad5d707e54626d78828c535a62fafdfff8f9fbfffffdf8f4f1fbf6f2fef9f3
+fffef8fff9f1fffaf4fffbf5fcf8f5fffffdfcffffeef5fbdce9f1abbcc49badb99aacba9aacba
+8d9fad8d9dac8999a675839074818a646f73778284e9f3f4f8ffffcfdadec1ced4adbbc4aebecb
+9fb2c199aebf8ea4b294aab781939d86959c939ea24d585ad6e3e9f4ffffeaf7fdeffafff8ffff
+f2f9fff2f7fbf8fdfffbfffff5fafef9fffff8ffffeef9fdf0fefff2ffffe0f2f6b9cdd4a0b7bf
+a8bfc7abc2ca8ea4af80949f54687155677166747d818c92f9fffffcfffff6f6f6fffffdfffefb
+fefdfbf3fbfdbfced1aabcc0b6c9cfb0c2cc97abb68da3b096acb98da1ac7e909a6172796a787b
+465051bac3c2f7fbfafcfef9fffff8fafaf0fffff6fdfdf3fdfff4fefff8f9fcf5fbfffbdbe6e2
+afbdbdb6c8caa7bcc1a5bec59fbac38fabb786a0ad5b6d7b5b6976707d863e4750e9f0f6fcffff
+f8f9fbfefffffefffff4f5f7fbfffff9ffffdae4eda8b5bebdcbd6b4c2cfa6b3c3a4b1c19dabb8
+94a2af93a1ae94a5af8d9ea881939d81939d586c75617580657b88526977657c8a506a79566d7d
+566b7c546a7854677852657451637151637152626f52626f495762404e59525f685c697268727b
+c8d3d9e9f2fbf9fffffffffdfdfef9fafcfbfafffff7ffffa2b0b99cacb99fb2c09db3c18ea4b1
+8fa5b095a9b297a8b084969a6f7e817e898b7075789d9ea0fbfbfdf9f9fbfffffff3f3f3fcfefd
+fafeffdfe7eac0cbd1abbcc4afc2d0a4becd8daabc82a2b78facbe879ba66f7e854b5860455056
+475057acb1b7fcfffffefffffffefffffefffffefff7f5f6fdfdfffffffffcfcfcffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffdf6fdfcf7fdfffcfbfffff2fbffecf9ffb8c9d3b2c4d0b4c7d5b5c8d7a2b5c393a5b39babb8
+9fadb886939c6a777f667177636e72656e73edf5f7f9fdfef8faf9fffffdfbfaf6fffffbfffffb
+fffffbfffffbfffffffefffffbfffffafefffffffdf7f7f5fefefcfefffffbfcfefcfffffbffff
+eaf1f7bfc8d1acb6c0b2c0cba4b4c192a4b28fa2b0889baa93a6b4677882626f78727c854a5358
+c6cbcef9fdfefefffffefffdfbfffef8fefcf6fefff6ffffcad9e0abbcc4b7c9d5a6b9c89eb5c7
+879eb08499aa8a9dac5b6b7863717a525c65899297f8fdfff9fdfefbfdfcfcfcfafdfcfafffbfa
+fffafafffbf8fefbf6fdfef8fefffbfbfffff8fffff3ffffd6e8ecafc2c9a2b6bfa9bdc89fb1bd
+92a2af92a0ad96a2b0707988929aa5575e64a0a8aaebf3f6f7ffffd2dde1b6c1c7b3c0c9b4c2cd
+a4b4c19eaebb97a7b48e9eab97a8b28d9ba4909da56b7880bbc8d0c4d1d9bdc7d0c7d1dac5d0d6
+bdc6cdd0d9e0d1dae1d0d9e0d0d9e0d0d9e0d0dbe1d0dbe1d1dce2cfdce2cfdee5bbcfd8c0d6e1
+a1b8c090a4ad9bacb47e8d945d6a706d767b4f575aaaafb2fefffffefffff3f3f5fffffff8f6f9
+feffffeaf1f7c4cfd5b2bfc5b9c8cfb1bfc89daeb896a8b299abb596a7af7081885160656a7879
+323c3be6efecf9fffbfefffbfdfcf8fffffafffefafcfbf7fffffbfefffbfbfdfafafffed6dee0
+bec8cab6c3c9b5c4cba6b4bf9cacb998aab88d9daa6270796b767c636c7370777df7fcfff3f7f8
+fefffffcfefdfffffff9fafcfefffff9fcffd6dde5b8c1cab4bcc7b9c3cfa4b0bea7b3c1a1adb9
+99a6afa1aeb699a8ab8393937e8e8d6b7b7a6d807e71838365777b73868c6a7d846d7f896c7d87
+717e87717e86727c86727c85727c85727c85727c85717b847d868d6f787f707980656e755a636a
+d3dce1f7fefffafffffffffbfcfbf6fbfcf7fcfffff1f9fbafbdc0a0afb6a1b4bba2b6bf97abb4
+8fa3aa97aab09aacb0879797798787808c8a7d83838b8c8efcfdfffefffffafefffcfffff6fbfe
+eff7fad1dae1b6c0c9b4c1cab4c5cf9caebc92a5b495abb98ea1af87949c606970545d6450595e
+62696fecf1f5fcfffffdfefffefffffffffffffefffffffdfffefffffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fdfdf5fbfcf6fbfdfafbffffeffafee7f6fdb8c9d3b3c5d1b7c9d7b5c7d5a3b5c397a7b4a2aeba
+a2acb58790976b747b7a8388535c619da5a8f3f8fbfcfffffafcfbfffffdfffefafffffbfffffb
+fffffbfffffbfffffffefffffdfefffcfefdfffffdfbfaf8fefefcfefffffbfcfefbfffff8fdff
+e2ebf2c1cad3b1bec7b8c4d0a8b6c395a5b496a6b58fa1af96a6b3738089626d73717a814b5356
+e3e7eafcfffffefffffbfdfafefffffafffff6feffeffafec5d4d9adbec6baccd6abbecca0b3c4
+90a2b68e9faf7686955866736b7881465157b7c1c3f7fffff9fffffcfefdfcfefdfefcfdfefcfd
+fffcfdfefdfbfcfbf7fefffbfafffbf4fdfaf7fffff0ffffd0e3e7b0c5caa5b9c0a9bdc6a0b2be
+96a6b393a1ae959fab78808d979ea840454bc1c6c9fbffffeef6f9c5ced5b7c2c8bfc9d2b1bec7
+a7b3bf97a5b0a5b3be9fadb8a0aeb99dabb6909ea788959e9ea8b1aab4bdadb7c0b2bcc5afb9c2
+abb5beb5bfc8b7c1cab6c0c9b6c0c9b7c1cab9c3ccb9c3ccbac4cdbac4cdb6c4cdc1d5e0b5cbd6
+9fb3bc9baeb599a8af707b7f5b63667b8083474b4cd5d6d8fcfcfcfffffff8f8fafffffff9f8fd
+feffffe5ecf2c6cfd6bac4cdbfc9d2b4c1caa2b0b99eacb5a0b1b891a0a76e7b815b696c748080
+414b4aeff8f5f8fefafbfffcfdfcf8fffefbfffffdfdfcfafffffdfefffffafefff8fefed4d9dd
+bec5cbbec7cebdc7d0aab4bea4aeba9eaab888929e646f757c86884e5659a2a7aafcfffff8fcfd
+fefffffefffffffffffdfdfffefffff6f9fed6d9e0bcc0c9b8bfc9bcc4cfacb5c499a5b3a6b2be
+a3b0b8a3b1b493a1a17988856b7a7534433c51625a63726f5161604c5a5d46555a4f5c64546169
+5a636a5c63695c63695e656b5f666c60676d61686e62696f656c725a61676a717770777d777e84
+d4dbe1f1f8fefcfffffffffafcfcf4fcfdf8fcfffdf4fdfcb7c2c4a7b6bba8b9c0a7bac19db0b7
+94a7ad9caeb2a0afb28d9b9c7e8c8c86908f7c82828f9190fefffff9fdfef5fafdfbfffff1f8fe
+e2e9efc5ced5bbc5cebfc9d3b1bec7929eaa8e9ca998a6b3909ea97079804a5157555c6241484e
+e0e5e9f8fdfff8fcfffcfffffefffffffffffffffdfffffdfffffdfffffdfffefbfffffbfffeff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefdf8fcfdf8fafcf9fbfffff1fbfde3f0f6bdcbd4b8cad6bbcddbb5c7d5a5b5c49fadb8aab4be
+a3acb5838c936a7179868f94394247d9e1e4f5fafdfcfffffcfefdfdfcfafffffdfffffbfffffb
+fffffbfffffbfffffffefffffdfffefcfefdfffffffefcfdfffffffdfffefbfcfefbfffff3f8fe
+d9e2e9c2cbd4b9c6cfbcc8d4a8b6c197a7b49cacb996a8b492a2af6f7c856871786b727a5f6468
+fcfffffdfefffffffffcfefdfdfffefcfffff9feffe6eff4c0cdd3b2c3cbbed0dab0c3d199acbd
+97a8ba96a7b7657582586671717e86414c50e7f1f3f7fffff9fffffcfefdfcfefdfefcfdfefcfd
+fffcfdfefdfbfbfaf6fefffbf6fbf7eef7f4f7ffffedfcffcbdde1b4c9ceb0c4cbadc1c8a5b7c1
+9fb0ba94a2ad919ba7818996969da72a2f35d3d8dcfbffffdee6e9c2c9d1bbc4cbc7d0d9b4bec7
+a8b2bc9ca9b2a3b0b9afbcc5a5b2bba1aeb79aa6b29eabb4939da69fa9b2b1bbc4afb9c2aeb8c1
+b6c0c9b4bec7b6c0c9bdc7d0bfc9d2c1cbd4c3cdd6c4ced7c4ced7c3cdd6c0cdd6c1d3dda8bcc7
+9eb0baa8b9c197a4ac626d715860638085883e4243fbfdfcf9f9f9fbfbfbfdfffefcfefdf9fafc
+fcffffdbe2e8c6cfd6c0cad3c3cdd6b4c1c9a5b4bba4b3baa9b8bf8a979f6a777d6d787c727c7d
+6c7574fafffef9fffbfbfdfafdfdfbfffffdfffffdfffefcfffffffefffffbfffff4fafacfd4d8
+bec5cbc6cfd6c4cdd6abb5bfaab4c0a2abba7c8692616a71858d90363e41d7dcdffcfffffafbfd
+fdfdfdfdfdfdfefefffdfdfffefffff1f4f9d3d6ddc0c4cdc0c7d1c3cbd6adb7c399a3afb2bcc6
+a6b1b795a0a4828e8e6b77753b47432d3a33707f78a8b4b2bbc9c9bfcaccc7d4dac6d0d9c7d2d8
+c3cad0c5cacec6cbcfc8cdd1c9ced2cacfd3cbd0d4ccd1d5d6dbdfc8cdd1d5daded2d7dbd8dde1
+f9fefffbfffffcfffffffffbfcfcf4fcfdf8fcfffff6feffbec9cdb0bdc3afc0c7afc0c8a4b5bd
+9cadb4a0b2b6a5b4b794a2a38792948d9798818787929697fcfffff9fdfef6fbfefbffffedf4fa
+d5dce2c1cad1bfc9d2bfc9d3a9b6bf939fab98a6b19eacb78c99a250596071787e3e43477e8387
+fbffffeef3f7fcfffffafefffefffffffffffffffdfffffdfffffdfffffdfffefbfffffbfffeff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffffbfefffafbfdfcfbfffff4feffdfeaf0c2d0d9c2d0dbbecedbb5c5d2a7b5c2a6b2beb0b9c2
+a2a9b18188906a717781888e30383bf7fcfff9fdfefafcfbfbfdfcfdfdfbfffffdfffffbfffffb
+fffffbfffffdfffffdfffffffdfffefcfefdfefefefffefffffffffcfcfefefffffcffffeff4f8
+d5dce2c2cbd2c1cbd4bcc9d2a7b5be9aa8b39fb0ba9bacb68b99a45f69727a81895a5f658e9196
+fefffff4f5f7fafafafffffffbfbfbfcfffffaffffdde6ebbdcad0bbc9d2bfd1dbb2c4d096a6b6
+9dadbd95a5b46775825f6c756f7982576065f9fffff9fefffafefffcfefdfdfdfdfefcfdfefcfd
+fffcfdfefcfdf9f9f7fefffdf6faf9eef7f6f7ffffebf9fcc6d8dcb8cbd1bacdd4b0c3caa7b8c0
+a6b4bd939fab86939c86909a888f993d4248e0e3e8f8fbffd9dee2d1d6dcbcc3cbc5ccd4b9c2c9
+a9b2bbacb6bf9ba5afb5bfc9a0adb696a3ac9ba7b393a0a9a8b2bbadb7c0c0cad3b5bfc8b6c0c9
+c6d0d9bac4cdbbc5ceb9c3ccbbc5cebec8d1c0cad3c1cbd4c1cbd4bfc9d2bcc9d1adbec893a5af
+8e9fa792a1a879848a545d62595e62767a7b565857fefffff8f8f8fdfdfdfefffffefffffafbfd
+f8fcffd1d8dec6cfd6c6cfd8c4ced7b4bec7a8b5bdaab7bfacb9bf8590966974787d8789586062
+adb3b3fbfffefcfffdfefffdfefefcfefefcfffffdfffffdfefffffefffffbffffeef2f3cfd4d7
+c2cacdcdd4dac7d0d7adb5c0aeb8c4a4aeba757d88656c7283888b3f4447f4f8fbf9fafcfcfdff
+f9f9f9fcfcfcfbfbfdfdfdfffcfdffecedf2d0d3dac6cad3caced9c8cfd9a6aebba7b1bdb8c1ca
+a0a9b0858f917680816f7978202b27ccd7d1f0fbf5f8fffff8fffff5fffff8fffff2fbfff3faff
+fbfffffbfffffbfefffafffffafdfff9fefff9fcfff8fdfffcfffff5fafdfcfffff0f5f8fcffff
+f9fefff1f4f9f4f5f7fffffbfdfcf7fdfdfbfcfffff7ffffc4cdd2b7c4cab5c4cbb6c4cdacbac3
+a3b2b9a6b5bca9b6bc9ba6aa8e979c949c9f858a8d909495fcfffffbfffff7fcfff7fcffe3eaf0
+ced5dbd0d9e0c1cad1b2bbc4a5afb9a2acb6a6b2be97a3af7380893e474e636a7044494debf0f4
+f2f7fbf9fefffcfffff8f9fbfffffffffffffffffdfffffdfffffdfffffdfffefbfffffbfffeff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffffdfefefcfbfdfcfcfffff6feffd8e1e6c7d1dac6d3dcc2cfd8b5c2cba9b3bdadb6bfb4bbc3
+a1a6ac80858b707579767b7f4c5154f8fdfffcfffff8faf9fbfdfcfffffdfcfcfafffffbfffffb
+fffffdfffffdfffffdfffffdfdfffefcfefdfdfdfffffffffffefffcfbfffefffffcffffebf0f4
+d4dbe1c5ced3c6d1d7bcc7cda8b5bd9eacb5a3b4bc9daeb6818f985960688c8f9645484fc7c8cd
+fcfdfff7f7f9fcfafbfffffff8f8fafefffff9fdffd8dfe5c1ccd2c4d1dac0ced9b1c1ce9dabb8
+a4b2bf8896a16e7b84667079606970889196f9fffff9fefffafefffcfefdfdfdfdfefcfdfefcfd
+fffcfdfefcfdf8f8f8fefffff9fdfcf2fbfaf8ffffe9f4f8c6d5dabdcfd3bfd0d7afc0c7a4b5bc
+a7b6bd909da6808d958d97a07079806e7379f7fafffafdffdde0e5d7dadfbdc2c8c3c8cebcc1c7
+b1b5beb0b7bfa9b0baafb8c197a1ab959fa987919d7b858f7e87907a838a828b92717a81727b82
+828b92737c83717a817a838a7b848b7e878e818a91828b92818a917f888f7d87906e7b8465737c
+64717a606a73525b62565e61686d70727677959796fcfefdfafcfbfefffff6f8f7fefffffafefd
+f4f8f9ccd3d9c9d0d8cbd2dac4cdd4b4bdc4adb8beafbac0acb7bd7e878e6c737981898c404548
+e8ecedf5f7f6fefffdfefffdfffffffbfdfcfffffffefffffcfefdfefffffafefde6eaebd2d6d7
+cacfd2d1d6dac4cbd1adb4beb0b8c3a2aab5727b84767b81777b7e6f7376fcfdfff7f8faffffff
+fdfdfffffffffcfcfefffffffafbffe5e6ebcccfd6c9ced4cdd1dac3cad4a4abb5b3bcc5b3bac2
+9fa6ac889093747c7e7c8584464f4cf9fffdf9fffdeaf3f0ecf5f4eaf0f0f8fdfff5fafefbffff
+fcfffffcfffffefffffafefffbfcfff7fbfcf8f9fdf6fafbf8f9fdf7fbfcfeffffedf1f2feffff
+fcfffffefffffefffffffffdfffefafdfdfbfbfffff8fdffc8cfd5bdc8ceb7c4ccb9c6cfb1bec7
+a7b4bdaab4bdaeb7bea1a8ae949ba1999ea2888c8f888c8df3f9f9fbfffff7fcffeaeff2d7dfe2
+ced5dbdbe2eabec7cea8b1baa6afb8aab3bca0aab47d879158626b72797f404549999ea2fbffff
+edf1f4fcfffff4f5f9fefffffffffffffffffffffdfffffdfffffdfffffdfffefbfffffbfffeff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefefcfdfdfdf9fafcfafefff7fcffced6d9c7d0d5c9d2d9c5ced7b5bec5aab1b9b1b8beb6bbbf
+9c9fa4818286787c7f707477818586f8fcfdfcfffffefffffbfdfcfffffdfbfbf9fffffbfffffb
+fffffdfffffdfffffdfffffdfdfffefcfefdfdfdfffffefffdfcfffcfbfffffefffbfcffe4e8eb
+d7dcdfcbd3d6cad4d6b9c2c7acb7bba6b3b9a8b7bc9eadb477848a696e748c8d924a4b50efeef3
+fafafcfffefffffdfefcfafbf8f6f9fcfcfef5f9fcd5dadec6cfd6ccd6dfbdcad3b1bec7a8b2be
+aeb8c27a848e6e78816e777e52595fc2cacdf8fdfffbfffffdfefffefefefefefefffdfefffdfe
+fffdfefffdfef9f9f9fefffffcfffff9fffff8ffffe3edefcad5d9c4d2d5c6d5dab2c1c6a7b6bb
+acb9bf94a1a784919798a3a9596267979ca0fefffffeffffd8d9ddcacbcfc0c1c5c8c9cdbbbcc0
+b6b9beabaeb5bdc1caa5acb689929b8c96a06c7680717984838c937f888d80878f757e83798088
+838c9180878f7d868b787f877881867b828a7b84897d848c7b84897b828a79828967717a727c85
+78818a6d767d656c7271767a73777a636768dbdddcf7f9f8fefffffefffff0f2f1fefffffcffff
+eef2f3ced3d7ced3d9ced3d9c3c8ceb3bac0b2b9bfb2b9bfa7aeb4797e8471767a7a7e814c5051
+fefffff0f2f1fdfdfbfffffffefffff9fafcfefffffefffffafcfbfefffffafcf9dce1ddd4d6d5
+d1d5d6ced2d5bec3c7b0b4bdaeb5bd9aa1ab72798182858a666769a8a9abf8f9fbf8f8faffffff
+fffffffffffffffffffffffff9fafedfe0e5cbccd1cdd0d7cccfd6b9bdc6b1b5beb9bdc6acb1b7
+9ea3a78f94977377786a6e6d8d9190f0f5f1f6fbf7f5f9f8fcfffffcfffffafefff4f5f9fdfeff
+fcfdfffcfefdfdfdfffbfdfcfcfcfefafcfbfbfbfdfafcfbfafafcfdfffeffffffeceeedfcfcfe
+f8faf9fefefff8f8f8fffefcfffffdfdfdfdfbfcfef8fcffced3d9c2cbd2bcc5cebdc7d0b5bfc8
+abb3beabb4bdb1b5bea5aab09a9da49da0a58a8e8f888c8df6fafbfbfffff5fbfbe1e6e9d4d9dc
+d3dbdeced3d9b8bfc7abb2baadb6bfaab1bb8f98a16d767f58616a63686e6c7175ecf1f5f0f5f8
+f0f4f7f7fbfefefffffafbfdfffffffffffffffffdfffffdfffffdfffffdfffefbfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fdfdfdfcfcfcf9fafcfcfdfff9fdfecaced1c9ced2cbd0d4c8cbd0b7babfacafb4b5b9bcb7b8ba
+999a9c8181838282846b6c6eb0b2b1fefffffcfefdfffffff8f8f6fffffdfefefcfffffdfffffd
+fffffdfffffdfffffdfffffdfefefcfdfdfdfffdfffffefffcfafffdfbfffffefff2f2f4dddddf
+d9dadcd2d6d7ccd2d2b3bbbdadb7b8adb8baa9b7ba9ba9ac6e797d7d808579787e717076fffeff
+f9f7fafffdfffffdfefaf8f9fbf9faf8f8faf1f2f6d1d4d9cbd0d6d1d8e0bbc4cbb2bcc5a8b1b8
+b3bcc3737c836970767d848a52575beaeff3fbfffffbfffffdfefffefefefefefefefefefefefe
+fffdfefffdfefcfcfcfdfffefcfffffbfffff0f5f8dbe3e5cdd7d9cbd5d7cdd8dcb7c2c6a9b4b8
+adb8bc95a0a48590949aa3a83b4346c6c9cefafbfff4f3f8d0ced1c1bfc2c7c5c8cbc9ccb6b4b7
+b1b0b5b2b1b6afb0b59a9da4767d855c656e7078837b848d747b81798184787d837b83867f848a
+7e8689898e94878f92878c92858d90888d93868e91888d93868e91878c92858c927b8288858c92
+868b91797e8272777b74787b6c7071616264fcfefdf8faf9fdfffcfcfefbf8faf7fafcf9fefffd
+e3e5e4ced2d5cfd2d7cbced3bcbfc4b0b3b8b4b7bcb0b3b89ea1a675787d7a7e816d6e72848587
+fefefef7f7f7fcfafbfefefefefffff6fafbfcfffffcfffff7f9f8fefffdf8faf5d6d8d3d1d1cf
+d5d7d4cacccbb7bbbcb3b6bbabb0b690949d74777e86878b575759cfcfd1fbfbfbfdfbfcf5f3f4
+fefcfdfffefffcfcfefffffff5f5f7d9dadecacbcfd3d4d9cecfd4b2b5bab7babfb7babfb0b4b7
+8d9192888c8d7d7f7e494b4acdcfccf9fbf8fefffdfefffdf7f9f6fefffff8faf9fafafcffffff
+fffffffffffdfffefffffffdfffefffffffdfffefffffffdfefcfdfefefcfffdfef9f9f7fffeff
+fcfcfafffefffffefcfefdfbfffffdfdfdfdfafbfdf9fdffd2d7ddcaced7c1c8d0c0c7cfb9c0c8
+b0b4bfaeb2bbb4b4bca9aaaf9f9ea4a2a1a6898b8a8e908ffdfffefcffffedf1f0dbdfe0d3d7da
+d5dadebcbfc4b7bcc2b3b8beafb6bea4a8b1818890636a725c6069353a3eaeb2b5fcfffffcffff
+fefffffefffffefffff3f4f6fffffffffffffffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefefefefefefafcfbfefffffefefecbcbcbcdced0cfd0d2cacaccb8b8b8aeaeaeb8b8b6b7b6b4
+98979582817f888785646462c6c8c5fffffff0f0eefffffdf4f4f2fcfcfafffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfefefcfdfdfdfffefffffefffbf9fcfdfbfefffeffeceaebd6d5d3
+d9d9d7d4d6d3cacfcbafb3b2adb6b3afb9baa9b5b598a4a466707188898e6463689d9ba0fffeff
+f8f3f7f7f3f4fefafbfffcfdfffcfdf7f5f6eeeef0d1d1d3cfd0d4d5d8ddbbc0c4b5babea3a8ac
+b6bbbf777c80676c708f9396585c5ffbfffffefffffdfefffdfefffefefefefefefefefefefefe
+fffdfefefefefefefefafcfbfefffffeffffe9edeed8dcddd2d8d8d1d7d7ccd4d6b5bdbfa3adae
+a6b0b18c96977b85868d97991b2325f8fcfff7f7f9e6e4e7d1cdcec7c3c2cec8c8c7c1c1aea8a8
+a9a3a3c4c0c18d8b8e919297696c73232a32868d9789909a868b9192979b8d92969a9fa3969b9f
+8b90949ba0a49a9fa3999ea2999ea2999ea2989da1989da1989da1979ca0979ca09a9da29a9da2
+94979c969a9dabacb0c3c4c6dbdcdef1f3f2fbfdfcf8faf7fafcf9fcfefbfefffdf7f9f4fefffb
+d6d8d3cfcfcfcfcfd1c8c8cab7b7b9adadafb4b4b6aeaeb097979978787a848486656567bababa
+efefeffffffffdfbfcfbfbfdfefffff5f9fcfcfffffcfffff6f8f5fffffbf8f9f3d4d4cccfcec9
+d7d6d1c7c8c3b5b5b3b6b7b9aaabaf8a8b90747579878789515153e2e2e2fffffffffeffedebec
+fffdfefefcfdf7f7f7fbfbfbf1f1f1d6d6d6cbcbcdd9d9dbd2d2d4b3b3b5b2b2b4b5b5b5bdbdbd
+7d7d7d8181819494923c3c3af8f8f6fbfaf8fffffdfffffdf1f1effffffffffffffffffffdfdfd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfcfbf9fdfcfafffffdfffffd
+fcfbf9fffffdfffefcfdfcfafffefffdfdfffafafcfcfdffd6d9decfd2d9c7cad1c4c7cebdc0c7
+b3b3bbb1b2b7b6b4b9adabaea49fa3a4a2a381817f8e8f8afefefcf7f7f5e1e3e0d4d6d5cfd0d2
+d0d1d3babbbfbbbec3b6b9beabaeb5989ba27478815659624c4f5695989dd9dde0fcfffffcfdff
+f6f7f9f4f5f7f6f7f9fefffffffffffffffffffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fcfefdfbfdfcfdfdfdfffffdfbfaf8cbcac8c7c3c0c9c5c2c6c1beb4afabaaa5a1b3aea8aea9a3
+8e8983817c78928f8a53524ed8d9d4f4f3f1fefefcfffffdf9f9f7f8f8f6fffffdfefefcfefefc
+fffffdfffffdfffffdfffffdfffffdfffffdfefcfdfffefffefafbfffdfcfffdfae6e2dfd1cec9
+d9d6d1d6d5d0bdbeb8b4b5b0bcc1bbb2b8b6a0a9a68a94935f68678d8e924a484dd6d1d7fffcff
+fff9fdfef8fafffcfefffdfdfffdfdfaf6f5d5d1d0d2cecdd0cecfd0d0d0b4b4b4b2b3b5b9babc
+9a9b9d7b7c7e78797b7172748c8d8ff7f8faffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffdfcfcfafffffdfafaf8dadad8cdcdcbd7d9d8dddfdea1a5a4cbcfceb4baba
+9da3a3959e9d959e9d747c7e676d6dfafbfdfefcffe6e2e3cbc5c5cbc3c1bcb2b0ccc3beb4aba6
+afa6a1a59d9a8781818c8a8d6e6f747b7e85ebf2fcf5fcfffafffffbfffffbfffffbfffffbffff
+fbfffffbfffffbfffffbfffffbfffffbfffffafefffafefffafefffafefff9fdfffbfcfffffeff
+fffefffefffffcfcfefbfcfefafbfdf9fbfafdfffefefffdfffffdfdfef9fdfef9fffffaf4f5ef
+d6d7d1cccbc7cecac7c7c3c0b3afacaaa6a3b3afacaeaaa9959190736f6e8884834b4746e9e7e8
+fffefffbf9fafefcfff8f8faf9fdfff7fcfff4f8f9fefffffcfdf8fffffae2dfd6d1cec5d1cdc4
+c9c5bcc2bdb7b1aea9b2b1afa4a2a379777a767477878586666465f7f5f6fdfbfcfffefff9f7f8
+fefdfbfffffdf9f8f6fffffde6e5e3ccc8c7d9d5d2dbd7d4c0bcb9afaba8b6b2afa4a09daaa9a5
+79787471706c858482484745fffffdfffdfcfffefcfffefcfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffefcfffffdfffffdfffffdfffffd
+fffffdfffefcfefdfbfbfbfbfffffffefefffefefffcfdffe3e4e8cacbd0cccdd2c9c8cdbfbec3
+b7b5b8b5b3b6b6b0b2b0aaaaaba2a3a5a09d94918c85857dfffff8e6e5e0d3d2cddddcd8c4c4c2
+c8c8c6aeaeaeb2b3b5bcbdc1a1a2a777787d70737a6b6b735c5d62c0c1c5fcfdfffeffffececec
+fffffffffffffafafafffffffffffffffffffffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fdfffefdfffefdfdfbfcfbf7f8f5f0cac5c1c5beb8c6bfb7c4bbb4b1a89fa89f96b3aaa1aea59c
+8d867c837c7497938a484540f1f0ecfffffbfbfaf6fdfcfafffffdfffffdfcfcfafefefcfefefc
+fffffdfffffdfffffdfffffdfffffdfffefcfefaf9fffcfcfffcf9fff8f5f5edeaded7d1d0c9c1
+d3ccc4cfc8c0bdb9b0b9b6afb7b8b2b4b6b19ba29b7a807c757b796f6f71636166faf5f9fffdff
+fdf7f9fffdfdf2ececfdf8f5fffefbf4ece9cbc3c0c6bebbc8c3bfcdc8c4b4afabb0aca9b3b2b0
+969593787775878684565553bcbcbcfffefffdfdffffffffffffffffffffffffffffffffffffff
+fffffffffffdfdfef9fcfbf6fffef9f3f0ebd5d2cdcdcac5d6d2cfd4d3cfafaeaac0c1bcafb1ae
+a5a7a48a8e8d9399974f5555b9bdbefefefefffeffdbd5d5c3bbb8c2b9b4b6aca3bfb1a8ac9e95
+b3a69eaa9f99877d7b9b9595605e61a0a1a6f4f9fffbfffffcfffffcfffffcfffffcfffffcffff
+fcfffffcfffffcfffffafefffafefffafefffafefff9fdfff9fdfff9fdfffbfcfefefcfffffeff
+fefcfdfffffffafafcfdfdfdf9fbfafdfffefcfefbfefffdfffffbfdfef9fefff9fffffaeeede8
+d2cfc8cac3bdcbc4bcc2b9b2ada69ea7a098afa8a2a49d97867e7b6e6663827d7a5b5653eae6e5
+fdfbfcfffdfefffdfffefefff8fcfff8fefef9fdfcfbfdfafefdf8fffff6d7d3c8cdc7bbcdc5ba
+c2baafb7aea5aca39aaaa39d9d9894706b687c7877767273918f90fffefffefcfdfffefffbfaf8
+fffefcfefdfbfdfcf8fffbf8dfdcd7c7c2bcd5cec8d2cbc3b8b1a9aaa39bbdb6aca29b93afaba2
+79746e77726e7f7a7776726ffffefdfffdfcfffdfcfffefcfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffefcfffffdfffffdfffffdfffffd
+fffffdfffefcfefcfdfbfbfdfffffffefefffdfdfffdfdffe2e2e4c8c8cacac8c9c6c4c5bebab9
+b6b1aeb3aeaab4aca9afa6a1aa9f99a59c959d968c888478f6f0e4d1cdc2d7d3cacbc6c0bfbcb7
+bab6b3b4b3b1aba9aac0bec1908f946d6c715f60654b4a529e9fa4ebebedfffffffffffff3f3f3
+fffffffffffff7f7f7fffffffffffffffffffffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fdfffefefffdfefffaf8f7f2f2ede7c5beb4bfb7acbeb4a8c0b4a6ab9f91a39789b0a496a9a091
+89807183796d9e968b3c382ffffffafffffaf9f8f3fbfaf6fffffbfffffdfcfcfafdfffefdfffe
+fffffffffffffffffdfffffdfffefafffefafffaf7fffaf7fffdf7f9f0e9e0d5cfd0c6bdcec1b8
+c8beb2bbb1a5b8b0a5bbb4aab6b3aab4b4ac8e918a646661797b78555557a09fa4fffefffdfbfe
+f2eeeffffdfdf6f1eefff9f6fffef8e9e0dbc0b7b0bfb6afc9bfb6cac0b7b3a9a0aea59eb2ada7
+88858074706d96928f474340edeceafffefffbf9fafffefffffefffffffffffffffefffffeffff
+fefffffffffdfffff7fffff6fefaf1e4e0d7cbc4bcc8c1b9cbc4bcc1bab2c2bbb5b5b0aa9c9994
+9596917f817e878c88343837ebedecf8f7f5fefaf7c6bebbb5aca5bcafa6b7a99eb4a296ab998b
+af9f92a4968b7c7269a19a94454140cacaccf6f9fefbfffffbfffffdfefffdfefffdfefffdfeff
+fdfefffdfefffdfefffcfdfffcfdfffcfdfffcfdfffbfcfefbfcfefbfcfefbfcfefefdfbfffefc
+f7f6f4fffffdf7f7f7fcfcfaf7f7f5fffffdfdfdfbfefefcfffefafffefafffffafcf9f2e3e0d9
+cac3bbc5bbb1c8bcb0bbada2a79b8fa69a8eac9f96958b8172685f7d746d7c756f8c8784f5f1f0
+fcfafbfffffffbfbfdfdfefff6fafdfafefffefffff6f7f2fffef7fffff4c8c0b3c6bdaecec2b2
+bcb0a0b0a496aa9e92a399909a8f8969605b8b8380575352c6c5c3fffffdfcfcfafffffdfafaf8
+fffffdfaf9f5fffffaf4f1ead5cec6c5bcb3cfc5bbc7bdb1b1a597a89f90b5ac9d999282a29a8d
+6f675c7c756d645d57b0aba8fff9f9fffdfcfffdfefffdfefefefefffffdfefffdfffffdfffffd
+fffefffffefffffefffffefffffefffffefffffefffffefffffdfefffefffffefffffefffffeff
+fffdfefffdfefefcfdfcfcfefefffffdfdfdfdfdfdfcfcfce2e1dfc5c4c2c5c1bec3bebabbb4ae
+b2a9a2b0a89dafa59baba195a79b8da4988aa59989968d7cd5c9b9c1b8a9cbc3b8bcb3aab0a9a1
+ada6a0b3aeaaaea9a6a4a0a185838665636851505557545be6e5eafffefffffffdfaf9f7f9f8f6
+fffefcfcfbf9f9f8f6fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fbfdfcfffffdfffffaf9f6eff1eae0c0b8abbaaea0b7aa99bdae9ba89984a0917eac9f8ca79a87
+867b698276669e95863c352bfffcf6fef9f5fefbf6fefdf9fdfcf8f9f9f7fffffdfdfffefdfffe
+fffffffffffffffffdfefefcfffefafffdf8fffdf7fffaf3fffaf1eee4dacdc1b5c4b6a9cbbbac
+c3b3a4b0a393b3a799b2a89cb2aca0a7a39a7f7f7766675f71726d535355e4e4e6faf8fbfaf8f9
+f5f1f0f5f1eefffdfafff9f3fffdf6d9cfc6b8aba2c2b6aacdbfb2bfb2a2ab9e8eaa9e90afa69d
+7a736b77706a8e89855f5a56fffefbfdf9f8fffdfefffefffffefffffffffffffffefffffeffff
+fefffffffffbfffef5fffff3f6f0e4d5cdc2c1b7adc4bab0c5b8afb7aaa1beb4abbbb2ab9c958f
+8b8883868580696b66686a67fdfffcf7f6f2fcf7f3b6afa7aca298b7a99cb9a898ac9988ac9786
+a794859684767a6c619e958c332e2ae9e9e7f7fbfcf9fdfffcfdfffcfdfffcfdfffcfdfffcfdff
+fcfdfffcfdfffcfdfffdfefffdfefffdfefffdfefffdfefffcfdfffcfdfffdfdfdfffefafffbf8
+f4f3effffffdf7f7f5fcfcfaf4f4f2fffffdfefefcfffffdfffefafffffafffff8f7f3ead7d3ca
+c2baafc3b6a6c6b5a3b5a492a59484aa9a8aab9b8c8b7d70675b4f8d83795d544dc8c0bdfffdfa
+fcfafbfefffffafbfffbfffff3f7faf9fdfefffffdf3f2edfffef5fdf5e8beb2a2c4b7a6ccbdaa
+b8a996ac9c8cad9d8e9f918493857a685b538e857e403c39e9e9e7fffffdf9f9f7fffffdf7f8f3
+fffefafdfcf7fffff8e9e5dac9c1b6c2b9aaccc0b0c1b4a3b1a28fafa08ba398829e937f877c6a
+675e4f867c72453c35e0d8d5fffaf7fffdfcfffdfefefefefdfffefdfffefbfffcfbfffcfdfffc
+fffffffffffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffdfe
+fefefefefcfdfdfdfdfcfdfffefffffcfcfcfcfcfafdfcfae2dedbc2bfb8bfbbb2bfb8aeb5ada0
+ada495aca090ada08fa99c89a79883a59681a79883aa9b86b0a18cc0b19eb7aa9ab8ac9ea0968a
+aaa097ada49da8a09d827c7c6c6869706b6f47454aafacb3fffefffdfbfcf5f4f2f6f5f3fefdfb
+fffefcfcfbf9fcfbf9fefdfbfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+f9fbf8fefffafffff8fefaeff3ebdebdb4a3b4a794b5a490bdab93aa997fa19178ad9d84a79881
+887c648377619c917f4a4237fbf4ecfffbf5fffdf8fffefafbfaf6f9f9f7fefffffdfffefdfffe
+fefffffefffffefefcfefefcfefdf9fffcf7fffef4fff9effef2e6e5d7cac5b5a6c0af9fc7b4a3
+beac98ac9b89ad9d8da79a8aaba29391897e736f6476736c61605b787878fefffff8f8fafffeff
+fffefdfaf6f3fffef8fcf3ecfffcf2ccc0b4b0a295c2b2a3c9b8a6ae9c88a3917dac9b899d9183
+756d62837a716b645c948d87fffefaf9f3f3fffefdfffefffffefffffffffffffffefffffeffff
+fefffffffffbfdf9edfff8e8e8e1cfc8bfaebfb3a3c5b8a8c3b3a4b7a79a9f9186b0a39a948a81
+7f7870827f7a33322ebabab8fffffdfffef9fef9f3b7aea5afa397baaa9ab8a692aa947faa917b
+a9937e8f7a678272639d9185332f26fdfcf8fdfffef7fbfcfdfefffefefefefefefefefefefefe
+fefefefefefefefefefffffffffffffffffffffffffffffffefefefefefefefefcfffffafffef9
+fbf8f3fffffbfbfcf7fdfef9f7f7f5fdfdfbfffffdfffffdfffdfafffffafffef8f1eae2cdc4bd
+c0b4a8c2b19dc3af97b19d85a8937eb29d88a99783857462675748877b6d362c22eee7dffffdfa
+f8f8f8fbfcfefcfffffcfffff2f6f9f7fbfafffffbf6f3ecfffef2efe6d7baad9ac7b6a2c4b29c
+b2a08aa89682ad9a899a89798674666a594f80736b4f4c47fbfdfaf6f8f5f9fbf8fefffbf4f5f0
+fbfaf5fffff8fffff4e0dacec2b9aac2b7a5c9baa5bbab94af9e84b2a1879f9176b1a58b756953
+7166548e85763d342bf9f2ecfffefbfffdfcfffdfefefefffdfffefbfffefafffefafffcfafffc
+fefffffefffffffffffefffffffffffefffffffffffefffffffffffefffffefefffdfefffdfdff
+fcfdfffdfdfffcfdfffcfdfffefffffbfbfbfcfcfafefdf8e2dfd8bfbbb0bab4a6bdb4a5b4a997
+ab9e8ba99d85ac9e84aa9c81a99a7da9987ca9957ab5a188a7937bbaa892b09f8bb1a28fa29585
+aea296a79d94938a85776f6d514b4b645f63605b61fffcfffcf7fdfefcfdfbfaf8fffffdfffffd
+fcfbf9fdfcfafffffdfbfaf8fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fafcf7fafbf5fdfdf5fffdf1f6efdfbcb19db3a48db9a88ec0ac91b29f81aa9779b09f83ac9c82
+93856b8a7c62988d7963594defe6dffffef8fffbf5fdfaf5fefffafffffff9fbfafdfffefdfffe
+fefffffdfffefefefcfdfdfbfdfcf8fffaf4fffef3fff5e7f2e5d5ddcdbdc8b7a5c3b19dc2ad98
+b9a48fa6917ca4927eab9b8baa9d8d81776b665e53635f564a4742c2c2c2fefffffffffff9f9f7
+fdfcfafffffaf7f2ecfffcf3fff9edccbeb1bbaa9ac4b29ec5b09ba7917aab937bb6a18c847767
+7c72668e847a4a4138c8bfb8fffdfafffaf8fffcfcfffdfefffdfefefefffefefffdfffefdfffe
+fdfffefefff9fffef0fcf4e1ddd5c2c5baa6c4b5a2c1b09eb5a492af9e8ea391839e8e817b6d64
+72685f766f693c3934f2f1edf9f8f4fffdf6f7f3e8bbb3a8b6a999c2b19fbba78fb69e86b2987f
+b0967f8f79628a77669a8e803b342afffffafdfffcf9fbfaffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefffefcfffffafffef7
+fffef9fefdf8fffffbfefffafefefcfdfdfbfefdfbfffffbfffdf8fffef8fffef8e8dfd8c4bab1
+c0b2a5c5b199c3ab8fb1997fad957bb9a189a58f78806b566e5d4b7c6f5f463c30fffbf3fffef9
+f8f8f8f6fafdfbfffffbfffff5f9faf9fbfafffffbfbf8effffbeeddd2c0beaf9acbb9a1c3af96
+b6a088ae9881b09b869a85747865567865576a5c51827f7afefffdf4f6f3fdfffafdfffaf4f7f0
+f8f8f0fffff6fefaeed8d2c2beb6a3c2b6a0c3b39ab4a387ad987bb09d7da59476bbad9074664c
+8478628478685b5147fff6f1fffdfafffdfcfefefefdfefffbfffff9fffff7fffdf7fffdf7fffd
+fbfffffdfefffdfefffdfefffdfefffdfefffdfefffdfefffefffffdfefffdfefffcfdfffcfdff
+fcfdfffcfdfffdfefffdfefffefffffafaf8fcfdf8fffef7e3dfd4bfb9adb6af9dbdb29eb3a78f
+ab9d83ab9c7fad9e7fae9e7cad9d7bb09d7cb19a7bb59c7eb59d83ae9880b8a48ca6947eae9d8b
+af9f929a8d84867b75655b595a5152474143b2adb1fffdfffdf8fefdfbfcfffefcfffffdfffefc
+f8f7f5fdfcfafffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfefefe
+fefefefefefefefefefefefefefefefefefefefefeffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefffbf7f8f2f9f9effffff3f9f0dfbaae98b4a48bc4b095c4af92bba687b39e7fb6a383b4a385
+a1927594866b988c767a7064cdc4bbfffcf4fffbf5fdfaf5f9faf5fffffff9fbfafdfefffdfeff
+fefffffdfffefefefcfefdfbfffbf8fffaf4fffbeffcefdee7d8c5d7c6b2d3c1abcbb79fbba58e
+b39d86ad9780a18c77b3a29097877770645660564c514a426a6762f6f6f6f8fcfdfefffff6f6f4
+f4f3f1fffffaf8f4ebfffef3f5e9dbd2c2b3cfbcabccb7a2c6ae96ae947bb79c81b8a08881725f
+85796b897d71483e34efe6dffff9f6fffdfbfff9f9fffdfefffdfefefefffefefffdfffefdfffe
+fbfffefefff9fffdedf2ead3d5cab4c8bca6cdbca8beac98ac9784ab9685b8a29497857776655b
+7568606259549a9591fffffbfcfbf6faf7eeede7dbc2b8acbcaf9ecab8a2bca68ec5ab92baa085
+b79d849781698977639c8f7e3d352afffef7f8faf5fdfffcfffffdfffffdfffffdfffffdfffffd
+fffffdfffffdfffffdfffefcfffefcfefdfbfefdfbfefdfbfefdfbfdfcfafdfcf8fffdf6fcf9f0
+fffff8eeede8fdfef9f9faf5fffffdfcfcfafcfbf7fffffbfefbf6fffcf6fffcf7e0d5cfbeb1a9
+c2b2a3cab49cc6ad8eb39a7cb59c7ebfa58aa28a707c6850796753756555908476fffef4fffffa
+fafcfbf5f9fcf9fffff5fdfffbfffffafcf9fcfbf6fffff6fff8e9c9bca9c5b59ed0bca3cab298
+c0a88eb8a086b69e869d8470715a488e776758483bbcb9b2fcfffdf4f9f3fbfffaf8faf5fbfef7
+fafaf2fffff4f5f2e3d2cbb9bfb4a0c4b59ec0af93b49f80b09979b29e7bb19e7dad9e7d807154
+978871685d4b978d81fff8f1fffaf7fffdfefefefffdfefffafefff7fffff6fffdf5fffcf6fffc
+fbfffffdfefffdfefffdfefffdfefffdfefffdfefffdfefffefffffdfefffcfdfffbfcfefbfcfe
+fbfcfefcfdfffdfefffbfffffefffffafaf8fdfef8fffff6e4e0d4beb8aab3ac99bdb29cb3a78d
+ac9f7fac9e7bb0a07cb4a27cb5a37db7a37eb99f7eb89b7bc0a588af957ab9a187aa947db2a08c
+a99789887a6f73665e5b524d574f4d7d7779fdf7fbf1ecf2fffdfffcf8f7fefaf7fffbf8fefaf7
+fdf9f6fffbf8fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfefefe
+fefefefefefefefefefefefefefefefefefefefefeffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefffbf6f7f1f7f7edfffff3f9f0dfb9ad97b7a58dccb79ac7b091c2ab8bbba482bda684bda988
+af9b7a9f8c6c9c8c728c7f6fa89e94f3e9e0fffbf4fffdf7f1eee9fffefcfffffdfefefefefefe
+fefefefefefcfefdfbfffbf8fffaf7fff9f2fff6e5fbebd4e1cfb7d8c4abdfcaafd0bba0b8a086
+b0987ec5ad95a49078b3a18d7565555b4d40665c525e554ebcb7b3f9f9f7f3f5f4f7f9f8feffff
+fcfcfaf7f6f1fffef5fcf4e7dfd2c1d1c0acdecab2d3bba1c7ae90b3987abba180ae967a8e7d69
+867a6a7a6e60594f45fffdf6faf2effff8f9fffafcfffdfefffdfefefefffefefefefefcfdfffc
+fdfffafffff5f7efdae7d9becdbda3cdbca2d9c5acc4b097ae9881b29c879b867586736578675d
+70635b382f2ae0dbd7f7f6f2fffffafffbf0ece4d7cdc1b1c4b5a2d0baa3baa085caac90b99c7e
+c3a589a68c718d7760a69581433729fffef4f8f8f0fffffafffbf8fffbf8fffbf8fffbf8fffbf8
+fffbf8fffbf8fffbf8fffbf8fffbf8fffbf8fffbf8fefaf7fefaf7fefaf7fefbf6fcf8eff7f3e8
+fffcf3e0e0d8f7f8f2f3f6effefffbf9fbf6f9faf5fffffafdfaf3fffaf2fff7eedfcec4bdaba1
+c7b2a1d2b89dcab08fb79d7cbca183c3aa8ca0886e7c664f816f5b665647cabeb2fff8eefffdf8
+fcfcfaf6fafbfbfffff5fafdfcfffffcfdf8fbf8f1fffff3fff6e4bfaf98cdb89dd5bc9eceb395
+c6ab8dbda285b69c819b836b68533e99847347392ce0ddd6fefffdf7fcf8f9fef8f3f5f0fefffa
+fefef4fffef1efead7cec6b1bfb399c6b798c3af8eb8a17fb6a07bb9a37ebaa8849c8d6c8f8063
+a5967f544736cec2b6fffdf6fffbf9fffdfefffdfffefdfffafefff9fffff6fffef6fffcf6fffc
+fbfffffdfefffdfefffdfefffefefffefefefefefefefefefffffffefefefdfdfdfbfdfcfbfdfc
+fbfcfefcfdfffdfefffefffffefffffafaf8fefdf8fffff6e7e1d3bfb8a5b5ab92c1b398b7a887
+afa079b09e76b5a278b8a57bb9a67cbda77ebfa37ebea17fbea483b89f80ae9479b49e86ae9984
+a3928280706354473f6a5f5b332b29f0eaecfffdfffffcfffdfbfefffdfefffefafffbfafffffb
+fffefdfefdfbf9f8f6fffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfffffdfefefe
+fefefefefefefefefefefefefefefefefefefefefeffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fefffbfbfcf6f4f4ecfffef2fff7e6bfb39dc4b29ad7c2a7ceb797c5ad8bbfa582c4a883c7ab84
+bfa37cb59972ad947595836fac9c8fd4c6bbfaede4fffcf3fff7f0faf5f1fef9f5fbf7f4faf6f5
+fbf7f6fefaf7fffefbfffefafff9f6fff5ecfeead2e5ceaeddc6a6e7cfaddcc4a2c8b08ec1a987
+c2a98a9f876bc9b39b9f8d777161516153465a50475c534ef5f0ecfefdfbfefffff5f7f6fafcfb
+fefffdfffef9fffef3fff8e7decfb8d6c2a7e3caabd7bd9ac2a883c1a880b89e79aa937396866d
+857867645848978d83fff6effffcfafffdfff1ecf0f9f4f8f9f7faf8f8f8f9f9f7fdfef8fffff8
+fdfff4fdf8e5fbeccfe6cfade4cdabe3ccaac9b091bba485bda589b29c8499846f7766566a5c51
+6d635a6c655ffcf8f5fffffffaf9f5fff9edf4ebdacabba8c2b09ad8bea5cdaf93c5a485caa787
+c4a181c3a283ac8e74b09781847160ddcfc2fffcf1fffef4fffef6fffef8fffdf7fffdf7fffdf7
+fffdf7fffef8fffef8fffbf5fffef8fff9f3fff8f2fffef8fffef8fffcf6fffcf5fffdf1eae0d4
+ece6dad1cfc3eff1e6fcfff8eff6eef6fef3f6fcf2fefff6fbf9ecfffeeffff6e6d9c2b2c8ab99
+dbbda5d9bc9cd1b590b19776ceb395bea4898f79617d68558d7c6c4e4035eae0d7faf1ecfffbf7
+fffffdf4f4f4eeeff1fefffffefffdfefff9fffff4fffcebfaead1d0bb9cdfc5a2d8bb93d7b78e
+cfaf88c2a681b8a07e8a765b776750857865655d50f3f0ebfffffdf8faf9f9fdfcfbfffef7f9f4
+fdfdf3fffdece6dec7cec0a3cbbb99d4c09bc7b188bca67dbfa980beab83bdad89a293748a7a60
+a0917a3e3120eaded2fff7f1fbf1f0fff7f8fef8fcfdf8fefaf9fef9fafcf8fcfdf9fdfcf9fdfc
+fefffffdfefffefefefffffffffefffffffdfefaf9faf6f5f8f7f3f4f3effffffdf8f8f6dbdbd9
+fcfcfcfefffffefffffcfdfffcfcfcfefdfbfdfaf5fffbf3ece3d4c3b79fbfb091c9b791c4b186
+b7a273bca675bfa97abda579c5ac83c2a981c3a780c4a883baa07bc0a886baa183b39e83b6a28a
+92816f655546776a614037329c9492fffcfdfffdfffbfafffdfcfffffffffffffdfffefffffffd
+fffefffffffffefefefefefefefefefefefefefefefefefefefefefefefefefefefffffffcfcfc
+fdfdfdfefefefefefefefefefefefefefefefefefefffffffffffffefefefdfdfdfefefeffffff
+ffffffffffffffffffffffff
+f7f9f4fefffaf9f9f1f9f5eafffeefe1d4c1c6b69fccb89dd0b99acdb593c5a984c0a27cc4a47d
+c3a37ac4a47bc9ad88b59d85a69382ad9c8cd2c2b3f9ebdefffdf1fffdf4fef5ecfdf6eefef7f1
+fffaf4fffdf5fffdf6fffaf1fff6edfff2e2ecd7baedd3b0f1d7b2e9cfaad0b691bfa580bea481
+c0a886c8b1929c866e8977615e4e3e6f6156584e45c9bfbdf5edebfbfaf8fdfdfbf5f7f6f8fcfb
+fcfefbfdfcf7fffdf2f7efdcddcdb3d6c2a1e1c7a2d7bb93c4a97ec3ab7fbba27ab09a75928165
+92836c665744ccbeb1fffbf2fffdf8fef6f4fffdfdfffdfffffdfdfffefbfffff8fffff4fffff0
+f8f5e4f2ebd1ecd8b5e7cea6ebd1ace1c7a2c3a986bda583c0a98ab09b808e79645e4f3c786c60
+423930d9d4d0fbfaf8fcfcfcfffffbfff9edf9eedcc9b8a4bfab93d9bfa4d1b295c7a383cfa887
+caa382c09c7cc6a78ab49880a6907bc4b3a1f6e9d9f6eddefffaeefffcf0fffdf3fffdf1fffcf2
+fffbeffffcf2fffdf1fef4eafffdf1fffbf1fff7ebfffaf0fff8ecfaf0e6f9ede1eddfd2d5c7ba
+b7afa2e1ddd1f4f6ebfbfff8f3fdf2f7fff6fafff7fefff4faf7e8fffdebffeedbdec4add7b49e
+e0bea2dbba97c8aa84bfa280c8ad8faf957c8d7760816c5b8a786a55473ef4e9e3fffdf8fffaf6
+fffbfafcfcfafffffffffffdf8faf7fdfdf5fffcf0fffae6f2e1c7d4bc9ae0c39bddbc91dcba8d
+caa97cc8ab83af9773917e608173597a725d847e70f7f4effffffdfafcfbfafefdfcfffff9fbf6
+fffff5fffdeae5d9bfcfbf9ecfbb96d7c096c7b084bba478bfaa7fbeab81b8a884b5a685897a5d
+ac9e844d3e2bfff9ecfffcf3fffcf6fffcfafffdfbfffdfdfffdfdfffefdfffffbfffffbfffffb
+fefdf9fcfbf7faf9f5fdfaf5fffbf7fffcf8fffcf6fffbf5fbf6f0fefbf4fffff8f7f6f1dad9d5
+fffffbf9f9f7fefffffefefffffffffffefffffbf7fffcf5f1e5d5c9bba1c5b593d0bd92ccb685
+bda672bfa874c3a978bfa477c7ab83c4a881cbaf88c4a881bea47fc1a985b79e7fbda88bbaa68e
+7a69557464555d5047605752fffefbfdf9fafefdfffefffffeffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe
+fefefefffffffffffffffffffffffffffffffefefefffffffffffffefefefdfdfdfdfdfdfefefe
+ffffffffffffffffffffffff
+f1f6f2fefffbfefdf8f7f5e9fffef1f2e7d5bbac95c1b096c9b497ceb596c3a684bea27bccaf87
+ccaf87c4a47bc4a680c0a789a9937b9d8971ad9b85cebda9ebdcc9fcefdffff9e9fffcedfffdee
+fffbecfff6e5f4ebdae8e0cde0d5c3decfb8e8d1b2e9cface3c9a6d0b693bea481c1a784c6ae8c
+c0a788c6b194917d645544306c5f4f32251c90857ffffcfbfef8f8fbfaf8fcfcfcf9fafcfeffff
+fafaf8fffff7fffff3eee3d1dac9afd6bf9fdfc39ed3b68ec5aa7fc5ad81bea57db8a27dac9778
+baa68b907e66eeddc9fff7e8fff9eefaece3fffcf4fbeee8fbf1e8fbf1e7f9f0e1faefddf7ecd6
+efe5cce9dbbedfc9a4ddc49cdcc29dcdb38ebba37fc0a788bca5869e8a6f72604a7e6f5c65594d
+70695ffffffaf2f1effdfdfdfaf9f5fffcf0fff4e4c9baa7bba78fdcc2a7d5b89ac8a683cfab87
+c29e7abc9a77cdac8db59a7dad977f9e8c76c0b19ec9beacd5cab6dacfb9dfd4c0e1d6c0e1d6c2
+e2d7c1e5dac6e9dec8e1d6c2ede2cce9decae0d5bfe1d6c2e2d7c1dacfbbd6c9b6cabaaab9ab9e
+867c70f7f3e8fcfdf5f9fef7f9fff9f9fffbfbfff8fcfff2fbf8e9fffbe9f8e4ccdec4abe3c1a5
+e3c2a1d9b993bea07acbae8cc1a7869f856a87715a857261786859887b72fff6effffef8fefbf6
+faf9f7fffffdfffffffafcf9f3f3f1fdfdf5fffaeefff8e4e5d4bad7bf9dddbf99e1c095d8b689
+c09f74c9ab859f87658e7b5d897b61675f4ab0aa9cfcf9f4fffffdfbfdfcfdfffefdfffefbfcf6
+fffff4fff8e6e1d3b9d1be9dd4be97d9c097c6ae82bba375c0a97dc1ac81b2a078c1b28b998967
+ac9d7e74644afffbe6fff3e3fff6e9fff7eefff8eefff7eefff8edfff9edfcf9eafcf9eafcf9ea
+fffdf1fffdf1fffdf1fffbeefffbeefffbeffffbeffffbeffff7eafffbeff7f3e8dcd9d0d0d0c8
+fffffaf5f6f1fffffdfcfefdfffffffffefffffbf7fffbf4f2e6d6ccbea4caba98d4c196d0ba89
+c0a975c3a976c4a878bfa276c6a981c3a57fc5a781c7ab84c0a681c4ac8ac4ab8db7a2879b8671
+6958467c6e61382e24b8b1abfffefdf7f5f8fefdfff8f9fef9fafffefeffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefefefefefefefefffffffffffffefefefefefefdfdfdfdfdfd
+fefefefefefeffffffffffff
+f8fcfbfcfffdfffffafffff6fff9edf2e9d8baae98c2b299bda88dcab394c2a887bda17cc9ad86
+c8ab83be9e77bea07ac9af8ec1aa8bb8a386b4a183b4a085b8a78dc7b79ed5c6afddceb7dfd3bb
+e3d7bfe2d6bcddd1b7d8cdb1d6c8add7c6a8e5ceaed5bb98c3a988b99f7cbfa584cdb593c6ae8c
+a893748c785d6a5a41746552493d2f6b6158f3eae5f8f0eefaf6f5fcfafbfafafafbfcfefeffff
+f8f8f6fffef7fffef1e3d6c3d7c3a8d4bc9adabe97cdb088c4a97ec6ad84bfa87fc0a882ae9674
+b9a081af977bb6a186cfbaa5cbb9a5c9b6a7cdbbadd7c5b7d8c7b7d6c5b3d5c5aed9c8aedecdaf
+dfcfaedfcda9e6cea8d8bf97cab08bc2aa86c3ab89c9b292b39e8189755c69594271645352483c
+d9d2c8fbf8f3fffffdfefffffbfbf9fffbf1fff9e9cabba8b3a18bd5bda3d2b597c3a27fcaa682
+c5a27ccdab86c6a582ccaf8fb1997dad9980a79780bbad93beb093c5b898ccbf9fcec1a1cbbe9e
+cbbe9ecfc2a2d3c6a6cbbe9ed2c5a5c9bc9cbdb090c3b696cabd9dc3b696bbad92b6a794a39588
+847a6efffef4fffff8f8faf5fafffcfbfffdfcfffafcfef3fffcecfffbe7ebd7bed9c0a2e7c9a7
+e1c19bd3b68ebb9d77c9ad88bea483987e637d674f8875645a4a3bdacdc4fffcf5fcf7f1fffcf9
+fffffdf8faf7fefffff9fbfaf4f5f0fffff8fffbeffff4e2dbcab0dac3a1dcc099e1c198ccab80
+ba9970c0a27c927a587e6a4f887a60534b36d8d2c2fffdf6fffffdfcfcfcfdfffcfbfdfafcfbf6
+fffff3f9f1dedfcfb5d3bf9edac199dcc196c7ac7fbea376c3ab7fc3ac80ad9a6fbbaa7fb6a47c
+a18f6ba49473e2d1b5e5d5bce0d0b9e5d6c3e3d6c3e4d7c4e3d8c4e3d8c2e3d9c0e1dac0e3d9c0
+e3d7c1e7dbc5e8dcc6e6dac4e6d7c2e4d5c0e0d1bedbcebbe3d8c6ddd4c3d1cbbbb1ada1d5d3c7
+fffff8f9f9f1fffffbf9fbfafefffffffefffef9f6fff9f2f2e6d8cebfa8cbbb9ad4c197d1bb8a
+c0a975c2a875c2a676bc9f73c4a77fc2a47eba9c76c7ab86bda07ec1a987cbb4959f897175634d
+7b6b5b55473a71685ffffdfaebe7e6fefefffefffffbfefffbfefffcfdfffdfdfdfdfdfdfdfdfd
+fdfdfdfefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe
+fdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfcfcfcfffffffffffffffffffefefefefefefefefe
+fefefefefefeffffffffffff
+fbffffecf0effdfffcfffffaf8f4ebfff7ead3c8b6b8a994b6a289c1ac8fbfa687b69c7bb99d78
+bb9f78c2a47ed0b28cbca079bda37ec2aa86c7b18cc7b08ebfab8abaa786b6a685bfaf8ec4b492
+cbbb99cfbf9bd1c19dd2c29ed5c5a1d9c7a3d5be9cc5ad8bbca384bea684c0a788baa3839f8a6b
+7e6b4d57462c6c5d485447374b4137e8dfd8fffefaf4f0effffdfef9f9fbf6f6f8f6f7f9fbfdfc
+f3f3f1fbf8f1fff5e9dacbb6d1bc9fd2b895d4b690c5a87ec1a67bc4ab82bda67dc3ac83c6aa83
+c1a57ed5b896a88d6fc6ad8fc9b197c5ad95c4ae97c4ae97c5af97c7af95c6af90cbb391d1b993
+d6bd95d5bc93d9c098c5ac84b9a17bbda581c2aa88b7a081917d6269573f7e6f5a4a3e2e938b7e
+fffff6fffffafffffdf5f7f6fefefcfffbf3fffcedcdc0afb0a089c7b297c7ac8ebd9f7bc09e79
+bf9d77d0ae88bb9b75cfb38eb8a07ecab596b2a185c3b294cbbc95d3c199d7c59dd6c49cd1bf97
+cdbb93cfbd95d2c098d0be96d2c098c7b58dc0ae86cbb991cfbd95bfad85ae9e7cab9a868f8174
+aea198fffcf4fffffaf8f8f6f9fdfcfcfffffefffbfdfdf3ffffeffff8e2dfccaed2ba96e5c8a0
+daba91cbae86bd9f79bea27db9a17f947c60735f46857462463929fff9effffef6f8f5eefffffb
+fefffdf0f4f3fbfffff9fdfcf9f8f4fffff6fffceff8ebdad4c3a9dec7a7dbbf9addbd94c0a077
+bd9d76b397728b7351715d4281725b584d39f5eedefffef8fffffbfcfcfafffffdfbfcf7fffcf5
+fffff1f1e6d2ddccb0d7c09edec29bdcbf95c6a97dbfa276c6ab80c3ab7fb09b6cb4a274c2af84
+9f8c62beaa85bca885cbb898ccb99bc9b698c8b79bcab99bcabb9cccbd9ccdbf9ccdbf9acebe9a
+cbb897cfba9bcfba9bcab596c6b395c6b395c2ae93bbaa90bcad96aea28ca9a18e9a9383eae6da
+fffff4fffff5f5f6f0f7f9f8fdfffefffefffbf7f4fff9f1f0e7d8cebfa8caba99d2bf95cfb98a
+c0a977c2a875c1a575bd9e72c5a57ec4a47ebea07cbb9f7abda07ebea586b39b7f8c785f705f4b
+796c5c2e2216dbd4ccfffaf6fffefffbfafff5f6fbfcfffffcfffffcfdfffdfdfdfdfdfdfdfdfd
+fdfdfdfefefefefefefefefefffffffefefefefefefdfdfdfdfdfdfcfcfcfcfcfcfbfbfbfbfbfb
+fbfbfbfafafaf9f9f9f9f9f9fafafafafafafbfbfbfefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffff
+fbffffeaf0f0fbfffefffffbf5f2ebfffff3e8dfd0a09382b4a48daa967da78f73ae9576b99f7e
+c3a684c8ac87c7ab84b2966eb69a72bea27bc4ab83c9b289cdb790d1bb94d2bf97d0bd95d2bf97
+d4c197d4c197d1be94cdba8fcbb88dc9b68ec4ad8bbda687bca586b59e7f9d8667846f50746045
+66563c4f40295f5440483f30c5bcb3fcf7f1f3efecfffefffffefff7f7f9f4f4f6eeeff1f3f3f3
+f1f0ecf4f0e7f4e8dad3c3accdb697d0b48fceb189c0a077bea177c0a77eb6a079c1a983c4a880
+b99972cdaf89bb9d79ceb191d8bd9fc9ae91d5bc9ecfb698d4b99bd5bb9ad6ba95d4b890d5b88e
+d1b586ccaf83bea57cb79f79b8a07abea883b59e7e927f616e5d435b4c35584d397c7364e0dace
+fffff6fdfcf7eff1eef5f9f8f9fbf8fffff6fffef1d8ccbcb7a893bda98ec0a788bfa280bb9b75
+b89871c1a178b59870bb9f78b9a17bc6af8dbaa786bcaa86c8b58bceb98cd2bd90d2bd90cfba8d
+ceb98cd0bb8ed3be91ceb98ccdb88bc7b285c8b386d3be91c8b386a994678e7c569d8d76796b5e
+dbcec5fbf2edfffcf9f8f6f7f8f9fbfdfefff9f9f7fffdf6fffeeefaeed6d5c2a2ccb48edfc497
+d0b485c3a67cba9e77b39976ae95768b73576f5b437e6d5b5d5040faf0e6fffbf3fffff8fdfef9
+fcfefbedf3f1fbfffff7fbfafcfbf6fffef5fff9ece7dac9cebca4ddc6a7d7bd9ad1b38db79a72
+c1a37da58b68836c4c71604675664f7a6f5bfffdedfffcf6fefaf7fbfaf8fffffbfaf9f4fefaf1
+fff9ece4d8c2ddc8abd7bd9adcbe98d8b88fc3a478bfa074c4a77dbda579b49e6fb49f70b9a477
+ae996eb8a279b39d76c2ac87cfb896cab391ccb593cdb994cfbc94d1be94d2bf94d3c193d5c093
+d8bf96d9c098d4ba95cdb38ecdb390cfb795ccb595c3ae91b9a58ca3937c9285729c9382f6f0e2
+f8f4e9fffff6f2f3edf4f6f5fafcfbfcfcfaf7f3f0fef7eff1e7dbccbda8c4b395cebb93ccb78a
+bfa777c2a877c0a475bb9b72c3a37dbfa17dbc9e7aab8e6cc4aa89bea5878f7a5f7c6a526c5b49
+4a3e307f756cfff9f3e6e2dffffffff5f6faf4f7fcf3f8fef8fbfffefffffffffffffffffefefe
+fefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfafafaf9f9f9f7f7f7f6f6f6f6f6f6f6f6f6
+f5f5f5f4f4f4f3f3f3f4f4f4f5f5f5f6f6f6f7f7f7f8f8f8f9f9f9fbfbfbfdfdfdfefefeffffff
+ffffffffffffffffffffffff
+fbfffff4f9fcfafefffcfefbf9f8f3fffdf4f8f0e5b6aa9ab0a18e91816a917d62a28d70a89172
+b09778b79d7caf936ec1a57ec4a77fc3a67ebca078b99d75bca37bc7ae86d0b990cab389cbb68b
+cdb88dceb98cccb78ac6b184bfaa7db9a37aa790709e896c998467897658715d42635236625239
+5d51396d624e5c5342cfc7bcfffff6f4f1ecf4f3f1e2e0e3e7e6ebeeedf2ebeaefdedee0e3e3e3
+ebe7e4e7e0d6e0d3c3cab8a0c9b092ceb08ccbab84ba9a71bb9e74bba27aaf9974bca681c1a57e
+bb9e76bea07ac9ab87d3b792cfb592ccb291d0b695cdb390d1b794d4b893d1b48ccdb086ccad7f
+c7a778c1a274b29971b59f7ab7a07eb09c7b9a87697564486050375e523c453d2acfc7baf2eee3
+f6f6eeeaebe6eef0edfcfffffcfefbfffaf4fffbf0e0d4c6bcad9aae9c84b69e82bea481b39770
+b99c74bb9e74bda076bda179baa37abaa47dbaa681baa681c0a980c2ab81c4ad83c6af85c6af85
+c7b086cab389cbb48abfa87ebca57bb8a177bfa87ec3ac82ab946a826b416753308d7c686a5e52
+f2e8dff8f0edfdf7f7f5f3f6f7f6fbfaf9fef7f5f6fffbf5fcf5e5ebdfc7cdbd9bcab48bd7bf8f
+c8ae7dbb9f77b09671b49a799b8465756045705e4674655295897bf2eadffcf8effffffaf1f3ee
+f4f9f5e9efedf4fafaeff3f2f9f8f3f8f1e9faf0e4d2c5b4c8b69ed7c2a5d2ba98c2a583ae926d
+bc9f7d977f5d715c3f7f6e54635741aa9f8dfffaedf8f3edf4f0edf4f3f1fbfaf6f5f2edf8f4e9
+f8efe0d5c6b1dac2a6d4b795d7b791cfae85bb9a71b99970bea179b49b72b39c72b29b71af986e
+b8a178ab936db49c76c2aa84c7af89cbb38dcdb58fd0b990d2bb91d4be8fd5bf8ed5bf8ed5bd8d
+d4b78bd7b88cd3b38accaf87cdaf89ceb28dc3a988b49d7ea28d7297856f7d6e5bb4a89af5ede2
+e9e5dcfefbf6f3f2eeeff1f0f3f5f4f4f4f2edece8f8f3edece4d7c4b7a4b8a98cc7b591c7b287
+bca476bea376bb9e74b3966eb99b77b79977af916fae9171bea386a48c707a664d6a59455c4c3d
+554b3fe2d9d2fdf8f4f5f4f2f3f3f5fefffffcffffeff4fafcfffffdfefffefefefdfdfdfcfcfc
+fbfbfbfafafafafafafafafaf7f7f7f6f6f6f5f5f5f3f3f3f0f0f0eeeeeeedededecececebebeb
+eaeaeae9e9e9e9e9e9eaeaeaecececeeeeeeefefeff2f2f2f3f3f3f6f6f6f9f9f9fbfbfbfdfdfd
+fefefefefefeffffffffffff
+fbfffff9fefff9fdfffefffffffffbf8f5eefffff4eee6d9a69a8a8c7d6a92826b95846a7a654a
+7a6548a08769af9574b39772b39770b39772b79b74bda17abfa67ebda47cb9a078bba47bbba47a
+bca57bbca57bb8a177ae976ba0895f957f58806b4e735f4669583e65543a63533a695a43625640
+4e4631948b7aebe5d7fbf7ece5e2dbedece8e2e2e2dadadcdedde2e0dfe4dedee0cbcbcdd2d1cf
+ded9d5d6cec3cdbdadbfa991c9ac8ecfaf89c9a87fb6966db89b73b79f79a99572b6a27fb9a17d
+c2a681b49873b99f7cc7ad8aac9470c2aa88ac9472b59d79b79f7bb79d78b49871b2956bb29569
+b49567b093699d855f9f8b6a9782638471536c5b41514329473b254f4430a49d8df7f1e5fdfaf1
+eeeee6ecede8f7f9f6dbdfdee8eae7f2efeaf6efe5d9cfc3b5a8979e8e77a59176b69f7fa68e68
+a99068ae926ab1986fc0a77ead966daf9972af9b76baa681baa27ebaa07bb99f7cb79d78b69c79
+b59b76b59b78b49a75baa07db59b76b19774b89e79b79d7a987e596f55325a432485746265584f
+f9f0e9fcf4f1fcf6f8f4eff3f6f3faf7f5faf8f4f5fffaf6f3ebdeded4bbc9ba99c8b78cd3bf8d
+c2ac7bb49d74a68e6cb89f808d7559624e3573634c6d5d4dc6baacfff7eef9f5ecf4f3eee7e9e4
+f3f7f6e3e9e7e6efeee7ebeaf5f4efefe8e0f2e8dcc3b6a6c2b29bd1bda4cdb697b69d7ea58b6a
+b097788b74555f4b30897962554835cbbfaffaf2e5efeae4eae6e3ecebe9f5f4f0eeebe6f0ece1
+f1e5d7c8b7a3d6bea4cfb292d1b18bc8a680b4946db2946eb89c77ad9370b09872ab936daf9773
+b69e7aa78f6bb09874c1a784b49a77bba17cbda47cbfa67ec2aa7ec3ab7dc3ab7bc2aa7ac3a879
+c2a176c7a47ac7a67dc6a47ec6a680c1a37fad9070947b5d664e3676614e655546cec2b6faf1ea
+e4dfdbf2eeebe9e8e6e9ebeaeaeeedebedeae6e5e1f2ede7e8e0d5bdb09faf9f86c1ae8dc0ad85
+b69f75b89f76b59972ab8f6ab09373ae9173a6896bbca184a88e7378624a735e495c4d3a564a3c
+a69d94cfcac4fffefbf3f3f3ecedeff4f8fbfcfffff1f6fafcfffffafbfdfafafafafafaf9f9f9
+f7f7f7f6f6f6f5f5f5f5f5f5f0f0f0efefefedededebebebe8e8e8e5e5e5e4e4e4e2e2e2e1e1e1
+e0e0e0dfdfdfdfdfdfe0e0e0e3e3e3e5e5e5e7e7e7edededefefeff2f2f2f6f6f6f9f9f9fbfbfb
+fcfcfcfdfdfdffffffffffff
+f8fdfffafffffbfffffcfdfffffffdfffffbfffff8fffcf2d7cfc29a8e7e786b5891826da18f77
+89785e7a654a826a4e886f508c725194795b9e8463a38968a38b69a68e6caa926ea48c689e8662
+97815c917b5686704b7a643d745e39725e3d6b5a4062513d63543f6e5f4a5f523f4b402c6e6653
+b0aa9ae5dfd1e5e1d6e4e1dae1e0dbe0dfdddbdbdbd1d1d3c6c7cbcccccebebec0bab8b9bdb9b6
+bdb6aebdb4a5bfae9abca48ac7a889c8a681bb9a71b9986fb1956eb09874b4a180a39372927d5e
+a28b6b937c5c8e795a958061897656816e4e7d6a4a7d6a497d69487e67457e68437f67437f6540
+7e653d7b633d6f5b3a6857396a593d6252385f5039473c264d45329d9686dcd6c8f2eee3f3f0e9
+e2e1dce3e4dfeceeebe8eae9e0e0dee7e4dfe9e2dae0d8cdc3baaba49784998970938264897554
+8e7853937d569b835da08a63a48e69a5916ea79372a99475a68c71a88e73aa9077a88e73a58b72
+a3896ea38970a58b70a48a71987e639a8067a0866b8c7259664c31553b225b452e7c6c5fa1978e
+eae1dcfcf4f2ebe5e7e3dee2dfdce3e4e2e7e0dcddf1ece8e9e1d4c6bba5b7aa8ac2b38ac3b183
+b39e71af9974887354a38e7174604755432d796a574c3f2fd9cfc3f9f2eaece9e2e3e2dde2e4df
+dfe3e2d8dedcd4dddadadfdbdddad5e7e0d8dbd1c7c7bbabc6b7a4c6b49cb7a388a79275967f60
+9a85687f6b506250388a7b66534836e0d7c8e2dcd0ddd8d2dcd8d5dad9d7dcdbd7e2dfdae0dcd3
+d5c9bdc7b6a4c9b39bc4a98bbb9d7bb49370ae906eac8f6fa98e71a58e6f9f88699d86679c8566
+9d8667a0896aa38c6da68d6fa78e6fa68e6ca78f6ba98f6caa9169aa9168a99165a99165aa8f64
+b4946da2805ba58360ac8a67a78665a8896c92745a5f452e4c35238e7b6c625147ddd0caeee4e3
+e5dfdfe3dfe0dbdbdde5e9e8dde2dee3e5e2e8e7e3f0ede8e3dcd2c0b4a6b7a893baa98db09d7c
+a38f6a9e88619e8662a08768a78c71ae927aa68a72a2886f9b836b6f5a455e4b3a53463660564c
+c2bbb3dedbd6e7e6e4ecececebeceef1f5f8fcfffffcfffff1f5f8f6f7f9f6f6f6f4f4f4f1f1f1
+eeeeeeebebebe8e8e8e7e7e7eaeaeae5e5e5dfdfdfdbdbdbd9d9d9d7d7d7d4d4d4d2d2d2d2d2d2
+d3d3d3d3d3d3d4d4d4d6d6d6dadadadfdfdfe3e3e3e8e8e8ebebebefefeff3f3f3f6f6f6f9f9f9
+fcfcfcfefefefefefefefefe
+fafdfffcfffffcfffffdfefffdfffefffffdfefdf8fbf8f1fffff4efe7dab5ac9d796e5c6c604a
+84755e8b7b647d6b537a644c7964497c674c826a50826a4e7d65497a62467b6347786142765f40
+735e3f735e3f6d583b6350325f4c2e5e4d336354417265546458484d4131685f4eaea797e8e2d4
+fffcf0e5e3d7e4e4dae1e0dbdadbd6d3d3d1ccccccc1c2c4b7b8bab0b0b2a5a5a5a1a09ea19e99
+a19a90ac9f8fb8a38eb89f81c5a481c29f79b08d65b08f66b0946fab9472a7967898886e7b6a50
+8b7a607a694f71614778684e7363497161476d5f447264477162456f5e406b5a3c6a5739675434
+655031624f315b4a306a5c426d5e474f432d4d4230645b4a8e8679d3cdc1e5e1d6e4e1dad7d6d1
+cfcecad5d6d1d6d8d5cfcfcdcbcbc9cfcbc8d0cbc7d9d2cad0c8bdaa9e8e82766074664c716245
+6c5c3b715e3d7662417864437865457966467a664b7b674e7e6853826857836958826857806655
+7e6453806655826857806655745a49684e3d664c3b684e3d664c3b6046355741335f5249c7beb7
+d8d0cdeae5e2dcd8d9cdc8cceceaefdbd9dcd9d5d4e5e0dadbd3c8b7af9aa2977b9a8c697f7047
+5b49216d5a3a59452a67553d53412b5a49377d70605d5347f4ebe2e9e4dedddad5d3d2ced0d2cf
+cbcfcec3c9c7c1c7c5c5cac6cfccc7d9d2cac9c0b7afa397a194839584707b695166553b604c33
+604f3552422b4f402b827564605446d0c8bbd3ccc2c9c4c0c4c3bfc1c0bec1c0bec7c3c0c8c3bd
+c1b7abb8a898b9a38ca88e73927557806345795e41795f4677614976624a7d69517b674f79634c
+77614a77614a77614a7860487860487b63497c64487e65477e65467f67457f67437f6743806643
+7c5f3f7455387b5c3f7a5b3f6b4d336d51396b503b503625604a3c7d6b61665750e6dbd9cac1c2
+f2ecf0d1cfd4dddce1dbdfded0d5d1d8dad7dcddd8e0ddd8d9d2cab5ab9fa194839c8c73887759
+756241705d3c756041745f446c563f664d396c533d60473368513f5a47364d3d2e5b4f43817a72
+c3bebacdcccad4d4d4dddee0e6e7e9ebeff0eef2f3ecf0f1eaebedf0f0f0eeeeeeebebebe8e8e8
+e4e4e4e0e0e0dddddddbdbdbdadadad5d5d5d0d0d0cccccccbcbcbc9c9c9c7c7c7c5c5c5c4c4c4
+c5c5c5c8c8c8cbcbcbcececed3d3d3d9d9d9dddddde4e4e4e7e7e7edededf2f2f2f5f5f5f9f9f9
+fcfcfcfefefefefefefefefe
+fdfefffefffffefffffdfefffcfdfffdfdfdf8f8f6f3f2eefffef7faf6edf2ebe1dbd3c6aea594
+857a687e716090816e8b7c6987766485746087756185735d7f6d577b665179644f7a65507c6752
+7e6c5682705a806f5b7c6b57796854776a59534739584e42746c61aea69be3ddd1ebe7dcd9d7cb
+d0d0c6dedfd7dfe0dadbdcd7d0d0cec6c6c6bcbcbcb2b2b4a9a9ab9797978f8f8d8a8984858178
+877f729e8f7cb49e86ba9d7fc29e7abd9770a68059a6845ead906ea0896a91806682735e574737
+8b7b6b9e8e7e9d907f9c8f7c90857190856f8f8770938b7491897290856f8d826c8a7e68897a65
+877863867762847764756a58635747534a3b766e61b7b1a5dbd7ccece9e0e0ddd6d2d1ccc3c2be
+c3c2bec6c5c1b9bab5b0afabb6b5b3b6b2b1b6b1aec1b9b6c2b9b2a79f928e8574897e6a8b7f67
+87795f87795e86765c8373598070577d6d547c6b577d6a5976625778645b79655c77635a746057
+74605775615878645b69554c715d547561586e5a51634f465e4a416551486b5a52776c66e4dfdb
+cac5c1d8d4d1cbc7c8bbb9bad5d3d6c6c4c5bbb7b4c8c3bdc2bcb0a8a18f9c917b9c91758f8262
+7667487d6d5373634c6859445e4e3e7063537d71655f574ce1dad2d6d1cdcac6c3bebdb9b9bbb8
+b2b6b5a9afada8aeacaeb3afb9b5b2c6bfb9bbb2aba49a909a8e8091847380715e72634e71624d
+6a5b46645744665a4a847b6c696156aea59cb6b2a9b6b2afb1b0aeaeacadaeaeacb3b2aeb7b2ac
+b3a9a0ae9e8f9c877490786080664d7a60477c634d7e69567b6a5a766657736252726151716050
+7261517562537865567966557966557c6a567c6a547d69517d69507d69507d694e7e6a4f7f6951
+856d55816651876c578166516e5541715746745d4d6451435b493f54453ea89a97e2d8d7cdc7c9
+dad5dbcdcad3d7d8dddadeddced3cddee0dde2e2e0e1dddaddd8d2bab1a892897a8e826c87795f
+7e6f527b6c4f77674e72624b6e5d4b6d5a4b796453614c3b68554667574a50433a635a53938e8a
+a8a7a5bfbfbfc4c5c7d4d5d7e4e5e7e9eaece3e5e4e0e2e1e4e4e4e3e3e3e1e1e1dedededadada
+d5d5d5d1d1d1cecececcccccc8c8c8c5c5c5c1c1c1bfbfbfbebebebdbdbdbcbcbcbbbbbbbcbcbc
+c0c0c0c5c5c5cacacacfcfcfd5d5d5dbdbdbdededee1e1e1e5e5e5ecececf2f2f2f6f6f6f9f9f9
+fcfcfcfefefefefefefefefe
+fcfbfffffefffffefffdfefffcfdfffafbfdf4f6f5eeeeece4e5e0e1e0dbdcd9d2d7d5c9d1cbbf
+bab4a6968e81797061665d4e605748615547695c4c7164547767577969597b6b5b7f6e5e726253
+6151425245354f4136574b3f675b4f72685ea49d95c4c0b7dad6cdd9d6cdd4d4ccd5d5cddedfd9
+edf0e9d3d5d0d4d6d1d1d3d0c7c9c6bdbdbdb2b2b2a7a7a79e9e9e88888681827d7c7972767267
+7d74659a8975b59d83ba9b7cbe9873ba936ca37c55a4805ca78a6a91795f7b6953695c4b34261b
+44372e2e211821170b33291d423b2b474131403b283d3a273e3b2a423c2c433d2d463f2f4a4034
+4d43374f45394c44375e56498c867ab4ada3c6c2b9d5d2cbd6d3cecac9c5c7c6c2c3c2c0bdbcba
+bbbab6b4b3afa39f9c9b9794a6a29f9c9698a7a1a3b7afadb9b1aeaea79da49c8f8e8574706855
+685d49695e4a6a5d4a6b5e4d6c5f4e6f625275655878675d796861796a657b6965786964776561
+746560796763796a6574625e7465607866626c5d5855433f4b3c376f5d599a8c89b6aeabd6d2cf
+c5c1becccbc9bdbcbac1c0beacaba9b9b8b4b3b0abbfbcb5b8b4a99993858279688075617f735d
+786c56796c59766958655949675b4d74675e736960605951aaa5a1c1bdbab4b3b1abaaa8a6a6a4
+a0a2a1989c9b9a9e9da2a4a1a8a7a3b4afaba9a29c928982877d73807768776b5b716654706553
+685c4c6b62536d6357736b6060594f847d759c97919695919393919494949797979d9c9aa09d98
+9e958e9c8e83927f708d7664856f5a826b59806d5e7c6c5f72655c695f566c5f566c5e536c5e53
+6e605572645975675c79685e786a5d766659766657756556746454746454756653776757776757
+796858746152766354766354705d4f736052705e525f4e4673665e635854dfd5d3d4cecedfdade
+cbc9ced2d1d9d0d1d6d3d8d4c8cdc7dfe1dee4e4e2dfdedae3e0dbc2bbb390887b857c6b847965
+81755d7d71597669566f62516e6055736258705e52614f4362514765584f544b4466615d92918f
+969696b1b2b4bdbec0cdced0dadcdbdbdddcd8d8d6d7d8d3d9d8d4d2d2d2d0d0d0cecececbcbcb
+c7c7c7c4c4c4c2c2c2c0c0c0bebebebdbdbdbcbcbcbcbcbcbdbdbdbebebebebebebebebec1c1c1
+c5c5c5ccccccd2d2d2d8d8d8dddddde2e2e2e5e5e5e4e4e4e9e9e9f0f0f0f6f6f6fafafafcfcfc
+fdfdfdfefefefefefefefefe
+fbf9fcfefcfffffefffefefffcfdfffafbfff3f4f6ecedefdee0dfe9ebe8e2e3dec7c8c2bab7b0
+bab8acafaba09b978c95918689857a7d766c767064746c6172685c70665a70665a73675b7f756b
+948a81a79e95b8afaac3bcb6c8c3bfc9c5c2dad6d3efeeeaeeede9dadbd6dbddd8e7e9e4e0e5e1
+d3d8d4cacfcbcbd0cccacccbc1c3c2b6b6b4a9a9a79c9b9991908e7f807a75766e726f66746e62
+8074649c8a74b2987db59473b48c68b58b65a47d56a4805e9d7f63826c556d5c4a594b406d605a
+a59a96baafabb2a9a2a7a09697938795938694928598998b9d9d91a4a498aeaba2b7b4abc0bbb5
+c8c3bfcec9c5dcd7d1ccc7c1cfccc5dddad5d5d4d0d1d1cfd1d1cfc1c1c1b5b5b5b7b7b7b1afb0
+a7a6a4a29e9b96918e8f8a86948f8c938d8f918b8f938d8f938e8b999490aea79fb7b1a5aea89a
+a29a8d9d9588938b80867e737b71687166606f625c6d5f5c6d62606f6563736866736967746967
+746a68796e6c7b716f766b69726866786d6b8177758a7f7d968c8ab5aaa8d2cac8d1cbcbb8b7b5
+bab9b7c6c6c4b1b1afc7c8c3a6a7a1b9bab4acaca4bcb9b0bcb9b0a9a59a97918591897e90867a
+8b8175887e72887e74857b718e857c8b827b8c857f877f7c928d8aa9a5a49e9c9d979596969696
+94949290928f9597949ea09da9a8a6b7b2afb0aba7a0999399928a958d828e86798b83768c8477
+80786b837d71847d737c786f6f6a6476716b8b88838382808080808181838688878f8f8f989491
+9e9791a3968e9a8a7d998678958273907e708b7d74847b747e79767c77747f76717c716b746b64
+6e655e696059665d54645a516259505e544b5e544b60564d62584f655b52695f556b62596d645b
+786e65766c637b716782786e8a7d7490837a8f827a847973b9b0abb7afacd4cfccd1d0cecbcbcd
+e5e6ead0d1d5cfd3d4d6dbd5cdd2cbe2e4dfe5e5e3e2e1dff0ece9dad5cfb1aaa09a928587806e
+756d5a6b6350645d4d5a52454c433c4439334e3d3555443c50413a52474358504d686463868686
+939496a1a2a4b2b6b7c2c3c5c3c5c4c4c5c0cac9c4ccc9c2c8c5c0c2c1bfc1c1c1c0c0c0bfbfbf
+bebebebebebebdbdbdbcbcbcbdbdbdbebebec0c0c0c2c2c2c4c4c4c7c7c7c9c9c9cbcbcbcccccc
+d0d0d0d6d6d6dcdcdce0e0e0e4e4e4e8e8e8eaeaeaeeeeeef2f2f2f8f8f8fcfcfcfefefefefefe
+fffffffffffffefefefefefe
+fdf9fafffcfdfffcfffefcfffcfbfff9fafef1f5f8eaeef1e3e7eabdc1c2a5a9a8afb1aeb0b1ab
+999a9285857d82827a80817978797175756d79796f8481788f8b809c958ba59e94b6afa7bcb5ad
+c1bcb6c7c2bfcecac9d7d5d6dfdfe1e3e3e5d4d4d4d1d3d2d4d6d5dde1e0dadeddc3c9c7bec4c2
+d3d9d7c8ceccc7cdcbc2c6c5babcbbb1b1afa5a4a29793928a868387877f7a7a7079776b827c6e
+8e8170a08e76af9477b18f6caa805aaa7e59a57a57a17d5d8d6f5578624d6c5a4c4d40376e6361
+988c8ca096959e9693a099939592899090868c8e83919388999a92a4a59fafb0abb9b9b7c4c2c3
+cecccfd4d2d3d3d2d0dfdedae7e6e4dfdfddc5c5c5bebfc1cecfd3c4c5c9b3b4b8afb0b29f9d9e
+938f8e97919198908e9088858d8583999397958e95a09a9eaba5a7a39e9b9a97929d9892a19d94
+a09c939e99939a958f978f8c938b8993898a948a8b968c8d958d8b98938f9e9996a39e9aa7a29f
+aba6a2b0aba8b4afabbcb7b4c5c0bcc8c3c0c3bebac4bfbccac5c1c3bebbb4b0adc3c1c2bababa
+b7b7b7c5c5c3afb0abbebfb9bdbeb6bbbdb2acaca2b3b3a9bbb8afbebbb4c5c0bad0c9c3d1c9c6
+ccc5bfcdc6becac3bbcbc2bdcac3bdb5adaaafaaa7aba5a5918d8e9793948f8d8e8d8b8c8f8f8f
+91918f9292909b9b99a6a6a4aeadabc2bebdcac5c2cbc6c2d2cdc7d4d0c7d2cbc1cecabfd3ccc2
+bdb9aeb4b0a5aeaba2a5a29b94918c807d787c7b778383837e807f7f8082868789929294a09f9d
+afaaa6bcb1abc3b5accbbab0d3c2b8d7c9c0d4cbc6cfc9c9c8c8cac5c5c7beb9b6b8b1aba9a49e
+9c9791928d878a857f847f79817c76837e7886817b8b8682928d899a9591a09d98a6a39eaaa7a2
+adaaa5b4b1acbab7b2bfbab4c2bdb7cac3bdd1cac4d5d0cad2cdc9e8e5e0cccbc7d7d7d5c2c4c3
+e8ecebd2d6d7dce0dfe3e8e1dbe1d7e9ebe6e5e7e4e7e6e4faf9f7f2efeaded9d3d7d3c8c6c0b2
+ada797979183837d716f6b62615c585e56534f423c5d4e47584d49544a48635d5d6e6c6d79797b
+909497999da0acb0b1b9bbbab6b6b4b8b7b3c3c0b9c6c2b9bebbb4bbbab8bbbbbbbcbcbcbdbdbd
+bfbfbfc1c1c1c2c2c2c3c3c3c4c4c4c6c6c6cacacacdcdcdd0d0d0d3d3d3d7d7d7dadadadddddd
+e0e0e0e5e5e5e9e9e9ecececeeeeeef1f1f1f3f3f3f7f7f7fafafafefefeffffffffffffffffff
+fffffffffffffefefefefefe
+fffafafffefdfffefffefcfffbfafff8f9fdf0f3f8e8edf1d2d7dbc9ced1b9bfbfa6aaa9929793
+898b86898a858c8f88797e77757c74767b7480837a8d8e869b9b91adaaa1b9b6adbcb9b2c7c4bf
+d0cfcbd6d4d5d9d9dbdbdce0d8dbe0d4d7dce6eaeddee2e3cfd3d4ced4d4dde3e3dde6e5ccd5d4
+bfc8c7c4cdccc2c8c8bbbfbeb5b7b6b2b2b0acaba9a19d9a94918c9e9e94909084908e819b9585
+9e917ea38f76ab8e70ac8a67a77d57a17550a075529a73547a5c447059476c5c4f42352f7a6e6e
+9f93959f9596928a88877f7c79766f84847c94958d95968e9c9f98a8aaa5b3b5b4bbbcbec4c3c8
+cccbd1d2d1d7d9d9dbdadadacccccecdced0cecfd3c9cdd0c0c3c8999ca1b4b5baaeafb3a09ea1
+9995949f9999a199979d93919e9493a1989d9790979c979ba29e9f9b9798969593a39f9cadaaa5
+9a9693989491959190918b8d8e888c8f858d90868f90899096928f9a9a92a3a29daaaaa2afaea9
+b4b4acb8b7b2bcbcb4c2c1bcccccc4cac9c4bebeb6bdbcb7cacac2cfcec9c9c8c4c0c0c0cbccce
+bfc1c0c5c7c4c1c4bdc1c4bbc7c9bec5c7bac7c9bcc4c6bbc1c1b9c2bfbac5c1bec9c3c3c8c2c4
+c5bfc1d3cecad1ccc6cec6c3c4bfbcb7b1b1ada9aaa8a4a59691959893979290939391929b999a
+a09f9da4a4a2afb0abbcbcbabab9b7cdc9c8d6d2d1d8d4d1e0ddd8e0ddd6d8d3cdd3d0c7d3cfc6
+c1beb5b4b1a8a9a9a1a7a6a19a99958d8c8880807e8888888687898a8b8f9296979fa0a2ababab
+bab6b3c9c0bbc9bcb4cec0b7d5c6bfd6cbc5d0cbc8c4c2c5b4b7beabaeb3acaba9a6a39e999691
+8e8b8686837e827f7a7e7d787d7c7783847f8788838f8f8d999997a3a3a3acaeadb3b5b4b6b8b7
+c1c3c2caccc9cdcfcccecfcacfd0cbd0cfcad6d5d0e0dfdacac9c4ddded8d8d9d3e1e3ded2d7d1
+dbe1dddce2e0e4eae6e4eae0e3e9dfeceee9e4e6e3e7e6e4f2f1efede9e6e9e6e1cac7bec1bdb2
+aeaa9e9593877a777066625f605e5f6761615e535160524f685e5c645c5a706c6d7f7f817f8084
+999da09ea2a5aaaeafb6b8b7b9bab5bcbbb6c3c0b9c6c2b7c4c0b7c1c0bcc1c1c1c3c3c3c7c7c7
+cacacacdcdcdd0d0d0d1d1d1d2d2d2d6d6d6dbdbdbdededee0e0e0e3e3e3e6e6e6e9e9e9ededed
+efefeff2f2f2f5f5f5f6f6f6f8f8f8fafafafcfcfcfbfbfbfdfdfdffffffffffffffffffffffff
+fffffffffffffefefefefefe
+fffdfcfffefdfffefffefcfdfafafcf7f8fceff3f6e8ecefd4d8dbcaced1b8bcbda6aaa99b9f9e
+9698958b8d8a81837e848985818881858a848d928c989b94a4a59fb3b4aec0bfbac6c5c1cecdc9
+d5d5d3d7d7d9d9dadedce0e3dcdfe4d9dce1d2d6d9dfe3e4dce0e3d0d4d5cbd0d3c8cecec2cacc
+c4cdccc2c8c8bcc2c2b5b9b8b3b5b4b6b6b4b8b7b5b2aeada7a3a0b2b2aaa4a296a5a195aea594
+a998849f8971a38467a78361aa7f5c9d714e9a7151916c516d4e396a53436c5b51392c268c8281
+9990938c83848e88889f9a979e9a979e9d989fa09aa3a5a0acaea9b8bab7c1c2c4c8c9cdcecfd4
+d5d4dadad9dfd5d6dadddee0d0d1d3d2d3d7cacbcfbbbfc2c6c7ccbdbec3b0b1b5b2b1b6aeaeb0
+adabacafabaaa9a4a1aba3a0b7afadb6b0b4b9b4bac0bbbfbcbabdb6b4b5b6b4b5adacaa989795
+9e9d9b9d9b9c9a989998939795909695909797929999949aa09f9da6a7a1afb0aab6b7b1babbb5
+bdbeb8c1c2bcc3c4becacbc5c7c8c2c7c8c2cccdc7cfd0cacecfc9cdcec8cdcec9cbcdcccecfd1
+c8cac9c6c8c5dddfdad4d7d0c3c4bcd8dacfcecfc7d3d4ccd8d7d2d7d6d2d2d1cfcccacdcdc8ce
+cec9cdc9c5c4cac6c3bdb9b6b2aeadb4b0b1a6a4a5a19ca0a3a1a4a09ea19d9b9ea19fa0aba9aa
+b2b1afb8b7b5c4c4c2d2d2d0d2d0d1dedcdde2dedddedddbe4e0dddfdedad7d4cfd0cfcac9c6bf
+bfbfb7b2b1aca3a29da2a19d9998969e9e9c9898989a9c9b9c9d9fa6a7a9b4b5b7bdbec0c2c2c2
+cbc7c6d2cdcae0d7d2dad1ccd3cac5cfc7c4cac6c7c3c2c7b9bcc3b3b6bbabababa5a4a09b9a96
+93928e908f8b908f8b91928d929290989a979d9f9ca5a7a6afb1b0babbbdc1c5c6c9cacccbcfd0
+c8cccdced2d3ced2d1d3d5d4dadcd9d8dad5d5d6d1dadbd6dadbd6d5d6d1d1d3ceedefeadadfd9
+e7ece8e2e8e4e4ebe4ecf1eaf5f8f1fdfffaf5f5f3f4f4f4f5f3f4e6e5e3e9e8e4d6d3cec1c1b9
+adaaa39b9b93908f8b8584827c7c7e797778837b79716765857d7b7d79787e7c7d9191938b8c90
+9ea2a5a4a8aba7abacb3b5b4bfbfbdc4c3bfc4c1bac7c3bacac7c0cac9c7cacacacdcdcdd1d1d1
+d6d6d6dadadadddddddededee1e1e1e4e4e4e9e9e9ebebebedededefefeff2f2f2f5f5f5f2f2f2
+f4f4f4f6f6f6f8f8f8f9f9f9fafafafdfdfdfffffffcfcfcfdfdfdfffffffffffffefefefefefe
+fefefefffffffefefefefefe
+fffdfefffefffffefffffffffefefef8f8faeff0f2eaebeddbdcded0d1d3c1c3c2b4b6b5acaead
+a6a6a6a0a0a09b9b999a9c9b9b9d9a9ea09da4a6a3aeaeacb8b8b6c2c2c0c8c8c6cfcfcdd2d2d0
+d8d8d8dededee2e2e4e2e3e5e1e2e4e0e1e3dedfe1dddfdedbdcded7d9d8d3d4d6cfd1d0cccdcf
+cacccbc6c8c7c6c8c7c5c7c6c5c5c5c4c4c4c2c2c2c2c0c1c1c0becac7c2bebab1c2b8aed2c2b3
+a38c7a9a7e68a482669c7858946b4ba47b5d8c674c88664d674b365b4434513f334b3e3697928f
+9593948f8d8e9d9b9c9e9d9bafaeacadadabb2b2b0b8b8b6bebebcc7c7c7d0d0d0d7d7d9dadadc
+dadadcdadadcdfdfe1ddddddd9d9d9d5d5d7d0d0d2cacbcdc8c8cac6c6c8c1c1c3c0c0c2bfbfbf
+bebebec0bebfc1c0bec3c2c0c4c3c1c8c6c7cac8cbcccacbcacacac5c5c5bebebeb6b6b6b0b0b0
+acacaca8a8a8a4a4a4a19fa0a2a0a3a5a3a6aba9acaeacafb4b4b4b7b7b5bdbdbbc3c3c1c8c8c6
+cbcbc9cdcdcbcdcdcbd0d0ced1d1cfd2d2d0d3d3d1d4d4d2d5d5d3d6d6d4d6d6d4d7d7d7d8d8d8
+d9d9d9dadadadcdcdadddddbdfdfdddfe0dbe2e2e0e3e3e1e4e4e2e3e3e1e0e0e0dbdbdbd6d4d7
+d2d0d1d2d0d1cccbc9c4c3c1bbb9bab4b2b3b0b0b0b0aeafafafafaeaeaeb1b1b1b7b7b7bfbfbf
+c8c8c8d1d1d1d8d8d8dbdbdbe1e1e1e7e7e7edebececececebeae8e6e6e4dedddbd5d5d3cecdcb
+c7c7c5bebebcb5b5b3afafadacacacacacacadadadb1b1b1b6b6b6bebebec7c7c7cfcfcfd5d5d5
+d9d7d8dbdad8dfdbdadedad9dbd7d6d5d4d2cecccdc5c5c7bdbec0b9babcb0b0b0acacaaa7a7a5
+a3a3a1a1a19fa2a2a0a5a5a3a7a7a7adadadb2b2b2bababac2c2c2c8c8c8cdcfced2d2d2d4d6d5
+d5d7d6d6d8d7d7d9d8d9d9d9dadadadbdbd9dcdcdadcdcdadddddbdddddbdfdfdde1e1dfe4e6e3
+e8eae9edefeeeff1eef1f3f0f7f7f5f9f9f7f8f8f8f7f7f7f5f5f5eeeeeee5e5e3d8d7d5cbcbc9
+bdbcbaafafada4a4a29a9a9a9696969696969695939894939796949a98999e9e9ea4a4a4aaaaac
+acadafb4b5b7babcbbc3c3c3c9c9c9cbcbc9cfceccd4d3cfd8d7d5d8d8d8dadadadddddde1e1e1
+e5e5e5e8e8e8eaeaeaebebebefefeff0f0f0f2f2f2f3f3f3f5f5f5f7f7f7f9f9f9f9f9f9f8f8f8
+f9f9f9fafafafbfbfbfcfcfcfdfdfdfefefefefefefefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffffffffffffffffffffefefef9f9f9f3f3f3eeeeeee7e7e7dededed3d3d3cbcbcbc6c6c6
+c2c2c2bdbdbdbababab7b7b7b8b8b8babababebebec5c5c5cdcdcdd4d4d4d8d8d8dbdbdbdddddd
+e1e1e1e5e5e5e8e8e8e8e8e8e7e7e7e6e6e6e5e5e5e4e4e4e2e2e2dfdfdfdcdcdcd8d8d8d5d5d5
+d3d3d3d1d1d1d2d2d2d3d3d3d4d4d4d5d5d5d5d5d5d5d5d5d6d5d3d8d5d0e2dbd3ddd0c7d4c2b4
+87705e9d7f679f7d61a07b5e936c4d7c573a7b593e81634b624734523d2c645244766960aca8a5
+b2b2b2b3b3b3bcbcbcb2b2b2bbbbbbbcbcbcc6c6c6ccccccd0d0d0d7d7d7dededee3e3e3e5e5e5
+e5e5e5e4e4e4e4e4e4e3e3e3e0e0e0dcdcdcd8d8d8d4d4d4d1d1d1d0d0d0cfcfcfcfcfcfd0d0d0
+d1d1d1d3d3d3d7d7d7dadadadcdcdcdedededfdfdfe0e0e0dfdfdfdadadad4d4d4cdcdcdc8c8c8
+c3c3c3c0c0c0bdbdbdbababababababdbdbdc2c2c2c5c5c5cacacacdcdcdd2d2d2d6d6d6dadada
+dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdddddddedededfdfdfe0e0e0e0e0e0e2e2e2e3e3e3
+e4e4e4e6e6e6e8e8e8eaeaeaebebebecececeeeeeeefefefefefefeeeeeeebebebe7e7e7e2e2e2
+dfdfdfd9d9d9d5d5d5cececec7c7c7c3c3c3c1c1c1c1c1c1c1c1c1c7c7c7cacacacfcfcfd6d6d6
+dddddde3e3e3e8e8e8ebebebefefeff4f4f4f7f7f7f4f4f4f0f0f0ebebebe3e3e3dbdbdbd6d6d6
+d2d2d2ccccccc6c6c6c3c3c3c3c3c3c4c4c4c6c6c6cccccccfcfcfd6d6d6dddddde3e3e3e8e8e8
+eaeaeaebebebe9e9e9e7e7e7e4e4e4dededed7d7d7d0d0d0c9c9c9c6c6c6c5c5c5c2c2c2bebebe
+bbbbbbbabababcbcbcbfbfbfc1c1c1c5c5c5cacacad0d0d0d5d5d5dadadadddddde0e0e0e2e2e2
+e0e0e0e0e0e0e1e1e1e2e2e2e3e3e3e3e3e3e4e4e4e4e4e4e4e4e4e5e5e5e6e6e6e9e9e9ececec
+f0f0f0f3f3f3f5f5f5f7f7f7fbfbfbfdfdfdfbfbfbfbfbfbfafafaf3f3f3ececece0e0e0d6d6d6
+cbcbcbc4c4c4bdbdbdb7b7b7b5b5b5b7b7b7b8b8b8b8b8b8b8b8b8babababdbdbdc1c1c1c6c6c6
+c8c8c8c5c5c5cbcbcbd3d3d3d7d7d7d9d9d9dcdcdce0e0e0e4e4e4e7e7e7e8e8e8ebebebeeeeee
+f1f1f1f4f4f4f6f6f6f7f7f7f8f8f8f8f8f8f9f9f9fbfbfbfcfcfcfefefefffffffffffffcfcfc
+fdfdfdfdfdfdfefefefffffffffffffffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffffffffffffffffffffefefefbfbfbf7f7f7f4f4f4efefefeaeaeae3e3e3dedededcdcdc
+dadadad7d7d7d5d5d5d3d3d3d4d4d4d5d5d5d7d7d7dbdbdbdfdfdfe3e3e3e5e5e5e9e9e9eaeaea
+ecececedededeeeeeeededededededecececebebebebebebe9e9e9e7e7e7e5e5e5e2e2e2e0e0e0
+dededee0e0e0e1e1e1e3e3e3e5e5e5e7e7e7e8e8e8e9e9e9eae9e7e2dfdaeae6dbf4eaded1c1b1
+8b76619b8168947558916e508865457f5c3e8a6b4e54391e6148326856424636269a9086bcb8b5
+c5c5c5c9c9c9d5d5d5cdcdcdd6d6d6d6d6d6dfdfdfdfdfdfe2e2e2e5e5e5e9e9e9ebebebececec
+ebebebebebebebebebeaeaeae8e8e8e5e5e5e3e3e3e0e0e0dfdfdfdddddddededededededfdfdf
+e1e1e1e4e4e4e8e8e8ebebebedededefefefefefefefefefedededeaeaeae5e5e5e0e0e0dddddd
+d9d9d9d7d7d7d5d5d5d4d4d4d4d4d4d6d6d6d8d8d8dadadadededee0e0e0e3e3e3e6e6e6e8e8e8
+e8e8e8e7e7e7e7e7e7e9e9e9e9e9e9e9e9e9eaeaeaeaeaeaeaeaeaebebebebebebeaeaeaebebeb
+ecececeeeeeef1f1f1f3f3f3f4f4f4f5f5f5f7f7f7f7f7f7f6f6f6f5f5f5f3f3f3efefefececec
+eaeaeae5e5e5e2e2e2ddddddd9d9d9d7d7d7d6d6d6d8d8d8d9d9d9dededee0e0e0e5e5e5eaeaea
+eeeeeef2f2f2f4f4f4f6f6f6f7f7f7fbfbfbfcfcfcf8f8f8f4f4f4f0f0f0eaeaeae3e3e3e3e3e3
+e1e1e1ddddddd9d9d9d8d8d8dadadadddddddfdfdfe2e2e2e4e4e4e9e9e9eeeeeef1f1f1f4f4f4
+f5f5f5f5f5f5f3f3f3f1f1f1eeeeeee9e9e9e4e4e4dfdfdfdbdbdbd9d9d9d8d8d8d7d7d7d4d4d4
+d2d2d2d2d2d2d5d5d5d8d8d8dadadadcdcdcdfdfdfe3e3e3e5e5e5e7e7e7e8e8e8e9e9e9eaeaea
+ebebebebebebebebebececececececededededededededededededeeeeeeefefeff2f2f2f4f4f4
+f6f6f6f8f8f8f9f9f9fbfbfbfefefefefefefefefefefefefdfdfdf9f9f9f4f4f4e9e9e9e2e2e2
+dbdbdbd9d9d9d7d7d7d4d4d4d4d4d4d6d6d6d0d0d0cfcfcfcecececfcfcfd0d0d0d3d3d3d5d5d5
+d7d7d7dbdbdbdfdfdfe5e5e5e8e8e8eaeaeaecececefefeff2f2f2f1f1f1f3f3f3f5f5f5f7f7f7
+f9f9f9fbfbfbfcfcfcfdfdfdfbfbfbfbfbfbfcfcfcfcfcfcfdfdfdfefefeffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffffffffefefefefefefefefefefefefbfbfbfafafaf5f5f5f2f2f2eeeeeeebebebeaeaea
+e8e8e8e5e5e5e3e3e3e5e5e5e6e6e6e7e7e7e8e8e8e9e9e9eaeaeaececececececf2f2f2f2f2f2
+f2f2f2f2f2f2f2f2f2f2f2f2f1f1f1f1f1f1f1f1f1f0f0f0f0f0f0efefefedededebebebeaeaea
+e9e9e9edededeeeeeeeeeeeeefefeff0f0f0f0f0f0f0f0f0efefedfffff8e8e4d9f6eee1a79a89
+887660856d53876c4f7d5e3f75543586674885674b4e341b4d39213e2d192e2110d2cabdd3cfcc
+d4d4d4d2d2d2e2e2e2e3e3e3f1f1f1ebebebecececedededeeeeeeefefeff0f0f0f1f1f1f1f1f1
+f1f1f1f1f1f1f0f0f0f0f0f0efefefeeeeeeedededebebebebebebeaeaeaebebebebebebececec
+ecececeeeeeef0f0f0f2f2f2f3f3f3f5f5f5f5f5f5f4f4f4f2f2f2f0f0f0ececece9e9e9e8e8e8
+e7e7e7e7e7e7e6e6e6e5e5e5e6e6e6e6e6e6e8e8e8e9e9e9eaeaeaebebebedededefefefefefef
+efefefeeeeeeeeeeeef2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f0f0f0f1f1f1
+f2f2f2f5f5f5f7f7f7f9f9f9fbfbfbfbfbfbfbfbfbfbfbfbfafafaf8f8f8f6f6f6f5f5f5f3f3f3
+f2f2f2eeeeeeecececeaeaeae7e7e7e7e7e7e7e7e7e9e9e9eaeaeaebebebedededf1f1f1f5f5f5
+f8f8f8f9f9f9fafafafafafaf9f9f9fcfcfcfdfdfdfafafaf8f8f8f8f8f8f5f5f5f0f0f0efefef
+edededeaeaeae7e7e7e6e6e6e8e8e8eaeaeaebebebecececeeeeeef1f1f1f4f4f4f6f6f6f7f7f7
+f7f7f7f7f7f7f6f6f6f5f5f5f3f3f3f0f0f0eeeeeeedededecececececece7e7e7e5e5e5e4e4e4
+e3e3e3e3e3e3e5e5e5e7e7e7e9e9e9ebebebecececeeeeeeefefefeeeeeeedededeeeeeeeeeeee
+f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f3f3f3f5f5f5f7f7f7f9f9f9
+fafafafbfbfbfbfbfbfdfdfdfdfdfdfdfdfdfdfdfdfefefefdfdfdfbfbfbf8f8f8f3f3f3eeeeee
+eaeaeaeaeaeae9e9e9e6e6e6e6e6e6e7e7e7e8e8e8e7e7e7e6e6e6e6e6e6e6e6e6e7e7e7e9e9e9
+eaeaeaebebebeeeeeef1f1f1f4f4f4f5f5f5f6f6f6f8f8f8fafafaf7f7f7f8f8f8f9f9f9fbfbfb
+fcfcfcfdfdfdfefefefefefefbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfefefe
+fefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffffffffefefefefefefffffffffffffffffffefefefafafaf9f9f9f8f8f8f7f7f7f6f6f6
+f4f4f4f2f2f2f1f1f1f3f3f3f4f4f4f4f4f4f5f5f5f5f5f5f6f6f6f6f6f6f6f6f6f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f6f6f6f5f5f5f4f4f4f3f3f3
+f3f3f3f6f6f6f6f6f6f6f6f6f7f7f7f6f6f6f6f6f6f5f5f5f4f4f2fffff8efede1f6f0e2938b78
+7869526f5b426a5236513819462b0d5d442541290d3d291035250e504330877c6ae6e0d2efeeea
+efefefe8e8e8f3f3f3f0f0f0fafafaf4f4f4f4f4f4f8f8f8f8f8f8f8f8f8f8f8f8f9f9f9f9f9f9
+fafafafafafaf7f7f7f6f6f6f6f6f6f6f6f6f6f6f6f5f5f5f5f5f5f5f5f5f8f8f8f8f8f8f8f8f8
+f8f8f8f8f8f8f9f9f9f9f9f9fafafafcfcfcfcfcfcfbfbfbf9f9f9f7f7f7f6f6f6f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f5f5f5f5f5f5f5f5f5f4f4f4f5f5f5f7f7f7f8f8f8f9f9f9
+f9f9f9f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f7f7f7f7f7f7f7f7f7f7f7f7f9f9f9fafafa
+fbfbfbfcfcfcfefefefffffffffffffffffffffffffffffffefefefdfdfdfcfcfcfcfcfcfbfbfb
+fbfbfbf6f6f6f5f5f5f4f4f4f3f3f3f2f2f2f3f3f3f4f4f4f4f4f4f5f5f5f7f7f7fafafafdfdfd
+fffffffffffffffffffffffffdfdfdfffffffffffffefefefefefefffffffffffffcfcfcf7f7f7
+f6f6f6f4f4f4f2f2f2f1f1f1f2f2f2f3f3f3f4f4f4f6f6f6f7f7f7f9f9f9fbfbfbfcfcfcfdfdfd
+fdfdfdfdfdfdfafafaf8f8f8f7f7f7f5f5f5f5f5f5f5f5f5f6f6f6f7f7f7f5f5f5f4f4f4f3f3f3
+f2f2f2f2f2f2f3f3f3f4f4f4f5f5f5f6f6f6f8f8f8f9f9f9f8f8f8f7f7f7f6f6f6f6f6f6f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f6f6f6f6f6f6f6f6f6f6f6f6f7f7f7f8f8f8f9f9f9fafafafcfcfc
+fcfcfcfdfdfdfdfdfdfffffffdfdfdfcfcfcfdfdfdfefefefefefefdfdfdfcfcfcfdfdfdf8f8f8
+f6f6f6f7f7f7f7f7f7f4f4f4f3f3f3f4f4f4f5f5f5f5f5f5f4f4f4f4f4f4f5f5f5f6f6f6f7f7f7
+f8f8f8f5f5f5f6f6f6f8f8f8f9f9f9fafafafbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfefefeffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffffffffefefefefefefffffffffffffffffffffffffbfbfbfcfcfcfcfcfcfdfdfdfdfdfd
+fcfcfcfcfcfcfcfcfcfafafafafafafafafafbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfbfbfbfbfbfb
+fbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfbfbfb
+fafafafbfbfbfbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfbf1f2ecfdfdf3f3efe39e9787
+62554267574059452c4631144830143c270a3d29103b2b12473b25776c5a8e8775e2ded2f9f8f4
+fffffffcfcfcfffffff2f2f2f9f9f9f8f8f8fffffffcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfd
+fefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfdfdfd
+fefefefefefefffffffffffffffffffffffffffffffffffffffffffefefefdfdfdfdfdfdfcfcfc
+fafafafbfbfbfbfbfbfbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfafafafbfbfbfcfcfcfdfdfdfefefe
+fefefefefefefefefefdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfdfdfdfd
+fefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefefe
+fefefefdfdfdfcfcfcfcfcfcfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfcfcfcfefefeffffff
+fffffffffffffffffffffffffffffffffffffffffffdfdfdfcfcfcfffffffefefefcfcfcfcfcfc
+fcfcfcfbfbfbfbfbfbfbfbfbfcfcfcfefefefefefefdfdfdfdfdfdfefefeffffffffffffffffff
+fffffffffffffffffffefefefdfdfdfbfbfbfafafafafafafbfbfbfbfbfbfdfdfdfdfdfdfcfcfc
+fbfbfbfbfbfbfafafafafafafbfbfbfcfcfcfdfdfdfefefefdfdfdfcfcfcfbfbfbfcfcfcfefefe
+fcfcfcfcfcfcfcfcfcfcfcfcfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfcfcfcfcfcfcfdfdfdfefefe
+fffffffffffffffffffffffffefefefdfdfdfffffffffffffffffffefefefffffffefefefafafa
+f9f9f9fbfbfbfcfcfcfafafafafafafcfcfcf7f7f7f7f7f7f7f7f7f7f7f7f8f8f8f8f8f8f9f9f9
+fafafafcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfefefefffffffffffffefefefefefeffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffefefefdfdfdfefefefffffffffffffffffffffffffbfbfbfcfcfcfdfdfdfefefefefefe
+fefefefefefefffffffbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfdfdfd
+fefefefefefefefefefefefefefefefdfdfdfefefefffffffffffffffffffffffffefefefefefe
+fdfdfdfdfdfdfdfdfdfefefefffffffffffffffffffffffffffffdfdfef9fffff8f1eee5b8b2a6
+736a5b605342594a355b4b3462503a3e2c1662513d5e513e564a3a3b3424767062fffcf3f9f8f4
+fffffffdfdfdfffffff6f6f6fcfcfcfcfcfcfffffffcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfd
+fdfdfdfdfdfdfffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfdfdfdfdfdfd
+fefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfdfdfdfdfdfd
+fefefefefefefefefefffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfdfdfd
+fdfdfdfcfcfcfcfcfcfbfbfbfbfbfbfbfbfbfcfcfcfcfcfcfdfdfdfefefefefefefefefefdfdfd
+fdfdfdfffffffffffffffffffffffffffffffffffffefefefefefefdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfffffffefefefbfbfbfafafafcfcfcfcfcfcfafafaffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffefefefdfdfdfdfdfdfdfdfdfefefefdfdfdfdfdfdfefefe
+fefefefdfdfdfdfdfdfdfdfdfcfcfcfdfdfdfefefefefefefdfdfdfcfcfcfcfcfcfdfdfdfefefe
+fffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfdfdfdfdfdfdfdfdfdfefefe
+fffffffffffffffffffffffffffffffefefefffffffffffffffffffefefefffffffdfdfdf9f9f9
+f8f8f8fbfbfbfdfdfdfcfcfcfcfcfcfefefeffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffefefefdfdfdfdfdfdfefefefffffffffffffffffffdfdfdfdfdfdfefefefefefe
+fefefefefefefdfdfdfdfdfdfefefefefefefefefefefefefefefefdfdfdfdfdfdfdfdfdffffff
+fffffffffffffffffffffffffffffffffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+fffffffefefefdfdfdfefefeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffefefefdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfefefefffffffcfcfcfdfdfd
+fefefefefefefefefefdfdfdfcfcfcfbfbfbfdfdfdfefefefefefefefefefefefefdfdfdfdfdfd
+fcfcfcfdfdfdfefefefefefefefefefefefefdfdfdfdfdfdfcfcfcf6f8f5f8f9f4fffffaf7f4ed
+c7c0b6655b4f463a2c3e31213e2e1f403323382c1e392f23342c213a3329fffff6fffffafffffd
+fffffff9f9f9fffffffdfdfdfffffffcfcfcfcfcfcffffffffffffffffffffffffffffffffffff
+fffffffffffffefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdffffffffffffffffff
+fffffffffffffffffffefefefdfdfdfefefefefefeffffffffffffffffffffffffffffffffffff
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefffffffefefefefefefefefefefefefefefe
+fefefefefefefffffffefefefefefefefefeffffffffffffffffffffffffffffffffffffffffff
+fefefefdfdfdfcfcfcfbfbfbfafafaf9f9f9fcfcfcfdfdfdffffffffffffffffffffffffffffff
+fffffffefefefefefefffffffffffffffffffffffffffffffffffffffffffffffffefefefdfdfd
+fdfdfdfcfcfcfcfcfcfcfcfcfdfdfdfffffffffffffdfdfdfdfdfdfffffffffffffefefeffffff
+fffffffffffffffffffffffffefefefefefefefefefffffffffffffffffffffffffefefefdfdfd
+fdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfefefefefefefffffffffffffffffffefefefefefeffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffefefefdfdfdfdfdfdfefefeffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfcfcfcfbfbfbfbfbfbfcfcfc
+fefefefffffffffffffffffffefefefdfdfdfffffffffffffefefefdfdfdfefefefffffffefefe
+fcfcfcfefefefffffffffffffffffffffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefffffffefefefcfcfcfdfdfdfefefefefefefefefefefefeffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe
+fefefefffffffffffffffffffffffffffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefeffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffdfdfdfefefefefefefffffffffffffefefefefefefdfdfdfffffffefefe
+fefefefefefefefefefdfdfdfdfdfdfdfdfdfffffffefefefefefefdfdfdfdfdfdfefefefefefe
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefffdfefffefefefffffd
+fffefbfffef8fffdf6fffdf6fffcf6fffcf6fffdf6fffef8fffefafffefbfffefdfffffdffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffefefefcfcfcfbfbfbfafafafafafaffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefcfcfcfefefefefefe
+fefefefefefefefefefefefefffffffffffffbfbfbfbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfcfcfc
+fcfcfcfffffffffffffffffffffffffffffffffffffffffffffffffefefefafafaf9f9f9fefefe
+fffffffffffffefefefefefefffffffffffffefefefefefefefefefefefefdfdfdfdfdfdfefefe
+fefefefffffffffffffffffffffffffefefefefefefefefefefefefefefefdfdfdfdfdfdfdfdfd
+fdfdfdfcfcfcfefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fefefefefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefdfdfdfdfdfd
+fefefefefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fdfdfdfefefefffffffefefefcfcfcfafafafbfbfbf9f9f9fafafafbfbfbfbfbfbf9f9f9fbfbfb
+fffffffefefefffffffffffffefefefdfdfdfcfcfcfdfdfdffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffefefefefefefefefefefefefefefefefefefefefefefefeffffffffffff
+fefefefefefefefefefefefefdfdfdfdfdfdfffffffefefefefefefdfdfdfdfdfdfefefefefefe
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefffdfefffefdfffffeff
+fffefffffdfdfffdfdfffefbfffdfbfffdfbfffdfdfffdfdfffefffffefffffefffffeffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffefefefdfdfdfcfcfcfcfcfcfbfbfbffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefcfcfcfcfcfcfcfcfc
+fcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfcfcfcfdfdfdfdfdfdfefefefefefefdfdfd
+fdfdfdfffffffffffffffffffffffffffffffffffffffffffffffffefefefbfbfbfafafafefefe
+fffffffefefefdfdfdfdfdfdfffffffffffffefefefefefefefefefefefefdfdfdfdfdfdfefefe
+fefefefffffffffffffffffffffffffefefefefefefefefefefefefefefefdfdfdfdfdfdfdfdfd
+fdfdfdfdfdfdfefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fefefefefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefdfdfdfdfdfd
+fefefefefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fefefefefefefffffffefefefcfcfcfafafafffffffdfdfdfdfdfdfffffffefefefdfdfdffffff
+fffffffefefefffffffffffffefefefdfdfdfcfcfcfdfdfdffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffefefefefefefefefefefefefefefefefefefefefefefefeffffffffffff
+fffffffefefefefefefefefefefefefefefefffffffffffffefefefefefefefefefefefeffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffefdfffefdfffefdfffffeff
+fffefffffdfffffdfffffdfffffdfffffdfffffdfffffefffffefffffefffffefffffeffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefefefefefefefefefefeffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefcfcfcfcfcfcfcfcfc
+fdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfdfdfdfefefefefefefffffffffffffefefe
+fefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfbfbfbffffff
+fffffffdfdfdfcfcfcfcfcfcfffffffffffffefefefefefefefefefefefefdfdfdfdfdfdfefefe
+fefefefffffffffffffffffffffffffefefefefefefefefefefefefefefefefefefdfdfdfdfdfd
+fdfdfdfdfdfdfefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fefefefefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefdfdfdfdfdfd
+fefefefefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fefefefefefefffffffefefefcfcfcfafafafcfcfcfafafafafafafcfcfcfbfbfbf9f9f9fcfcfc
+fffffffefefefffffffffffffefefefdfdfdfcfcfcfdfdfdffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+showpage
+%%Trailer
+end
+%%EOF
Added: packages/openev/branches/upstream/current/doc/openevreport.cls
===================================================================
--- packages/openev/branches/upstream/current/doc/openevreport.cls (rev 0)
+++ packages/openev/branches/upstream/current/doc/openevreport.cls 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,132 @@
+\NeedsTeXFormat{LaTeX2e}
+
+\ProvidesClass{openevreport}[1998/01/13 OpenEV report class]
+
+% Switch off some of the report options.
+
+\DeclareOption{a4paper}{\OptionNotUsed}
+\DeclareOption{a5paper}{\OptionNotUsed}
+\DeclareOption{b5paper}{\OptionNotUsed}
+\DeclareOption{letterpaper}{\OptionNotUsed}
+\DeclareOption{legalpaper}{\OptionNotUsed}
+\DeclareOption{executivepaper}{\OptionNotUsed}
+\DeclareOption{landscape}{\OptionNotUsed}
+\DeclareOption{twoside}{\OptionNotUsed}
+\DeclareOption{titlepage}{\OptionNotUsed}
+\DeclareOption{onecolumn}{\OptionNotUsed}
+
+% The default action for any option is to pass it to the report class.
+
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}
+
+% Execute the options.
+
+\ProcessOptions
+
+% Load the report class.
+
+\LoadClass[oneside]{report}
+
+% Load the graphics package (for including figures)
+
+\RequirePackage{graphicx}
+
+% Load the PostScript fonts package
+
+\RequirePackage{pslatex}
+
+% Load the fancy headings package
+
+\RequirePackage{fancyhdr}
+
+% Load the latex2html package
+
+\RequirePackage{html}
+
+% Define the heading fonts
+
+\newcommand{\@headingfont}{\fontfamily{phv}\selectfont}
+
+\newcommand{\@chapterfont}{%
+ \@headingfont\bfseries\huge
+}
+\newcommand{\@sectionfont}{%
+ \@headingfont\bfseries\Large
+}
+\newcommand{\@subsectionfont}{%
+ \@headingfont\bfseries\slshape\large
+}
+\newcommand{\@subsubsectionfont}{%
+ \@headingfont\bfseries\normalsize
+}
+
+% Redefine headings
+
+\renewcommand\section{\@startsection {section}{1}{\z@}%
+ {-3.5ex \@plus -1ex \@minus -.2ex}%
+ {2.3ex \@plus.2ex}%
+ {\@sectionfont}}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\@subsectionfont}}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+ {-3.25ex\@plus -1ex \@minus -.2ex}%
+ {1.5ex \@plus .2ex}%
+ {\@subsubsectionfont}}
+
+\renewcommand{\chapter}{%
+ \if at openright\cleardoublepage\else\clearpage\fi
+ \global\@topnum\z@
+ \@afterindentfalse
+ \secdef\@chapter\@schapter}
+
+\def\@makechapterhead#1{%
+ \vspace*{30\p@}%
+ {\parindent \z@ \raggedright \normalfont
+ \ifnum \c at secnumdepth >\m at ne
+ \@chapterfont \@chapapp\space \thechapter.\hspace*{20\p@}%
+ \fi
+ \@chapterfont #1\par\nobreak
+ \vskip 40\p@
+ }}
+
+% Page margins
+
+\setlength{\textwidth}{6.0in}
+\setlength{\oddsidemargin}{0.25in}
+\setlength{\textheight}{8.0in}
+\setlength{\topmargin}{0.0in}
+
+\newcommand{\verticaloffset}[1]{\setlength{\voffset}{#1}}
+
+% Headers and footers.
+
+\pagestyle{fancy}
+
+\lhead{\scshape OpenEV}
+\chead{}
+\rhead{\scshape\leftmark}
+
+\lfoot{\slshape\today}
+\cfoot{}
+\rfoot{\thepage}
+
+\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
+
+\renewcommand{\headrulewidth}{0.4pt}
+\renewcommand{\footrulewidth}{0.4pt}
+
+\newcommand{\headtext}[1]{\rhead{\scshape #1}}
+\newcommand{\foottext}[1]{\lfoot{\slshape #1}}
+
+% Set maximum number of figures/tables at top of page to 1
+
+\setcounter{topnumber}{1}
+\setcounter{totalnumber}{2}
+
+% Other useful commands
+
+% That's it!
+
+\endinput
Added: packages/openev/branches/upstream/current/doc/openevreport.perl
===================================================================
--- packages/openev/branches/upstream/current/doc/openevreport.perl (rev 0)
+++ packages/openev/branches/upstream/current/doc/openevreport.perl 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,16 @@
+package main;
+
+&do_require_package('report');
+&do_require_package('graphicx');
+&do_require_package('html');
+
+sub do_env_members {
+ &do_env_description;
+}
+
+&ignore_commands( <<_IGNORED_CMDS_);
+headtext # {}
+foottext # {}
+_IGNORED_CMDS_
+
+1; # Must be last line
Added: packages/openev/branches/upstream/current/doc/phaseclip.fig
===================================================================
--- packages/openev/branches/upstream/current/doc/phaseclip.fig (rev 0)
+++ packages/openev/branches/upstream/current/doc/phaseclip.fig 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,39 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+1 3 0 1 0 7 100 0 -1 0.000 1 0.0000 2700 3600 1200 1200 2700 3600 3900 3600
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 4825 2700 50 50 4825 2700 4875 2700
+1 3 0 1 0 0 100 0 20 0.000 1 0.0000 3925 3075 50 50 3925 3075 3975 3075
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 600 3600 4800 3600
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 2700 5700 2700 1500
+2 2 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 5
+ 1500 2400 3900 2400 3900 4800 1500 4800 1500 2400
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+ 2700 3600 4800 2700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4125 2700 4050 2925
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 4290 4455 3990 4605
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+ 0 0 1.00 60.00 120.00
+ 1950 4875 2025 4650
+4 0 0 100 0 22 12 0.0000 4 135 150 2850 1500 Q\001
+4 0 0 100 0 22 12 0.0000 4 135 60 4875 3525 I\001
+4 0 0 100 0 20 12 0.0000 4 180 585 5100 2625 sample\001
+4 0 0 100 0 20 12 0.0000 4 180 405 5100 2850 point\001
+4 0 0 100 0 20 12 0.0000 4 180 300 4125 2400 clip\001
+4 0 0 100 0 20 12 0.0000 4 180 405 4125 2625 point\001
+4 0 0 100 0 20 12 0.0000 4 180 1185 4200 4350 LUT boundary\001
+4 0 0 100 0 20 12 0.0000 4 135 750 1650 5100 maximum\001
+4 0 0 100 0 20 12 0.0000 4 180 855 1650 5325 magnitude\001
+4 0 0 100 0 22 12 0.0000 4 135 150 2775 3825 O\001
Added: packages/openev/branches/upstream/current/doc/toolbar.eps
===================================================================
--- packages/openev/branches/upstream/current/doc/toolbar.eps (rev 0)
+++ packages/openev/branches/upstream/current/doc/toolbar.eps 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,3931 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: GIMP PostScript file plugin V 1.06 by Peter Kirchgessner
+%%Title: /home/srawlin/devel/doc/technote/gview/toolbar.eps
+%%CreationDate: Fri Jun 16 11:22:21 2000
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 2
+%%Pages: 1
+%%BoundingBox: 14 14 202 99
+%%EndComments
+%%BeginProlog
+% Use own dictionary to avoid conflicts
+5 dict begin
+%%EndProlog
+%%Page: 1 1
+% Translate for offset
+14.400000 14.400000 translate
+% Translate to begin of first scanline
+0.000000 84.071856 translate
+187.200000 -84.071856 scale
+% Variable to keep one line of raster data
+/scanline 334 3 mul string def
+% Image geometry
+334 150 8
+% Transformation matrix
+[ 334 0 0 150 0 0 ]
+{ currentfile scanline readhexstring pop } false 3
+colorimage
+8080804b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b5f5b53776e5e575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757575757575757575757
+57575757575757575757575770695c6762564b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b808080
+4b4b4b464646858585858585858585858585858585858585858585858585858585858585858585
+858585858585858585858585858585858585858585858585858585858585858585858585858585
+8585856f6e6e7a7771a29c91878787878787878787878787878787878787878787878787878787
+878787878787878787878787878787878787878787878787878787878787878787878787878787
+878787878787878787878787878787878787878787878787878787878787878787878787898989
+8b8b8b8b8b8b8b8b8b8b8b8b8989898888888787878787878787878989898a8a8a8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b
+8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8a8a8a898989878787878787
+8787878888888989898b8b8b8b8b8b8b8b8b8a8a8a898989878787878787878787878787878787
+878787878787878787878787878787878787878787878787878787878787878787878787878787
+878787878787878787878787878787878787878787878787878787878787878787878787878787
+878787878787878787878787837e74837e76858585858585858585858585858585858585858585
+858585858585858585858585858585858585858585858585858585858585858585858585858585
+858585858585858585858585858585858585858585858585858585858585858585858585858585
+858585858585858585858585858585858585858585858585858585858585858585858585858585
+858585858585858585858585858585858585858585858585858585858585858585858585858585
+8585858585858585858585858585858585855f5f5e1515154b4b4b
+4b4b4b858585f8f8f8edededededededededededededededededededededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+edededc7c7c6cac9c9f7f6f7d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9
+d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9
+d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9e4dde5f0eef0
+f5f5f5f6f6f6f6f6f6e6e2e8dcd6ded7d2dad7d2d9d7d2d9e3dde4efedf0f5f5f5f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f5f5f5efedf0e6dfe6d9d3db
+d7d2d9d7d2dadcd7dee6e2e8f6f6f6f6f6f6f5f5f5f0edf0e4dde4d7d2d9d7d2d9d7d2d9d7d2d9
+d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9
+d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9d7d2d9
+d7d2d9d7d2d9d7d2d9d7d2d9bab8bad0d0cfffffffedededededededededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+ededededededededededededededededededadacab2726264b4b4b
+4b4b4b858585edededcbcbcbc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7a9a8a8bababaebe8ed9e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea5
+9e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea5
+9e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea5a090a7c9b8cbe3dee4
+ececececececeae8e9baadbfa495ab9e8ea59f8fa6a090a7c7b7cae2dce3ececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ececececececececececececececececececececececececececececececececececececececec
+ecececececececececececececececececececececececececececececece2dce2d0bfd1a595ac
+9f8fa69e8ea5a595acbaaec0eae8e9ecebebececece3dde3c8b8cba090a79e8ea59e8ea59e8ea5
+9e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea5
+9e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea59e8ea5
+9e8ea59e8ea59e8ea59e8ea5959098c2c2c2ffffffc9c9c8c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c79b9b9b2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b2afb3b2b0b2b1afb2b1afb2b2afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92839b92839a92849a92839a92849a92839b92839b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b9d8ca4dbd9dce6e6e6
+e6e6e6e5e5e5dacbd49e8fa393849b93849b96869d9d8ca4d9d6dae6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6a495ab
+95869d93849b93849b9f90a4dacbd4e2dde0e6e6e6e6e6e6dad8db9d8ca493849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1b0b3b2b0b2b1b0b2b1afb2b1b0b2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1b0b2b1afb2b1b0b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839b92839a92839a92839b92839a92839a92839b92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b94859bad9eb3dedbdee6e6e6
+e6e6e6e4e4e4b7a8b998899f93849b93849b9a8ca2ad9eb3dcd9dde6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6b3a6b9
+9a8ba293849b93849b998aa0b7a8b9d7d3d8e6e6e6e6e6e6dddbdead9eb393849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1b0b2b1afb2b1afb3b2b0b2b1b0b2b1b0
+b2b1b0b2b1afb2b1afb2b1afb2b1b0b2b1b0b3b2b0b2b1afb2b1afb2b1afb2b1b0b2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839a92849a92839a92839a92839a92839a93839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b97889fcdc6d0e2e1e2e6e6e6
+e4e4e4e2e2e29c8da494859c93849b93849ca699adcdc6d0e1e0e2e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6d0cad3
+a598ac93849c93849b94859c9c8da4cec9d0e5e5e5e6e6e6e2e1e2cdc6d096879f93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92839a92839a92849a92839a92849a92839b92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b95869da091a8e6e6e6e6e6e6e6e6e6
+dcdaddd1ccd393849b93849b93849b9888a0b3a8b9e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6afafaf9b9b9b9b9b9b9b9b9b9b9b9bd1d1d1e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e3e3e39b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9bcccccce6e6e6e6e6e69b9b9bd8d8d8
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6b7b7b7bcbcbce6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+b2a7b89888a093849b93849b93849bbfb7c3dcdadde6e6e6e6e6e6e6e6e69f90a895869d93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afafaeacafaeacafaeac
+afaeadb2b1afafaeacafaeacafaeacb0afaeb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb93849a92849a93839a93849b92849a93849a92849a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b9889a0af9fb5e6e6e6e6e6e6e6e6e6
+cbc4cfb0a2b793849b93849b93849b9f90a6beb3c2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6c8c8c84c4c4c202020202020202020202020969696d6d6d6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+dedede0000001b1b1b202020202020202020202020202020a1a1a1e6e6e6e6e6e6000000bcbcbc
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6565656656565e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+bdb2c29f8fa693849b93849b93849ba799afccc5cfe6e6e6e6e6e6e6e6e6af9eb49889a093849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1afafaeacafaeacafaeacafaeacafaeacafaeac
+afaeacafaeacafaeacb0afadb2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b1b0aeafaeacafaeacafaeacb1b0afb3b2b0b3b2b0b3b2b0afaeadafaeacb1b0aeb3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1af999999989898989898
+9c9c9cb2b1af9a9a9a989898989898a3a3a2b3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92839a93839b92839b92839b92839a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b9a8ca2b8abbee6e6e6e6e6e6e6e6e6
+c6becaa596ad93849b93849b93849ba495abc5bbc9e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6131313a8a8a8e6e6e6e6e6e6e6e6e6e6e6e64141417b7b7be6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6000000bcbcbc
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6565656656565e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+c4bac8a395aa93849b93849b93849ba091a8c6bfcae6e6e6e6e6e6e6e6e6b8aabe9a8ba293849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af999999999999999999999999999999999999
+999999999999999999a09f9fb2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a4a4a3999999999999999999abaaa9b3b2b0b3b2b0b3b2b09c9c9c999999a6a5a4b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1b0b3b2b0b2b1afb2b1afb2b1b0b2b1af999999252525060606
+262626fcfbfb9d9d9d2727270606066b6b6bfcfbfbb7b6b4b2b1afb2b1afb2b1b0b2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92839a92839a92839a92839a92839a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba293a7d9cad3e6e6e6e6e6e6e6e6e6
+c1b9c59d8ca493849b93849b93849bb4a5b6dcd2d8e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6909090090909cacacae3e3e3e6e6e6e6e6e6e6e6e6e6e6e6dfdfdf6b6b6b575757e6e6e6
+e6e6e6090909bdbdbd9a9a9a090909090909e1e1e1e6e6e6e6e6e6e6e6e6e6e6e6101010090909
+090909666666e6e6e6e6e6e6e6e6e6646464636363b3b3b3090909090909878787e6e6e6e6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6dcdcdc2f2f2f
+969696e6e6e6e6e6e6e6e6e63434348d8d8de0e0e0e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+dcd1d8b3a4b593849b93849b93849b9a89a1c2bac6e6e6e6e6e6e6e6e6e6d8cad3a192a693849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af9999991e1e1e060606060606060606060606
+060606060606060606494949f5f4f4b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a4a4a38f8f8f060606060606b2b2b2d5d5d4aaa9a89a9999191919060606828282e4e3e3b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1af999999202020000000
+212121fefefe9d9d9d222222000000686868ffffffb7b6b5b2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839b92839a92839a92839a92839a92839a92839b92839b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba396a9ded7dbe6e6e6e6e6e6e6e6e6
+bfb7c39888a093849b93849b93849bb7abb9e0dbdee6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e68c8c8c000000d2d2d2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e66a6a6a525252e6e6e6
+e6e6e60000006060607474746f6f6f6f6f6f767676cfcfcfe6e6e6d5d5d57676766f6f6f6f6f6f
+6f6f6f727272767676e0e0e0e6e6e65e5e5e3030307474746f6f6f6f6f6f737373a2a2a2e6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6292929
+939393e6e6e6e6e6e6e6e6e62d2d2d8f8f8fe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e0dbdeb6aab993849b93849b93849b97879ec0b8c4e6e6e6e6e6e6e6e6e6ded7dba295a893849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af999999191919000000000000000000000000
+000000000000000000464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a4a4a38f8f8f0000000000005c5c5cafafaea8a8a74e4e4e0a0a0a000000818181e6e5e5b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb3b1afb2b1afb2b1afa1a1a05f5e5e4d4d4d
+646464fefefea5a5a46060604d4d4d969696ffffffb7b6b5b2b1afb2b1afb3b1afb3b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839b92839a92839a92839a92839a92839a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba499aae3e3e3e6e6e6e6e6e6e6e6e6
+bdb5c194849c93849b93849b93849bbab2bee4e4e4e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e68c8c8c000000d2d2d2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e66a6a6a525252e6e6e6
+e6e6e60000003838387c7c7ce6e6e6e6e6e6040404b8b8b8e6e6e6c4c4c4000000dddddde6e6e6
+e6e6e6848484000000dadadae6e6e65e5e5e1c1c1c6a6a6ae6e6e6e5e5e56262625a5a5ae6e6e6
+dedede000000888888a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0cdcdcde6e6e6e6e6e6e6e6e6292929
+939393e6e6e6e6e6e6e6e6e62d2d2d8f8f8fe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e4e4e4b9b1bd93849b93849b93849b93849bbeb6c2e6e6e6e6e6e6e6e6e6e3e3e3a397aa93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af9999991919193232324d4d4d4d4d4d4d4d4d
+4d4d4d3e3e3e1d1d1d464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a9a8a79999982e2e2e0505050000005c5c5c7474740000000000003535359b9b9bd6d6d5b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2afb3b2b0b2b1afb2b1afb2b1afb2b1afafafade4e4e3f2f2f2
+f2f2f2f5f5f5b3b2b0e3e3e2f2f2f2f3f3f3f5f5f5b7b6b4b2b1afb2b2afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92849a92849a92849a92849a92849a92849a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba599abe5e5e5e6e6e6e6e6e6e6e6e6
+bcb5c093849b93849b93849b93849bbab3bee5e5e5e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e68c8c8c000000d2d2d2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e66a6a6a525252e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6040404b8b8b8e6e6e6c4c4c4000000c2c2c2c9c9c9
+c9c9c9747474000000dadadae6e6e65e5e5e5d5d5de6e6e6e6e6e6e5e5e56262625a5a5ae6e6e6
+dedede0000001717171c1c1c1c1c1c1c1c1c1c1c1c1c1c1ca0a0a0e6e6e6e6e6e6e6e6e6404040
+8b8b8bd6d6d6dededec9c9c93e3e3e9a9a9ae6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e5e5e5b9b1be93849b93849b93849b93849bbdb6c1e6e6e6e6e6e6e6e6e6e5e5e5a498aa93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af999999191919a6a6a6fafafaf5f5f5f5f5f5
+f5f5f5c9c8c75f5f5e464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b1b0ae9c9c9b2222220505050000000000000000001a1a1ab2b2b2d3d3d2b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1af999999989898989898
+9c9c9cb2b1af9a9a9a999999989898a3a3a2b3b2b0b2b2afb2b1afb2b2afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839a92839a92839a92839a92849a92849a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba498aae3e3e3e6e6e6e6e6e6e6e6e6
+bdb5c194849c93849b93849b93849bb9b1bde3e3e3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e68c8c8c000000d2d2d2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e66a6a6a525252e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6040404b8b8b8e6e6e6c4c4c4000000000000000000
+000000000000000000dadadae6e6e65e5e5e5d5d5de6e6e6e6e6e6e5e5e56262625a5a5ae6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+525252696969a5a5a5000000b8b8b8e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e3e3e3b8b0bc93849b93849b93849b94849cbeb6c2e6e6e6e6e6e6e6e6e6e3e3e3a397a993849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af999999191919a6a6a6dbdad9b3b2b0b3b2b0
+b3b2b0a2a2a1535353464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b09c9b9b2d2d2d000000000000000000ddddddcacac8b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1af999999272727090909
+292929fafafa9d9d9d2929290909096c6c6cfafafab7b6b4b2b1afb2b1afb3b1afb2b1afb3b1af
+b2b1af878786a0a0a0e9e6eb92839b92839a92839a92839b92839b92839b92839b92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849ba293a7dacdd5e6e6e6e6e6e6e6e6e6
+c1b8c49c8ba393849b93849b93849bb5a6b6ddd4dae6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e68c8c8c000000d2d2d2e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e66a6a6a525252e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6040404b8b8b8e6e6e6c4c4c4000000d0d0d0d8d8d8
+d8d8d8d8d8d8d8d8d8e5e5e5e6e6e65e5e5e5d5d5de6e6e6e6e6e6e5e5e56262625a5a5ae6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+525252696969a5a5a5000000b8b8b8e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+ddd3d9b4a6b693849b93849b93849b9989a0c2bac5e6e6e6e6e6e6e6e6e6dacdd5a192a693849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+9f9f9f9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9b9b9bb3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af999999191919a6a6a6dbdad9b3b2b0b3b2b0
+b3b2b0a2a2a1535353464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b1b0ae9a9a9a1a19190202020000000000000000000d0d0db0b0b0d6d5d4b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1af999999202020000000
+212121ffffff9d9d9d222222000000686868ffffffb7b6b5b2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839b92839a92839a92839a93839a92839a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b9c8da3c0b3c3e6e6e6e6e6e6e6e6e6
+c5bdc8a393ab93849b93849b93849ba899aecbc1cde6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6d0d0d0aeaeae414141b7b7b7e6e6e6e6e6e6e6e6e6e6e6e6686868777777c2c2c2e6e6e6
+e6e6e60000002d2d2d727272e6e6e6e6e6e6040404b8b8b8e6e6e6c4c4c4000000dddddde6e6e6
+e6e6e69b9b9b373737dddddde6e6e65e5e5e5d5d5de6e6e6e6e6e6e5e5e56262625a5a5ae6e6e6
+dedede000000c3c3c3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+c2c2c2777777585858aeaeaedbdbdbe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+cac0cca799ad93849b93849b93849b9e8fa6c5bec9e6e6e6e6e6e6e6e6e6c0b2c39c8da393849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+9e9e9e5353532424242424242424242424242424242424242424242d2d2decececbab9b8b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af99999919191980807fb3b2b19f9f9e9f9f9e
+9f9f9e9b9b9b535353464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a8a7a69797962424240404040000006565657f7f7f0000000000002a2a2a969695d9d9d8b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afa0a0a05a5a5a484848
+606060fefefea4a4a45c5c5c484848939393ffffffb7b6b5b2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb93849a93849a93849a93849a93849a93839a93849b92849a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b9a8ba1b5a7bbe6e6e6e6e6e6e6e6e6
+c7c0cba99ab093849b93849b93849ba293a9c3b8c7e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e64f4f4f8a8a8aa4a4a4a4a4a4a4a4a4a4a4a45d5d5d999999e6e6e6e6e6e6
+e6e6e6000000353535636363a4a4a4a4a4a4434343c5c5c5e6e6e6cecece414141a1a1a1a4a4a4
+a4a4a47a7a7a414141dddddde6e6e65e5e5e5d5d5de6e6e6e6e6e6e5e5e56262625a5a5ae6e6e6
+dedede0000008c8c8ca4a4a4a4a4a4a4a4a4a4a4a4a4a4a4cfcfcfe6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e67c7c7c404040e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+c2b7c6a293a993849b93849b93849ba293aac8c1cce6e6e6e6e6e6e6e6e6b5a6bb998aa193849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+9e9e9e3d3d3d0000000000000000000000000000000000000000000b0b0bffffffbdbcbab3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af9999991919195353527777766d6d6d6d6d6d
+6d6d6d6d6d6d3b3b3b464646f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a4a4a38f8f8f0000000000003232329c9c9cb2b2b1484848090909000000818181e6e5e5b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb3b1afb2b1afb2b1afb3b2b0e8e8e7f7f7f6
+f7f7f6f7f7f6b6b5b3e7e7e6f7f7f6f7f7f6f7f7f6b7b6b4b2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92849a92849a92849a92839a92849a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b98889fac9cb2e6e6e6e6e6e6e6e6e6
+cec8d2b6aabd93849b93849b93849b9e8ea5bcb0c0e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e64e4e4e171717171717171717171717abababe6e6e6e6e6e6e6e6e6
+e6e6e6000000bbbbbb9f9f9f171717171717e1e1e1e6e6e6e6e6e6e6e6e6e6e6e61e1e1e171717
+1717176f6f6fe6e6e6e6e6e6e6e6e66c6c6c6b6b6be6e6e6e6e6e6e5e5e56f6f6f686868e6e6e6
+dfdfdf1717171717171717171717171717171717171717179e9e9ee6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6878787515151e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+bbafbf9d8da493849b93849b93849bac9fb3cfc9d2e6e6e6e6e6e6e6e6e6ab9bb197889f93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a0a09f4d4d4d1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a242424ffffffbdbcbab3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1af9b9b9b2f2f2f1a1a1a1a1a1a1a1a1a1a1a1a
+1a1a1a1a1a1a1a1a1a595959f7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+a6a5a49393931a1a1a1a1a1ab5b5b5d3d2d1cac9c8f7f7f63737371a1a1a8e8e8ee6e5e5b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb93839a92839a92839a92839a92839a92839a93839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849c9a8ba3e6e6e6e6e6e6e6e6e6
+e4e4e4e0dfe093849b93849b93849b94859daea4b5e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+ada3b494859d93849b93849b93849bc9c5cce4e4e4e6e6e6e6e6e6e6e6e6998aa293849c93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0e0e0dfffffffffffffffffffffffffffffffffffffffffffffffffffffffbdbcbab3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0f2f2f1ffffffffffffffffffffffff
+fffffffffffffffffffffffff7f7f7b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b7b6b5ffffffffffffc9c8c7b3b2b0b3b2b0b3b2b0f4f4f4ffffffffffffe6e5e5b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb3b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb93839a92839a92839a92839a93839a92839a93839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b94859cb8abbedfdde0e6e6e6
+e5e5e5e4e3e4a596ac95869d93849b93849b9e90a6b8abbededbdfe6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6bdb2c2
+9e8fa593849b93849b96879da596acd2cdd4e5e5e5e6e6e6dfdddfb8abbe94859c93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b6b5b3b8b8b6b8b8b6b8b8b6b8b8b6b8b8b6b8b8b6b8b8b6b8b8b6b8b8b6b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b7b7b5b8b8b6b8b8b6b8b8b6b8b8b6
+b8b8b6b8b8b6b8b8b6b8b8b6b8b7b5b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b8b8b6b8b8b6b4b3b1b3b2b0b3b2b0b3b2b0b8b7b5b8b8b6b8b8b6b7b6b4b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b2afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb3b1afb3b1afb2b2afb2b2afb3b2b0b2b1afb2b1afb2b1afb3b1afb2b1afb3b2af
+b2b2af878786a0a0a0e9e6eb92849b92849b92849a92839b92849b92849b92849b92849a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849ba393a9dcdadde6e6e6
+e6e6e6e5e5e5ccbdca9c8da293849b93849b97889fa393a9dad7dbe6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6000000bbbbbbe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6aa9cb0
+97889f93849b93849b9c8da2ccbdcaded9dde6e6e6e6e6e6dbd9dca393a993849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92849a92849a92839a92839a92839a93839b92839b92839b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b97879ec2b8c6dcdadd
+e6e6e6e5e5e5e0dadeaa9db197889f93849b94859c97879ec0b7c4dbd8dde6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6808080d3d3d3e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6dbd8dcc9c1cc9c8da3
+94859c93849b9788a0ab9eb2e0dadee4e2e3e6e6e6dcd9ddc1b8c597879e93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b2afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb93839a92839a93839a93839a92839a92839a93839b92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849ba495abcfcbd2
+e4e4e4e6e6e6e6e6e6c7bfcca497ac94859c93849b93849ba394aacdc8d0e4e4e4e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e4e4e4cdc7cfa697ad95869d
+93849b94859ca598acc8c0cce6e6e6e6e6e6e4e4e4cfcad1a394aa93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb3b1afb2b1afb2b1afb3b2b0b2b1afb3b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b3b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1af878786a0a0a0e9e6eb92839a92839a92839a92839a92839a92839a92839a92839a93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849bc6c1c9
+e2e2e2e6e6e6e6e6e6e6e6e6b4aab997889f93849b93849b93849bc4bec6e2e2e2e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e5e5e5e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e2e2e2c3bdc693849b93849b
+93849b97889fb5abbae6e6e6e6e6e6e6e6e6e2e2e2c5c0c893849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b93849b
+93849b93849b93849b93849b767179abababffffffb4b3b1b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b6c6c6773726dafacae83758b83758b83758b83758b83758b83758b83758b83758b83758b
+83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b
+83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b8a7c92
+94869d9c8da49c8da49c8da495859c8b7c9283758b83758b83758b8a7c9294869c9c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da4
+9c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da49c8da494869c8a7c9283758b83758b
+83758b8b7c9295869c9c8da49c8da49c8da494869c8a7c9283758b83758b83758b83758b83758b
+83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b
+83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b83758b
+83758b83758b83758b83758b5d585b7b7b75bab9b79c9c9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b
+9b9b9b9b9b9ba7a6a5b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999996060602a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a1d1d1c332e245c5242302c32302c32302c32302c32302c32302c32302c32302c32302c32
+302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32
+302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32312d33
+332f36353138353138353138353037322e34302c32302c32302c32312d33332f35353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138353138353138353138353138
+353138353138353138353138353138353138353138353138353138332f35312d33302c32302c32
+302c32322e34353037353138353138353138332f35312d33302c32302c32302c32302c32302c32
+302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32
+302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32302c32
+302c32302c32302c32302c323f372a3e382a3231312a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a
+2a2a2a2a2a2a767676bfbebdb3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b2424246f6f6f717171717171707070707070
+7070706f6f6f6f6f6f6f6f6f6f6f6f6f6f6f707070707070707070707070717171727272727272
+7272727272727e7b768e887d787878787878777777767676747474737373727272737373747474
+7575757878787a7a7a7b7b7b7c7c7c7c7c7c7b7b7b797979787878787878787878797979787878
+767676757575747474737373727272747474757575757575747474737373737373737373747474
+757575757575767676777777787878797979797979797979777777757575747474757575757575
+7676767777777878787979797a7a7a7a7a7a787878777777767676767676757575757575757575
+757575747474737373747474757575767676767676767676767676787878787878767676747474
+737373737373747474757575757575757575747474737373737373737373737373737373737373
+747474757575757575727272727272737373747474747474737373727272727272727272737373
+7474747575757777777878787a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7979797979797a7a7a
+7a7a7a7a7a7a7a7a7a7b7b7b7b7b7b7c7c7c7c7c7c7c7c7c7a7a7a767676757575747474737373
+737373737373747474757575757575757575757575757575757575767676767676797979797979
+787878787878777777767676767676767676767676777777787878787878787878787878787878
+7a7a7a7a7a7a7a7a7a797979797979797979787878787878777777757575747474737373727272
+7373737474747676767878787a7a7a7b7b7b7c7c7c7c7c7c7b7b7b797979787878787878787878
+797979797979777777757575747474737373727272747474757575757575747474737373737373
+737373737373747474767676767676777777787878787878797979797979777777757575747474
+7474747575757676767777777878787979797a7a7a7a7a7a787878777777767676767676757575
+757575757575757575747474737373747474757575767676767676767676767676787878787878
+777777747474737373737373858078807c756e6e6e6e6e6e6c6c6c6b6b6b6b6b6b6b6b6b6b6b6b
+6b6b6b6b6b6b6c6c6c6d6d6d6d6d6d6a6a6a6a6a6a6b6b6b6c6c6c6c6c6c6b6b6b6a6a6a6a6a6a
+6a6a6a6b6b6b6c6c6c6d6d6d6f6f6f717171727272727272727272727272727272727272717171
+7171717272727272727272727272727373737373737474747575757474747272726f6f6f6d6d6d
+6c6c6c6b6b6b6b6b6b6b6b6b6c6c6c6d6d6d6e6e6e6e6e6e6e6e6e6e6e6e6d6d6d6e6e6e6f6f6f
+717171030303646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b434343cdcdcdcfcfcfd0d0d0d0d0d0cfcfcf
+cfcfcfcdcdcdcdcdcdcdcdcdcdcdcdcecececfcfcfcfcfcfcfcfcfcfcfcfd0d0d0d2d2d2d3d3d3
+d4d4d4d3d3d3d3d3d3d2d2d2d1d1d1d0d0d0cfcfcfcdcdcdcacacac8c8c8c7c7c7c7c7c7c9c9c9
+cbcbcbcfcfcfd3d3d3d5d5d5d7d7d7d7d7d7d7d7d7d3d3d3d1d1d1d1d1d1d1d1d1d2d2d2d2d2d2
+cecececccccccacacac8c8c8c6c6c6c9c9c9cbcbcbcacacac9c9c9c7c7c7c7c7c7c8c8c8c9c9c9
+cbcbcbcccccccecececfcfcfd1d1d1d3d3d3d3d3d3d3d3d3cecececbcbcbcacacacbcbcbcccccc
+cecececfcfcfd0d0d0d2d2d2d3d3d3d3d3d3d1d1d1cecececdcdcdcdcdcdcccccccccccccccccc
+cccccccbcbcbc9c9c9cbcbcbcccccccecececfcfcfcfcfcfcececed0d0d0d1d1d1cfcfcfcbcbcb
+c9c9c9c8c8c8c9c9c9cacacacccccccccccccacacac9c9c9c9c9c9c8c8c8c8c8c8c7c7c7c6c6c6
+c8c8c8cacacacacacac6c6c6c6c6c6c7c7c7c9c9c9c9c9c9c8c8c8c6c6c6c6c6c6c6c6c6c8c8c8
+c9c9c9cacacacdcdcdd0d0d0d3d3d3d3d3d3d3d3d3d2d2d2d2d2d2d2d2d2d0d0d0d0d0d0d2d2d2
+d3d3d3d3d3d3d2d2d2d4d4d4d4d4d4d5d5d5d6d6d6d5d5d5d2d2d2cecececdcdcdcbcbcbcacaca
+cacacacacacacbcbcbcbcbcbcccccccbcbcbcbcbcbcbcbcbcacacacbcbcbcccccccfcfcfd0d0d0
+d0d0d0cfcfcfcececececececdcdcdcdcdcdcececececececfcfcfcfcfcfcfcfcfcfcfcfd0d0d0
+d2d2d2d3d3d3d4d4d4d3d3d3d3d3d3d2d2d2d1d1d1d0d0d0cfcfcfcccccccacacac8c8c8c7c7c7
+c7c7c7c9c9c9cccccccfcfcfd3d3d3d5d5d5d7d7d7d7d7d7d6d6d6d3d3d3d1d1d1d1d1d1d1d1d1
+d2d2d2d2d2d2cecececcccccc9c9c9c8c8c8c6c6c6c9c9c9cacacacacacac9c9c9c7c7c7c7c7c7
+c8c8c8c9c9c9cacacacccccccecececfcfcfd1d1d1d2d2d2d4d4d4d3d3d3cecececbcbcbcacaca
+cacacacccccccdcdcdcfcfcfd0d0d0d1d1d1d3d3d3d3d3d3d1d1d1cfcfcfcdcdcdcdcdcdcccccc
+cccccccccccccccccccbcbcbc9c9c9cbcbcbcccccccecececfcfcfcfcfcfcececed1d1d1d1d1d1
+cfcfcfcbcbcbc9c9c9c8c8c8c9c9c9cbcbcbcccccccccccccbcbcbc9c9c9c9c9c9c8c8c8c8c8c8
+c7c7c7c6c6c6c8c8c8cacacacacacac6c6c6c6c6c6c7c7c7c8c8c8c9c9c9c8c8c8c6c6c6c6c6c6
+c6c6c6c8c8c8c9c9c9cacacacdcdcdd1d1d1d3d3d3d3d3d3d3d3d3d3d3d3d2d2d2d1d1d1d0d0d0
+d0d0d0d1d1d1d2d2d2d3d3d3d3d3d3d4d4d4d4d4d4d5d5d5d6d6d6d6d6d6d2d2d2cfcfcfcccccc
+cbcbcbcacacacacacacacacacbcbcbcbcbcbcccccccccccccbcbcbcbcbcbcacacacbcbcbcdcdcd
+cfcfcf060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cbcbcbcdcdcdcdcdcdcdcdcd
+cdcdcdcdcdcdcccccccdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcfcfcfcecececececed0d0d0d1d1d1
+d3d3d3d4d4d4d4d4d4d3d3d3d3d3d3d2d2d2d0d0d0cfcfcfcccccccbcbcbc9c9c9c8c8c8c9c9c9
+cacacacececed1d1d1d3d3d3d6d6d6d7d7d7d8d8d8d5d5d5d3d3d3d1d1d1d1d1d1d2d2d2d2d2d2
+cfcfcfcdcdcdcbcbcbc9c9c9c7c7c7c8c8c8c9c9c9c9c9c9c9c9c9c8c8c8c8c8c8c9c9c9cacaca
+cccccccdcdcdcdcdcdd0d0d0d3d3d3d5d5d5d6d6d6d5d5d5cfcfcfcccccccbcbcbcccccccecece
+cecececfcfcfd0d0d0d1d1d1d1d1d1d2d2d2d1d1d1cecececdcdcdcccccccccccccccccccdcdcd
+cececececececccccccecececfcfcfd1d1d1d1d1d1d1d1d1d0d0d0d0d0d0d1d1d1d0d0d0cecece
+cbcbcbc8c8c8c9c9c9cacacacccccccccccccecececececececececccccccacacac7c7c7c6c6c6
+c8c8c8c9c9c9c9c9c9c7c7c7c6c6c6c7c7c7c8c8c8c9c9c9c9c9c9c8c8c8c8c8c8c8c8c8c9c9c9
+c9c9c9c9c9c9cbcbcbcdcdcdd0d0d0d2d2d2d1d1d1d0d0d0cfcfcfcfcfcfcdcdcdcdcdcdcdcdcd
+cfcfcfd0d0d0d0d0d0d1d1d1d0d0d0d0d0d0d1d1d1d1d1d1d0d0d0d0d0d0d0d0d0cfcfcfcecece
+cececed0d0d0cececececececccccccccccccbcbcbcacacac9c9c9c8c8c8c9c9c9cbcbcbcdcdcd
+cdcdcdcecececececececececccccccdcdcdcecececdcdcdcdcdcdcdcdcdcfcfcfcececececece
+cfcfcfd1d1d1d4d4d4d4d4d4d4d4d4d3d3d3d3d3d3d2d2d2d1d1d1cecececdcdcdcbcbcbcacaca
+c9c9c9c9c9c9cbcbcbcececed1d1d1d3d3d3d5d5d5d7d7d7d7d7d7d5d5d5d2d2d2d1d1d1d1d1d1
+d2d2d2d2d2d2cfcfcfcccccccbcbcbcacacac7c7c7c8c8c8c9c9c9c9c9c9c9c9c9c8c8c8c8c8c8
+c8c8c8cacacacbcbcbcdcdcdcdcdcdcfcfcfd2d2d2d5d5d5d6d6d6d5d5d5cecececbcbcbcbcbcb
+cccccccececececececfcfcfd0d0d0d1d1d1d1d1d1d2d2d2d1d1d1cfcfcfcdcdcdcccccccccccc
+cccccccdcdcdcececececececccccccecececfcfcfd1d1d1d1d1d1d1d1d1d0d0d0d0d0d0d1d1d1
+d1d1d1cecececbcbcbc9c9c9c9c9c9cacacacccccccccccccdcdcdcecececdcdcdcccccccacaca
+c7c7c7c6c6c6c7c7c7c9c9c9c9c9c9c7c7c7c6c6c6c6c6c6c8c8c8c9c9c9c9c9c9c8c8c8c8c8c8
+c8c8c8c9c9c9c9c9c9c9c9c9cbcbcbcdcdcdd0d0d0d2d2d2d1d1d1d0d0d0d0d0d0cfcfcfcdcdcd
+cdcdcdcdcdcdcececed0d0d0d0d0d0d1d1d1d0d0d0d0d0d0d1d1d1d2d2d2d0d0d0d0d0d0d0d0d0
+cfcfcfcecececececed0d0d0cfcfcfcdcdcdcccccccccccccbcbcbcacacac9c9c9c8c8c8c9c9c9
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c5c5c5c7c7c7cbcbcbcdcdcdcdcdcd
+cecececdcdcdcccccccdcdcdcdcdcdcdcdcdcccccccbcbcbcdcdcdcdcdcdcdcdcdcecececfcfcf
+d2d2d2d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d1d1d1cdcdcdcdcdcdcccccccccccc
+cccccccecececececed0d0d0d3d3d3d6d6d6d9d9d9d8d8d8d4d4d4d2d2d2d2d2d2d2d2d2d1d1d1
+cecececccccccccccccbcbcbc9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9cacacacacacacacaca
+cacacacbcbcbccccccd0d0d0d4d4d4d7d7d7d8d8d8d6d6d6d1d1d1cdcdcdcccccccccccccecece
+cecececfcfcfd0d0d0d1d1d1d1d1d1d2d2d2d0d0d0cecececdcdcdcccccccccccccccccccecece
+d0d0d0d1d1d1d1d1d1d1d1d1d2d2d2d4d4d4d5d5d5d4d4d4d3d3d3d1d1d1d1d1d1d2d2d2d1d1d1
+cecececccccccbcbcbcbcbcbcccccccccccccfcfcfd1d1d1d1d1d1d0d0d0ccccccc8c8c8c7c7c7
+c8c8c8c9c9c9c9c9c9c8c8c8c7c7c7c7c7c7c8c8c8cacacacbcbcbcbcbcbcbcbcbcbcbcbcacaca
+cacacac9c9c9c9c9c9cacacaccccccd0d0d0cecececececececececdcdcdcbcbcbcbcbcbcbcbcb
+cdcdcdcecececececececececccccccdcdcdcecececececed0d0d0d0d0d0d1d1d1d0d0d0d0d0d0
+d0d0d0d2d2d2d2d2d2d1d1d1d0d0d0cdcdcdcccccccacacac7c7c7c5c5c5c5c5c5c8c8c8cbcbcb
+cdcdcdcecececececececececccccccdcdcdcecececdcdcdcccccccccccccdcdcdcececececece
+cececed0d0d0d2d2d2d3d3d3d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d2d2d2d1d1d1cececececece
+cccccccccccccccccccececececececfcfcfd2d2d2d6d6d6d8d8d8d8d8d8d4d4d4d3d3d3d2d2d2
+d2d2d2d2d2d2cecececccccccccccccbcbcbcacacac9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9
+cacacacacacacacacacbcbcbcccccccfcfcfd3d3d3d7d7d7d8d8d8d6d6d6d0d0d0cccccccccccc
+cccccccececececececfcfcfd0d0d0d1d1d1d1d1d1d1d1d1d0d0d0cecececdcdcdcccccccccccc
+cccccccececed0d0d0d1d1d1d1d1d1d1d1d1d2d2d2d4d4d4d5d5d5d4d4d4d3d3d3d1d1d1d1d1d1
+d2d2d2d2d2d2cecececccccccbcbcbcbcbcbcccccccccccccfcfcfd1d1d1d1d1d1cfcfcfcccccc
+c8c8c8c7c7c7c7c7c7c9c9c9c8c8c8c8c8c8c7c7c7c7c7c7c8c8c8cacacacbcbcbcbcbcbcbcbcb
+cbcbcbcacacacacacac9c9c9c9c9c9cacacaccccccd0d0d0cecececececececececdcdcdcbcbcb
+cbcbcbcbcbcbcccccccecececdcdcdcecececccccccccccccecececececed0d0d0d0d0d0d1d1d1
+d0d0d0d0d0d0d0d0d0d1d1d1d2d2d2d1d1d1cfcfcfcecececccccccacacac7c7c7c5c5c5c5c5c5
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c3c3c3c5c5c5c9c9c99a9a9a8d8d8d
+8d8d8d8d8d8d8c8c8c8d8d8d8d8d8d8d8d8d8c8c8c8c8c8c8d8d8d8d8d8d8d8d8d8d8d8d8e8e8e
+8e8e8e8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8e8e8e8d8d8d8d8d8d8d8d8d8c8c8c
+8d8d8d8d8d8d8d8d8d8e8e8e8f8f8f9090909090909090908f8f8f8e8e8e8e8e8e8e8e8e8e8e8e
+8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c
+8c8c8c8c8c8c8c8c8c8e8e8e8f8f8f9090909090908f8f8f8e8e8e8d8d8d8c8c8c8d8d8d8d8d8d
+8d8d8d8d8d8d8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c8d8d8d
+8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8f8f8f8f8f8f8f8f8f8f8f8f8e8e8e8e8e8e8e8e8e8e8e8e
+8d8d8d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8e8e8e8e8e8e8e8e8e8e8e8e8c8c8c8b8b8b8b8b8b
+8b8b8b8c8c8c8c8c8c8b8b8b8b8b8b8b8b8b8b8b8b8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c
+8c8c8c8c8c8c8c8c8c8c8c8c8d8d8d8e8e8e8d8d8d8d8d8d8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c
+8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e
+8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8d8d8d8c8c8c8c8c8c8b8b8b8a8a8a8a8a8a8b8b8b8c8c8c
+8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8c8c8c8c8c8c8d8d8d8d8d8d8d8d8d
+8d8d8d8e8e8e8e8e8e8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8e8e8e8d8d8d8d8d8d
+8d8d8d8c8c8c8d8d8d8d8d8d8d8d8d8e8e8e8e8e8e8f8f8f9090909090908f8f8f8f8f8f8e8e8e
+8e8e8e8e8e8e8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c
+8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8d8d8d8f8f8f9090909090908f8f8f8e8e8e8d8d8d8c8c8c
+8d8d8d8d8d8d8d8d8d8d8d8d8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8d8d8d8d8d8d8c8c8c8c8c8c
+8c8c8c8d8d8d8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8f8f8f8f8f8f8f8f8f8f8f8f8e8e8e8e8e8e
+8e8e8e8e8e8e8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c8c8c8c8d8d8d8e8e8e8e8e8e8e8e8e8c8c8c
+8b8b8b8b8b8b8b8b8b8c8c8c8c8c8c8b8b8b8b8b8b8b8b8b8b8b8b8c8c8c8c8c8c8c8c8c8c8c8c
+8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8e8e8e8d8d8d8d8d8d8d8d8d8d8d8d8c8c8c
+8c8c8c8c8c8c8d8d8d8d8d8d8d8d8d8d8d8d8c8c8c8d8d8d8d8d8d8d8d8d8e8e8e8e8e8e8e8e8e
+8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8d8d8d8d8d8d8c8c8ca8a8a8c4c4c4c3c3c3
+c5c5c5060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b3f3f3fc2c2c2c4c4c4c6c6c6848484878787
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5bcbcbcc3c3c3c2c2c2
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c3c3c3c3c3c3c5c5c58383839a9a9a
+f3f3f3f2f2f2f1f1f1f2f2f2f2f2f2f1f1f1f1f1f1f1f1f1f2f2f2f1f1f1f0f0f0f1f1f1f2f2f2
+f1f1f1f1f1f1f0f0f0f1f1f1f2f2f2f1f1f1f2f2f2f2f2f2f1f1f1f2f2f2f1f1f1f1f1f1f1f1f1
+f1f1f1f1f1f1f0f0f0f0f0f0f0f0f0efefefefefefefefeff1f1f1f2f2f2f2f2f2f2f2f2f0f0f0
+f1f1f1f1f1f1f1f1f1f0f0f0efefeff0f0f0f0f0f0efefefefefefeeeeeeefefefefefefefefef
+efefefefefefeeeeeeeeeeeeeeeeeeeeeeeeefefeff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0eeeeee
+eeeeeeeeeeeeeeeeeeefefefefefefeeeeeeeeeeeeeeeeeeefefefefefefeeeeeeeeeeeeeeeeee
+ededededededeeeeeeefefefeeeeeeeeeeeeeeeeeeeeeeeef0f0f0efefefefefefeeeeeeededed
+eeeeeeeeeeeeeeeeeeedededecececedededececececececededededededededededededeeeeee
+ecececebebebeaeaeaebebebebebebebebebebebebebebebebebebebebebebebebebebebebebeb
+ebebebebebebebebebebebebebebebeaeaeaebebebecececebebebebebebecececebebebebebeb
+eaeaeaebebebebebebebebebebebebebebebebebebeaeaeaeaeaeaeaeaeaebebebebebebebebeb
+ecececebebebe9e9e9e9e9e9ebebebececececececebebebe9e9e9e9e9e9eaeaeae9e9e9e8e8e8
+eaeaeaeaeaeae9e9e9eaeaeaeaeaeae9e9e9e9e9e9eaeaeaeaeaeae8e8e8e8e8e8e9e9e9eaeaea
+e9e9e9e9e9e9e8e8e8eaeaeaeaeaeaeaeaeaeaeaeae9e9e9eaeaeae9e9e9e9e9e9eaeaeae9e9e9
+e9e9e9e8e8e8e8e8e8e8e8e8e8e8e8e7e7e7e7e7e7e8e8e8e9e9e9eaeaeaeaeaeae9e9e9e8e8e8
+e9e9e9eaeaeae8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e7e7e7e6e6e6e6e6e6e7e7e7e7e7e7e7e7e7
+e7e7e7e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e7e7e7e8e8e8e8e8e8e9e9e9e8e8e8e6e6e6e6e6e6
+e6e6e6e6e6e6e7e7e7e7e7e7e7e7e7e7e7e7e6e6e6e7e7e7e7e7e7e6e6e6e5e5e5e5e5e5e6e6e6
+e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e7e7e7e7e7e7e6e6e6e5e5e5e5e5e5
+e6e6e6e6e6e6e5e5e5e4e4e4e5e5e5e5e5e5e4e4e4e4e4e4e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5
+e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3
+e3e3e3e3e3e3e2e2e2e3e3e3e2e2e2e2e2e2e3e3e3e4e4e4e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3
+e2e2e2e2e2e2e3e3e3e3e3e3e3e3e3e3e3e3e2e2e2e2e2e2e3e3e3e3e3e3e3e3e3e3e3e3e4e4e4
+e3e3e3e3e3e3e0e0e0e3e3e3e4e4e4e4e4e4e3e3e3e1e1e1cbcbcbe6e6e6dbdbdbc3c3c3c3c3c3
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c3c3c3c5c5c58383839a9a9a
+f3f3f3efefefecececefefefeeeeeeedededededededededefefefecececeaeaeaebebebefefef
+ecececebebebebebebecececf0f0f0edededefefefeeeeeeedededf0f0f0ecececedededececec
+ebebebebebebebebebeaeaeae9e9e9e8e8e8e7e7e7e8e8e8ebebebeeeeeeefefefeeeeeee9e9e9
+ecececececececececeaeaeae7e7e7e9e9e9e8e8e8e7e7e7e6e6e6e3e3e3e5e5e5e5e5e5e5e5e5
+e5e5e5e6e6e6e5e5e5e3e3e3e3e3e3e4e4e4e5e5e5e8e8e8e8e8e8eaeaeaeaeaeae8e8e8e4e4e4
+e3e3e3e3e3e3e4e4e4e5e5e5e5e5e5e4e4e4e4e4e4e5e5e5e5e5e5e5e5e5e4e4e4e3e3e3e2e2e2
+e2e2e2e2e2e2e4e4e4e5e5e5e4e4e4e3e3e3e3e3e3e3e3e3e8e8e8e6e6e6e5e5e5e3e3e3e0e0e0
+e2e2e2e3e3e3e2e2e2e0e0e0dddddde0e0e0dfdfdfdfdfdfdfdfdfe1e1e1e1e1e1e2e2e2e2e2e2
+dddddddadadad9d9d9dbdbdbdbdbdbdbdbdbdbdbdbdbdbdbdadadadadadadbdbdbdbdbdbdbdbdb
+dcdcdcdcdcdcd9d9d9d9d9d9dadadad8d8d8dadadadcdcdcdbdbdbdbdbdbdcdcdcdbdbdbd9d9d9
+d9d9d9d9d9d9dadadad9d9d9dadadadadadad9d9d9d8d8d8d9d9d9d8d8d8d9d9d9dadadadadada
+dcdcdcd9d9d9d5d5d5d7d7d7dbdbdbdcdcdcdddddddadadad6d6d6d6d6d6d7d7d7d3d3d3d2d2d2
+d5d5d5d6d6d6d6d6d6d8d8d8d6d6d6d4d4d4d4d4d4d6d6d6d8d8d8d3d3d3d2d2d2d4d4d4d6d6d6
+d4d4d4d4d4d4d3d3d3d6d6d6d7d7d7d6d6d6d7d7d7d5d5d5d7d7d7d6d6d6d4d4d4d7d7d7d3d3d3
+d3d3d3d3d3d3d3d3d3d2d2d2d1d1d1d0d0d0d0d0d0d1d1d1d4d4d4d8d8d8d8d8d8d5d5d5d2d2d2
+d4d4d4d6d6d6d2d2d2d0d0d0d0d0d0d1d1d1d1d1d1cfcfcfcccccccccccccdcdcdcdcdcdcdcdcd
+cecececdcdcdcccccccbcbcbcbcbcbcccccccececed0d0d0d1d1d1d4d4d4d2d2d2cdcdcdcccccc
+cccccccccccccdcdcdcdcdcdcdcdcdcdcdcdcccccccdcdcdcdcdcdcccccccacacacacacacacaca
+cacacacbcbcbcccccccdcdcdcbcbcbcccccccbcbcbcdcdcdd0d0d0cecececbcbcbc8c8c8c9c9c9
+cbcbcbcbcbcbc9c9c9c6c6c6c8c8c8c8c8c8c7c7c7c7c7c7c9c9c9c9c9c9c9c9c9cacacac9c9c9
+c4c4c4c2c2c2c3c3c3c4c4c4c3c3c3c3c3c3c3c3c3c3c3c3c2c2c2c3c3c3c3c3c3c3c3c3c4c4c4
+c4c4c4c3c3c3c1c1c1c2c2c2c1c1c1c1c1c1c2c2c2c6c6c6c3c3c3c4c4c4c4c4c4c3c3c3c1c1c1
+c1c1c1c1c1c1c2c2c2c3c3c3c4c4c4c2c2c2c0c0c0c0c0c0c2c2c2c2c2c2c2c2c2c2c2c2c4c4c4
+c3c3c3c1c1c1bcbcbcc3c3c3c4c4c4c5c5c5c3c3c3bdbdbd7c7c7ccbcbcbdbdbdbc4c4c4c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c3c3c3c5c5c58383839a9a9a
+f2f2f2e8e8e8efefefededededededededededededededededededecececeaeaeaeaeaeaeeeeee
+ecececededededededececececececebebebecececededededededefefefedededeeeeeeececec
+ebebebebebebedededebebebeaeaeaeaeaeaecececeaeaeae9e9e9eaeaeaedededededede6e6e6
+e7e7e7e7e7e7e8e8e8e8e8e8e6e6e6e5e5e5e6e6e6e8e8e8e9e9e9e3e3e3e3e3e3e1e1e1e3e3e3
+e5e5e5e8e8e8e9e9e9e5e5e5e3e3e3e1e1e1e2e2e2e6e6e6e7e7e7eaeaeaeaeaeae7e7e7e4e4e4
+e4e4e4e4e4e4e3e3e3e3e3e3e3e3e3e4e4e4e4e4e4e5e5e5e4e4e4e3e3e3e3e3e3e2e2e2e2e2e2
+e2e2e2e2e2e2e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e6e6e6e6e6e6e4e4e4e1e1e1dfdfdf
+e2e2e2e1e1e1e3e3e3e4e4e4e1e1e1dcdcdce3e3e3e0e0e0dfdfdfdddddde4e4e4e4e4e4e0e0e0
+dbdbdbdbdbdbdfdfdfdfdfdfdddddddbdbdbdbdbdbdadadadadadadcdcdcdddddddddddddddddd
+dddddddcdcdcdbdbdbdbdbdbdbdbdbd9d9d9d9d9d9dcdcdcdbdbdbdadadadcdcdcdbdbdbd8d8d8
+d9d9d9dadadadadadad9d9d9dbdbdbd9d9d9d8d8d8d8d8d8d9d9d9d8d8d8d9d9d9dadadadadada
+d9d9d9d6d6d6dbdbdbdbdbdbd8d8d8d6d6d6d5d5d5d5d5d5d8d8d8d8d8d8d6d6d6d1d1d1d5d5d5
+d2d2d2d4d4d4d7d7d7d5d5d5d6d6d6d5d5d5d5d5d5d6d6d6d5d5d5d3d3d3d2d2d2d3d3d3d5d5d5
+d5d5d5d7d7d7d4d4d4d4d4d4d5d5d5d5d5d5d6d6d6d5d5d5d7d7d7d7d7d7d7d7d7d8d8d8d4d4d4
+d3d3d3d4d4d4d5d5d5d3d3d3d3d3d3d4d4d4d3d3d3d1d1d1d1d1d1d5d5d5d7d7d7d3d3d3cecece
+cececed1d1d1d1d1d1cecececcccccccccccd0d0d0d2d2d2cdcdcdcbcbcbcacacacacacacbcbcb
+cfcfcfd1d1d1cfcfcfcbcbcbcacacac9c9c9cbcbcbcececed0d0d0d4d4d4d1d1d1cdcdcdcccccc
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccacacacacacacacacacacaca
+cacacacacacacbcbcbcbcbcbcbcbcbcccccccbcbcbcccccccecececfcfcfcbcbcbc8c8c8c9c9c9
+cacacac9c9c9cdcdcdcbcbcbc7c7c7c8c8c8ccccccc8c8c8c6c6c6c9c9c9cccccccacacac7c7c7
+c2c2c2c4c4c4c7c7c7c7c7c7c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c5c5c5c6c6c6c6c6c6c6c6c6
+c5c5c5c3c3c3c3c3c3c3c3c3c2c2c2c1c1c1c1c1c1c6c6c6c2c2c2c3c3c3c4c4c4c2c2c2c1c1c1
+c2c2c2c2c2c2c2c2c2c2c2c2c4c4c4c0c0c0c0c0c0c1c1c1c2c2c2c2c2c2c3c3c3c2c2c2c2c2c2
+bfbfbfbdbdbdc5c5c5c1c1c1c0c0c0bebebebfbfbfc3c3c37c7c7ccbcbcbdbdbdbc4c4c4c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c4c4c4c5c5c58383839a9a9a
+f2f2f2eaeaeae9e9e9ecececebebebeaeaeaeaeaeaedededececececececeaeaeae7e7e7eaeaea
+e7e7e7e5e5e5e5e5e5e7e7e7e8e8e8e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9ebebebeaeaeaeaeaea
+eaeaeaeaeaeae4e4e4e6e6e6e8e8e8eaeaeaeaeaeae9e9e9ebebebededededededebebebe7e7e7
+e6e6e6e5e5e5e5e5e5e7e7e7e7e7e7e5e5e5e3e3e3e4e4e4e7e7e7e6e6e6e6e6e6e5e5e5e4e4e4
+e5e5e5e6e6e6e5e5e5e1e1e1e0e0e0e2e2e2e6e6e6e8e8e8e6e6e6e8e8e8e5e5e5e1e1e1e2e2e2
+e2e2e2e2e2e2e3e3e3e3e3e3e4e4e4e4e4e4e4e4e4e4e4e4e3e3e3e2e2e2e1e1e1e1e1e1e1e1e1
+e2e2e2e2e2e2e2e2e2e1e1e1e1e1e1e0e0e0dfdfdfe1e1e1e4e4e4e0e0e0e1e1e1e1e1e1dddddd
+e1e1e1e0e0e0dedededededee2e2e2dadadadcdcdcdededededededcdcdcdcdcdcdfdfdfe0e0e0
+dbdbdbd9d9d9ddddddddddddd9d9d9d8d8d8d8d8d8d9d9d9d9d9d9dbdbdbdedededcdcdcd8d8d8
+dddddddbdbdbdcdcdcdcdcdcdcdcdcdcdcdcdadadadddddddbdbdbd8d8d8d7d7d7d7d7d7d7d7d7
+d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d8d8d8d9d9d9dadadad8d8d8d9d9d9d8d8d8d7d7d7
+d7d7d7d6d6d6d5d5d5d5d5d5d5d5d5d2d2d2d6d6d6d7d7d7d6d6d6d5d5d5d6d6d6cecececfcfcf
+d1d1d1d2d2d2d2d2d2d5d5d5d4d4d4d2d2d2d3d3d3d5d5d5d4d4d4d3d3d3cececed0d0d0d1d1d1
+cecececccccccfcfcfd0d0d0d1d1d1d1d1d1d1d1d1d1d1d1d2d2d2d2d2d2d3d3d3d2d2d2d2d2d2
+d2d2d2cfcfcfcdcdcdd0d0d0d2d2d2d2d2d2d1d1d1d2d2d2d5d5d5d5d5d5d5d5d5d3d3d3d0d0d0
+cdcdcdcccccccdcdcdcfcfcfcdcdcdcccccccccccccfcfcfcecececdcdcdcdcdcdcbcbcbcbcbcb
+cdcdcdcdcdcdcbcbcbc9c9c9c8c8c8cacacacecececfcfcfcececed2d2d2c9c9c9c9c9c9cacaca
+cbcbcbcccccccccccccccccccccccccccccccccccccccccccbcbcbcacacacacacacacacac9c9c9
+cacacacacacacacacacacacac9c9c9c8c8c8c8c8c8cacacacbcbcbc8c8c8cbcbcbc6c6c6c6c6c6
+c9c9c9c9c9c9c5c5c5cacacac5c5c5c4c4c4c7c7c7c7c7c7c5c5c5c4c4c4c5c5c5c8c8c8c8c8c8
+c1c1c1c3c3c3c5c5c5c3c3c3c0c0c0c0c0c0c0c0c0c1c1c1c1c1c1c5c5c5c7c7c7c1c1c1c3c3c3
+c4c4c4c3c3c3c5c5c5c5c5c5c4c4c4c3c3c3c1c1c1c6c6c6c2c2c2c0c0c0bfbfbfbfbfbfc0c0c0
+c0c0c0c0c0c0c0c0c0bfbfbfbfbfbfc0c0c0c1c1c1c2c2c2c2c2c2c1c1c1c3c3c3c0c0c0c0c0c0
+bebebebdbdbdbdbdbdbebebebcbcbcbdbdbdbebebebdbdbd7b7b7bcbcbcbdbdbdbc4c4c4c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c4c4c4c6c6c68383839a9a9a
+f2f2f2e8e8e8e8e8e8eaeaeaebebebebebebeaeaeaebebebebebebebebebe9e9e9e7e7e7e7e7e7
+e6e6e6e5e5e5e5e5e5e6e6e6e6e6e6e7e7e7e7e7e7e6e6e6e6e6e6e7e7e7e5e5e5e7e7e7e7e7e7
+e7e7e7e7e7e7e8e8e8eaeaeae8e8e8e5e5e5e2e2e2e5e5e5e8e8e8e8e8e8e7e7e7e7e7e7eaeaea
+e9e9e9e8e8e8e7e7e7e5e5e5e4e4e4e2e2e2e2e2e2e4e4e4e5e5e5e4e4e4e6e6e6e5e5e5e5e5e5
+e4e4e4e3e3e3e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e6e6e6e4e4e4e3e3e3e2e2e2e0e0e0e0e0e0
+e0e0e0e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e2e2e2e3e3e3e2e2e2e1e1e1dedededfdfdf
+dededededededddddddfdfdfdedededddddddedededfdfdfdededee0e0e0e1e1e1dfdfdfdddddd
+dddddde0e0e0e0e0e0dededededededcdcdcdedededbdbdbdadadad9d9d9d8d8d8d9d9d9dadada
+d9d9d9d8d8d8d8d8d8d8d8d8d8d8d8d9d9d9dadadadadadad9d9d9dadadad9d9d9d8d8d8d8d8d8
+d9d9d9dadadadbdbdbdbdbdbdbdbdbd9d9d9dadadadadadad7d7d7d5d5d5d6d6d6d6d6d6d6d6d6
+d6d6d6d5d5d5d4d4d4d5d5d5d4d4d4d5d5d5d6d6d6d7d7d7d7d7d7d7d7d7d6d6d6d4d4d4d3d3d3
+d3d3d3d3d3d3d5d5d5d5d5d5d5d5d5d5d5d5d4d4d4d4d4d4d2d2d2d1d1d1d1d1d1cdcdcdcecece
+cfcfcfd0d0d0d1d1d1d2d2d2d3d3d3d2d2d2d2d2d2d3d3d3d4d4d4d2d2d2cecececececececece
+cdcdcdcdcdcdcececececececececed0d0d0cececececececfcfcfcecececdcdcdcececed0d0d0
+d0d0d0d0d0d0d1d1d1d2d2d2cecececccccccccccccececed0d0d0cfcfcfcdcdcdd0d0d0d2d2d2
+d1d1d1cfcfcfcecececdcdcdcbcbcbcacacacbcbcbcecececccccccdcdcdcdcdcdcdcdcdcccccc
+cccccccccccccbcbcbcbcbcbcbcbcbcbcbcbcdcdcdcdcdcdcccccccbcbcbc9c9c9c8c8c8c8c8c8
+c8c8c8c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9cbcbcbcbcbcbc8c8c8c7c7c7c8c8c8cacaca
+c7c7c7c6c6c6c7c7c7c8c8c8c6c6c6c6c6c6c7c7c7c7c7c7c7c7c7c9c9c9c9c9c9c5c5c5c5c5c5
+c7c7c7c9c9c9c7c7c7c6c6c6c6c6c6c6c6c6c7c7c7c2c2c2c1c1c1c0c0c0c1c1c1c2c2c2c2c2c2
+c1c1c1c1c1c1c1c1c1c0c0c0c0c0c0c3c3c3c2c2c2c2c2c2c2c2c2c3c3c3c0c0c0c0c0c0c1c1c1
+c2c2c2c3c3c3c5c5c5c3c3c3c2c2c2c2c2c2c2c2c2c3c3c3bdbdbdbdbdbdbdbdbdbdbdbdbfbfbf
+bdbdbdbcbcbcbcbcbcbdbdbdbdbdbdbdbdbdbfbfbfbfbfbfbfbfbfbfbfbfbebebebcbcbcbcbcbc
+bbbbbbbbbbbbbebebebebebebebebebdbdbdbbbbbbb9b9b97b7b7bcbcbcbdbdbdbc4c4c4c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c4c4c4c7c7c78484849a9a9a
+f2f2f2e7e7e7e7e7e7e8e8e8e9e9e9eaeaeae9e9e9eaeaeaebebebeaeaeae9e9e9e7e7e7e7e7e7
+e6e6e6e6e6e6e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e4e4e4e6e6e6e4e4e4e6e6e6e6e6e6
+e6e6e6e6e6e6e8e8e8eaeaeae7e7e7e4e4e4e1e1e1e4e4e4e6e6e6e5e5e5e4e4e4e4e4e4e8e8e8
+e9e9e9e8e8e8e6e6e6e5e5e5e5e5e5e4e4e4e3e3e3e4e4e4e4e4e4e3e3e3e4e4e4e4e4e4e4e4e4
+e3e3e3e3e3e3e3e3e3e4e4e4e4e4e4e4e4e4e5e5e5e6e6e6e3e3e3e1e1e1e0e0e0dfdfdfdfdfdf
+dfdfdfe0e0e0e1e1e1e1e1e1dfdfdfdedededfdfdfe1e1e1e2e2e2e1e1e1e1e1e1dededededede
+dddddddcdcdcdbdbdbdededededededddddddddddddedededcdcdce0e0e0e1e1e1dfdfdfdcdcdc
+dcdcdcdfdfdfdedededddddddcdcdcdddddddddddddbdbdbdadadad9d9d9d7d7d7d8d8d8d8d8d8
+d8d8d8d7d7d7d6d6d6d7d7d7d8d8d8dadadadadadadadadad9d9d9d9d9d9d8d8d8d8d8d8d9d9d9
+d8d8d8dadadadadadad9d9d9d8d8d8d7d7d7d9d9d9d7d7d7d5d5d5d4d4d4d5d5d5d5d5d5d5d5d5
+d5d5d5d4d4d4d3d3d3d4d4d4d3d3d3d3d3d3d4d4d4d5d5d5d6d6d6d6d6d6d5d5d5d3d3d3d3d3d3
+d3d3d3d3d3d3d5d5d5d5d5d5d4d4d4d4d4d4d3d3d3d3d3d3d1d1d1cfcfcfcfcfcfcecececdcdcd
+cecececfcfcfcfcfcfd0d0d0d2d2d2d2d2d2d2d2d2d3d3d3d4d4d4d2d2d2cfcfcfcececececece
+cececececececdcdcdcdcdcdcdcdcdcecececdcdcdcccccccecececdcdcdcccccccececececece
+cfcfcfcfcfcfd0d0d0d2d2d2cecececbcbcbcbcbcbcdcdcdcfcfcfcdcdcdcbcbcbcdcdcdd0d0d0
+d0d0d0cfcfcfcdcdcdcdcdcdcccccccccccccbcbcbcccccccbcbcbcbcbcbcccccccccccccbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcccccccccccccdcdcdcdcdcdcbcbcbc9c9c9c8c8c8c7c7c7c7c7c7
+c8c8c8c9c9c9c9c9c9c8c8c8c7c7c7c7c7c7c7c7c7c9c9c9cacacac8c8c8c6c6c6c6c6c6c8c8c8
+c5c5c5c4c4c4c5c5c5c7c7c7c6c6c6c6c6c6c7c7c7c7c7c7c6c6c6c9c9c9c9c9c9c5c5c5c5c5c5
+c5c5c5c7c7c7c6c6c6c4c4c4c5c5c5c6c6c6c6c6c6c2c2c2c1c1c1c0c0c0c0c0c0c1c1c1c0c0c0
+c0c0c0bfbfbfbfbfbfc0c0c0c1c1c1c3c3c3c2c2c2c2c2c2c1c1c1c1c1c1bfbfbfc1c1c1c1c1c1
+c1c1c1c2c2c2c3c3c3c1c1c1c0c0c0c0c0c0c1c1c1c0c0c0bcbcbcbcbcbcbcbcbcbcbcbcbdbdbd
+bcbcbcbbbbbbbbbbbbbcbcbcbcbcbcbcbcbcbdbdbdbebebebebebebebebebdbdbdbbbbbbbbbbbb
+bbbbbbbbbbbbbebebebdbdbdbdbdbdbbbbbbbababab9b9b97b7b7bcbcbcbdbdbdbc3c3c3c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b2af9999994b4b4b404040c5c5c5c6c6c6c7c7c78484849a9a9a
+f1f1f1e4e4e4e3e3e3e5e5e5e7e7e7e8e8e8e8e8e8e9e9e9d2d2d2cacacac9c9c9c8c8c8c8c8c8
+c7c7c7c6c6c6d1d1d1e3e3e3e4e4e4c3c3c3dededee2e2e2dbdbdbc4c4c4e3e3e3e6e6e6e5e5e5
+e4e4e4e5e5e5e4e4e4e7e7e7e7e7e7e5e5e5e4e4e4e3e3e3e4e4e4e3e3e3e2e2e2e1e1e1e3e3e3
+e4e4e4e3e3e3e3e3e3e4e4e4e7e7e7e8e8e8e6e6e6e4e4e4e1e1e1e0e0e0e0e0e0e1e1e1e2e2e2
+e2e2e2e1e1e1c2c2c2c3c3c3c4c4c4c6c6c6c6c6c6c6c6c6c3c3c3d4d4d4dedededddddddddddd
+dfdfdfe0e0e0e1e1e1d8d8d8c1c1c1dbdbdbdcdcdcc8c8c8c8c8c8dfdfdfdfdfdfc4c4c4d4d4d4
+dcdcdcdbdbdbdadadadcdcdcdddddddddddddddddddedededbdbdbdfdfdfe0e0e0dfdfdfdcdcdc
+dadadadbdbdbdbdbdbdadadadadadadcdcdcdadadadddddddddddddadadad8d8d8d8d8d8d8d8d8
+d8d8d8d7d7d7d5d5d5d7d7d7dadadadadadad9d9d9d8d8d8d8d8d8d7d7d7d7d7d7d8d8d8d9d9d9
+d8d8d8d7d7d7d6d6d6d5d5d5d4d4d4d5d5d5d5d5d5d2d2d2d3d3d3d4d4d4d4d4d4d2d2d2d2d2d2
+d3d3d3d3d3d3d2d2d2d3d3d3d2d2d2d2d2d2d2d2d2d3d3d3d4d4d4d5d5d5d4d4d4d3d3d3d3d3d3
+d3d3d3d6d6d6d6d6d6d5d5d5d2d2d2cfcfcfd1d1d1d0d0d0d0d0d0cfcfcfcecececfcfcfcccccc
+cbcbcbcccccccccccccececed0d0d0d0d0d0d1d1d1d2d2d2d3d3d3d2d2d2d0d0d0d0d0d0d0d0d0
+cfcfcfcdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcccccccacacacbcbcbcbcbcbcbcbcbcdcdcdcccccc
+cdcdcdcccccccdcdcdcfcfcfcecececccccccbcbcbcccccccdcdcdccccccc9c9c9cacacacbcbcb
+cbcbcbcbcbcbcbcbcbcececed0d0d0d0d0d0cecececacacac9c9c9c9c9c9c8c8c8c9c9c9cacaca
+cbcbcbcacacacacacacbcbcbcccccccccccccdcdcdccccccc9c9c9c6c6c6c7c7c7c7c7c7c7c7c7
+c8c8c8c9c9c9cacacac7c7c7c5c5c5c4c4c4c5c5c5c7c7c7c8c8c8c8c8c8c6c6c6c4c4c4c4c4c4
+c4c4c4c3c3c3c4c4c4c5c5c5c6c6c6c5c5c5c6c6c6c6c6c6c5c5c5c8c8c8c9c9c9c5c5c5c4c4c4
+c3c3c3c4c4c4c3c3c3c2c2c2c4c4c4c4c4c4c2c2c2c6c6c6c3c3c3c1c1c1c0c0c0c1c1c1c0c0c0
+c0c0c0bebebebebebec1c1c1c3c3c3c2c2c2aaaaaab1b1b1c1c1c1bebebec0c0c0c1c1c1c0c0c0
+bababaa6a6a6bfbfbfbdbdbdbcbcbcbdbdbdbcbcbcbabababcbcbcbcbcbcbbbbbbbababab7b7b7
+a1a1a1b1b1b1bbbbbbbcbcbcbabababbbbbbbbbbbbbbbbbbbcbcbcbcbcbcbcbcbcbbbbbbbbbbbb
+bcbcbcbdbdbdbdbdbdbbbbbbb9b9b9b9b9b9b9b9b9bababa7b7b7bcbcbcbdbdbdbc4c4c4c5c5c5
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c6c6c6c7c7c78484849a9a9a
+f1f1f1e4e4e4e3e3e3e5e5e5e7e7e7e8e8e8e7e7e7e6e6e6383838000000000000000000000000
+000000000000555555e2e2e2dfdfdf000000bfbfbfe3e3e3b8b8b8000000e1e1e1e3e3e3e2e2e2
+e2e2e2e5e5e5e3e3e3e4e4e4e5e5e5e5e5e5e4e4e4e0e0e0e1e1e1e3e3e3e5e5e5e4e4e4e2e2e2
+e1e1e1dedededddddddddddde1e1e1e4e4e4e4e4e4e5e5e5e5e5e5e0e0e0e5e5e5e5e5e5e1e1e1
+dfdfdfd9d9d90000000000000000000000000000000000000000008e8e8edededee0e0e0e2e2e2
+e1e1e1dddddddcdcdca0a0a0131313dddddddddddd3b3b3b383838dfdfdfdfdfdf1717179d9d9d
+dfdfdfe1e1e1dfdfdfd9d9d9d8d8d8d8d8d8dadadadcdcdcd7d7d7dddddde0e0e0dfdfdfdadada
+d9d9d9dbdbdbdcdcdcdbdbdbd9d9d9dadadad9d9d9d9d9d9d9d9d9d9d9d9dadadad8d8d8dddddd
+dbdbdbd7d7d7d4d4d4d1d1d1d8d8d8dbdbdbdadadad8d8d8d8d8d8d6d6d6d6d6d6d6d6d6d7d7d7
+d6d6d6d4d4d4d3d3d3d3d3d3d4d4d4d5d5d5d5d5d5d2d2d2d2d2d2d2d2d2d2d2d2cececed0d0d0
+d1d1d1d1d1d1d1d1d1d1d1d1d0d0d0d2d2d2d4d4d4d2d2d2d1d1d1d1d1d1d2d2d2d3d3d3d3d3d3
+d3d3d3d6d6d6d7d7d7d6d6d6d3d3d3cccccccccccccccccccfcfcfcfcfcfcececececececbcbcb
+cbcbcbcccccccccccccececed0d0d0cfcfcfcecececfcfcfcececececececccccccccccccbcbcb
+c9c9c9c9c9c9c9c9c9cbcbcbcbcbcbcbcbcbcccccccacacacacacacbcbcbcbcbcbcccccccacaca
+cbcbcbcccccccccccccececececececccccccacacac8c8c8cbcbcbcecececccccccbcbcbcacaca
+c8c8c8c6c6c6c5c5c5c7c7c7cacacacccccccecececececec9c9c9cacacacccccccececec8c8c8
+c8c8c8cacacacccccccdcdcdccccccc9c9c9c9c9c9c9c9c9c7c7c7c6c6c6c8c8c8cacacacacaca
+c8c8c8c5c5c5c5c5c5c4c4c4c4c4c4c5c5c5c6c6c6c7c7c7c8c8c8c6c6c6c5c5c5c5c5c5c5c5c5
+c9c9c9c8c8c8c4c4c4c1c1c1c1c1c1c2c2c2c3c3c3c2c2c2c0c0c0c8c8c8c9c9c9c4c4c4c3c3c3
+c2c2c2c4c4c4c4c4c4c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c2c2c2c1c1c1c1c1c1c7c7c7
+c3c3c3bdbdbdbabababcbcbcc3c3c3c5c5c51717174d4d4dbfbfbfbdbdbdbdbdbdbfbfbfbdbdbd
+959595050505bbbbbbbbbbbbbcbcbcbdbdbdbcbcbcbababababababbbbbbb9b9b9b8b8b8a4a4a4
+000000767676babababababab9b9b9bdbdbdbbbbbbbababababababbbbbbbbbbbbbbbbbbbbbbbb
+bcbcbcbdbdbdc0c0c0bdbdbdb8b8b8b6b6b6b7b7b7bababa7b7b7bcbcbcbdcdcdcc6c6c6c6c6c6
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c6c6c6c7c7c78484849a9a9a
+f1f1f1e4e4e4e2e2e2e0e0e0e1e1e1e3e3e3e4e4e4e5e5e53737377e7e7edbdbdbd9d9d9d9d9d9
+d9d9d9d8d8d8dbdbdbe1e1e1e1e1e1d7d7d7dcdcdcddddddb4b4b4000000e0e0e0dfdfdfdddddd
+dddddddfdfdfe1e1e1dfdfdfdfdfdfdedededddddddfdfdfdddddddfdfdfdfdfdfdddddddddddd
+dddddddddddddedededfdfdfdddddddcdcdcdddddddedededfdfdfe1e1e1e3e3e3e1e1e1dedede
+ddddddd8d8d8000000b5b5b5d8d8d8d6d6d6d3d3d3d3d3d3d3d3d3d8d8d8dbdbdbdadadadadada
+dbdbdbdbdbdbdbdbdb9f9f9f131313dcdcdcdcdcdcd5d5d5d5d5d5dcdcdcdbdbdb1717179b9b9b
+dbdbdbdcdcdcd9d9d9d9d9d9d9d9d9d9d9d9dbdbdbddddddd7d7d7d7d7d7d8d8d8d9d9d9dadada
+d9d9d9d9d9d9d9d9d9d8d8d8d6d6d6dadadad9d9d9d4d4d4d3d3d3d5d5d5d6d6d6d4d4d4d6d6d6
+d6d6d6d5d5d5d5d5d5d7d7d7dadadad9d9d9d9d9d9d8d8d8d2d2d2d4d4d4d5d5d5d5d5d5d6d6d6
+d6d6d6d4d4d4d3d3d3d2d2d2d1d1d1d0d0d0cececececececdcdcdcccccccccccccccccccfcfcf
+d0d0d0cfcfcfcecececccccccccccccdcdcdcececececececfcfcfcececececececdcdcdcccccc
+cecececececececececfcfcfd1d1d1cdcdcdcdcdcdc9c9c9cacacacbcbcbcbcbcbcacacacbcbcb
+cbcbcbcbcbcbc9c9c9c9c9c9cacacacbcbcbcccccccecececececececececccccccccccccbcbcb
+cacacac9c9c9c9c9c9cacacac9c9c9c8c8c8c5c5c5c6c6c6c6c6c6c7c7c7c8c8c8c7c7c7c5c5c5
+c7c7c7c8c8c8c8c8c8c7c7c7c9c9c9c7c7c7c7c7c7c7c7c7c5c5c5c9c9c9c7c7c7c7c7c7c6c6c6
+c5c5c5c6c6c6c7c7c7c7c7c7c5c5c5c4c4c4c5c5c5c7c7c7c8c8c8cacacacacacacacacac6c6c6
+c5c5c5c6c6c6c7c7c7c9c9c9cbcbcbc6c6c6c5c5c5c6c6c6c5c5c5c4c4c4c2c2c2c2c2c2c2c2c2
+c4c4c4c4c4c4c3c3c3c4c4c4c4c4c4c5c5c5c5c5c5c6c6c6c6c6c6c2c2c2c0c0c0c3c3c3c6c6c6
+c5c5c5c2c2c2c1c1c1c2c2c2c1c1c1c2c2c2c5c5c5c4c4c4bfbfbfbfbfbfc1c1c1c1c1c1c2c2c2
+c2c2c2c2c2c2c1c1c1bfbfbfc1c1c1c2c2c2c1c1c1bbbbbbbcbcbcbdbdbdbcbcbcbcbcbcbfbfbf
+bdbdbdbdbdbdbebebec1c1c1c2c2c2c2c2c21717174b4b4bbbbbbbbdbdbdbdbdbdbdbdbdbdbdbd
+959595050505bbbbbbbababab8b8b8b7b7b7b7b7b7b6b6b6b5b5b5b4b4b4b5b5b5b6b6b6a4a4a4
+000000757575b7b7b7b5b5b5b5b5b5b8b8b8b7b7b7b7b7b7b7b7b7b6b6b6b7b7b7b6b6b6b6b6b6
+b6b6b6b6b6b6b6b6b6bababab8b8b8b6b6b6b5b5b5b3b3b37a7a7acbcbcbdededec8c8c8c7c7c7
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9c6c6c6c5c5c58383839a9a9a
+f1f1f1e0e0e0e0e0e0e0e0e0e0e0e0e1e1e1e0e0e0e1e1e1363636838383e4e4e4e5e5e5e3e3e3
+e2e2e2e0e0e0dededededededcdcdc323232c3c3c3dfdfdfb6b6b6000000dfdfdfe1e1e1dedede
+c0c0c03232323232323232329c9c9cdcdcdcdddddddbdbdbdcdcdcdddddddddddddddddddddddd
+dddddddddddddddddddfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdddddddadadad9d9d9
+d9d9d9d5d5d5000000b8b8b8dcdcdcdcdcdcdbdbdbdddddddbdbdbdadadadbdbdbdcdcdccbcbcb
+3131313131317c7c7c9d9d9d131313d9d9d9dadada5f5f5f5c5c5ccccccc313131050505222222
+888888d6d6d6d5d5d5d6d6d6d7d7d7d9d9d9dadadadadadadadadad9d9d9dadadadbdbdbdbdbdb
+dbdbdbd9d9d9d8d8d8d7d7d7d5d5d5d7d7d7d3d3d3d2d2d2d2d2d2d4d4d4d6d6d6d4d4d4d4d4d4
+d6d6d6d6d6d6d4d4d4d5d5d5d9d9d9d7d7d7d6d6d6d7d7d7d2d2d2d3d3d3d3d3d3d3d3d3d3d3d3
+d2d2d2d2d2d2d1d1d1d1d1d1d1d1d1d0d0d0cecececccccccccccccccccccccccccccccccccccc
+cdcdcdcdcdcdcecececdcdcdcccccccccccccccccccccccccecececacacacbcbcbcbcbcbcbcbcb
+cccccccccccccdcdcdcdcdcdcdcdcdcccccccfcfcfcecececbcbcbcacacacacacac8c8c8c8c8c8
+c8c8c8c8c8c8c8c8c8c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9cccccccdcdcdcccccccbcbcb
+c9c9c9c7c7c7c7c7c7c8c8c8c8c8c8c8c8c8c7c7c7c8c8c8c7c7c7c7c7c7c8c8c8c9c9c9c5c5c5
+c4c4c4c5c5c5c5c5c5c5c5c5c4c4c4c4c4c4c4c4c4c4c4c4c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5
+c5c5c5c6c6c6c7c7c7c8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c8c8c8c6c6c6c4c4c4c3c3c3c1c1c1
+c2c2c2c2c2c2c3c3c3c3c3c3c4c4c4c3c3c3c4c4c4c4c4c4c4c4c4c2c2c2c4c4c4c5c5c5c5c5c5
+c4c4c4c3c3c3c0c0c0c0c0c0c1c1c1c2c2c2c3c3c3c2c2c2c1c1c1c1c1c1c1c1c1c0c0c0bdbdbd
+bdbdbdbdbdbdbebebebebebec0c0c0c2c2c2c3c3c3c3c3c3c2c2c2c2c2c2c4c4c4c3c3c3c3c3c3
+c3c3c3c2c2c2c0c0c0bdbdbdbebebebdbdbdbbbbbbbabababbbbbbbcbcbcbcbcbcbcbcbcbbbbbb
+bebebebcbcbcbcbcbcbebebec1c1c1bebebe1616164b4b4bbbbbbbbbbbbbbbbbbbbbbbbbbababa
+939393050505bababab9b9b9b8b8b8727272292929282828282828848484b5b5b5b5b5b5a0a0a0
+000000757575b7b7b78f8f8f363636b5b5b53434342929294d4d4db2b2b2b3b3b3b3b3b3b4b4b4
+b4b4b4b4b4b4b7b7b7b7b7b7b6b6b6b7b7b7b5b5b5b2b2b27a7a7acbcbcbdededec9c9c9c9c9c9
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac8c8c8c5c5c58383839a9a9a
+f1f1f1e1e1e1e1e1e1e0e0e0e0e0e0e0e0e0dfdfdfdfdfdf363636818181e1e1e1e1e1e1e2e2e2
+e0e0e0dedededededededededadada000000b9b9b9ddddddb4b4b4000000dddddddddddd888888
+606060848484848484828282686868939393dcdcdcdadadadadadadadadadbdbdbdbdbdbdbdbdb
+dadadadadadadbdbdbdcdcdcdcdcdcdcdcdcdbdbdbdbdbdbdbdbdbdbdbdbd9d9d9d6d6d6d7d7d7
+d8d8d8d4d4d4000000b6b6b6d8d8d8d8d8d8d9d9d9dadadadadadadadadadadadab6b6b65e5e5e
+8181818181816e6e6e3f3f3f131313d6d6d6d6d6d63a3a3a363636cfcfcf8080800d0d0d595959
+aaaaaad2d2d2d0d0d0d3d3d3d2d2d2d4d4d4d6d6d6d6d6d6d6d6d6d9d9d9dbdbdbdadadad9d9d9
+d9d9d9d5d5d5d6d6d6d6d6d6d4d4d4d4d4d4d2d2d2d4d4d4d4d4d4d3d3d3d3d3d3d3d3d3d2d2d2
+d1d1d1d3d3d3d5d5d5d2d2d2d3d3d3d4d4d4d4d4d4d4d4d4d1d1d1d3d3d3d3d3d3d3d3d3d3d3d3
+d2d2d2d1d1d1d0d0d0d0d0d0d0d0d0cfcfcfcccccccccccccbcbcbcbcbcbcccccccccccccbcbcb
+cacacacacacacbcbcbcbcbcbcacacacbcbcbcbcbcbcbcbcbcacacac9c9c9cacacacacacacacaca
+cacacacccccccccccccbcbcbcbcbcbcbcbcbcdcdcdd0d0d0cecececdcdcdccccccc9c9c9c8c8c8
+c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c8c8c8c8c8c8c7c7c7c6c6c6c9c9c9c9c9c9cacacac9c9c9
+c8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c6c6c6c6c6c6c5c5c5c5c5c5c5c5c5c6c6c6c5c5c5
+c5c5c5c5c5c5c5c5c5c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3
+c2c2c2c3c3c3c4c4c4c5c5c5c4c4c4c4c4c4c3c3c3c3c3c3c3c3c3c2c2c2c0c0c0bebebebfbfbf
+c1c1c1c1c1c1c0c0c0c0c0c0c0c0c0c1c1c1c2c2c2c2c2c2c2c2c2c2c2c2c3c3c3c3c3c3c3c3c3
+c3c3c3c1c1c1bebebebfbfbfbfbfbfbebebebfbfbfbdbdbdbebebebfbfbfbfbfbfbcbcbcb9b9b9
+bababab9b9b9babababbbbbbbabababebebebebebebfbfbfc0c0c0c3c3c3c3c3c3c1c1c1c1c1c1
+c1c1c1bdbdbdbebebebdbdbdbcbcbcbbbbbbbabababdbdbdbbbbbbbabababbbbbbbbbbbbb9b9b9
+babababbbbbbbbbbbbbabababcbcbcbdbdbd1616164b4b4bbabababcbcbcbbbbbbbcbcbcbbbbbb
+939393050505b8b8b8b7b7b76f6f6f5a5a5a6b6b6b6b6b6b6a6a6a5555557c7c7cb4b4b49f9f9f
+000000727272b4b4b48282820707074949496767676a6a6a616161505050b3b3b3b3b3b3b3b3b3
+b3b3b3b4b4b4b5b5b5b4b4b4b4b4b4b5b5b5b6b6b6b6b6b67b7b7bcbcbcbdfdfdfcbcbcbcacaca
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cbcbcbc8c8c8c6c6c68383839a9a9a
+f1f1f1e2e2e2e2e2e2e1e1e1e0e0e0e0e0e0dfdfdfdfdfdf363636717171c5c5c5c5c5c5c6c6c6
+c5c5c5d2d2d2dddddddfdfdfdadada000000b8b8b8dbdbdbb2b2b2000000dadadadadada4e4e4e
+252525dededededededbdbdb515151626262dbdbdbdadadad9d9d9d9d9d9d9d9d9d9d9d9d9d9d9
+d8d8d8d9d9d9dadadadadadadadadadadadad9d9d9d8d8d8d8d8d8d8d8d8d8d8d8d5d5d5d7d7d7
+d8d8d8d3d3d3000000a0a0a0bdbdbdbebebebebebebfbfbfc0c0c0d1d1d1dadada9b9b9b161616
+d8d8d8d8d8d8828282121212131313d4d4d4d4d4d4393939353535d4d4d4d7d7d7161616979797
+d2d2d2d1d1d1cececed1d1d1cfcfcfd0d0d0d3d3d3d4d4d4d3d3d3d7d7d7d9d9d9d8d8d8d6d6d6
+d6d6d6d3d3d3d4d4d4d5d5d5d4d4d4d2d2d2d3d3d3d6d6d6d5d5d5d2d2d2d1d1d1d2d2d2d0d0d0
+cfcfcfd1d1d1d5d5d5d1d1d1d0d0d0d2d2d2d4d4d4d2d2d2d0d0d0d3d3d3d3d3d3d3d3d3d4d4d4
+d2d2d2d0d0d0cfcfcfcfcfcfcfcfcfcecececccccccbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+c9c9c9c9c9c9cacacacacacac8c8c8cacacacbcbcbcacacac9c9c9c9c9c9cacacacacacacacaca
+cacacacbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcccccccecececfcfcfcecececccccccacacac9c9c9
+cacacacacacac9c9c9c9c9c9c9c9c9c8c8c8c7c7c7c7c7c7c5c5c5c7c7c7c6c6c6c7c7c7c8c8c8
+c7c7c7c6c6c6c7c7c7c6c6c6c6c6c6c5c5c5c4c4c4c4c4c4c3c3c3c3c3c3c3c3c3c3c3c3c4c4c4
+c5c5c5c6c6c6c5c5c5c3c3c3c3c3c3c3c3c3c3c3c3c2c2c2c2c2c2c2c2c2c1c1c1c1c1c1c1c1c1
+c0c0c0c1c1c1c2c2c2c2c2c2c2c2c2c1c1c1c1c1c1c0c0c0c0c0c0c0c0c0bfbfbfbdbdbdbfbfbf
+c1c1c1c0c0c0bfbfbfc0c0c0bfbfbfc0c0c0c0c0c0c1c1c1c1c1c1c2c2c2c2c2c2c1c1c1c1c1c1
+c1c1c1c0c0c0bcbcbcbebebebdbdbdbcbcbcbcbcbcbabababcbcbcbebebebdbdbdbababab9b9b9
+b9b9b9b8b8b8b8b8b8b9b9b9b7b7b7babababbbbbbbcbcbcbdbdbdc1c1c1c1c1c1bfbfbfbfbfbf
+bfbfbfbbbbbbbcbcbcbcbcbcbbbbbbbababababababfbfbfbbbbbbb9b9b9b9b9b9b9b9b9b8b8b8
+b7b7b7babababbbbbbb9b9b9b8b8b8bcbcbc161616424242a3a3a3a6a6a6a4a4a4a6a6a6a5a5a5
+828282050505b7b7b7b7b7b73c3c3c585858b4b4b4b4b4b4b3b3b33e3e3e555555b4b4b49f9f9f
+000000717171b2b2b2818181010101141414a5a5a5b2b2b28383830e0e0eb2b2b2b2b2b2b2b2b2
+b3b3b3b4b4b4b4b4b4b4b4b4b3b3b3b4b4b4b6b6b6b8b8b87b7b7bcbcbcbdfdfdfcccccccbcbcb
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cbcbcbc7c7c7c7c7c78484849a9a9a
+f1f1f1e2e2e2e2e2e2e1e1e1e0e0e0e0e0e0e1e1e1e0e0e0363636000000000000000000000000
+0000007b7b7bdbdbdbdadadad6d6d6000000b7b7b7dadadab2b2b2000000d9d9d9dadada4e4e4e
+242424dbdbdbd8d8d8dbdbdb525252616161dadadad8d8d8d9d9d9d9d9d9d8d8d8d7d7d7d7d7d7
+d8d8d8d8d8d8d8d8d8d9d9d9dadadadadadad8d8d8d7d7d7d7d7d7d8d8d8d9d9d9d7d7d7d7d7d7
+d7d7d7d2d2d20000000000000000000000000000000000000000008b8b8bd6d6d6989898161616
+d7d7d7d6d6d6d4d4d4999999121212d2d2d2d1d1d1383838353535d2d2d2d4d4d4161616959595
+d2d2d2d2d2d2d2d2d2cececed0d0d0cfcfcfcecececececed2d2d2d0d0d0d0d0d0d0d0d0d0d0d0
+cececed7d7d7d4d4d4d0d0d0d0d0d0d0d0d0d1d1d1d1d1d1d0d0d0d0d0d0d1d1d1d0d0d0d0d0d0
+d1d1d1d2d2d2d4d4d4d4d4d4d5d5d5d4d4d4d4d4d4d3d3d3d0d0d0cdcdcdcececed0d0d0cfcfcf
+cececececececececececececfcfcfcecececccccccbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cacacacacacaccccccccccccc9c9c9c9c9c9c9c9c9c9c9c9cacacac9c9c9c8c8c8c8c8c8cacaca
+cacacac9c9c9cbcbcbcccccccbcbcbcbcbcbccccccc6c6c6c4c4c4c4c4c4c5c5c5cacacacacaca
+cbcbcbcacacac9c9c9c9c9c9c9c9c9c9c9c9c9c9c9c8c8c8c5c5c5c5c5c5c5c5c5c6c6c6c6c6c6
+c5c5c5c5c5c5c3c3c3c3c3c3c4c4c4c4c4c4c4c4c4c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3c3
+c3c3c3c2c2c2c2c2c2c4c4c4c4c4c4c2c2c2c1c1c1c1c1c1c2c2c2c2c2c2bfbfbfbfbfbfbfbfbf
+c0c0c0c1c1c1c1c1c1c1c1c1c2c2c2c1c1c1c1c1c1bfbfbfbfbfbfc1c1c1c1c1c1c0c0c0bfbfbf
+bfbfbfbfbfbfc0c0c0c1c1c1c1c1c1c0c0c0c0c0c0c0c0c0bfbfbfbfbfbfbfbfbfbfbfbfbfbfbf
+bebebebdbdbdbbbbbbbabababababab9b9b9b9b9b9b9b9b9b9b9b9bcbcbcbcbcbcbabababdbdbd
+bbbbbbbababab8b8b8b6b6b6b9b9b9b7b7b7b7b7b7b8b8b8b9b9b9b9b9b9b9b9b9b9b9b9b8b8b8
+b8b8b8c1c1c1b8b8b8b9b9b9b8b8b8b8b8b8bababab9b9b9b8b8b8b8b8b8b8b8b8b8b8b8b9b9b9
+b9b9b9babababbbbbbbdbdbdbcbcbcbbbbbb161616000000000000000000000000000000000000
+000000050505b7b7b7b7b7b73d3d3d575757b3b3b3b3b3b3b3b3b33e3e3e545454b3b3b39f9f9f
+000000737373b4b4b4828282101010b1b1b1b1b1b1b1b1b18484840d0d0db0b0b0b1b1b1b3b3b3
+b2b2b2b2b2b2b4b4b4b4b4b4b4b4b4b4b4b4b1b1b1acacac797979cbcbcbe0e0e0cdcdcdcbcbcb
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8c7c7c7c7c7c78484849a9a9a
+f1f1f1dddddde2e2e2e3e3e3e2e2e2e1e1e1e1e1e1dddddd353535777777cfcfcfcecececccccc
+ccccccd5d5d5d9d9d9d6d6d6d2d2d2000000b7b7b7dadadab1b1b1000000d9d9d9d9d9d94d4d4d
+0202020d0d0d0d0d0d0d0d0d050505606060d8d8d8dadadadbdbdbdadadad9d9d9d9d9d9d8d8d8
+d8d8d8d8d8d8d7d7d7d7d7d7d7d7d7d8d8d8d8d8d8d8d8d8d7d7d7d7d7d7d6d6d6d4d4d4d4d4d4
+d5d5d5d0d0d0000000a9a9a9cbcbcbcacacac7c7c7c7c7c7c7c7c7d1d1d1d6d6d6989898161616
+d2d2d2d4d4d4d3d3d3999999121212d0d0d0cecece373737343434cfcfcfcccccc151515919191
+cfcfcfd2d2d2d1d1d1cccccccfcfcfcfcfcfcdcdcdccccccd1d1d1d3d3d3d4d4d4d2d2d2d0d0d0
+d1d1d1cecececdcdcdcccccccbcbcbc9c9c9d1d1d1d3d3d3d2d2d2cdcdcdc7c7c7c8c8c8cccccc
+cccccccbcbcbcccccccccccccfcfcfcfcfcfcecececececececececbcbcbcecececfcfcfcecece
+cfcfcfd0d0d0cecececdcdcdcbcbcbcacacacbcbcbcbcbcbcacacac9c9c9c8c8c8c9c9c9cbcbcb
+cacacac9c9c9c8c8c8c9c9c9cacacac9c9c9c9c9c9c9c9c9c7c7c7c6c6c6c7c7c7c7c7c7c5c5c5
+c4c4c4c6c6c6c4c4c4c5c5c5c8c8c8cacacacdcdcdc3c3c3c2c2c2c3c3c3c3c3c3c6c6c6c7c7c7
+c6c6c6c8c8c8cbcbcbcbcbcbcacacac9c9c9c7c7c7c6c6c6c6c6c6c5c5c5c5c5c5c4c4c4c3c3c3
+c2c2c2c4c4c4bfbfbfbdbdbdbebebec1c1c1c2c2c2c2c2c2c2c2c2c1c1c1c1c1c1c1c1c1c1c1c1
+c2c2c2c1c1c1c1c1c1c1c1c1c0c0c0c0c0c0c1c1c1c3c3c3c3c3c3c2c2c2c1c1c1c1c1c1c1c1c1
+c0c0c0c1c1c1bfbfbfbfbfbfbfbfbfc0c0c0c1c1c1c0c0c0bfbfbfbfbfbfbdbdbdbbbbbbbcbcbc
+bdbdbdbcbcbcbcbcbcc0c0c0c1c1c1bebebebdbdbdbdbdbdbdbdbdbfbfbfbdbdbdbabababababa
+babababdbdbdbababab7b7b7b7b7b7b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b7b7b7b7b7b7bbbbbb
+bbbbbbbababab8b8b8b6b6b6b8b8b8b6b6b6b5b5b5b6b6b6b9b9b9bcbcbcbababab9b9b9b9b9b9
+bababab7b7b7b5b5b5b5b5b5b2b2b2b5b5b5babababababab7b7b7b1b1b1afafafb3b3b3b8b8b8
+b3b3b3b3b3b3b4b4b4b6b6b6b8b8b8b7b7b7161616444444a9a9a9a7a7a7adadadaaaaaaababab
+888888050505b7b7b7b3b3b33b3b3b0505050b0b0b0b0b0b0b0b0b030303535353b2b2b29f9f9f
+000000707070b1b1b1808080101010b1b1b1b2b2b2b0b0b08181810d0d0db0b0b0aeaeaeacacac
+adadadaeaeaeacacacb0b0b0b1b1b1b4b4b4b1b1b1aaaaaa797979cbcbcbdfdfdfcacacac8c8c8
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2af9999994b4b4b414141c7c7c7c6c6c6c7c7c78484849a9a9a
+f0f0f0d9d9d9d9d9d9d9d9d9dadadadadadadadadadadada3535357d7d7ddcdcdcddddddd6d6d6
+d7d7d7d9d9d9d9d9d9d6d6d6d3d3d3000000b6b6b6d9d9d9b0b0b0000000d8d8d8d9d9d94d4d4d
+1b1b1ba6a6a6a4a4a4a6a6a6a6a6a6bdbdbddadadad8d8d8d5d5d5d7d7d7d9d9d9d8d8d8d8d8d8
+d7d7d7d7d7d7d7d7d7d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d1d1d1d1d1d1d3d3d3
+d4d4d4cfcfcf000000afafafd2d2d2d1d1d1cfcfcfcfcfcfd1d1d1d0d0d0d1d1d1959595151515
+cdcdcdcfcfcfd0d0d0979797121212cecececccccc373737343434cecececdcdcd151515929292
+cdcdcdcdcdcdcececececececfcfcfcfcfcfcdcdcdcbcbcbcacacacdcdcdcecececdcdcdcccccc
+cbcbcbcfcfcfcdcdcdcbcbcbcacacac9c9c9cdcdcdcdcdcdcccccccbcbcbc5c5c5c5c5c5c6c6c6
+cbcbcbcecececdcdcdd0d0d0cfcfcfcfcfcfd0d0d0d0d0d0cecececacacacbcbcbcdcdcdcccccc
+cccccccdcdcdcccccccbcbcbcacacac9c9c9c9c9c9cacacac9c9c9c9c9c9c8c8c8c7c7c7c6c6c6
+c5c5c5c5c5c5c5c5c5c7c7c7c9c9c9c8c8c8c7c7c7c8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c6c6c6
+c7c7c7c9c9c9c9c9c9c7c7c7c3c3c3c2c2c2c4c4c4c0c0c0c1c1c1c1c1c1c2c2c2c2c2c2c4c4c4
+c3c3c3c2c2c2c1c1c1c2c2c2c2c2c2c3c3c3c2c2c2c2c2c2c3c3c3c2c2c2c7c7c7c3c3c3bfbfbf
+c1c1c1c3c3c3c0c0c0bfbfbfc0c0c0c1c1c1c2c2c2c0c0c0c0c0c0bfbfbfc0c0c0c1c1c1c2c2c2
+c3c3c3c3c3c3c2c2c2c3c3c3c4c4c4c3c3c3c1c1c1bfbfbfbdbdbdc1c1c1c1c1c1c0c0c0c0c0c0
+bfbfbfbfbfbfbfbfbfbfbfbfbebebebdbdbdbdbdbdbdbdbdbdbdbdbbbbbbb9b9b9b8b8b8bbbbbb
+bbbbbbb9b9b9b8b8b8b9b9b9bbbbbbb9b9b9b8b8b8b9b9b9bababab8b8b8b9b9b9b8b8b8b7b7b7
+b6b6b6b9b9b9b7b7b7b6b6b6b7b7b7b7b7b7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b5b5b5b4b4b4
+b4b4b4b6b6b6b7b7b7b8b8b8b8b8b8b6b6b6b5b5b5b4b4b4b4b4b4b6b6b6b5b5b5b5b5b5b5b5b5
+b4b4b4b7b7b7b5b5b5b3b3b3b1b1b1b3b3b3b7b7b7b5b5b5b5b5b5afafafadadadaeaeaeaeaeae
+b4b4b4b6b6b6b7b7b7b8b8b8b6b6b6b8b8b8161616494949b5b5b5b0b0b0b6b6b6b4b4b4b4b4b4
+8f8f8f050505b5b5b5b2b2b23b3b3b414141858585878787868686858585999999afafaf9b9b9b
+0000006f6f6faeaeae7e7e7e101010b0b0b0b1b1b1b0b0b08181810d0d0db0b0b0afafafafafaf
+b0b0b0b1b1b1b1b1b1adadadabababababababababaaaaaa797979cbcbcbddddddc7c7c7c7c7c7
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c8c8c8c9c9c98484849a9a9a
+f0f0f0d6d6d6d6d6d6d7d7d7d7d7d7d7d7d7d6d6d6d6d6d63434347c7c7cdadadadcdcdcd3d3d3
+d6d6d6d8d8d8d9d9d9d8d8d8d4d4d4000000b6b6b6d8d8d8afafaf000000d6d6d6d8d8d84d4d4d
+242424d7d7d7d7d7d7d8d8d88b8b8b939393d6d6d6d7d7d7d4d4d4d5d5d5d7d7d7d7d7d7d6d6d6
+d6d6d6d6d6d6d5d5d5d5d5d5d6d6d6d6d6d6d5d5d5d4d4d4d4d4d4d5d5d5d1d1d1d0d0d0d1d1d1
+d1d1d1cbcbcb000000adadadd0d0d0cfcfcfcececed0d0d0cfcfcfcdcdcdcecece959595151515
+cdcdcdcfcfcf9a9a9a3f3f3f121212cecececdcdcd373737333333cccccccbcbcb151515939393
+cccccccacacacccccccdcdcdcdcdcdcdcdcdcccccccbcbcbc8c8c8cacacacbcbcbcbcbcbc9c9c9
+cacacacdcdcdcdcdcdcbcbcbc8c8c8c8c8c8c9c9c9cbcbcbcacacac7c7c7c8c8c8cacacac5c5c5
+c9c9c9cbcbcbcacacacacacacbcbcbc7c7c7c8c8c8cececec8c8c8c8c8c8c9c9c9cacacac9c9c9
+cdcdcdcdcdcdcacacac9c9c9c7c7c7c9c9c9c9c9c9c9c9c9c8c8c8c7c7c7c6c6c6c6c6c6c6c6c6
+c6c6c6c5c5c5c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c5c5c5c5c5c5c6c6c6c6c6c6c5c5c5c4c4c4
+c4c4c4c5c5c5c4c4c4c3c3c3c2c2c2c0c0c0c1c1c1c0c0c0bfbfbfbfbfbfc0c0c0bfbfbfc0c0c0
+bebebebebebebfbfbfc0c0c0bfbfbfbfbfbfbebebebfbfbfc0c0c0c0c0c0c6c6c6c2c2c2bcbcbc
+c0c0c0c3c3c3c1c1c1c1c1c1c1c1c1c0c0c0c2c2c2c0c0c0bebebebebebebfbfbfc1c1c1c0c0c0
+bfbfbfbfbfbfc0c0c0c0c0c0c1c1c1bfbfbfbebebebebebebcbcbcbebebebfbfbfbfbfbfbebebe
+bdbdbdbdbdbdbdbdbdbdbdbdbebebebebebebdbdbdbbbbbbbcbcbcbbbbbbb9b9b9b8b8b8b9b9b9
+b9b9b9b7b7b7b6b6b6b6b6b6b9b9b9b7b7b7b7b7b7b8b8b8b7b7b7b5b5b5bababab8b8b8b7b7b7
+b6b6b6b9b9b9b7b7b7b7b7b7b7b7b7b7b7b7b6b6b6b6b6b6b5b5b5b4b4b4b5b5b5b5b5b5b2b2b2
+b2b2b2b4b4b4b5b5b5b6b6b6b6b6b6b5b5b5b5b5b5b4b4b4b1b1b1b3b3b3b4b4b4b1b1b1b1b1b1
+b2b2b2b5b5b5b5b5b5b2b2b2b0b0b0b1b1b1b2b2b2b3b3b3afafafafafafb1b1b1b0b0b0acacac
+b2b2b2b3b3b3b3b3b3b2b2b2b3b3b3acacac141414474747b0b0b0b0b0b0b2b2b2b0b0b0b3b3b3
+8f8f8f050505b2b2b2b0b0b03a3a3a565656b1b1b1b1b1b1afafaf6e6e6e797979aeaeae9b9b9b
+0000006e6e6eaeaeae7e7e7e0707074a4a4aa5a5a5adadad8080800d0d0daeaeaeacacacacacac
+acacacadadadacacacabababa9a9a9a9a9a9a8a8a8a7a7a7797979cbcbcbdcdcdcc6c6c6c7c7c7
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8c9c9c9c9c9c98484849a9a9a
+efefefd5d5d5d6d6d6d7d7d7d6d6d6d5d5d5d4d4d4d3d3d3333333797979d6d6d6d9d9d9d3d3d3
+d5d5d5d7d7d7d8d8d8d7d7d7d4d4d4000000b6b6b6d8d8d8afafaf000000d3d3d3d6d6d6828282
+5b5b5b8080808181818181816363638b8b8bd1d1d1d4d4d4d3d3d3d2d2d2d2d2d2d2d2d2d2d2d2
+d1d1d1d3d3d3d5d5d5d6d6d6d6d6d6d5d5d5d5d5d5d3d3d3d1d1d1d3d3d3d2d2d2d2d2d2d0d0d0
+cfcfcfcacaca0000006969697e7e7e7d7d7d7c7c7c7f7f7f7d7d7db0b0b0cdcdcdababab555555
+7c7c7c7e7e7e6969693a3a3a121212cecececccccc373737333333cacacac9c9c9151515595959
+a5a5a5c9c9c9cacacacccccccccccccccccccccccccacacac8c8c8c8c8c8c8c8c8c8c8c8c6c6c6
+c8c8c8c9c9c9cacacacacacac8c8c8c9c9c9c9c9c9cbcbcbc9c9c9c6c6c6cacacaccccccc7c7c7
+c6c6c6c6c6c6c6c6c6c4c4c4c7c7c7c3c3c3c3c3c3c9c9c9c4c4c4c6c6c6c6c6c6c6c6c6c7c7c7
+ccccccc9c9c9c8c8c8c6c6c6c5c5c5c9c9c9cacacac9c9c9c6c6c6c5c5c5c4c4c4c5c5c5c7c7c7
+c6c6c6c6c6c6c6c6c6c5c5c5c4c4c4c5c5c5c5c5c5c4c4c4c4c4c4c4c4c4c3c3c3c2c2c2c1c1c1
+c0c0c0c2c2c2c0c0c0c0c0c0c0c0c0bfbfbfc0c0c0c0c0c0bfbfbfbebebebfbfbfbebebebfbfbf
+bebebebebebebfbfbfbfbfbfbdbdbdbdbdbdbcbcbcbcbcbcbdbdbdbcbcbcc1c1c1bfbfbfbcbcbc
+bebebec1c1c1c0c0c0c1c1c1c1c1c1bfbfbfc1c1c1bfbfbfbcbcbcbcbcbcbcbcbcbfbfbfbebebe
+bcbcbcbcbcbcbdbdbdbcbcbcbcbcbcbabababbbbbbbcbcbcbababababababbbbbbbababab9b9b9
+b9b9b9bcbcbcbebebebebebebdbdbdbdbdbdbdbdbdb9b9b9babababababababababababab8b8b8
+b8b8b8b6b6b6b5b5b5b6b6b6b6b6b6b6b6b6b7b7b7b7b7b7b5b5b5b5b5b5b8b8b8b7b7b7b7b7b7
+b6b6b6b8b8b8b6b6b6b6b6b6b6b6b6b7b7b7b5b5b5b5b5b5b3b3b3b1b1b1b1b1b1b3b3b3b1b1b1
+b2b2b2b1b1b1b3b3b3b5b5b5b5b5b5b5b5b5b4b4b4b3b3b3b1b1b1b0b0b0b1b1b1adadadaeaeae
+afafafb1b1b1b4b4b4b1b1b1b1b1b1b1b1b1b1b1b1b3b3b3aeaeaeb0b0b0b3b3b3b2b2b2adadad
+aeaeaeaeaeaeaeaeaeadadadafafafa7a7a7141414454545adadadafafafaeaeaeaeaeaeb2b2b2
+8e8e8e040404afafafacacac6767675858586b6b6b6a6a6a696969505050757575aeaeae9c9c9c
+0000006e6e6eadadad7e7e7e0606064444446565656868685e5e5e4a4a4aabababa9a9a9a8a8a8
+a9a9a9aaaaaaa7a7a7a8a8a8a8a8a8a8a8a8a8a8a8a7a7a7797979cbcbcbdbdbdbc5c5c5c8c8c8
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8c9c9c9cacaca8484849a9a9a
+f0f0f0d8d8d8d6d6d6d5d5d5d4d4d4d3d3d3d4d4d4d2d2d2333333767676d0d0d0d4d4d4d5d5d5
+d5d5d5d6d6d6d5d5d5d4d4d4d3d3d3000000b6b6b6d7d7d7adadad000000cfcfcfd3d3d3d4d4d4
+b1b1b1000000000000000000828282d0d0d0d0d0d0d0d0d0d0d0d0cecececdcdcdcccccccbcbcb
+cbcbcbd0d0d0d5d5d5d7d7d7d6d6d6d4d4d4d4d4d4d2d2d2cececed1d1d1d2d2d2d3d3d3cfcfcf
+cfcfcfcccccc000000000000000000000000000000000000000000858585cdcdcdccccccb8b8b8
+0000000000005b5b5b949494121212cecececbcbcb363636333333cacacac9c9c9151515000000
+6b6b6bc8c8c8c7c7c7cdcdcdcccccccdcdcdccccccc9c9c9cacacac7c7c7c5c5c5c4c4c4c4c4c4
+c5c5c5c6c6c6c7c7c7c9c9c9c9c9c9cccccccbcbcbcbcbcbcacacacacacacacacacacacac8c8c8
+c5c5c5c3c3c3c4c4c4c4c4c4c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c4c4c4c4c4c4c6c6c6
+cacacac3c3c3c5c5c5c4c4c4c3c3c3c9c9c9cacacacacacac6c6c6c4c4c4c4c4c4c5c5c5c7c7c7
+c6c6c6c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c3c3c3c0c0c0bfbfbfbfbfbfbfbfbf
+c0c0c0c3c3c3bfbfbfbfbfbfbebebebdbdbdbfbfbfbfbfbfc0c0c0c0c0c0c0c0c0c0c0c0c0c0c0
+c0c0c0c0c0c0bebebebdbdbdbbbbbbbcbcbcbcbcbcbbbbbbbababab7b7b7babababcbcbcbebebe
+bdbdbdbfbfbfbdbdbdbfbfbfc0c0c0bfbfbfc1c1c1bdbdbdbababab9b9b9b9b9b9bdbdbdbdbdbd
+bbbbbbbbbbbbbcbcbcbababab8b8b8b8b8b8b8b8b8b8b8b8b7b7b7b7b7b7b5b5b5b5b5b5b4b4b4
+b3b3b3bbbbbbbfbfbfc0c0c0bdbdbdbbbbbbbdbdbdb6b6b6b8b8b8b9b9b9bbbbbbbdbdbdb7b7b7
+b8b8b8b6b6b6b4b4b4b5b5b5b3b3b3b5b5b5b6b6b6b5b5b5b4b4b4b8b8b8b5b5b5b5b5b5b6b6b6
+b6b6b6b5b5b5b5b5b5b4b4b4b5b5b5b6b6b6b4b4b4b4b4b4b3b3b3aeaeaeacacacaeaeaeb0b0b0
+b0b0b0afafafb1b1b1b7b7b7b5b5b5b7b7b7b3b3b3b1b1b1b1b1b1adadadacacacacacacacacac
+acacacaeaeaeb0b0b0b1b1b1b3b3b3b4b4b4b4b4b4b3b3b3b3b3b3b2b2b2b2b2b2b1b1b1b0b0b0
+ababababababacacacaeaeaeaeaeaeaeaeae141414464646aeaeaeadadadacacacadadadb0b0b0
+8c8c8c040404aeaeaeaaaaaaaeaeae5a5a5a000000000000000000707070acacacaeaeae9c9c9c
+0000006d6d6dacacac7e7e7e101010aeaeae0e0e0e0000002b2b2ba8a8a8a8a8a8a7a7a7a8a8a8
+aaaaaaabababa7a7a7a7a7a7a7a7a7a7a7a7a8a8a8a9a9a9797979cbcbcbdbdbdbc5c5c5c8c8c8
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c9c9c9c9c9c98484849a9a9a
+efefefd0d0d0d3d3d3d1d1d1d3d3d3d4d4d4d4d4d4d5d5d5c9c9c9cbcbcbcecececdcdcdd2d2d2
+d3d3d3d0d0d0cfcfcfd1d1d1d2d2d2c1c1c1d3d3d3d6d6d6d0d0d0bebebed0d0d0d0d0d0cfcfcf
+ccccccc0c0c0bbbbbbbebebecacacad1d1d1d0d0d0cccccccccccccccccccccccccbcbcbcbcbcb
+cbcbcbcacacacccccccdcdcdc7c7c7cccccccccccccbcbcbcacacac9c9c9c9c9c9cccccccdcdcd
+cfcfcfcfcfcfbcbcbcbebebebdbdbdbcbcbcbbbbbbbbbbbbbbbbbbc5c5c5cbcbcbcccccccacaca
+bbbbbbbbbbbbc2c2c2c7c7c7bcbcbccccccccbcbcbbcbcbcbcbcbccbcbcbc8c8c8b7b7b7b7b7b7
+c3c3c3cdcdcdcdcdcdc9c9c9c3c3c3c6c6c6cbcbcbcdcdcdcacacac8c8c8c6c6c6c5c5c5c4c4c4
+c3c3c3c2c2c2c3c3c3c4c4c4c5c5c5c7c7c7c4c4c4c5c5c5c5c5c5c6c6c6c6c6c6c5c5c5c6c6c6
+c7c7c7c6c6c6c2c2c2c3c3c3c4c4c4c5c5c5c5c5c5c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4
+c4c4c4c6c6c6c3c3c3c2c2c2c2c2c2c8c8c8c3c3c3c3c3c3c2c2c2c1c1c1c5c5c5c7c7c7c7c7c7
+c5c5c5c2c2c2c1c1c1c2c2c2c4c4c4c5c5c5c3c3c3c1c1c1c0c0c0bfbfbfbfbfbfbfbfbfc0c0c0
+c0c0c0bfbfbfbfbfbfbebebebdbdbdbcbcbcbbbbbbbcbcbcbdbdbdbdbdbdbdbdbdbfbfbfbcbcbc
+bababababababababab8b8b8bbbbbbbcbcbcbcbcbcbdbdbdbebebeb8b8b8b4b4b4b7b7b7bbbbbb
+bababab6b6b6b9b9b9babababbbbbbbbbbbbc0c0c0bdbdbdbababab9b9b9b9b9b9b9b9b9b7b7b7
+b9b9b9b8b8b8b7b7b7b8b8b8b9b9b9b8b8b8b6b6b6b5b5b5b4b4b4b4b4b4b4b4b4b3b3b3b3b3b3
+b3b3b3b3b3b3b6b6b6b1b1b1b2b2b2b5b5b5b4b4b4b2b2b2b1b1b1b1b1b1b3b3b3b6b6b6b6b6b6
+b7b7b7b7b7b7b7b7b7b8b8b8b6b6b6b5b5b5b5b5b5b5b5b5b5b5b5b4b4b4b4b4b4b4b4b4b5b5b5
+b5b5b5b5b5b5b5b5b5b4b4b4b5b5b5b5b5b5b5b5b5b1b1b1b3b3b3b0b0b0afafafb1b1b1b2b2b2
+b4b4b4b5b5b5b3b3b3afafafabababb2b2b2b4b4b4b4b4b4b2b2b2afafafadadadacacacababab
+aaaaaaaaaaaaacacacacacacadadadadadadacacacacacacaeaeaeaeaeaeadadadacacacaeaeae
+b0b0b0adadadaaaaaaaaaaaaacacacaeaeae9f9f9fa3a3a3acacacacacacacacacacacacacacac
+a9a9a99f9f9faaaaaaaaaaaaaeaeaea6a6a69b9b9b9b9b9b9b9b9ba7a7a7aeaeaeafafafacacac
+9d9d9da5a5a5aaaaaa7b7b7b101010aeaeae9d9d9d9b9b9b9d9d9da8a8a8a7a7a7a8a8a8a9a9a9
+a9a9a9a8a8a8a7a7a7a6a6a6a5a5a5a5a5a5a5a5a5a6a6a6787878cbcbcbdbdbdbc4c4c4c6c6c6
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c6c6c6c8c8c88484849a9a9a
+efefefd2d2d2d1d1d1d1d1d1d2d2d2d2d2d2d2d2d2d3d3d3d1d1d1cfcfcfcfcfcfcfcfcfcfcfcf
+cfcfcfcfcfcfcecececdcdcdcccccccdcdcdcececed0d0d0d3d3d3d1d1d1d2d2d2cfcfcfcecece
+cdcdcdccccccc9c9c9cdcdcdd0d0d0d0d0d0cecececbcbcbcbcbcbcccccccbcbcbcacacac9c9c9
+cbcbcbcbcbcbcbcbcbcbcbcbc9c9c9cbcbcbcacacacacacac9c9c9c8c8c8c9c9c9c9c9c9c9c9c9
+cacacacbcbcbcececed0d0d0cecececacacac8c8c8c8c8c8c8c8c8c8c8c8c7c7c7c6c6c6c7c7c7
+c8c8c8c6c6c6c4c4c4c3c3c3c5c5c5c9c9c9c9c9c9c6c6c6c6c6c6c7c7c7c5c5c5c3c3c3c6c6c6
+c8c8c8c9c9c9ccccccc9c9c9c7c7c7c6c6c6c7c7c7c8c8c8c8c8c8c8c8c8c7c7c7c6c6c6c5c5c5
+c5c5c5c4c4c4c4c4c4c3c3c3c1c1c1bfbfbfc0c0c0c3c3c3c3c3c3c1c1c1c0c0c0c4c4c4c3c3c3
+c4c4c4c3c3c3c2c2c2c1c1c1c0c0c0c3c3c3c4c4c4c2c2c2c2c2c2c1c1c1c2c2c2c2c2c2c2c2c2
+c1c1c1c3c3c3c2c2c2c2c2c2c2c2c2c4c4c4c1c1c1c0c0c0bebebebebebec3c3c3c5c5c5c2c2c2
+c1c1c1c1c1c1c1c1c1bfbfbfc2c2c2c3c3c3c1c1c1bfbfbfbdbdbdbdbdbdbdbdbdbdbdbdbcbcbc
+bcbcbcbfbfbfbfbfbfbebebebdbdbdbbbbbbb9b9b9bbbbbbbbbbbbbbbbbbbabababdbdbdbcbcbc
+bbbbbbbabababababab9b9b9bbbbbbbbbbbbbabababababab8b8b8b7b7b7b7b7b7b7b7b7b7b7b7
+b8b8b8b7b7b7b6b6b6b5b5b5b5b5b5b6b6b6b8b8b8bbbbbbbababababababababab7b7b7b7b7b7
+b5b5b5b3b3b3b3b3b3b6b6b6bababab8b8b8b5b5b5b3b3b3b4b4b4b4b4b4b2b2b2b2b2b2b2b2b2
+b3b3b3b3b3b3b3b3b3b2b2b2b3b3b3b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b2b2b2
+b3b3b3b5b5b5b7b7b7b8b8b8b4b4b4b2b2b2b1b1b1b1b1b1b1b1b1afafafaeaeaeafafafafafaf
+afafafaeaeaeabababacacacafafafb1b1b1b1b1b1adadadafafafadadadacacacafafafb1b1b1
+b1b1b1b3b3b3b4b4b4b1b1b1aeaeaeafafafb0b0b0b1b1b1b1b1b1afafafaeaeaeadadadadadad
+acacacacacacacacacaaaaaaa8a8a8a8a8a8a9a9a9abababaaaaaaa9a9a9aaaaaaabababababab
+abababaaaaaaa9a9a9a9a9a9a8a8a8aeaeaeaaaaaaaaaaaaaaaaaaa9a9a9acacacaaaaaaaaaaaa
+aaaaaaabababaaaaaaaaaaaaabababaaaaaaa9a9a9a8a8a8a7a7a7a9a9a9acacacadadadaaaaaa
+a9a9a9a9a9a9a9a9a97a7a7a101010abababa8a8a8a6a6a6a5a5a5a6a6a6a6a6a6a5a5a5a6a6a6
+a6a6a6a7a7a7a7a7a7a6a6a6a4a4a4a2a2a2a2a2a2a4a4a4787878cbcbcbdbdbdbc3c3c3c4c4c4
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b404040c3c3c3c5c5c5c7c7c78484849a9a9a
+efefefd0d0d0cecececfcfcfcfcfcfcfcfcfcfcfcfd1d1d1cececececececfcfcfcececed0d0d0
+cdcdcdcecececfcfcfcececececececdcdcdcdcdcdcdcdcdcecececfcfcfd0d0d0cecececccccc
+cccccccececececececfcfcfcecececdcdcdcccccccbcbcbcbcbcbcccccccbcbcbcbcbcbcbcbcb
+cdcdcdcccccccccccccccccccdcdcdcbcbcbcacacacacacacbcbcbc9c9c9cccccccacacac8c8c8
+c8c8c8c9c9c9c9c9c9cccccccecececccccccacacacacacacacacac9c9c9c9c9c9c9c9c9c8c8c8
+c6c6c6c4c4c4c4c4c4c5c5c5c5c5c5c9c9c9c8c8c8c7c7c7c6c6c6c5c5c5c5c5c5c4c4c4c4c4c4
+c4c4c4c4c4c4c7c7c7c6c6c6c7c7c7c7c7c7c6c6c6c4c4c4c6c6c6c5c5c5c5c5c5c5c5c5c4c4c4
+c5c5c5c2c2c2c2c2c2c2c2c2c0c0c0bfbfbfbebebec1c1c1c1c1c1bebebec1c1c1c1c1c1c1c1c1
+c0c0c0c0c0c0c1c1c1c0c0c0bfbfbfc0c0c0c1c1c1c2c2c2c1c1c1c0c0c0c0c0c0bfbfbfc0c0c0
+c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c1c1c1c1c1c1c0c0c0bebebebdbdbdbfbfbfc2c2c2c1c1c1
+bfbfbfc0c0c0c1c1c1bfbfbfbebebebebebebfbfbfbfbfbfbebebebebebebdbdbdbcbcbcbcbcbc
+bcbcbcbdbdbdbdbdbdbdbdbdbcbcbcbabababababab9b9b9b9b9b9b9b9b9b9b9b9b9b9b9bababa
+b9b9b9b8b8b8b7b7b7b7b7b7b8b8b8b8b8b8b9b9b9b8b8b8b6b6b6b8b8b8b6b6b6b7b7b7b8b8b8
+b6b6b6b8b8b8b6b6b6b6b6b6b6b6b6b6b6b6b7b7b7b6b6b6b7b7b7b8b8b8b8b8b8b7b7b7b5b5b5
+b6b6b6b6b6b6b6b6b6b7b7b7b7b7b7b6b6b6b4b4b4b3b3b3b4b4b4b5b5b5b3b3b3b3b3b3b4b4b4
+b5b5b5b5b5b5b5b5b5b5b5b5b4b4b4b3b3b3b2b2b2b3b3b3b2b2b2b3b3b3b4b4b4b2b2b2b0b0b0
+b1b1b1b2b2b2b3b3b3b5b5b5b6b6b6b3b3b3b3b3b3b3b3b3b3b3b3b1b1b1b2b2b2b1b1b1b0b0b0
+adadadacacacaeaeaeadadadafafafb1b1b1b1b1b1aeaeaeaeaeaeacacacacacacacacacaeaeae
+adadadadadadaeaeaeaeaeaeaeaeaeafafafaeaeaeadadadadadadacacacacacacacacacacacac
+acacacabababaaaaaaa9a9a9a8a8a8a7a7a7a7a7a7aaaaaaa8a8a8a8a8a8a8a8a8a9a9a9a8a8a8
+a8a8a8a8a8a8a8a8a8a7a7a7a7a7a7a9a9a9a9a9a9aaaaaaa9a9a9a8a8a8a8a8a8a8a8a8a9a9a9
+a9a9a9a8a8a8a8a8a8a8a8a8a9a9a9a9a9a9a9a9a9a8a8a8a6a6a6a7a7a7a9a9a9aaaaaaa8a8a8
+a8a8a8a9a9a9a9a9a97a7a7a101010a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a6a6a6a5a5a5a5a5a5
+a6a6a6a6a6a6a5a5a5a4a4a4a3a3a3a2a2a2a2a2a2a2a2a2787878cbcbcbdbdbdbc3c3c3c3c3c3
+c5c5c5060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c4c4c4c6c6c68383839a9a9a
+eeeeeecdcdcdcbcbcbcccccccdcdcdcdcdcdcececed0d0d0cdcdcdcdcdcdcdcdcdcbcbcbcecece
+cccccccccccccdcdcdcecececdcdcdcccccccccccccbcbcbcacacacbcbcbcbcbcbcccccccbcbcb
+cbcbcbcececed1d1d1cecececbcbcbcacacacacacac9c9c9cbcbcbcbcbcbcbcbcbcccccccdcdcd
+cecececccccccbcbcbcbcbcbcdcdcdcccccccacacacbcbcbccccccc9c9c9cececec8c8c8c5c5c5
+c6c6c6c7c7c7c5c5c5c7c7c7cbcbcbcccccccbcbcbcbcbcbcacacacbcbcbcccccccbcbcbc8c8c8
+c3c3c3c2c2c2c4c4c4c7c7c7c6c6c6c8c8c8c7c7c7c6c6c6c6c6c6c5c5c5c5c5c5c8c8c8c5c5c5
+c2c2c2c1c1c1c2c2c2c2c2c2c4c4c4c6c6c6c6c6c6c3c3c3c4c4c4c2c2c2c2c2c2c2c2c2c1c1c1
+c3c3c3c0c0c0c1c1c1c2c2c2c0c0c0bebebebdbdbdbfbfbfbfbfbfbdbdbdc1c1c1bfbfbfc1c1c1
+c0c0c0bfbfbfbfbfbfc0c0c0bfbfbfbebebebebebebfbfbfbebebebebebebdbdbdbdbdbdbebebe
+bebebebebebebdbdbdbdbdbdbdbdbdbdbdbdbebebebebebebdbdbdbcbcbcbebebebfbfbfbfbfbf
+bebebebebebebebebebebebebabababbbbbbbcbcbcbebebebebebebdbdbdbcbcbcbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbabababababab9b9b9b9b9b9b8b8b8b8b8b8b8b8b8b8b8b8b7b7b7b8b8b8
+b7b7b7b5b5b5b4b4b4b4b4b4b5b5b5b6b6b6b7b7b7b7b7b7b4b4b4b7b7b7b3b3b3b4b4b4b6b6b6
+b5b5b5b5b5b5b6b6b6b6b6b6b6b6b6b5b5b5b6b6b6b3b3b3b3b3b3b4b4b4b4b4b4b4b4b4b2b2b2
+b5b5b5b7b7b7b8b8b8b5b5b5b3b3b3b2b2b2b2b2b2b2b2b2b3b3b3b5b5b5b4b4b4b4b4b4b5b5b5
+b5b5b5b4b4b4b3b3b3b5b5b5b4b4b4b4b4b4b3b3b3b4b4b4b2b2b2b4b4b4b4b4b4b1b1b1adadad
+aeaeaeaeaeaeadadadb0b0b0b6b6b6b4b4b4b3b3b3b3b3b3b3b3b3b5b5b5b5b5b5b1b1b1aeaeae
+abababaaaaaab0b0b0aeaeaeafafafb0b0b0afafafaeaeaeaeaeaeafafafaeaeaeabababababab
+aaaaaaa9a9a9a9a9a9aaaaaaacacacb0b0b0adadadababababababaaaaaaabababaaaaaaaaaaaa
+aaaaaaa9a9a9aaaaaaa9a9a9a7a7a7a6a6a6a6a6a6a8a8a8a6a6a6a8a8a8a8a8a8a8a8a8a9a9a9
+a8a8a8a8a8a8a7a7a7a8a8a8a7a7a7a6a6a6a7a7a7a7a7a7a7a7a7a6a6a6a6a6a6a6a6a6a6a6a6
+a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a7a7a7a7a7a7a7a7a7
+a7a7a7a7a7a7a7a7a7898989464646a4a4a4a5a5a5a6a6a6a6a6a6a6a6a6a4a4a4a4a4a4a4a4a4
+a4a4a4a4a4a4a3a3a3a2a2a2a1a1a1a2a2a2a1a1a1a0a0a0787878cbcbcbdcdcdcc4c4c4c4c4c4
+c5c5c5060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c5c5c5c6c6c68383839a9a9a
+eeeeeecccccccacacacacacacbcbcbcccccccdcdcdcecececacacacacacacacacac8c8c8c8c8c8
+c9c9c9c9c9c9c9c9c9cacacac8c8c8cacacacacacac9c9c9c9c9c9c7c7c7c7c7c7c8c8c8c9c9c9
+c9c9c9c7c7c7cccccccacacac9c9c9c8c8c8c8c8c8c9c9c9c9c9c9cacacacacacacacacacacaca
+cccccccacacac8c8c8c6c6c6c8c8c8cacacacacacacacacac9c9c9c8c8c8cacacac4c4c4c1c1c1
+c2c2c2c4c4c4c4c4c4c4c4c4c7c7c7c8c8c8c8c8c8c6c6c6c8c8c8c9c9c9c9c9c9c7c7c7c2c2c2
+c0c0c0c0c0c0c1c1c1c3c3c3c3c3c3c4c4c4c3c3c3c3c3c3c3c3c3c3c3c3c5c5c5c8c8c8c6c6c6
+c3c3c3c2c2c2c2c2c2c2c2c2c1c1c1c4c4c4c6c6c6c4c4c4c2c2c2c1c1c1c1c1c1c0c0c0bdbdbd
+c0c0c0c0c0c0c1c1c1c1c1c1bfbfbfbbbbbbbfbfbfbfbfbfbebebebcbcbcbebebec0c0c0c3c3c3
+c1c1c1bfbfbfbfbfbfc1c1c1c1c1c1bfbfbfbcbcbcbbbbbbbababab9b9b9bbbbbbbcbcbcbababa
+bbbbbbbbbbbbbbbbbbbbbbbbbabababababab9b9b9bababababababbbbbbbebebebcbcbcbcbcbc
+bcbcbcbcbcbcbbbbbbbbbbbbb9b9b9b9b9b9babababababababababababab9b9b9b8b8b8b8b8b8
+b8b8b8b9b9b9b8b8b8b8b8b8b8b8b8b7b7b7b7b7b7b7b7b7b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6
+b5b5b5b4b4b4b3b3b3b3b3b3b4b4b4b5b5b5b6b6b6b5b5b5b1b1b1b3b3b3b0b0b0b0b0b0b1b1b1
+b3b3b3b0b0b0b3b3b3b1b1b1b0b0b0b2b2b2b2b2b2b1b1b1afafafafafafb0b0b0b1b1b1b1b1b1
+b0b0b0b2b2b2b4b4b4b2b2b2b2b2b2b0b0b0b0b0b0b1b1b1b1b1b1b3b3b3b2b2b2b2b2b2b3b3b3
+b4b4b4b1b1b1adadadb0b0b0b2b2b2b3b3b3b3b3b3b1b1b1b0b0b0b1b1b1afafafacacaca9a9a9
+abababacacacacacacacacacb0b0b0b1b1b1afafafaeaeaeb1b1b1b3b3b3b2b2b2abababa9a9a9
+a8a8a8a8a8a8ababababababacacacadadadababababababacacacafafafafafafacacacaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaeaeadadadabababaaaaaaa9a9a9a9a9a9a6a6a6a6a6a6
+a8a8a8a9a9a9aaaaaaa8a8a8a5a5a5a5a5a5a7a7a7a7a7a7a5a5a5a6a6a6a7a7a7a9a9a9ababab
+a9a9a9a8a8a8a7a7a7a8a8a8a8a8a8a6a6a6a4a4a4a4a4a4a2a2a2a1a1a1a6a6a6a3a3a3a3a3a3
+a3a3a3a4a4a4a4a4a4a3a3a3a3a3a3a2a2a2a2a2a2a2a2a2a4a4a4a5a5a5a5a5a5a5a5a5a5a5a5
+a5a5a5a5a5a5a4a4a4a3a3a3a1a1a1a2a2a2a2a2a2a3a3a3a3a3a3a2a2a2a0a0a0a0a0a0a1a1a1
+a1a1a1a1a1a1a0a0a0a0a0a0a0a0a09f9f9f9f9f9f9e9e9e777777cbcbcbddddddc6c6c6c6c6c6
+c5c5c5060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c7c7c7c8c8c88484849a9a9a
+eeeeeecbcbcbcdcdcdcbcbcbcacacacacacacacacacacacac9c9c9c9c9c9c9c9c9c9c9c9c9c9c9
+c8c8c8c8c8c8c8c8c8c9c9c9cacacacacacacacacac9c9c9c7c7c7c7c7c7c7c7c7c9c9c9c8c8c8
+c7c7c7c6c6c6c6c6c6c7c7c7cbcbcbcdcdcdcdcdcdcdcdcdc6c6c6c5c5c5c6c6c6c6c6c6c5c5c5
+c7c7c7c5c5c5c4c4c4c3c3c3c3c3c3c4c4c4c5c5c5c4c4c4c3c3c3c3c3c3c3c3c3c3c3c3c5c5c5
+c5c5c5c5c5c5c5c5c5c5c5c5c4c4c4c4c4c4c5c5c5c4c4c4c6c6c6c5c5c5c4c4c4c5c5c5c3c3c3
+c3c3c3c2c2c2c1c1c1c2c2c2c1c1c1c1c1c1c1c1c1c0c0c0bfbfbfbfbfbfc1c1c1c1c1c1c1c1c1
+c4c4c4c6c6c6c6c6c6c5c5c5c2c2c2c1c1c1c2c2c2c2c2c2bdbdbdbfbfbfc0c0c0bfbfbfbfbfbf
+bfbfbfbdbdbdbcbcbcbdbdbdbfbfbfc1c1c1c0c0c0c0c0c0bfbfbfbababababababebebebebebe
+bdbdbdbebebec0c0c0bbbbbbbfbfbfbfbfbfbebebebcbcbcbdbdbdb9b9b9b9b9b9b9b9b9b7b7b7
+bababababababababababababababab9b9b9b9b9b9b9b9b9bababab9b9b9b6b6b6b9b9b9bababa
+babababcbcbcbebebebcbcbcbbbbbbbababab9b9b9b9b9b9b8b8b8b6b6b6b4b4b4b3b3b3b4b4b4
+b7b7b7bcbcbcb8b8b8b8b8b8b8b8b8b6b6b6b5b5b5b4b4b4b4b4b4b4b4b4b3b3b3b4b4b4b3b3b3
+b3b3b3b4b4b4b5b5b5b3b3b3b3b3b3b3b3b3b3b3b3b2b2b2b1b1b1b1b1b1b2b2b2b2b2b2b2b2b2
+b0b0b0b0b0b0b0b0b0b2b2b2b2b2b2b2b2b2b1b1b1b1b1b1b0b0b0afafafb0b0b0b0b0b0b0b0b0
+aeaeaeaeaeaeaeaeaeafafafb6b6b6b6b6b6b6b6b6b3b3b3acacacaeaeaeaeaeaeaeaeaeaeaeae
+afafafacacacacacacacacacacacacacacacaeaeaeaaaaaaabababaaaaaaaaaaaaacacacadadad
+adadadadadadadadadababababababadadadadadadaeaeaeafafafacacacadadadacacacababab
+abababa9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a8a8a8a8a8a8a7a7a7a8a8a8a9a9a9aaaaaaababab
+adadadafafafafafafadadada9a9a9a9a9a9abababa9a9a9a6a6a6a8a8a8a8a8a8a7a7a7a7a7a7
+a7a7a7a6a6a6a4a4a4a6a6a6a8a8a8a9a9a9a9a9a9a8a8a8a4a4a4a2a2a2a4a4a4a6a6a6a6a6a6
+a6a6a6a7a7a7a6a6a6a5a5a5a8a8a8a7a7a7a6a6a6a5a5a5a4a4a4a0a0a0a4a4a49f9f9fa1a1a1
+a3a3a3a4a4a4a3a3a3a3a3a3a2a2a2a1a1a1a1a1a1a2a2a2a2a2a2a0a0a0a0a0a0a2a2a2a3a3a3
+a3a3a3a6a6a6a6a6a6a4a4a4a3a3a3a1a1a1a2a2a2a2a2a29f9f9f9c9c9c9b9b9b9b9b9b9e9e9e
+a3a3a3a5a5a59f9f9fa0a0a0a0a0a09e9e9e9c9c9c9c9c9c777777cbcbcbdededec9c9c9c7c7c7
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacacacacacbcbcb8585859a9a9a
+eeeeeec9c9c9c8c8c8c9c9c9cacacacacacacacacac8c8c8cacacac9c9c9c9c9c9cbcbcbc9c9c9
+cbcbcbc8c8c8c5c5c5c7c7c7c8c8c8c3c3c3c3c3c3c3c3c3c4c4c4c6c6c6c7c7c7c5c5c5c5c5c5
+c6c6c6cacacac8c8c8c7c7c7c6c6c6c4c4c4c3c3c3c2c2c2c5c5c5c9c9c9cbcbcbc9c9c9c5c5c5
+c5c5c5c6c6c6c6c6c6c6c6c6c6c6c6c7c7c7c6c6c6c6c6c6c6c6c6c6c6c6c8c8c8c8c8c8c6c6c6
+c4c4c4c3c3c3c4c4c4c4c4c4c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c1c1c1bfbfbfbdbdbd
+bdbdbdbfbfbfbfbfbfbdbdbdbdbdbdbdbdbdbdbdbdbebebebfbfbfc0c0c0c1c1c1c1c1c1c1c1c1
+bebebebdbdbdbdbdbdbebebebcbcbcbbbbbbbbbbbbbcbcbcc2c2c2c1c1c1c0c0c0bfbfbfbcbcbc
+b9b9b9b9b9b9b9b9b9bbbbbbbababab9b9b9b9b9b9babababbbbbbbbbbbbbdbdbdbdbdbdbdbdbd
+bebebebdbdbdb9b9b9b7b7b7b9b9b9bbbbbbbbbbbbbbbbbbbdbdbdbbbbbbbebebebfbfbfbcbcbc
+bababab7b7b7b5b5b5b5b5b5b7b7b7b8b8b8b8b8b8babababbbbbbbababab7b7b7b9b9b9b8b8b8
+b8b8b8b8b8b8b9b9b9b4b4b4b5b5b5b6b6b6b7b7b7b9b9b9b8b8b8b6b6b6b6b6b6b6b6b6b6b6b6
+b8b8b8bbbbbbb7b7b7b7b7b7b8b8b8b7b7b7b6b6b6b3b3b3b2b2b2b2b2b2b3b3b3b4b4b4b3b3b3
+b2b2b2b1b1b1b1b1b1b2b2b2b3b3b3b2b2b2b1b1b1b1b1b1b3b3b3b0b0b0b3b3b3b3b3b3b2b2b2
+b4b4b4aeaeaeaeaeaeb0b0b0afafafacacacacacacacacacadadadafafafafafafacacacadadad
+b0b0b0b1b1b1afafafaeaeaeaeaeaeabababaaaaaaabababaeaeaeb4b4b4b3b3b3afafafacacac
+acacacaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeafafafb0b0b0b1b1b1aeaeae
+acacacacacacacacacabababaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacacaca9a9a9a7a7a7a7a7a7
+a7a7a7a9a9a9a6a6a6a6a6a6a6a6a6a5a5a5a5a5a5a6a6a6a7a7a7a8a8a8a9a9a9a8a8a8a6a6a6
+a5a5a5a5a5a5a6a6a6a6a6a6a4a4a4a4a4a4a4a4a4a6a6a6a9a9a9a8a8a8a8a8a8a6a6a6a4a4a4
+a1a1a1a1a1a1a2a2a2a4a4a4a2a2a2a1a1a1a2a2a2a3a3a3a4a4a4a5a5a5a6a6a6a6a6a6a5a5a5
+a7a7a7a3a3a3a0a0a0a0a0a0a3a3a3a4a4a4a4a4a4a4a4a4a4a4a4a4a4a4a9a9a9a5a5a5a3a3a3
+a2a2a29e9e9e9d9d9d9e9e9ea0a0a0a1a1a1a1a1a1a4a4a4a4a4a4a0a0a0a0a0a0a2a2a2a0a0a0
+a0a0a0a0a0a09f9f9f9d9d9d9e9e9e9d9d9da0a0a0a1a1a1a1a1a19e9e9e9d9d9d9d9d9d9f9f9f
+a2a2a2a3a3a39f9f9f9f9f9fa0a0a09e9e9e9b9b9b999999777777cbcbcbe0e0e0cdcdcdcbcbcb
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cccccccccccccdcdcd858585848484
+ababab9a9a9a9999999a9a9a9b9b9b9b9b9b9a9a9a9a9a9a9b9b9b9a9a9a9a9a9a9b9b9b9a9a9a
+9b9b9b9999999898989999999a9a9a989898979797979797989898999999999999989898989898
+9999999a9a9a9999999999999999999898989797979797979898989a9a9a9b9b9b9a9a9a989898
+9898989999999999999999999999999999999999999999999999999999999999999a9a9a999999
+989898979797989898989898979797979797979797979797979797979797969696959595949494
+949494969696959595949494949494949494949494959595959595969696969696969696969696
+959595949494949494959595949494939393939393949494979797969696969696959595949494
+929292929292939393939393939393929292939393939393939393949494949494949494949494
+959595949494929292929292939393939393939393949494949494949494959595969696949494
+939393929292919191919191929292929292929292939393939393939393929292939393929292
+929292929292929292909090919191919191929292929292929292929292919191919191919191
+9292929393939292929292929292929292929191919090908f8f8f8f8f8f909090909090909090
+8f8f8f8f8f8f8f8f8f8f8f8f9090909090908f8f8f8f8f8f9090908e8e8e909090909090909090
+9090908d8d8d8d8d8d8e8e8e8e8e8e8c8c8c8c8c8c8c8c8c8d8d8d8e8e8e8e8e8e8c8c8c8d8d8d
+8f8f8f8f8f8f8e8e8e8d8d8d8d8d8d8c8c8c8c8c8c8c8c8c8e8e8e9090909090908e8e8e8c8c8c
+8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8e8e8e8e8e8e8f8f8f8e8e8e
+8d8d8d8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8b8b8b8a8a8a8a8a8a
+8a8a8a8b8b8b8a8a8a8a8a8a8a8a8a8a8a8a8989898a8a8a8a8a8a8b8b8b8b8b8b8b8b8b8a8a8a
+8989898989898a8a8a8a8a8a8989898989898989898a8a8a8b8b8b8b8b8b8b8b8b8a8a8a898989
+8787878787878888888989898888888888888888888989898989898989898a8a8a8a8a8a898989
+8a8a8a8989898787878787878888888989898989898989898989898989898b8b8b898989898989
+888888868686858585868686878787878787878787898989898989878787878787888888878787
+878787878787868686868686868686858585878787888888878787868686858585858585868686
+888888898989868686878787878787868686858585848484747474cbcbcbe1e1e1cecececccccc
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cececececececececea9a9a9a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0d9d9d9e1e1e1cfcfcfcecece
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444d0d0d0d0d0d0d0d0d0e7e7e7ededed
+edededededededededededededededededededededecececececececececececececececededed
+ededededededededededededededededededededededededececececececededededededededed
+edededededededededecececececececececededededededededededededededededededededed
+ededededededededededededecececededededededededededededececececececedededededed
+ededededededededededededededededededededededededededededededededededededececec
+ecececececececececececececececededededededededededededededededededecececececec
+ececececececececececececececececececececececececededededededeeeeeeedededededed
+ededededededededededededeeeeeeededededededededededededeeeeeeeeeeeeeeeeeeeeeeee
+eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeededed
+edededededededededecececececececececececececececececececececececececececececec
+ecececececececececececececececececececececececececececedededededededededededed
+ededededededededededededededededededededededededededededededededededededededed
+edededededededededededededededededededededededededededecececececececececececec
+ecececededededededededededededededededededededededededecececececececececededed
+edededededededededededededededecececececececececededededededededededededededed
+ededededededededededededededededededecececededededededededededededecececececec
+ededededededededededededededededededededededededededededededededededededededed
+edededececececececececececececececececececedededededededededededededededededed
+ececececececececececececececececececececececececececececececededededededeeeeee
+eeeeeeededededededededededededeeeeeeeeeeeeedededededededededeeeeeeeeeeeeeeeeee
+eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+eeeeeeededededededededededededecececececececececececececececececececececececec
+ecececececececececececececececececececececececececececececececececedededededed
+ededededededededededededededededededededededededededededededdededed0d0d0d0d0d0
+d0d0d0060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444d0d0d0d0d0d0d1d1d1d0d0d0d0d0d0
+d0d0d0d0d0d0d0d0d0cecececccccccccccccccccccbcbcbcacacacacacacacacacbcbcbcccccc
+cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcccccccbcbcbcacacacbcbcbcccccccdcdcdcecece
+cececececececccccccbcbcbcbcbcbcbcbcbcccccccccccccccccccdcdcdcececececececfcfcf
+cececececececdcdcdcbcbcbcbcbcbcccccccccccccccccccbcbcbcbcbcbcbcbcbcbcbcbcdcdcd
+cececececececececed0d0d0d1d1d1d0d0d0cfcfcfcecececfcfcfd0d0d0cfcfcfcdcdcdcacaca
+cacacac8c8c8c8c8c8c8c8c8c9c9c9ccccccd0d0d0d1d1d1d0d0d0cdcdcdcccccccacacac7c7c7
+c6c6c6c6c6c6c6c6c6c6c6c6c7c7c7c9c9c9cacacacbcbcbcececed0d0d0d2d2d2d1d1d1cfcfcf
+cccccccdcdcdcfcfcfd1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d2d2d2d4d4d4d4d4d4d5d5d5
+d5d5d5d5d5d5d5d5d5d5d5d5d4d4d4d3d3d3d3d3d3d4d4d4d6d6d6d5d5d5d3d3d3d2d2d2d0d0d0
+d0d0d0cecececccccccbcbcbc9c9c9c8c8c8c8c8c8c8c8c8c9c9c9cacacacbcbcbcacacacacaca
+cacacac9c9c9c9c9c9c9c9c9cacacacacacacbcbcbcbcbcbcbcbcbcbcbcbcdcdcdcececececece
+cececed0d0d0d0d0d0d0d0d0d0d0d0cdcdcdcccccccccccccdcdcdcfcfcfd1d1d1d1d1d1d1d1d1
+d1d1d1d1d1d1d1d1d1d1d1d1d0d0d0cecececdcdcdcccccccbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcccccccdcdcdcecececececececececececececececccccccbcbcbcbcbcbcbcbcbcbcbcb
+cdcdcdcececececececdcdcdcccccccbcbcbcbcbcbcbcbcbcccccccccccccccccccccccccecece
+cececed0d0d0cececececececccccccbcbcbcbcbcbcbcbcbcccccccccccccbcbcbcbcbcbcbcbcb
+cbcbcbcdcdcdcececececececececed0d0d0d1d1d1d0d0d0cfcfcfcecececfcfcfd0d0d0cfcfcf
+cdcdcdcbcbcbcacacac8c8c8c8c8c8c8c8c8c9c9c9cbcbcbcfcfcfd1d1d1cfcfcfcdcdcdcccccc
+cacacac8c8c8c6c6c6c6c6c6c6c6c6c7c7c7c7c7c7c8c8c8cacacacbcbcbcececed1d1d1d2d2d2
+d1d1d1d0d0d0cccccccdcdcdcfcfcfd1d1d1d2d2d2d1d1d1d1d1d1d1d1d1d1d1d1d2d2d2d4d4d4
+d4d4d4d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d4d4d4d3d3d3d3d3d3d4d4d4d6d6d6d5d5d5d3d3d3
+d2d2d2d0d0d0d0d0d0cecececccccccbcbcbc9c9c9c8c8c8c8c8c8c8c8c8c9c9c9cacacacacaca
+cacacacacacacacacac9c9c9c9c9c9cacacacacacacacacacbcbcbcbcbcbcbcbcbcbcbcbcdcdcd
+cecececececececececfcfcfd0d0d0d0d0d0cfcfcfcecececccccccccccccdcdcdcececed1d1d1
+d1d1d1070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cececed1d1d1d3d3d3d3d3d3d3d3d3
+d2d2d2d1d1d1d1d1d1d1d1d1cfcfcfcdcdcdcccccccbcbcbcbcbcbcbcbcbcacacacacacacacaca
+cacacacbcbcbcccccccccccccccccccccccccbcbcbcbcbcbcacacacbcbcbcbcbcbcbcbcbcdcdcd
+cececececececdcdcdcccccccdcdcdcdcdcdcccccccccccccccccccccccccccccccececececece
+cfcfcfcecececdcdcdcbcbcbcbcbcbcccccccdcdcdcdcdcdcbcbcbcccccccdcdcdcdcdcdd0d0d0
+d0d0d0d0d0d0d0d0d0d0d0d0d1d1d1d0d0d0d0d0d0cfcfcfcfcfcfd0d0d0cfcfcfcdcdcdcacaca
+c8c8c8c7c7c7c6c6c6c6c6c6c6c6c6c9c9c9cbcbcbcdcdcdcdcdcdcccccccccccccbcbcbc8c8c8
+c5c5c5c5c5c5c5c5c5c5c5c5c6c6c6c8c8c8cacacacacacacacacacbcbcbcdcdcdcececececece
+cfcfcfcecececececed0d0d0d0d0d0d0d0d0d0d0d0cecececececececececececed1d1d1d4d4d4
+d6d6d6d7d7d7d7d7d7d7d7d7d6d6d6d4d4d4d3d3d3d3d3d3d3d3d3d3d3d3d1d1d1d0d0d0d0d0d0
+d0d0d0cfcfcfcecececdcdcdcbcbcbcacacacacacacacacacacacacacacacbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbc9c9c9c9c9c9c9c9c9cacacacbcbcbcacacacacacacbcbcbcdcdcdcececececece
+d1d1d1d1d1d1d1d1d1d1d1d1cfcfcfcacacac7c7c7c9c9c9cccccccecececececed1d1d1d3d3d3
+d3d3d3d3d3d3d2d2d2d1d1d1d1d1d1d1d1d1cfcfcfcdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cacacacacacacacacacbcbcbcccccccccccccccccccccccccbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcccccccecececdcdcdcdcdcdcccccccccccccdcdcdcccccccccccccccccccccccccccccc
+cececececececfcfcfcecececccccccbcbcbcbcbcbcbcbcbcdcdcdcccccccbcbcbcbcbcbcdcdcd
+cdcdcdcfcfcfd0d0d0d0d0d0d0d0d0d0d0d0d1d1d1d0d0d0d0d0d0cfcfcfcfcfcfd0d0d0cfcfcf
+cdcdcdcbcbcbc8c8c8c7c7c7c6c6c6c6c6c6c6c6c6c8c8c8cbcbcbcdcdcdcdcdcdcccccccccccc
+cbcbcbc8c8c8c6c6c6c5c5c5c5c5c5c5c5c5c6c6c6c8c8c8cacacacacacacacacacbcbcbcccccc
+cececececececfcfcfcecececfcfcfd0d0d0d0d0d0d0d0d0d0d0d0cececececececececececece
+d1d1d1d3d3d3d5d5d5d7d7d7d7d7d7d7d7d7d6d6d6d5d5d5d3d3d3d3d3d3d3d3d3d3d3d3d1d1d1
+d0d0d0d0d0d0d0d0d0cfcfcfcecececdcdcdcbcbcbcacacacacacacacacacacacacacacacbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbc9c9c9c9c9c9c9c9c9cacacacbcbcbcacacacacacacbcbcbcdcdcd
+cecececececed0d0d0d1d1d1d1d1d1d1d1d1cecececbcbcbc7c7c7c9c9c9cccccccececececece
+d1d1d1070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cececed1d1d1d4d4d4d5d5d5d5d5d5
+d4d4d4d3d3d3d3d3d3d2d2d2d0d0d0cecececccccccbcbcbcbcbcbcacacacacacac9c9c9c9c9c9
+c9c9c9c9c9c9cacacacbcbcbcbcbcbcacacacacacacacacacacacacacacac9c9c9cacacacccccc
+cecececfcfcfd0d0d0d0d0d0d1d1d1d0d0d0d0d0d0cfcfcfcdcdcdcecececfcfcfcfcfcfcfcfcf
+cececececececdcdcdcbcbcbcbcbcbcccccccdcdcdcdcdcdcccccccdcdcdd0d0d0d1d1d1d2d2d2
+d2d2d2d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d0d0d0d0d0d0d0d0d0d0d0d0cfcfcfcdcdcdcacaca
+c8c8c8c7c7c7c6c6c6c5c5c5c5c5c5c7c7c7cacacacbcbcbcccccccccccccccccccbcbcbc8c8c8
+c6c6c6c5c5c5c4c4c4c4c4c4c6c6c6c9c9c9cbcbcbcbcbcbcacacac9c9c9cacacacbcbcbcccccc
+cececed0d0d0d0d0d0cfcfcfcececececececececececececdcdcdcbcbcbc9c9c9cacacacecece
+d2d2d2d5d5d5d8d8d8d7d7d7d5d5d5d5d5d5d4d4d4d3d3d3d2d2d2d2d2d2d1d1d1d1d1d1d0d0d0
+cecececececececececdcdcdcdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcdcdcd
+cccccccbcbcbcacacacacacacacacacacacacacacac9c9c9c8c8c8cbcbcbcbcbcbcdcdcdcecece
+cececed1d1d1d2d2d2d2d2d2d0d0d0cacacac7c7c7c8c8c8cbcbcbcdcdcdcececed2d2d2d4d4d4
+d5d5d5d5d5d5d4d4d4d3d3d3d3d3d3d2d2d2d0d0d0cecececccccccccccccbcbcbcacacacacaca
+cacacac9c9c9c9c9c9cacacacacacacbcbcbcbcbcbcacacacacacacacacacacacacacacac9c9c9
+cacacacccccccecececfcfcfd0d0d0d0d0d0d1d1d1d0d0d0cfcfcfcfcfcfcdcdcdcecececfcfcf
+cfcfcfcfcfcfcececececececccccccbcbcbcbcbcbcbcbcbcdcdcdcccccccccccccdcdcdd0d0d0
+d1d1d1d2d2d2d2d2d2d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d0d0d0d0d0d0d0d0d0d0d0d0cfcfcf
+cdcdcdcbcbcbc8c8c8c7c7c7c6c6c6c5c5c5c5c5c5c7c7c7c9c9c9cbcbcbcccccccccccccccccc
+cbcbcbc9c9c9c7c7c7c5c5c5c4c4c4c5c5c5c6c6c6c9c9c9cbcbcbcbcbcbcacacac9c9c9c9c9c9
+cbcbcbcccccccececed0d0d0d0d0d0cfcfcfcececececececececececececccccccacacac9c9c9
+cacacacdcdcdd1d1d1d5d5d5d7d7d7d7d7d7d5d5d5d5d5d5d5d5d5d3d3d3d2d2d2d2d2d2d1d1d1
+d1d1d1d0d0d0cecececececececececdcdcdcdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cccccccdcdcdcccccccbcbcbcacacacacacacacacacacacacacacac9c9c9c8c8c8cacacacccccc
+cdcdcdcecececececed0d0d0d2d2d2d2d2d2cfcfcfcbcbcbc7c7c7c8c8c8cacacacccccccecece
+d2d2d2070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2af9999994b4b4b434343cdcdcdd0d0d0d4d4d4c4c4c4bfc0bf
+bfbfbfbebebebebebebdbdbdbcbcbcbabbbab9b9b9b9b9b9b8b9b8b8b8b8b7b8b7b7b8b7b7b7b7
+b7b7b7b7b7b7b8b8b8b8b8b8b8b8b8b7b8b7b7b8b7b7b8b7b7b8b7b7b8b7b7b7b7b8b8b8b9bab9
+babbbabbbcbbbcbcbcbdbdbdbdbdbdbcbdbcbcbcbcbbbcbbbabbbabbbbbbbbbcbbbbbcbbbbbcbb
+bababababababababab9b9b9b9b9b9b9b9b9babababababab9b9b9babbbabcbcbcbdbebdbdbebd
+bdbdbdbdbdbdbdbdbdbdbdbdbcbdbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbbbbbbbababab8b8b8
+b6b6b6b6b6b6b5b5b5b5b5b5b4b5b4b5b6b5b7b8b7b8b9b8b9b9b9b9b9b9b9b9b9b8b8b8b7b7b7
+b5b6b5b5b5b5b3b4b3b4b4b4b5b6b5b7b8b7b9b9b9b9b9b9b7b8b7b7b7b7b7b7b7b8b8b8b9b9b9
+babababcbcbcbcbcbcbbbbbbbababababababababababababababab8b8b8b6b6b6b7b7b7b9bab9
+bcbdbcbfbfbfc1c1c1c0c0c0bfbfbfbfbfbfbfbfbfbebebebdbdbdbdbdbdbdbdbdbdbdbdbcbcbc
+bababababababababababababababab9b9b9b9b9b9b8b9b8b8b8b8b8b8b8b8b8b8b9b9b9bababa
+b9bab9b8b9b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b7b7b7b6b7b6b8b8b8b8b9b8b9bab9bababa
+babababcbcbcbdbebdbdbebdbcbcbcb8b8b8b5b6b5b7b7b7b8b8b8b9bab9babababdbdbdbebfbe
+bfc0bfbfbfbfbfbfbfbebebebebebebdbebdbcbcbcbbbbbbb9b9b9b9b9b9b8b8b8b8b8b8b7b8b7
+b7b8b7b7b7b7b7b7b7b7b8b7b8b8b8b8b8b8b8b8b8b8b8b8b7b8b7b7b8b7b7b8b7b7b8b7b7b7b7
+b8b8b8b9b9b9bbbbbbbcbcbcbcbcbcbdbdbdbdbdbdbdbdbdbcbcbcbbbcbbbabbbabbbbbbbbbcbb
+bbbcbbbbbcbbbabbbabababab9bab9b9b9b9b9b9b9b9b9b9bababab9bab9b9bab9babababcbcbc
+bdbdbdbdbebdbdbebdbdbdbdbdbdbdbdbdbdbcbdbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbbbbbb
+bababab8b8b8b6b7b6b6b6b6b5b5b5b5b5b5b4b4b4b5b6b5b7b7b7b8b9b8b9b9b9b9b9b9b9b9b9
+b8b9b8b7b7b7b6b6b6b4b5b4b3b4b3b4b4b4b5b6b5b7b7b7b9b9b9b9b9b9b7b8b7b7b7b7b7b7b7
+b8b8b8b9b9b9babababcbcbcbcbcbcbbbbbbbabababababababababababab9bab9b8b8b8b6b6b6
+b7b7b7b9b9b9bcbcbcbfbfbfc1c1c1c0c0c0bfbfbfbfbfbfbfbfbfbebebebdbdbdbdbdbdbdbdbd
+bdbdbdbcbcbcbababababababababababababababab9b9b9b9b9b9b8b9b8b8b8b8b8b8b8b8b9b8
+b9b9b9bababab9bab9b9b9b9b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b7b7b7b6b6b6b8b8b8b9b9b9
+b9bab9bababababababcbcbcbdbdbdbdbdbdbbbbbbb8b8b8b6b6b6b6b7b6c1c1c1cccccccdcdcd
+d0d0d0070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2af9999994b4b4b434343cccccccdcdcdd2d2d2a1a2a1989998
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a29495949fa09fa2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a29c9d9c979897a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a29596959f9f9f
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a29c9d9c979897a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a29596959e9f9ea2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a29d9e9d949594a1a1a1
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a29a9b9a999a99a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2949594a0a1a0a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2
+a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2a2a3a2b6b7b6cbcbcbcccccc
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cccccccdcdcdd0d0d0a0a1a0b2b2b2
+f3f3f3f3f3f3f4f4f4f3f3f3f4f4f4f3f3f3f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f3f3f3f3f3f3f3f3f3f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4969796dfe0dff4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4c8c9c8adaeadf4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f49a9b9adbdcdb
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4cccdcca9aaa9f4f4f4f3f3f3f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f49e9f9ed7d8d7f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4d0d1d0949594e9e9e9
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4bfbfbfb7b8b7f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f1f1f1949594e5e5e5f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4dededec9c9c9cccccc
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b424242cbcbcbcbcbcbcccccc9fa09fb2b2b2
+f3f3f3f1f1f1ebebebebebebedededeaeaeae6e6e6e6e6e6e7e7e7e7e7e7e6e6e6e5e5e5e2e2e2
+dedededfdfdfe3e3e3e4e4e4e2e2e2dbdbdbd7d7d7d6d6d6d5d5d5d2d2d2d0d0d0d4d4d4d2d2d2
+d0d0d0cdcdcdcfcfcfcfcfcfabacabc0c0c0f4f4f4969796dfe0dff2f2f2eeeeeeebebebececec
+eeeeeee9e9e9e6e6e6e6e6e6e8e8e8e6e6e6e6e6e6e4e4e4e1e1e1dddddde1e1e1e4e4e4e3e3e3
+dfdfdfdbdbdbd6d6d6d6d6d6d3d3d3d1d1d1d2d2d2d5d5d5d1d1d1cececececececfcfcfc9c9c9
+969796d1d1d1c8c9c8adaeadf3f3f3f1f1f1ebebebebebebecececededede6e6e6e6e6e6e7e7e7
+e7e7e7e6e6e6e6e6e6e2e2e2dfdfdfdfdfdfe2e2e2e4e4e4e2e2e2ddddddd9d9d9d6d6d6d5d5d5
+d2d2d2d1d1d1d3d3d3d4d4d4d0d0d0cdcdcdcecececfcfcfbebebea0a1a0f4f4f49a9b9adbdcdb
+f2f2f2eeeeeeebebebecececededede9e9e9e6e6e6e6e6e6e8e8e8e6e6e6e6e6e6e4e4e4e1e1e1
+dddddde1e1e1e4e4e4e4e4e4e1e1e1dbdbdbd6d6d6d6d6d6d4d4d4d2d2d2d0d0d0d5d5d5d2d2d2
+cecececdcdcdcfcfcfcfcfcfa3a4a3cdcdcdcccdcca9aaa9f3f3f3f1f1f1edededebebebececec
+ededede6e6e6e6e6e6e7e7e7e7e7e7e6e6e6e6e6e6e3e3e3dfdfdfdfdfdfe1e1e1e5e5e5e3e3e3
+dededed9d9d9d6d6d6d5d5d5d3d3d3d1d1d1d3d3d3d4d4d4d0d0d0cdcdcdcecececfcfcfc1c1c1
+9c9d9cf4f4f49e9f9ed7d8d7f3f3f3f0f0f0ebebebecececedededeaeaeae6e6e6e6e6e6e8e8e8
+e7e7e7e6e6e6e5e5e5e1e1e1dddddde0e0e0e3e3e3e4e4e4e1e1e1dbdbdbd7d7d7d6d6d6d5d5d5
+d2d2d2d0d0d0d5d5d5d2d2d2cecececdcdcdcfcfcfcfcfcfa6a6a6c9cac9d0d1d0949594e9e9e9
+f1f1f1edededebebebecececeeeeeee8e8e8e6e6e6e7e7e7e8e8e8e6e6e6e6e6e6e3e3e3e0e0e0
+dededee1e1e1e5e5e5e3e3e3dedededbdbdbd6d6d6d5d5d5d3d3d3d1d1d1d2d2d2d4d4d4d0d0d0
+cececececececfcfcfc3c3c3989998f4f4f4bfbfbfb7b8b7f3f3f3f1f1f1ebebebecececececec
+ececece6e6e6e6e6e6e7e7e7e7e7e7e6e6e6e6e6e6e2e2e2dededee0e0e0e3e3e3e4e4e4e2e2e2
+ddddddd8d8d8d6d6d6d5d5d5d2d2d2d0d0d0d5d5d5d3d3d3d0d0d0cdcdcdcfcfcfcfcfcfa8a9a8
+aaaaaaf1f1f1949594e5e5e5f2f2f2eeeeeeebebebecececededede9e9e9e6e6e6e6e6e6e8e8e8
+e6e6e6e6e6e6e4e4e4e1e1e1dededee1e1e1e5e5e5e4e4e4e0e0e0dbdbdbd6d6d6d5d5d5d3d3d3
+d1d1d1d1d1d1d5d5d5d1d1d1cececececececfcfcfcfcfcf9e9e9ed6d7d6ddddddc9c9c9cbcbcb
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacacacacacacaca9fa09fb2b2b2
+f2f2f2e8e8e8eeeeeeedededececece8e8e8e5e5e5e8e8e8e6e6e6e6e6e6e6e6e6e6e6e6e4e4e4
+e0e0e0dededee0e0e0e3e3e3dcdcdcd6d6d6dadadad6d6d6d0d0d0d6d6d6ccccccd2d2d2d0d0d0
+cecececccccccccccccccccca9a9a9bebfbef4f4f4969796dfe0dfecececebebebeeeeeeececec
+ebebebe7e7e7e6e6e6e7e7e7e6e6e6e6e6e6e7e7e7e6e6e6e3e3e3dfdfdfdddddde3e3e3dfdfdf
+d9d9d9d6d6d6dadadad1d1d1d4d4d4d1d1d1cfcfcfd4d4d4cfcfcfccccccccccccccccccc6c6c6
+949594d0d0d0c8c9c8adaeadf2f2f2e8e8e8eeeeeeedededecececdddddd2f2f2f2f2f2f303030
+3030302f2f2f2f2f2f2f2f2f2e2e2e2e2e2e2f2f2f2f2f2f2f2f2f2e2e2e2d2d2d2c2c2c2c2c2c
+2b2b2b2b2b2b2b2b2b2c2c2c3f3f3fccccccccccccccccccbcbcbc9e9f9ef4f4f49a9b9adbdcdb
+edededeaeaeaeeeeeeecececebebebe8e8e8e6e6e6e7e7e7e6e6e6e6e6e6e6e6e6e6e6e6e3e3e3
+dfdfdfdddddde3e3e3e2e2e2dbdbdbd6d6d6dadadad1d1d1d3d3d3d5d5d5ccccccd3d3d3cfcfcf
+cccccccccccccccccccccccca1a1a1cccccccccdcca9aaa9f3f3f3e8e8e8ecececeeeeeeececec
+ebebebe5e5e5e7e7e7e7e7e7e6e6e6e6e6e6e7e7e7e4e4e4e1e1e1dedededddddde5e5e5dddddd
+d8d8d8d8d8d8d7d7d7cfcfcfd5d5d5d0d0d0d0d0d0d2d2d2cecececcccccccccccccccccbebebe
+9a9b9af4f4f49e9f9ed7d8d7f1f1f1e8e8e8eeeeeeedededebebebe8e8e8e5e5e5e8e8e8e6e6e6
+e6e6e6e6e6e6e6e6e6e3e3e3dfdfdfdededee1e1e1e2e2e2dbdbdbd6d6d6dadadad5d5d5d1d1d1
+d5d5d5ccccccd3d3d3cfcfcfcdcdcdcccccccccccccccccca3a4a3c8c8c8d0d1d0949594e9e9e9
+ebebebebebebeeeeeeecececebebebe7e7e7e6e6e6e7e7e7e6e6e6e6e6e6e7e7e7e5e5e5e2e2e2
+dfdfdfdddddde4e4e4dededed8d8d8d6d6d6dadadad0d0d0d5d5d5d0d0d0cfcfcfd2d2d2cecece
+ccccccccccccccccccc0c1c0969796f4f4f4bfbfbfb7b8b7f1f1f1e8e8e8eeeeeeedededececec
+eaeaeae5e5e5e8e8e8e6e6e6e6e6e6e6e6e6e7e7e7e4e4e4e0e0e0dededee0e0e0e2e2e2dcdcdc
+d7d7d7d8d8d8d6d6d6d1d1d1d6d6d6ccccccd3d3d3d1d1d1cdcdcdcccccccccccccccccca5a6a5
+a8a8a8f1f1f1949594e5e5e5ecececebebebeeeeeeecececebebebe7e7e7e6e6e6e7e7e7e6e6e6
+e6e6e6e7e7e7e6e6e6e2e2e2dfdfdfdddddde4e4e4e1e1e1dadadad6d6d6dadadad0d0d0d4d4d4
+d1d1d1cdcdcdd4d4d4cfcfcfcccccccccccccccccccccccc9b9c9bd5d6d5ddddddc8c8c8cacaca
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac9c9c9c9c9c99fa09fb2b2b2
+f2f2f2e8e8e8e9e9e9eaeaeaeaeaeae7e7e7e3e3e3e1e1e1e3e3e3e3e3e3e3e3e3e2e2e2dedede
+dfdfdfdfdfdfe0e0e0e0e0e0d8d8d8d4d4d4d8d8d8d6d6d6d2d2d2d4d4d4ccccccd1d1d1cecece
+cccccccccccccccccccbcbcba8a9a8bebfbef4f4f4969796dfe0dfececece9e9e9eaeaeaeaeaea
+e9e9e9e5e5e5e2e2e2c1c1c15959595959595a5a5a595959585858575757565656585858565656
+5454545353535555555151515252528d8d8dcececed2d2d2cdcdcdcccccccccccccbcbcbc4c5c4
+949594d0d0d0c8c9c8adaeadf2f2f2e8e8e8e9e9e9eaeaeaeaeaead8d8d80000004545454e4e4e
+4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e434343
+000000000000000000000000191919cccccccccccccbcbcbbabbba9e9f9ef4f4f49a9b9adbdcdb
+ededede9e9e9e9e9e9eaeaeae9e9e99999995959595a5a5a5959595959595a5a5a5a5a5a585858
+5757575656565858585757575454545353535555555151515252525353534f4f4f525252505050
+9b9b9bcccccccccccccacacaa0a1a0cccccccccdcca9aaa9f3f3f3e8e8e8e9e9e9eaeaeaeaeaea
+e9e9e9e3e3e3e1e1e1e2e2e2e3e3e3e3e3e3e3e3e3dfdfdfdfdfdfdfdfdfdfdfdfe2e2e2dadada
+d6d6d6d7d7d7d7d7d7d1d1d1d3d3d3cfcfcfcfcfcfd1d1d1cccccccccccccccccccbcbcbbdbdbd
+9a9b9af4f4f49e9f9ed7d8d7f1f1f1e8e8e8e9e9e9eaeaeaeaeaeae6e6e6e3e3e3e1e1e1e3e3e3
+e3e3e3e3e3e3e2e2e2dededee0e0e0dfdfdfe0e0e0dfdfdfd8d8d8d5d5d5d9d9d9d5d5d5d2d2d2
+d3d3d3ccccccd2d2d2cecececccccccccccccccccccacacaa3a3a3c8c8c8d0d1d0949594e9e9e9
+ebebebe9e9e9eaeaeaeaeaeae9e9e9e5e5e5e2e2e2e2e2e2e3e3e3e3e3e3e3e3e3dfdfdfdedede
+dfdfdfdfdfdfe2e2e2dadadad6d6d6d5d5d5d9d9d9d2d2d2d3d3d3cfcfcfcececed1d1d1cccccc
+cccccccccccccbcbcbbfbfbf969796f4f4f4bfbfbfb7b8b7f1f1f1e8e8e8e9e9e9eaeaeaeaeaea
+e8e8e8e3e3e3e1e1e1e3e3e3e3e3e3e3e3e3e3e3e3dedededfdfdfdfdfdfe0e0e0dfdfdfd8d8d8
+d5d5d5d7d7d7d6d6d6d2d2d2d3d3d3ccccccd1d1d1d0d0d0cccccccccccccccccccacacaa5a6a5
+a8a8a8f1f1f1949594e5e5e5ececece9e9e9e9e9e9eaeaeae9e9e9e5e5e5e2e2e2e2e2e2e3e3e3
+e3e3e3e3e3e3e1e1e1dedededfdfdfdfdfdfe2e2e2dededed7d7d7d5d5d5d9d9d9d2d2d2d3d3d3
+cfcfcfccccccd2d2d2cdcdcdcccccccccccccbcbcbcacaca9b9c9bd5d6d5ddddddc8c8c8cacaca
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2af9999994b4b4b424242c9c9c9c9c9c9cacaca9fa09fb2b2b2
+f2f2f2e8e8e8e6e6e6e8e8e8e9e9e9e6e6e6e2e2e2dededee0e0e0e0e0e0dfdfdfdedededcdcdc
+dddddddedededddddddbdbdbd8d8d8d4d4d4d6d6d6d6d6d6d3d3d3d1d1d1cececed0d0d0cdcdcd
+cbcbcbcbcbcbcacacacacacaa8a8a8bebfbef4f4f4969796dfe0dfededede7e7e7e7e7e7e9e9e9
+e9e9e9e5e5e5e0e0e0aaaaaa0505056d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d
+6d6d6d6d6d6d6d6d6d6d6d6d242424636363cfcfcfd1d1d1cccccccbcbcbcacacacacacac4c4c4
+949594d0d0d0c8c9c8adaeadf2f2f2e8e8e8e6e6e6e8e8e8e9e9e9d8d8d8000000979797a9a9a9
+a8a8a8a7a7a7a7a7a7a9a9a9a7a7a7a7a7a7a6a6a6a5a5a5a7a7a7a4a4a4a4a4a4a4a4a48d8d8d
+000000343434363636262626191919cbcbcbcacacacacacabababa9e9f9ef4f4f49a9b9adbdcdb
+ededede7e7e7e6e6e6e9e9e9e9e9e9686868141414363636363636363636363636363636363636
+3636363636363636363636363636363636363636363636363636362e2e2e000000000000000000
+7a7a7acacacacacacacacacaa0a1a0cccccccccdcca9aaa9f3f3f3e8e8e8e7e7e7c0c0c0858585
+8484848181817e7e7e7f7f7f8181818181818080807d7d7d7e7e7e8080808080808080807b7b7b
+7a7a7a7a7a7a7a7a7a797979787878757575757575767676747474747474c1c1c1cacacabcbdbc
+9a9b9af4f4f49e9f9ed7d8d7f1f1f1e8e8e8e6e6e6e9e9e9e9e9e9e5e5e5e1e1e1dededee0e0e0
+e0e0e0dfdfdfdedededcdcdcdddddddedededddddddbdbdbd8d8d8d4d4d4d6d6d6d5d5d5d3d3d3
+d1d1d1cececed0d0d0cccccccbcbcbcbcbcbcacacacacacaa2a3a2c8c8c8d0d1d0949594e9e9e9
+ebebebe7e7e7e7e7e7e9e9e9e9e9e9e4e4e4e0e0e0dfdfdfe0e0e0dfdfdfdfdfdfdddddddcdcdc
+dddddddedededcdcdcd9d9d9d5d5d5d4d4d4d7d7d7d4d4d4d2d2d2cfcfcfcfcfcfcfcfcfcbcbcb
+cbcbcbcacacacacacabfbfbf969796f4f4f4bfbfbfb7b8b7f1f1f1e8e8e8e6e6e6e8e8e8e9e9e9
+e8e8e8e2e2e2dededee0e0e0e0e0e0dfdfdfdfdfdfdcdcdcdddddddedededddddddbdbdbd8d8d8
+d5d5d5d5d5d5d6d6d6d3d3d3d1d1d1cececed0d0d0cecececbcbcbcbcbcbcacacacacacaa5a5a5
+a8a8a8f1f1f1949594e5e5e5ececece7e7e7e6e6e6e9e9e9e9e9e9e4e4e4e0e0e0dfdfdfe0e0e0
+dfdfdfdfdfdfdedededcdcdcdddddddedededcdcdcdadadad7d7d7d4d4d4d7d7d7d4d4d4d2d2d2
+cfcfcfcececed1d1d1cbcbcbcbcbcbcacacacacacacacaca9b9c9bd5d6d5ddddddc8c8c8c9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b2af9999994b4b4b424242c9c9c9c9c9c9cacaca9fa09fb2b2b2
+f2f2f2e6e6e6e7e7e7e9e9e9e9e9e9e6e6e6e2e2e2e0e0e0dfdfdfdedededcdcdcdddddddfdfdf
+dcdcdcdadadad9d9d9d7d7d7dadadad2d2d2d5d5d5d5d5d5d4d4d4d0d0d0d0d0d0d0d0d0cccccc
+cacacacacacac8c8c8cacacaa8a9a8bebfbef4f4f4969796dfe0dfececece7e7e7e7e7e7eaeaea
+eaeaeae5e5e5e1e1e1ababab0d0d0dffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff565656646464d0d0d0d0d0d0cbcbcbcacacac9c9c9c8c8c8c5c5c5
+949594d0d0d0c8c9c8adaeadf2f2f2e7e7e7e7e7e7e9e9e9eaeaead8d8d8000000c8c8c8e0e0e0
+dedededddddddddddddfdfdfdcdcdcdbdbdbd9d9d9d7d7d7dbdbdbd5d5d5d4d4d4d5d5d5b6b6b6
+0000007b7b7b808080585858191919cacacac8c8c8cacacabbbbbb9e9f9ef4f4f49a9b9adbdcdb
+ececece7e7e7e7e7e7e9e9e9eaeaea6868682f2f2f808080808080808080808080808080808080
+8080808080808080808080808080808080808080808080808080806d6d6d000000000000000000
+7a7a7ac9c9c9c8c8c8cacacaa0a1a0cccccccccdcca9aaa9f3f3f3e6e6e6e7e7e78c8c8c000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000b4b4b4c9c9c9bdbdbd
+9a9b9af4f4f49e9f9ed7d8d7f0f0f0e7e7e7e7e7e7e9e9e9eaeaeae5e5e5e1e1e1e0e0e0e0e0e0
+dddddddddddddddddddfdfdfdbdbdbdbdbdbd9d9d9d8d8d8dadadad3d3d3d5d5d5d5d5d5d3d3d3
+d1d1d1d1d1d1d0d0d0cbcbcbcacacac9c9c9c8c8c8cacacaa3a3a3c8c8c8d0d1d0949594e9e9e9
+eaeaeae7e7e7e8e8e8eaeaeaeaeaeae4e4e4e0e0e0e0e0e0dfdfdfdddddddddddddfdfdfdedede
+dbdbdbdbdbdbd7d7d7dadadad6d6d6d3d3d3d6d6d6d5d5d5d1d1d1d1d1d1d0d0d0cecececacaca
+cacacac8c8c8c9c9c9bfbfbf969796f4f4f4bfbfbfb7b8b7f1f1f1e7e7e7e7e7e7e9e9e9eaeaea
+e8e8e8e2e2e2e0e0e0e0e0e0dedededddddddddddddfdfdfdcdcdcdbdbdbd9d9d9d8d8d8dbdbdb
+d4d4d4d4d4d4d5d5d5d4d4d4d1d1d1d1d1d1d0d0d0cdcdcdcacacac9c9c9c8c8c8cacacaa5a6a5
+a8a8a8f1f1f1949594e5e5e5ebebebe7e7e7e7e7e7eaeaeaeaeaeae4e4e4e1e1e1e0e0e0dfdfdf
+dddddddddddddededededededadadadbdbdbd7d7d7d8d8d8d8d8d8d3d3d3d6d6d6d5d5d5d2d2d2
+d1d1d1d0d0d0d0d0d0cacacacacacac8c8c8c9c9c9cbcbcb9b9c9bd5d6d5ddddddc8c8c8cacaca
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cacacacbcbcb9fa09fb2b2b2
+f1f1f1e3e3e3e1e1e1e5e5e5e7e7e7e6e6e6e4e4e4e0e0e0dddddddadadadadadadcdcdcdbdbdb
+dbdbdbdadadad6d6d6d3d3d3d6d6d6dbdbdbd2d2d2d0d0d0d0d0d0d0d0d0d1d1d1cecececacaca
+c9c9c9cbcbcbc3c3c3c7c7c7a7a8a7bebfbef4f4f4969796dfe0dfe9e9e9e2e2e2e2e2e2e6e6e6
+e8e8e8e6e6e6e2e2e2ababab0d0d0dffffff2a2a2a0c0c0c414141ffffffffffffffffffffffff
+ffffffffffffffffffffffff565656646464d0d0d0cececec9c9c9cacacac7c7c7c4c4c4c2c2c2
+949594d0d0d0c8c9c8adaeadf2f2f2e3e3e3e1e1e1e4e4e4e6e6e6d6d6d6000000c8c8c8dddddd
+dadadad9d9d9dddddddbdbdbdbdbdbdadadad7d7d7d3d3d3d6d6d6d9d9d9d6d6d6919191191919
+797979c9c9c9a7a7a7585858191919cbcbcbc3c3c3c6c6c6b9b9b99e9f9ef4f4f49a9b9adbdcdb
+eaeaeae2e2e2e1e1e1e5e5e5e7e7e7676767515151dadadad7d7d7d5d5d5d6d6d6d7d7d7d6d6d6
+d7d7d7d4d4d4d0d0d0d0d0d0d2d2d2d7d7d7cdcdcd2d2d2d5151518a8a8ac7c7c77c7c7c1a1a1a
+7b7b7bc8c8c8c3c3c3c7c7c7a0a0a0cccccccccdcca9aaa9f3f3f3e3e3e3e2e2e28888882e2e2e
+dcdcdcdadadad6d6d6d3d3d3d1d1d1cececed2d2d2d0d0d0d1d1d1d0d0d0cececec9c9c9cbcbcb
+cfcfcfccccccc6c6c6c6c6c6c6c6c6c6c6c6c5c5c5c3c3c3afafaf000000b0b0b0c5c5c5bbbbbb
+9a9b9af4f4f49e9f9ed7d8d7f0f0f0e3e3e3e1e1e1e5e5e5e7e7e7e6e6e6e4e4e4e0e0e0dcdcdc
+dadadadbdbdbdcdcdcdbdbdbdbdbdbdadadad6d6d6d4d4d4d6d6d6dbdbdbd1d1d1d0d0d0d0d0d0
+d0d0d0d1d1d1cecececacacacacacacbcbcbc3c3c3c7c7c7a2a3a2c8c8c8d0d1d0949594e9e9e9
+e8e8e8e2e2e2e2e2e2e6e6e6e8e8e8e5e5e5e2e2e2dedededbdbdbd9d9d90f0f0f0a0a0a0a0a0a
+262626d9d9d9d3d3d3d5d5d5d9d9d9dadadad1d1d1d0d0d0d0d0d0d0d0d0cfcfcfccccccc9c9c9
+cbcbcbc7c7c7c5c5c5bdbdbd969796f4f4f4bfbfbfb7b8b7f0f0f0e3e3e3e1e1e1e5e5e5e6e6e6
+e7e7e7e4e4e4e0e0e0dcdcdcdadada7b7b7b0a0a0a0a0a0a0a0a0a898989d6d6d6d3d3d3d6d6d6
+dadadad5d5d5d0d0d0d0d0d0d0d0d0d1d1d1cecececcccccc9c9c9cbcbcbc3c3c3c7c7c7a4a5a4
+a8a8a8f1f1f1949594e5e5e5e8e8e8e2e2e2e1e1e1e6e6e6e7e7e75757570a0a0a0a0a0a0a0a0a
+0a0a0a909090dcdcdcdbdbdbc7c7c70a0a0a0a0a0a0a0a0a0a0a0a0909090a0a0a0a0a0a090909
+090909161616cececec9c9c9cbcbcbc7c7c7c4c4c4c8c8c89a9b9ad5d6d5ddddddc8c8c8c9c9c9
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cacacacbcbcb9fa09fb2b2b2
+f1f1f1e2e2e2e1e1e1e5e5e5e5e5e5e3e3e3e1e1e1dbdbdbdbdbdbd9d9d9d9d9d9dbdbdbd9d9d9
+dbdbdbd9d9d9d7d7d7b6b6b63030303232323030306b6b6bd3d3d3d2d2d2d0d0d0cccccccccccc
+cbcbcbc7c7c7c4c4c4c7c7c7a7a8a7bebfbef4f4f4969796dfe0dfe9e9e9e2e2e2e3e3e3e6e6e6
+e4e4e4e2e2e2dededea7a7a70d0d0dffffffccccccc4c4c4d1d1d1ffffffffffffffffffffffff
+ffffffffffffffffffffffff565656646464cfcfcfcbcbcbccccccc9c9c9c6c6c6c5c5c5c2c2c2
+949594d0d0d0c8c9c8adaeadf2f2f2e2e2e2e1e1e1e5e5e5e6e6e6d3d3d3000000c4c4c4dbdbdb
+dadadad9d9d9dbdbdbd9d9d9dbdbdbd9d9d9d7d7d7d6d6d6cfcfcfd4d4d48383834040406f6f6f
+c0c0c0d0d0d0a9a9a9585858191919c7c7c7c4c4c4c7c7c7b8b9b89e9f9ef4f4f49a9b9adbdcdb
+e9e9e9e2e2e2e1e1e1e6e6e6e5e5e5666666515151dbdbdbdbdbdbd9d9d9dadadadadadad9d9d9
+dcdcdcd6d6d6d7d7d7d4d4d4d1d1d1d7d7d73232325858589c9c9cc2c2c2d1d1d18282821b1b1b
+787878c6c6c6c4c4c4c7c7c7a0a0a0cccccccccdcca9aaa9f3f3f3e2e2e2e1e1e1898989303030
+dfdfdf343434333333323232525252d9d9d9dbdbdbd9d9d9dbdbdbd9d9d9d6d6d6d7d7d7d1d1d1
+d4d4d4d7d7d7d6d6d6d3d3d34f4f4f2f2f2f2f2f2f585858bbbbbb000000b1b1b1c6c6c6bbbbbb
+9a9b9af4f4f49e9f9ed7d8d7efefefe2e2e2e1e1e1e6e6e6e5e5e5e2e2e2e0e0e0dbdbdbdbdbdb
+d9d9d9dadadadadadad9d9d9dcdcdcd8d8d8d7d7d7d5d5d5d0d0d0d7d7d7d7d7d7d5d5d5d3d3d3
+d2d2d2d1d1d1ccccccccccccc9c9c9c7c7c7c4c4c4c7c7c7a2a2a2c8c8c8d0d1d0949594e9e9e9
+e7e7e7e1e1e1e3e3e3e6e6e6e4e4e4e2e2e2dededea2a2a2323232313131a5a5a5a7a7a7a8a8a8
+999999313131303030acacacd4d4d4d7d7d7d7d7d7d4d4d4d2d2d2d1d1d1cecececbcbcbcccccc
+c8c8c8c5c5c5c5c5c5bdbdbd969796f4f4f4bfbfbfb7b8b7f0f0f0e2e2e2e1e1e1e5e5e5e6e6e6
+e4e4e4e1e1e1dbdbdb515151313131676767a8a8a8a7a7a7a9a9a95f5f5f303030595959cfcfcf
+d5d5d5d7d7d7d5d5d5d3d3d3d2d2d2d1d1d1cccccccccccccbcbcbc7c7c7c4c4c4c7c7c7a4a5a4
+a8a8a8f1f1f1949594e5e5e5e8e8e8e2e2e2e1e1e1e6e6e6525252929212c4c400c4c400c4c400
+c4c4006767207e7e7edadadac7c7c7000000b4b4b4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4
+5a5a5a0202022f2f2fbababac8c8c8c5c5c5c5c5c5c8c8c89a9b9ad5d6d5ddddddc8c8c8c9c9c9
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac9c9c9c9c9c99fa09fb2b2b2
+f1f1f1e2e2e2e1e1e1e2e2e2e2e2e2e2e2e2e1e1e1dedededadadad9d9d9d8d8d8d8d8d8d6d6d6
+d7d7d7d5d5d5a4a4a45f5f5f7a7a7a7878787b7b7b6e6e6e6d6d6dcfcfcf555555b5b5b5cacaca
+c9c9c9c5c5c5c6c6c6c6c6c6a6a7a6bebfbef4f4f4969796dfe0dfe9e9e9e2e2e2e1e1e1e2e2e2
+e2e2e2e1e1e1dfdfdfa9a9a90d0d0dffffff7b7b7b686868686868686868686868686868686868
+686868686868686868e7e7e7565656636363ccccccc9c9c9cacacac7c7c7c6c6c6c6c6c6c0c1c0
+949594d0d0d0c8c9c8adaeadf2f2f2e2e2e2e1e1e1e2e2e2e2e2e2d1d1d1000000c6c6c6dbdbdb
+d9d9d9d8d8d8d8d8d8d6d6d6d7d7d7d5d5d5d2d2d2d1d1d1cfcfcf7d7d7d5151516c6c6cb6b6b6
+d0d0d0cececea8a8a8585858181818c5c5c5c6c6c6c6c6c6b7b7b79e9f9ef4f4f49a9b9adbdcdb
+eaeaeae2e2e2e1e1e1e2e2e2e2e2e2656565525252ddddddd9d9d9d9d9d9d8d8d8d7d7d7d6d6d6
+d8d8d8d3d3d3d2d2d2d1d1d1bbbbbb5757574b4b4b9d9d9dc4c4c4cfcfcfcecece8282821b1b1b
+777777c5c5c5c6c6c6c6c6c69fa09fcccccccccdcca9aaa9f3f3f3e2e2e2e1e1e1888888303030
+dbdbdb000000000000303030919191d8d8d8d8d8d8d6d6d6d7d7d7d5d5d5d3d3d3d2d2d2cfcfcf
+cfcfcfd2d2d2d4d4d4d5d5d58b8b8b2d2d2d000000353535b9b9b9000000b3b3b3c6c6c6b9bab9
+9a9b9af4f4f49e9f9ed7d8d7efefefe2e2e2e1e1e1e2e2e2e2e2e2e1e1e1dcdcdc595959595959
+afafafd8d8d8d7d7d7d6d6d6d8d8d8d4d4d4d2d2d2d1d1d1cfcfcfd0d0d0d4d4d4d4d4d4d3d3d3
+c3c3c3555555535353abababc7c7c7c5c5c5c6c6c6c6c6c6a1a2a1c8c8c8d0d1d0949594e9e9e9
+e7e7e7e1e1e1e1e1e1e2e2e2e2e2e2e1e1e19b9b9b666666808080808080d6d6d6ea7373e88181
+cbcbcb7b7b7b7979795c5c5c9e9e9ed0d0d0d4d4d4d4d4d4d1d1d1cecececcccccc9c9c9cacaca
+c6c6c6c6c6c6c6c6c6bbbcbb969796f4f4f4bfbfbfb7b8b7f0f0f0e2e2e2e1e1e1e2e2e2e2e2e2
+e2e2e2e1e1e15a5a5a787878808080a8a8a8d8d8d8d6d6d6d7d7d79f9f9f7a7a7a707070545454
+b4b4b4d2d2d2d4d4d4d3d3d3cfcfcfcecececacacacacacac9c9c9c5c5c5c6c6c6c6c6c6a3a4a3
+a8a8a8f1f1f1949594e5e5e5e8e8e8e2e2e2dfdfdf5e5e5e8d8d0fdada00b7b700686800797900
+ffff00bcbc007a7a287c7c7cc3c3c3000000e9e9e9ffffffffffffffffffffffffffffffffffff
+7575750909099696965c5c5ca3a3a3c6c6c6c6c6c6c6c6c69a9b9ad5d6d5ddddddc9c9c9cacaca
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cbcbcbc8c8c8c8c8c89f9f9fb2b2b2
+f1f1f1e1e1e1dfdfdfdededee0e0e0e1e1e1e1e1e1dedededadadad9d9d9d8d8d8d6d6d6d3d3d3
+d3d3d3d1d1d1a0a0a06c6c6ccfcfcfcececed1d1d1a3a3a3595959797979000000a6a6a6c9c9c9
+c8c8c8c4c4c4c5c5c5c4c4c4a5a6a5bebfbef4f4f4969796dfe0dfe8e8e8e0e0e0dfdfdfdedede
+e2e2e2e1e1e1e0e0e0aaaaaa0d0d0dffffff7b7b7b686868686868686868686868686868686868
+686868686868686868e7e7e7565656626262cbcbcbcacacac9c9c9c5c5c5c4c4c4c5c5c5bebebe
+949594d0d0d0c8c9c8adaeadf2f2f2e1e1e1dfdfdfdedededfdfdfd1d1d1000000c6c6c6dadada
+d9d9d9d9d9d9d7d7d7d3d3d3d3d3d3d1d1d1cececec0c0c07a7a7a4a4a4a6b6b6bb0b0b0cfcfcf
+cbcbcbcbcbcba7a7a7585858181818c4c4c4c5c5c5c4c4c4b5b6b59e9f9ef4f4f49a9b9adbdcdb
+e9e9e9e0e0e0dfdfdfdededee0e0e0656565525252ddddddd9d9d9d9d9d9d8d8d8d5d5d5d3d3d3
+d3d3d3cfcfcfcdcdcdb1b1b16f6f6f3434349f9f9fc6c6c6cdcdcdcbcbcbcccccc8282821b1b1b
+767676c4c4c4c5c5c5c3c3c39f9f9fcccccccccdcca9aaa9f3f3f3e1e1e1e0e0e08787872f2f2f
+dadada0000004c4c4c686868919191d9d9d9d7d7d7d3d3d3d3d3d3d1d1d1cfcfcfcdcdcdcecece
+cececed0d0d0d1d1d1d0d0d08a8a8a6161612e2e2e343434b8b8b8000000b2b2b2c4c4c4b7b8b7
+9a9b9af4f4f49e9f9ed7d8d7efefefe1e1e1dfdfdfdededea0a0a0858585808080000000000000
+939393d8d8d8d6d6d6d3d3d3d3d3d3d1d1d1cecececdcdcdcfcfcfcececed2d2d2ababab7c7c7c
+6d6d6d000000000000959595c6c6c6c4c4c4c5c5c5c3c3c3a1a1a1c8c8c8d0d1d0949594e9e9e9
+e6e6e6e0e0e0dedededededee2e2e2e1e1e16d6d6d484848d9d9d9d9d9d9d7d7d7f62c2cf14343
+d3d3d3cfcfcfcdcdcd2d2d2d7b7b7bcfcfcfd2d2d2d0d0d0cccccccbcbcbcbcbcbc9c9c9c8c8c8
+c5c5c5c4c4c4c4c4c4b9bab9969796f4f4f4bfbfbfb7b8b7f0f0f0e1e1e1dfdfdfdedededfdfdf
+e1e1e1e1e1e1010101b0b0b0d9d9d9d8d8d8d7d7d7d3d3d3d3d3d3d1d1d1cecece989898000000
+a1a1a1d0d0d0d1d1d1cecececbcbcbcccccccacacac9c9c9c7c7c7c4c4c4c5c5c5c4c4c4a3a3a3
+a8a8a8f1f1f1949594e5e5e5e7e7e7e0e0e0dcdcdc000000d4d400baba0079792a5959595f5f4e
+969600d8d8008a8a003a3a3abfbfbf000000e9e9e9ffffffffffffffffffffffffffffffffffff
+7575750909099696961111115151519e9e9ec4c4c4c3c3c39a9b9ad5d6d5dededecacacacbcbcb
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac9c9c9c8c8c89f9f9fb2b2b2
+f1f1f1dfdfdfdddddddcdcdcdedededfdfdfdededeacacaca7a7a7a8a8a8bbbbbbd6d6d6d2d2d2
+d2d2d2d0d0d0cdcdcdcbcbcbcdcdcdd1d1d1d0d0d0bdbdbd7e7e7e000000000000a6a6a6c9c9c9
+c8c8c8c2c2c2c1c1c1c0c0c0a4a5a4bebfbef4f4f4969796dfe0dfe7e7e7dedededddddddddddd
+e0e0e0dfdfdfdcdcdca6a6a60d0d0dffffffccccccc4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4
+c4c4c4c4c4c4c4c4c4f5f5f5565656616161cacacacacacac9c9c9c5c5c5c2c2c2c1c1c1bbbbbb
+949594d0d0d0c8c9c8adaeadf2f2f2dfdfdfddddddddddddddddddcfcfcf000000c2c2c2d9d9d9
+dadadadadadad8d8d8d3d3d3d2d2d2d0d0d0bebebe8989891d1d1d6c6c6cb0b0b0cdcdcdc8c8c8
+c6c6c6cacacaa6a6a6585858181818c2c2c2c1c1c1c0c0c0b3b3b39e9f9ef4f4f49a9b9adbdcdb
+e8e8e8dedededddddddcdcdcdfdfdf646464515151d9d9d9d9d9d9dadadad9d9d9d6d6d6d2d2d2
+d2d2d2cececea6a6a67171712f2f2f919191cfcfcfc9c9c9c7c7c7c7c7c7cacaca8282821b1b1b
+757575c2c2c2c1c1c1c0c0c09e9f9ecccccccccdcca9aaa9f3f3f3dfdfdfdedede8686862f2f2f
+dadada323232c1c1c19a9a9a494949a9a9a9d8d8d8d3d3d3d2d2d2d0d0d0cecececbcbcbcdcdcd
+cfcfcfd0d0d0c1c1c19b9b9b4242428f8f8f848484555555b8b8b8000000aeaeaec1c1c1b5b5b5
+9a9b9af4f4f49e9f9ed7d8d7efefefdfdfdfdddddddcdcdc444444000000000000000000000000
+939393d9d9d9d6d6d6d2d2d2d2d2d2b0b0b09e9e9eabababcdcdcdd1d1d1d0d0d06f6f6f000000
+000000000000000000959595c5c5c5c2c2c2c1c1c1c0c0c0a0a0a0c8c8c8d0d1d0949594e9e9e9
+e5e5e5dedededddddddddddde0e0e0bcbcbc6d6d6d696969d9d9d9dbdbdbd8d8d8f62c2cf04242
+d1d1d1cecececbcbcb515151737373a8a8a8d0d0d0c8c8c8c7c7c7c9c9c9cacacac9c9c9c9c9c9
+c4c4c4c2c2c2c1c1c1b7b7b7969796f4f4f4bfbfbfb7b8b7f0f0f0dfdfdfdddddddcdcdcdedede
+d7d7d7acacac313131b9b9b9dadadad9d9d9d8d8d8d2d2d2d2d2d2d0d0d0cdcdcda3a3a32e2e2e
+898989bebebecdcdcdc7c7c7c7c7c7cacacacacacac9c9c9c7c7c7c2c2c2c1c1c1c0c0c0a2a2a2
+a8a8a8f1f1f1949594e5e5e5e6e6e6dedededadada000000a3a300444400666666d9d9d9c1c1c1
+000000a2a2008a8a00393939bebebe000000e9e9e9ffffffffffffffffffffffffffffffffffff
+9494943a3a3a3a3a3a3a3a3a111111656565c1c1c1c0c0c0999a99d5d6d5dfdfdfcccccccbcbcb
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cbcbcbcbcbcbcbcbcb9fa09fb2b2b2
+f1f1f1e2e2e2e0e0e0dcdcdcdbdbdbdadadadbdbdb0d0d0d000000000000555555d7d7d7d3d3d3
+d5d5d5d3d3d3cdcdcdc9c9c9cbcbcbcacacac8c8c87f7f7f000000000000000000a1a1a1c5c5c5
+c5c5c5c2c2c2c0c0c0bbbbbba2a3a2bebfbef4f4f4969796dfe0dfe8e8e8e1e1e1dedededbdbdb
+dbdbdbdbdbdbd9d9d9a4a4a40d0d0dffffff1f1f1f000000000000000000000000000000000000
+000000000000000000d6d6d65656565f5f5fc6c6c6c4c4c4c5c5c5c3c3c3c1c1c1bebebeb6b6b6
+949594d0d0d0c8c9c8adaeadf2f2f2e2e2e2e0e0e0dddddddbdbdbcacaca000000c0c0c0d9d9d9
+dadadadadadad9d9d9d4d4d4d5d5d5d3d3d38a8a8a141414808080b3b3b3c9c9c9c7c7c7c5c5c5
+c3c3c3c6c6c6a4a4a4585858181818c2c2c2c0c0c0bcbcbcafafaf9e9f9ef4f4f49a9b9adbdcdb
+e9e9e9e1e1e1e0e0e0dcdcdcdbdbdb616161505050d7d7d7dadadadadadad9d9d9d7d7d7d4d4d4
+d6d6d6d1d1d12626262b2b2b8c8c8ccbcbcbc8c8c8c6c6c6c4c4c4c3c3c3c7c7c78282821b1b1b
+757575c1c1c1c0c0c0bbbbbb9d9d9dcccccccccdcca9aaa9f3f3f3e1e1e1e0e0e08888882e2e2e
+dbdbdbdbdbdbd7d7d7d8d8d8afafaf030303d9d9d9d4d4d4d5d5d5d3d3d3d1d1d1c8c8c8cbcbcb
+cbcbcbc9c9c99090900000009c9c9cc5c5c5c5c5c5c4c4c4b5b5b5000000adadadbdbdbdb1b1b1
+9a9b9af4f4f49e9f9ed7d8d7efefefe1e1e1e0e0e0dcdcdc444444000000000000000000000000
+939393dadadad7d7d7d4d4d4d6d6d64848480000003c3c3ccbcbcbcbcbcbc8c8c86b6b6b000000
+000000000000000000929292c3c3c3c1c1c1c0c0c0bbbbbb9e9f9ec8c8c8d0d1d0949594e9e9e9
+e7e7e7e0e0e0dedededbdbdbdbdbdb4242426e6e6ed8d8d8dadadadbdbdbd9d9d9f72c2cf14444
+d5d5d5d1d1d1c9c9c9cbcbcb525252181818c8c8c8c6c6c6c3c3c3c5c5c5c5c5c5c4c4c4c6c6c6
+c3c3c3c0c0c0bebebeb3b3b3969796f4f4f4bfbfbfb7b8b7f0f0f0e1e1e1e0e0e0dcdcdcdbdbdb
+b5b5b5000000d5d5d5d9d9d9dadadadadadad9d9d9d4d4d4d5d5d5d2d2d2cdcdcdc9c9c9cccccc
+2c2c2c787878c7c7c7c5c5c5c3c3c3c7c7c7c4c4c4c4c4c4c5c5c5c1c1c1c0c0c0bbbbbba0a1a0
+a8a8a8f1f1f1949594e5e5e5e7e7e7e1e1e1dddddd000000000000000000656565d7d7d7c1c1c1
+000000a2a2008a8a003a3a3ac1c1c1000000e9e9e9ffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff4b4b4b646464bebebebbbbbb999a99d5d6d5e0e0e0cdcdcdcccccc
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cdcdcdcdcdcdcbcbcb9fa09fb2b2b2
+f1f1f1e0e0e0dddddddedededcdcdc979797363636b7b703bfbf00bfbf00898915353535343434
+343434343434333333323232323232323232aeaeaeb4b4b4949494929292949494bbbbbbc2c2c2
+c1c1c1bfbfbfbcbcbcbbbbbba2a3a2bebfbef4f4f4969796dfe0dfe8e8e8dfdfdfdddddddedede
+dbdbdbd9d9d99494942828280d0d0dffffffc7c7c7bfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbf
+bfbfbfbfbfbfbfbfbff5f5f55656561717175d5d5dc4c4c4c2c2c2c0c0c0bebebebbbbbbb6b6b6
+949594d0d0d0c8c9c8adaeadf2f2f2e0e0e0dddddddedededdddddcacaca000000bebebed7d7d7
+d8d8d8d8d8d8d4d4d4d2d2d2d1d1d17f7f7f4242426e6e6eb9b9b9c4c4c4c8c8c8c6c6c6c5c5c5
+c3c3c3c5c5c5a3a3a3585858181818bfbfbfbcbcbcbbbbbbafafaf9e9f9ef4f4f49a9b9adbdcdb
+e8e8e8dfdfdfdddddddedededbdbdb6161614f4f4fd5d5d5d7d7d7d8d8d8d6d6d6d3d3d3d2d2d2
+d1d1d1cdcdcd2525252b2b2b8b8b8bcacacac6c6c6c6c6c6c4c4c4c3c3c3c5c5c58282821b1b1b
+737373bebebebcbcbcbbbbbb9d9d9dcccccccccdcca9aaa9f3f3f3e0e0e0dedede8686862e2e2e
+dadadad7d7d7d5d5d5d6d6d6cdcdcda3a3a3d4d4d4d2d2d2d1d1d1cfcfcfcdcdcdcbcbcbcbcbcb
+cacacac8c8c8b8b8b8949494b9b9b9c4c4c4c4c4c4c3c3c3b2b2b2000000a9a9a9bbbbbbb1b1b1
+9a9b9af4f4f49e9f9ed7d8d7efefefe0e0e0dddddddededeb6b6b6a3a3a39b9b9b000000000000
+929292d6d6d6d3d3d3d2d2d2d1d1d14747470000003c3c3ccbcbcbcacacac6c6c6afafaf949494
+838383000000000000909090c0c0c0bfbfbfbcbcbcbbbbbb9e9f9ec8c8c8d0d1d0949594e9e9e9
+e6e6e6dfdfdfdddddddddddddbdbdb4242426d6d6de0a0a0f53636f63636f53535fd0b0bfb1010
+f43434f33333f13131d4a9a9525252181818c6c6c6c6c6c6c3c3c3c4c4c4c4c4c4c3c3c3c2c2c2
+c0c0c0bdbdbdbbbbbbb3b3b3969796f4f4f4bfbfbfb7b8b7f0f0f0e0e0e0dddddddedededddddd
+b5b5b5000000d3d3d3ef5353f53636f53636f53535f43434f43434f43434f23232e75959cccccc
+2c2c2c777777c6c6c6c5c5c5c3c3c3c5c5c5c4c4c4c3c3c3c1c1c1bfbfbfbcbcbcbbbbbba0a1a0
+a8a8a8f1f1f1949594e5e5e5e6e6e6dfdfdfdddddda7a7a7a5a5a5a2a2a2bababaa7a7a7454530
+bfbf00e7e7008a8a00393939bdbdbd000000e9e9e9ffffffcdcdcd3f3f3f3f3f3f3f3f3fc9c9c9
+ffffffffffffffffffffffff4b4b4b626262bbbbbbbbbbbb999a99d5d6d5e1e1e1cecececdcdcd
+cdcdcd060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cecececdcdcdcccccc9fa09fb2b2b2
+f1f1f1dedededfdfdfdddddddcdcdc818181000000eeee00fefe00fefe00d3d300919100919100
+9191009191009191009191008e8e00000000a5a5a5c4c4c4c4c4c4c4c4c4c4c4c4c3c3c3c0c0c0
+bebebebfbfbfb9b9b9b8b8b8a1a2a1bebfbef4f4f4969796dfe0dfe6e6e6dededededededddddd
+dcdcdcd9d9d97e7e7e0000000505056d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d
+6d6d6d6d6d6d6d6d6d6d6d6d2424240000003a3a3ac2c2c2bfbfbfbebebebcbcbcb9b9b9b4b4b4
+949594d0d0d0c8c9c8adaeadf2f2f2dedededfdfdfdddddddcdcdccbcbcb000000bebebed4d4d4
+d5d5d5d5d5d5d1d1d1cecece7c7c7c5050506a6a6ab1b1b1ccccccc9c9c9c6c6c6c4c4c4c4c4c4
+c4c4c4c4c4c4a3a3a3585858171717bfbfbfbababab8b8b8aeaeae9e9f9ef4f4f49a9b9adbdcdb
+e7e7e7dedededfdfdfdddddddcdcdc6262624f4f4fd4d4d4d4d4d4d5d5d5d3d3d3d0d0d0cecece
+cdcdcd5757574b4b4b6a6a6ab0b0b0c8c8c8c4c4c4c4c4c4c4c4c4c4c4c4c5c5c58282821b1b1b
+737373bcbcbcb9b9b9b8b8b89c9d9ccccccccccdcca9aaa9f2f2f2dededededede8787872e2e2e
+dbdbdbd7d7d7d5d5d5d4d4d4d4d4d4d5d5d5d1d1d1cfcfcfcecececdcdcdcdcdcdcdcdcdcccccc
+c9c9c9c7c7c7c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c1c1c1aeaeae000000a7a7a7b9b9b9afafaf
+9a9b9af4f4f49e9f9ed7d8d7eeeeeededededfdfdfdddddddcdcdcd9d9d9cfcfcf000000000000
+909090d3d3d3d0d0d0cecececdcdcd9393937575758f8f8fcbcbcbc8c8c8c5c5c5c4c4c4c4c4c4
+b0b0b00000000000008d8d8dbebebebebebeb9b9b9b8b8b89e9e9ec8c8c8d0d1d0949594e9e9e9
+e4e4e4dededededededddddddcdcdc4343436d6d6ddab6b6e57878e67979e47676f91818f52525
+e27474e37575e37575d1b8b8525252171717c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c1c1c1bebebe
+bebebebcbcbcb9b9b9b1b1b1969796f4f4f4bfbfbfb7b8b7efefefdedededfdfdfdddddddcdcdc
+b6b6b6000000d3d3d3e28989e67878e57777e47676e17474e17474e27575e37575dd8b8bcccccc
+2c2c2c767676c4c4c4c4c4c4c4c4c4c5c5c5c3c3c3c1c1c1bebebebebebeb9b9b9b8b8b89fa09f
+a8a8a8f1f1f1949594e5e5e5e5e5e5dedededfdfdfdddddddcdcdcd9d9d99c9c9c6b6b409d9d00
+ffff00a2a2007070358d8d8dbababa000000e9e9e9ffffffe2e2e2919191919191919191e0e0e0
+ffffffffffffffffffffffff4b4b4b616161b9b9b9b8b8b8989998d5d6d5e2e2e2cfcfcfcecece
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cdcdcdcccccccbcbcb9fa09fb2b2b2
+f0f0f0dadadadcdcdcd9d9d9dbdbdb818181000000eeee00fefe00fefe00fefe00fefe00fefe00
+fefe00fefe00fefe00fefe00fafa00000000a4a4a4c2c2c2c1c1c1c3c3c3c1c1c1c0c0c0bdbdbd
+bcbcbcbdbdbdb7b7b7b5b5b5a0a1a0bebfbef4f4f4969796dfe0dfe4e4e4dbdbdbdbdbdbd3d3d3
+8686868585854d4d4d0b0b0b343434636363636363636363585858333333636363636363636363
+4a4a4a333333636363636363636363333333232323767676737373a3a3a3bababab6b6b6b1b2b1
+949594d0d0d0c8c9c8adaeadf1f1f1dadadadcdcdcd9d9d9d9d9d9cccccc000000c0c0c0d5d5d5
+d3d3d3d1d1d1cfcfcf8686864848486a6a6aadadadcbcbcbcacacac8c8c8c5c5c5c2c2c2c1c1c1
+c3c3c3c1c1c1a1a1a1585858171717bdbdbdb7b7b7b5b5b5abacab9e9f9ef4f4f49a9b9adbdcdb
+e5e5e5dbdbdbdcdcdcd9d9d9dbdbdb626262505050d7d7d7d4d4d4d2d2d2d0d0d0cecececdcdcd
+cacaca000000686868999999c9c9c9c7c7c7c3c3c3c1c1c1c2c2c2c2c2c2c1c1c18282821b1b1b
+727272bababab7b7b7b5b5b59b9c9bcccccccccdcca9aaa9f2f2f2dadadadbdbdb8686862e2e2e
+dcdcdcd9d9d9d8d8d8d6d6d6d4d4d4d1d1d1cfcfcfcecececbcbcbcccccccecececbcbcbcacaca
+c8c8c8c5c5c5c3c3c3c1c1c1c2c2c2c1c1c1c0c0c0bebebeacacac000000a5a5a5b6b6b6adadad
+9a9b9af4f4f49e9f9ed7d8d7eeeeeedadadadcdcdcd9d9d9dbdbdbdbdbdbd2d2d2000000000000
+8d8d8dd0d0d0cecececdcdcdcacacacccccccccccccbcbcbc9c9c9c7c7c7c3c3c3c2c2c2c1c1c1
+afafaf0000000000008b8b8bbcbcbcbcbcbcb7b7b7b5b5b59d9d9dc8c8c8d0d1d0949594e9e9e9
+e2e2e2dbdbdbdbdbdbd9d9d9dcdcdc7f7f7f6c6c6c9d9d9dd4d4d4d1d1d1cfcfcff52a2aee4040
+cacacacecececbcbcb8e8e8e323232171717c3c3c3c1c1c1c2c2c2c2c2c2c0c0c0bfbfbfbbbbbb
+bcbcbcb9b9b9b6b6b6aeaeae969796f4f4f4bfbfbfb7b8b7efefefdadadadcdcdcd9d9d9dadada
+c5c5c5565656818181c5c5c5d2d2d2d0d0d0cfcfcfcecececbcbcbccccccccccccb7b7b77c7c7c
+1b1b1b757575c2c2c2c1c1c1c3c3c3c1c1c1c0c0c0bebebebcbcbcbcbcbcb7b7b7b5b5b59e9f9e
+a8a8a8f1f1f1949594e5e5e5e3e3e3dbdbdbdcdcdcd8d8d8dbdbdba2a2a2747445909000f3f300
+9b9b006b6b33898989cdcdcdb7b7b7000000e9e9e9ffffffe5e5e59b9b9b9b9b9b9b9b9be3e3e3
+ffffffffffffffffffffffff4b4b4b5f5f5fb6b6b6b5b5b5989998d5d6d5e2e2e2d0d0d0cdcdcd
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cbcbcbcacacacacaca9fa09fb2b2b2
+f0f0f0d7d7d7d6d6d6d4d4d4d7d7d7808080000000eeee00fefe00fefe00fefe00f3f300c9c900
+c9c900c9c900c9c900c9c900c5c500000000818181999999979797979797939393959595acacac
+b9b9b9b9b9b9b4b4b4b3b3b39fa09fbebfbef4f4f4969796dfe0dfe2e2e2d7d7d7cbcbcb9d9d9d
+1a1a1a2a2a2a2a2a2a3838389e9e9ee4e4e4fbfbfbf4f4f4d4d4d49d9d9de4e4e4fbfbfbededed
+bfbfbf9c9c9ce4e4e4fafafaededed8f8f8f2d2d2d1a1a1a303030717171a2a2a2b4b4b4afafaf
+949594d0d0d0c8c9c8adaeadf1f1f1d7d7d7d6d6d6d4d4d4d5d5d5cacaca000000c2c2c2d7d7d7
+d2d2d2cbcbcba3a3a32b2b2b6d6d6dafafafcbcbcbc7c7c7c7c7c7c7c7c7c5c5c5c2c2c2bfbfbf
+bebebeb9b9b99d9d9d585858171717b9b9b9b5b5b5b3b3b3a9aaa99e9f9ef4f4f49a9b9adbdcdb
+e3e3e3d7d7d7d6d6d6d4d4d4d8d8d8616161515151d9d9d9d6d6d6d0d0d0cdcdcdcececec8c8c8
+9e9e9e1b1b1b797979a2a2a2c7c7c7c7c7c7c3c3c3c0c0c0bebebebdbdbdb9b9b98282821b1b1b
+707070b7b7b7b4b4b4b2b2b29b9b9bcccccccccdcca9aaa9f2f2f2d7d7d7d7d7d78282822e2e2e
+dadadadadadad9d9d9d8d8d8d5d5d5cecececdcdcdd0d0d0cccccccbcbcbccccccc7c7c7c7c7c7
+c7c7c7c5c5c5c2c2c2bfbfbfbebebebbbbbbbabababbbbbba9a9a9000000a3a3a3b3b3b3ababab
+9a9b9af4f4f49e9f9ed7d8d7edededd7d7d7d6d6d6d4d4d4d8d8d8dadadad2d2d2000000000000
+8b8b8bcecececececed0d0d0c9c9c9b0b0b0a0a0a0aaaaaac7c7c7c7c7c7c3c3c3c1c1c1bfbfbf
+aaaaaa000000000000898989b9b9b9b9b9b9b4b4b4b2b2b29c9d9cc8c8c8d0d1d0949594e9e9e9
+dfdfdfd7d7d7d5d5d5d4d4d4dadadadadada6a6a6a393939b0b0b0cecececdcdcdf42a2aee4040
+cacacaccccccc8c8c82c2c2c1818183c3c3cc3c3c3bfbfbfbebebebbbbbbbabababbbbbbb9b9b9
+b9b9b9b6b6b6b4b4b4acacac969796f4f4f4bfbfbfb7b8b7eeeeeed7d7d7d6d6d6d4d4d4d6d6d6
+dadadadadada0101018a8a8ac1c1c1cecececdcdcdd1d1d1cbcbcbcbcbcbcacaca949494000000
+202020858585c1c1c1bfbfbfbdbdbdb9b9b9bbbbbbbbbbbbb9b9b9b9b9b9b4b4b4b3b3b39d9e9d
+a8a8a8f1f1f1949594e5e5e5e1e1e1d7d7d7d6d6d6d3d3d3d9d9d94c4c4c787800efef00b8b804
+2b2b2b929292cfcfcfcfcfcfb6b6b6000000e9e9e9ffffffcacaca353535353535353535c6c6c6
+ffffffffffffffffffffffff4b4b4b5e5e5eb4b4b4b2b2b2989898d5d6d5e2e2e2cfcfcfcbcbcb
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b424242c8c8c8c8c8c8c8c8c89f9f9fb2b2b2
+f0f0f0dadadad9d9d9d4d4d4d4d4d47d7d7d000000eeee00fefe00fefe00fcfc00c3c300030300
+030300030300030300030300030300030300030300030300030300030300000000040404777777
+b7b7b7b8b8b8b7b7b7b3b3b39f9f9fbebfbef4f4f4969796dfe0dfe4e4e4dadadaa3a3a3090909
+838383cdc8c8cbc4c4a09999f8f1f1838383efefefcdcdcd9e9d9dfaf3f3837c7cede6e6aba4a4
+c1bdbdfcfcfc838383ebebebada8a8bfb8b8d9d4d4838383e6e6e6585858555555b6b6b6aeaeae
+949594d0d0d0c8c9c8adaeadf1f1f1dadadad9d9d9d4d4d4d3d3d3c4c4c4000000bbbbbbd1d1d1
+cdcdcdbebebe030303727272b9b9b9ccccccc8c8c8c8c8c8c8c8c8c7c7c7c5c5c5c3c3c3c0c0c0
+bababab4b4b49a9a9a585858171717b8b8b8b7b7b7b3b3b3a9a9a99e9f9ef4f4f49a9b9adbdcdb
+e5e5e5dadadad9d9d9d3d3d3d4d4d45f5f5f4e4e4ed2d2d2d1d1d1d0d0d0cdcdcdcccccca9a9a9
+0000007f7f7fbababac8c8c8c7c7c7c6c6c6c4c4c4c1c1c1bdbdbdb9b9b9b4b4b48181811b1b1b
+6f6f6fb8b8b8b7b7b7b2b2b29a9b9acccccccccdcca9aaa9f2f2f2dadadadadada8484842d2d2d
+d4d4d4d1d1d1d1d1d1d2d2d2d0d0d0cacacacccccccdcdcdcfcfcfccccccc8c8c8c8c8c8c8c8c8
+c7c7c7c5c5c5c2c2c2bbbbbbbbbbbbb6b6b6b6b6b6b8b8b8a7a7a7000000a5a5a5b5b5b5aaaaaa
+9a9b9af4f4f49e9f9ed7d8d7eeeeeedadadad9d9d9d3d3d3d4d4d4d2d2d2c9c9c9000000000000
+8c8c8ccdcdcdcccccccececed0d0d04747470000003b3b3bc7c7c7c6c6c6c5c5c5c3c3c3bfbfbf
+a7a7a7000000000000878787b8b8b8b8b8b8b7b7b7b2b2b29c9c9cc8c8c8d0d1d0949594e9e9e9
+e2e2e2dadadad7d7d7d3d3d3d4d4d4d2d2d26868680303031f1f1fcacacaccccccf32e2eef4646
+cececec2c2c2c2c2c22b2b2b737373c1c1c1c3c3c3c1c1c1bcbcbcb6b6b6b6b6b6b8b8b8b7b7b7
+b8b8b8b8b8b8b5b5b5ababab969796f4f4f4bfbfbfb7b8b7efefefdadadad9d9d9d4d4d4d3d3d3
+d4d4d4d1d1d10707070101017f7f7fcbcbcbcccccccececed0d0d0c7c7c7c2c2c2909090000000
+979797c2c2c2c2c2c2bfbfbfbababab4b4b4b8b8b8b8b8b8b7b7b7b8b8b8b7b7b7b2b2b29d9e9d
+a8a8a8f1f1f1949594e5e5e5e3e3e3dadadad9d9d9d3d3d3d4d4d44a4a4a747400afaf00171717
+cfcfcfcdcdcdcccccccececebcbcbc000000e9e9e9fffffffdfdfdf7f7f7f7f7f7f7f7f7fdfdfd
+ffffffffffffffffffffffff4b4b4b606060b5b5b5b1b1b1979897d5d6d5e0e0e0ccccccc9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c8c8c8c8c8c8c8c8c89f9f9fb2b2b2
+efefefd2d2d2d2d2d2d2d2d2cecece787878000000eeee00fefe00ffff009a9a001b1b007f7f00
+7f7f007f7f007f7f007f7f007f7f007f7f007f7f007f7f007f7f007f7f00000000999999bababa
+bababab8b8b8b3b3b3aeaeae9d9e9dbebfbef4f4f4969796dfe0dfdfdfdfd2d2d29d9d9d121212
+ffffffff6767ff0000ff0000ff0d0dffffffffffffffffffffc7c7ff0000ff0000ff0000ff0000
+ff7f7fffffffffffffffffffff5656ff0000ff4d4dffffff9595952d2d2d535353b1b1b1ababab
+949594d0d0d0c8c9c8adaeadf1f1f1d3d3d3d2d2d2d2d2d2d1d1d1bcbcbc000000c0c0c0cfcfcf
+5f5f5f070707808080c6c6c6cdcdcdcccccccacacac8c8c8c9c9c9c4c4c4c3c3c3c1c1c1bebebe
+b8b8b8b6b6b69b9b9b585858171717b8b8b8b3b3b3afafafa6a6a69e9f9ef4f4f49a9b9adbdcdb
+e1e1e1d2d2d2d2d2d2d2d2d2cdcdcd5b5b5b505050d4d4d4cccccccacacacccccccececeababab
+0000007f7f7fbababac8c8c8c8c8c8c3c3c3c3c3c3bfbfbfbababab7b7b7b6b6b68181811b1b1b
+6f6f6fb5b5b5b3b3b3aeaeae9a9a9acccccccccdcca9aaa9f2f2f2d2d2d2d2d2d27f7f7f2b2b2b
+ccccccd3d3d3d6d6d6d2d2d2a3a3a3030303cecececfcfcfcdcdcdccccccccccccc7c7c7c8c8c8
+c5c5c5c3c3c38c8c8c000000939393b6b6b6b7b7b7bababaababab000000a1a1a1b0b0b0a7a7a7
+9a9b9af4f4f49e9f9ed7d8d7ecececd2d2d2d2d2d2d2d2d2cecececfcfcfcbcbcb000000000000
+888888cbcbcbcecececfcfcfcccccc4545450000003c3c3cc8c8c8c3c3c3c3c3c3c1c1c1bdbdbd
+a5a5a50000000000008a8a8ab9b9b9b7b7b7b3b3b3aeaeae9b9b9bc8c8c8d0d1d0949594e9e9e9
+dcdcdcd2d2d2d2d2d2d1d1d1ccccccd0d0d0d5d5d58f8f8f000000000000c8c8c8cfcfcfcecece
+afafaf0000000000000000000000000f0f0f808080bbbbbbb9b9b9b6b6b6b7b7b7babababbbbbb
+b8b8b8b5b5b5b1b1b1a8a8a8969796f4f4f4bfbfbfb7b8b7edededd2d2d2d2d2d2d2d2d2d0d0d0
+cdcdcdd3d3d3d6d6d62828280000005d5d5dcecececfcfcfcccccc4e4e4e000000000000000000
+0000004c4c4c9a9a9abdbdbdb7b7b7b6b6b6b9b9b9babababababab7b7b7b3b3b3aeaeae9c9c9c
+a8a8a8f1f1f1949594e5e5e5ddddddd2d2d2d2d2d2d3d3d3cdcdcd474747000000000000161616
+cacacacccccccecececececeb8b8b8000000e9e9e9ffffffbcbcbc000000000000000000b7b7b7
+ffffffffffffffffffffffff4b4b4b5d5d5db1b1b1aeaeae979897d5d6d5dededec9c9c9c9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c8c8c8c8c8c8c9c9c99fa09fb2b2b2
+efefefd3d3d3d3d3d3d3d3d3d1d1d17a7a7a000000eeee00fefe00aeae006161005252007f7f00
+7f7f007f7f007f7f007f7f007f7f007f7f007f7f007f7f00737300393900636363a6a6a6b7b7b7
+b7b7b7b6b6b6b1b1b1b0b0b09e9f9ebebfbef4f4f4969796dfe0dfe0e0e0d3d3d39e9e9e0d0d0d
+b9b9b9e29e9ee16f6fc95656fb8e8eb9b9b9f6f6f6e3e3e3c8afaffc8989b94646f58282cf5d5d
+dba2a2fdfdfdb9b9b9f3f3f3d08484da6868e99999b9b9b9c3c3c3454545525252b1b1b1adadad
+949594d0d0d0c8c9c8adaeadf1f1f1d3d3d3d3d3d3d3d3d3d2d2d2c0c0c0000000bcbcbc7d7d7d
+5050504c4c4ca4a4a4c9c9c9cbcbcbc8c8c8c4c4c4c0c0c0c1c1c1c0c0c0c2c2c2c2c2c2bebebe
+b8b8b8b5b5b59b9b9b585858161616b6b6b6b2b2b2b0b0b0a8a8a89e9f9ef4f4f49a9b9adbdcdb
+e1e1e1d3d3d3d3d3d3d3d3d3d0d0d05c5c5c4e4e4ed2d2d2d0d0d0ccccccc9c9c9a1a1a1595959
+464646a4a4a4bbbbbbc0c0c0c1c1c1bfbfbfc4c4c4c0c0c0bababab7b7b7b5b5b58181811b1b1b
+6e6e6eb4b4b4b1b1b1b0b0b09a9b9acccccccccdcca9aaa9f2f2f2d3d3d3d3d3d38080802c2c2c
+cccccc5e5e5ec1c1c1a6a6a65f5f5f717171c7c7c7cdcdcdcbcbcbc8c8c8c6c6c6c0c0c0c1c1c1
+c0c0c0c1c1c1ababab6969695757579090908a8a8a6e6e6ea8a8a8000000a0a0a0b1b1b1a9a9a9
+9a9b9af4f4f49e9f9ed7d8d7ecececd3d3d3d3d3d3d3d3d3d1d1d1cececec6c6c6000000000000
+888888c9c9c9cacacacececec9c9c98b8b8b696969828282c1c1c1bfbfbfc4c4c4c2c2c2bdbdbd
+a5a5a5000000000000888888b7b7b7b5b5b5b1b1b1b0b0b09b9c9bc8c8c8d0d1d0949594e9e9e9
+dcdcdcd3d3d3d3d3d3d2d2d2cfcfcfcececed0d0d0b3b3b37474746f6f6f5c5c5c5d5d5d5c5c5c
+4e4e4e000000626262161616000000070707393939969696b1b1b1b6b6b6b5b5b5b5b5b5b8b8b8
+b6b6b6b3b3b3b1b1b1aaaaaa969796f4f4f4bfbfbfb7b8b7edededd3d3d3d3d3d3d3d3d3d2d2d2
+cfcfcfcdcdcdd3d3d38686867171716767675c5c5c5d5d5d5b5b5b2323232c2c2c4c4c4c000000
+000000222222636363a2a2a2b7b7b7b5b5b5b5b5b5b6b6b6b7b7b7b6b6b6b1b1b1b0b0b09c9d9c
+a8a8a8f1f1f1949594e5e5e5dededed3d3d3d3d3d3d3d3d3d0d0d09090907070707373737e7e7e
+cacacac8c8c8cbcbcbcdcdcdb6b6b6000000e9e9e9ffffffe1e1e18c8c8c8c8c8c8c8c8cdedede
+ffffffffffffffffffffffff4b4b4b5d5d5db1b1b1b0b0b0979897d5d6d5dededec9c9c9c9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9c9c9c9cacaca9fa09fb2b2b2
+efefefd2d2d2d3d3d3d2d2d2d0d0d0797979000000eeee00b7b7005f5f004f4f007f7f007f7f00
+7f7f007f7f007f7f007f7f007f7f007f7f007f7f006e6e004e4e0c464646b9b9b9b4b4b4b5b5b5
+b6b6b6b4b4b4b2b2b2b2b2b29f9f9fbebfbef4f4f4969796dfe0dfdfdfdfd2d2d29e9e9e0c0c0c
+aeaeaededededdddddb6b6b6cececeaeaeaef4f4f4dfdfdfb6b6b6cececeaeaeaef3f3f3c8c8c8
+bfbfbfcfcfcfaeaeaef2f2f2c9c9c9bebebec6c6c6aeaeaef1f1f15a5a5a535353b2b2b2aeaeae
+949594d0d0d0c8c9c8adaeadf0f0f0d2d2d2d3d3d3d2d2d2d1d1d1bfbfbf000000757575474747
+6969699f9f9fc2c2c2c8c8c8c7c7c7c4c4c4c0c0c0bbbbbbbbbbbbbcbcbcbfbfbfbfbfbfbababa
+b9b9b9b9b9b99d9d9d585858161616b4b4b4b2b2b2b2b2b2a9a9a99e9f9ef4f4f49a9b9adbdcdb
+e0e0e0d2d2d2d3d3d3d1d1d1cfcfcf5c5c5c4c4c4ccfcfcfd2d2d2cececea0a0a05f5f5f414141
+989898c2c2c2bcbcbcbbbbbbbbbbbbbdbdbdc1c1c1bbbbbbbababab9b9b9b9b9b98282821b1b1b
+6d6d6db3b3b3b2b2b2b2b2b29a9b9acccccccccdcca9aaa9f2f2f2d2d2d2d2d2d28080802b2b2b
+c8c8c80000006f6f6f6e6e6e666666cbcbcbc2c2c2c8c8c8c7c7c7c4c4c4c2c2c2bbbbbbbbbbbb
+bcbcbcbebebebfbfbfbababa5c5c5c6161613f3f3f303030a7a7a7000000a1a1a1b2b2b2aaaaaa
+9a9b9af4f4f49e9f9ed7d8d7ecececd2d2d2d3d3d3d1d1d1cfcfcfcdcdcdc5c5c5000000000000
+898989c7c7c7c4c4c4c9c9c9c6c6c6c3c3c3bfbfbfbbbbbbbbbbbbbdbdbdc0c0c0bebebebababa
+a6a6a6000000000000878787b5b5b5b4b4b4b2b2b2b2b2b29c9c9cc8c8c8d0d1d0949594e9e9e9
+dcdcdcd2d2d2d2d2d2d1d1d1cecececdcdcdcdcdcdcfcfcfd1d1d1cccccc4a4a4a474747474747
+484848484848b6b6b64e4e4e1313130000000000004b4b4b8f8f8fb0b0b0b7b7b7b4b4b4b6b6b6
+b5b5b5b3b3b3b2b2b2abacab969796f4f4f4bfbfbfb7b8b7edededd2d2d2d3d3d3d2d2d2d0d0d0
+cecececccccccececed2d2d2cecece9090904747474747474848484848487a7a7a9797972f2f2f
+0a0a0a000000212121646464a4a4a4b9b9b9b4b4b4b4b4b4b6b6b6b4b4b4b2b2b2b2b2b29d9e9d
+a8a8a8f1f1f1949594e5e5e5ddddddd2d2d2d3d3d3d1d1d1cfcfcf9a9a9a8080808383838d8d8d
+ccccccc5c5c5c5c5c5c8c8c8b3b3b3000000e9e9e9ffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff4b4b4b5d5d5db2b2b2b2b2b2979897d5d6d5dededec9c9c9c9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cacacacbcbcb9fa09fb2b2b2
+efefefd0d0d0cfcfcfcecececacaca757575000000c1c1004444005353007f7f007f7f007f7f00
+7f7f007f7f007f7f007f7f007f7f007f7f006b6b004e4e0c3e3e3ebcbcbcbfbfbfb8b8b8b6b6b6
+b5b5b5b2b2b2b3b3b3b1b1b19e9f9ebebfbef4f4f4969796dfe0dfdededecfcfcf9b9b9b0e0e0e
+cececececececececeb6b6b66d6d6dcececececececececeb8b8b86b6b6bcecececececececece
+9b9b9b6a6a6acecececececececece9d9d9d868686cececececece494949535353b2b2b2adadad
+949594d0d0d0c8c9c8adaeadf0f0f0d0d0d0cfcfcfcecececcccccb9b9b90000000000004a4a4a
+898989a6a6a69c9c9c9d9d9d9d9d9d9e9e9e9c9c9c999999979797989898979797949494929292
+9999999c9c9c828282484848161616b2b2b2b3b3b3b1b1b1a8a8a89e9f9ef4f4f49a9b9adbdcdb
+dfdfdfcfcfcfcfcfcfcececec9c9c95959593d3d3da5a5a5a9a9a9b9b9b96c6c6c494949959595
+c3c3c3c1c1c1bdbdbdbbbbbbbbbbbbbcbcbcb8b8b8b4b4b4b9b9b9bcbcbcbfbfbf8282821b1b1b
+6b6b6bb2b2b2b3b3b3b1b1b19a9b9acccccccccdcca9aaa9f2f2f2d0d0d0cfcfcf7e7e7e2a2a2a
+c1c1c10000000000003f3f3fb0b0b0cdcdcdc1c1c1c0c0c0c2c2c2c2c2c2c1c1c1bcbcbcbbbbbb
+bbbbbbbababab7b7b7b3b3b39e9e9e3939390000002f2f2fa6a6a6000000a2a2a2b2b2b2a9a9a9
+9a9b9af4f4f49e9f9ed7d8d7ebebebd0d0d0cfcfcfcececec9c9c9cccccccacaca252525242424
+969696c7c7c7c1c1c1c1c1c1c3c3c3c2c2c2bfbfbfbcbcbcbbbbbbbcbcbcb8b8b8b6b6b6b5b5b5
+acacac2222222121218f8f8fb3b3b3b2b2b2b3b3b3b1b1b19b9c9bc8c8c8d0d1d0949594e9e9e9
+dadadacfcfcfcfcfcfcdcdcdc8c8c8cecececdcdcdcbcbcbcecececdcdcdc1c1c1c0c0c0c1c1c1
+c3c3c3c1c1c1bcbcbc9696964646461515150000000000004f4f4fa2a2a2c3c3c3b6b6b6b6b6b6
+b3b3b3b2b2b2b2b2b2aaabaa969796f4f4f4bfbfbfb7b8b7edededd0d0d0cfcfcfcecececbcbcb
+c9c9c9d0d0d0cacacacdcdcdcdcdcdc8c8c8c1c1c1c0c0c0c2c2c2c2c2c2bfbfbfafafaf8b8b8b
+3131310909090000001818186d6d6dccccccb9b9b9b6b6b6b5b5b5b2b2b2b3b3b3b1b1b19d9d9d
+a8a8a8f1f1f1949594e5e5e5dcdcdccfcfcfcfcfcfcececec9c9c9454545161600222200161616
+cdcdcdc5c5c5c1c1c1c1c1c1b0b0b0000000bdbdbdcececececececececececececececececece
+cececececececececececece3d3d3d5d5d5db2b2b2b0b0b0979897d5d6d5dfdfdfcacacac9c9c9
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacacacacacbcbcb9fa09fb2b2b2
+efefefd0d0d0cecececdcdcdcbcbcb7676760000000000006060007e7e007e7e007e7e007e7e00
+7e7e007e7e007e7e007e7e007e7e007e7e00151501424242b6b6b6bababab7b7b7b2b2b2afafaf
+adadadaaaaaaadadadacacac9c9d9cbebfbef4f4f4969796dfe0dfdededecfcfcf9a9a9a010101
+000000000000000000000000010101010101010101010101010101010101010101010101010101
+010101010101010101010101010101000000000000000000000000000000515151adadada9a9a9
+949594d0d0d0c8c9c8adaeadf0f0f0d0d0d0cecececdcdcdccccccbababa010101010101010101
+010101010101010101010101010101010101010101010101010101010101010101010101010101
+010101010101010101010101161616aaaaaaadadadacacaca5a5a59e9f9ef4f4f49a9b9adbdcdb
+e0e0e0cfcfcfcdcdcdcdcdcdcacaca5959590000000000000000005b5b5ba3a3a3bfbfbfbbbbbb
+c3c3c3bbbbbbb9b9b9b8b8b8b9b9b9b8b8b8b4b4b4b3b3b3b7b7b7b8b8b8b5b5b58080801b1b1b
+666666abababaeaeaeacacac999a99cccccccccdcca9aaa9f2f2f2d0d0d0cfcfcf7d7d7d2a2a2a
+c2c2c2010101010101010101292929cacacac4c4c4bcbcbcc1c1c1c1c1c1bdbdbdbabababababa
+bababab8b8b8b5b5b5b5b5b52424240101010101012e2e2e9f9f9f0000009d9d9dadadada6a6a6
+9a9b9af4f4f49e9f9ed7d8d7ebebebd0d0d0cdcdcdcdcdcdcacacac9c9c9cacacac8c8c8c3c3c3
+c8c8c8c7c7c7c1c1c1bcbcbcc4c4c4bfbfbfbbbbbbbababababababababab6b6b6b5b5b5b6b6b6
+bababab7b7b7b2b2b2afafafabababaaaaaaaeaeaeacacac9a9b9ac8c8c8d0d1d0949594e9e9e9
+dbdbdbcfcfcfcdcdcdcdcdcdc9c9c9cacacac9c9c9c6c6c6c4c4c4cacacac4c4c4bcbcbcbebebe
+c3c3c3bdbdbdbabababababa989898707070010101000000010101959595e0e0e0b1b1b1aeaeae
+abababacacacadadada7a7a7969796f4f4f4bfbfbfb7b8b7edededd0d0d0cdcdcdcdcdcdcccccc
+c9c9c9cacacac8c8c8c3c3c3c8c8c8c7c7c7c4c4c4bbbbbbc2c2c2c0c0c0bbbbbbbabababbbbbb
+8d8d8d333333000000000000111111ffffffbbbbbbb0b0b0adadadaaaaaaaeaeaeacacac9b9c9b
+a8a8a8f1f1f1949594e5e5e5dcdcdccfcfcfcdcdcdcdcdcdc9c9c9454545777700b3b300161616
+cacacac6c6c6bfbfbfbdbdbdb2b2b2010101010101010101010101010101010101010101010101
+0101010101010101010101010101015b5b5badadadacacac979897d5d6d5dfdfdfcacacacacaca
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b414141c8c8c8c9c9c9cacaca9fa09fb2b2b2
+eeeeeecccccccacacac9c9c9c9c9c9767676000000000000000000000000000000000000000000
+0000000000000000000000000000000000009e9e9ebbbbbbb6b6b6b2b2b2bcbcbcb8b8b8b6b6b6
+b3b3b3aaaaaab0b0b0acacac9c9d9cbebfbef4f4f4969796dfe0dfdbdbdbcbcbcbcacacabbbbbb
+0000000000000000002e2e2ec6c6c6c0c0c0c3c3c3c5c5c5c6c6c6c0c0c0bdbdbdbebebebdbdbd
+bcbcbcbbbbbbbdbdbdb8b8b8b4b4b45c5c5c0000000000000000006d6d6dadadadafafafa9a9a9
+949594d0d0d0c8c9c8adaeadf0f0f0cccccccacacacacacac9c9c9c8c8c8c5c5c5c9c9c9c7c7c7
+c3c3c3c0c0c0c4c4c4c7c7c7c3c3c3bebebebdbdbdbebebebdbdbdbbbbbbbcbcbcbbbbbbb7b7b7
+b2b2b2bcbcbcbababab7b7b7b4b4b4aaaaaab0b0b0adadada5a5a59e9f9ef4f4f49a9b9adbdcdb
+ddddddcbcbcbcacacacacacac9c9c9595959000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000
+666666acacacb1b1b1acacac999a99cccccccccdcca9aaa9f2f2f2cbcbcbcacaca7a7a7a2a2a2a
+c8c8c8c5c5c5c9c9c9c8c8c8c5c5c5c0c0c0c4c4c4c7c7c7c3c3c3bfbfbfbdbdbdbfbfbfbdbdbd
+bbbbbbbbbbbbbbbbbbb8b8b8b3b3b3b8b8b8bababab7b7b7a6a6a60000009f9f9faeaeaea6a6a6
+9a9b9af4f4f49e9f9ed7d8d7eaeaeacbcbcbcacacacacacac9c9c9c6c6c6c5c5c5cacacac7c7c7
+c2c2c2c1c1c1c5c5c5c7c7c7c1c1c1bebebebdbdbdbebebebcbcbcbbbbbbbcbcbcbababab6b6b6
+b3b3b3bdbdbdb8b8b8b6b6b6afafafaaaaaab1b1b1acacac9a9b9ac8c8c8d0d1d0949594e9e9e9
+d7d7d7cacacacacacac9c9c9c9c9c9c6c6c6c7c7c7c8c8c8c5c5c5c0c0c0c3c3c3c7c7c7c5c5c5
+c0c0c0bdbdbdbebebebdbdbdbbbbbbb3b3b3808080070707c2c2c2ffffffe2e2e2b7b7b7b6b6b6
+adadadadadadafafafa7a7a7969796f4f4f4bfbfbfb7b8b7ecececcbcbcbcacacacacacac9c9c9
+c8c8c8c5c5c5c9c9c9c7c7c7c2c2c2c1c1c1c4c4c4c7c7c7c2c2c2bebebebdbdbdbebebebdbdbd
+bbbbbb9797974a4a4a3d3d3dffffffffffffc0c0c0b7b7b7b3b3b3aaaaaab1b1b1acacac9b9c9b
+a8a8a8f1f1f1949594e5e5e5d9d9d9cbcbcbcacacacacacac9c9c9454545000000000000151515
+c0c0c0c2c2c2c5c5c5c6c6c6c0c0c0bdbdbdbebebebebebebcbcbcbbbbbbbdbdbdb8b8b8b3b3b3
+b7b7b7bcbcbcb8b8b8b6b6b6adadadadadadafafafacacac979897d5d6d5ddddddc8c8c8c8c8c8
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c9c9c9c9c9c99fa09fb2b2b2
+eeeeeecacacac6c6c6c7c7c7c5c5c5b5b5b59f9f9f9e9e9e9f9f9f9f9f9f9d9d9d9d9d9da2a2a2
+9c9c9c9b9b9b9c9c9c9b9b9b9a9a9a9c9c9cb5b5b5b7b7b7b0b0b0aeaeaeb6b6b6b4b4b4aeaeae
+abababa7a7a7acacacacacac9c9d9cbebfbef4f4f4969796dfe0dfdadadac8c8c8c7c7c7c5c5c5
+a1a1a1a0a0a09f9f9fa7a7a7c1c1c1c0c0c0bebebec0c0c0c2c2c2bcbcbcbdbdbdbdbdbdbbbbbb
+bbbbbbbcbcbcbababab2b2b2afafafa2a2a29595959393938d8d8d9d9d9daaaaaaacacaca9a9a9
+949594d0d0d0c8c9c8adaeadf0f0f0cacacac7c7c7c7c7c7c7c7c7c3c3c3c1c1c1c1c1c1c1c1c1
+c0c0c0bfbfbfbebebec3c3c3bebebebcbcbcbdbdbdbdbdbdbbbbbbbcbcbcbbbbbbb7b7b7b1b1b1
+aeaeaeb6b6b6b5b5b5b1b1b1abababa7a7a7acacacacacaca5a5a59e9f9ef4f4f49a9b9adbdcdb
+dcdcdcc8c8c8c6c6c6c8c8c8c5c5c5afafaf9f9f9f9e9e9e9f9f9f9e9e9e9d9d9d9e9e9ea0a0a0
+9a9a9a9c9c9c9c9c9c9b9b9b9a9a9a9c9c9c9999999393939090909090909595959494948e8e8e
+9c9c9ca9a9a9acacacacacac999a99cccccccccdcca9aaa9f2f2f2cacacac8c8c8787878070707
+222222222222222222222222222222212121212121222222212121212121202020212121202020
+2020202020202020201f1f1f1f1f1f2020202020201f1f1f1c1c1c0000009c9c9cacacaca6a6a6
+9a9b9af4f4f49e9f9ed7d8d7eaeaeacacacac6c6c6c8c8c8c5c5c5c2c2c2c1c1c1c1c1c1c1c1c1
+c0c0c0bfbfbfc0c0c0c3c3c3bcbcbcbcbcbcbdbdbdbcbcbcbbbbbbbcbcbcbababab6b6b6b0b0b0
+afafafb6b6b6b4b4b4aeaeaea9a9a9a7a7a7acacacacacac9a9b9ac8c8c8d0d1d0949594e9e9e9
+d6d6d6c8c8c8c7c7c7c7c7c7c4c4c4c2c2c2c1c1c1c1c1c1c1c1c1c0c0c0bebebec3c3c3c1c1c1
+bcbcbcbdbdbdbdbdbdbbbbbbbcbcbcbbbbbbafafafd0d0d0f4f4f4dbdbdbbcbcbcb2b2b2acacac
+a8a8a8aaaaaaacacaca7a7a7969796f4f4f4bfbfbfb7b8b7ecececcacacac6c6c6c8c8c8c6c6c6
+c3c3c3c1c1c1c1c1c1c1c1c1c0c0c0bfbfbfbebebec4c4c4bdbdbdbcbcbcbdbdbdbcbcbcbbbbbb
+bcbcbcb5b5b5bebebeddddddfbfbfbc1c1c1b5b5b5b0b0b0abababa7a7a7acacacacacac9b9c9b
+a8a8a8f1f1f1949594e5e5e5d8d8d8c8c8c8c6c6c6c8c8c8c4c4c4acacac9f9f9f9e9e9ea3a3a3
+c0c0c0bebebec1c1c1c2c2c2bcbcbcbdbdbdbdbdbdbcbcbcbbbbbbbcbcbcbababab2b2b2afafaf
+b2b2b2b6b6b6b3b3b3acacaca8a8a8aaaaaaacacacacacac979897d5d6d5dcdcdcc6c6c6c6c6c6
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c9c9c9c9c9c99fa09fb2b2b2
+eeeeeec9c9c9c8c8c8c7c7c7c4c4c4c2c2c2c2c2c2c0c0c0c1c1c1bfbfbfbebebebebebebdbdbd
+bfbfbfbbbbbbb8b8b8b8b8b8b5b5b5b5b5b5b4b4b4b2b2b2b0b0b0afafafb0b0b0b2b2b2adadad
+aaaaaaa7a7a7a9a9a9a7a7a79b9b9bbebfbef4f4f4969796dfe0dfd9d9d9c9c9c9c8c8c8c6c6c6
+c2c2c2c2c2c2c1c1c1c0c0c0c1c1c1bebebebebebebdbdbdbebebebfbfbfb7b7b7b9b9b9b7b7b7
+b5b5b5b5b5b5b4b4b4b1b1b1b0b0b0b0b0b0b1b1b1b2b2b2acacaca8a8a8a8a8a8a8a8a8a4a4a4
+949594d0d0d0c8c9c8adaeadf0f0f0c9c9c9c8c8c8c7c7c7c5c5c5c2c2c2c2c2c2c0c0c0c1c1c1
+bfbfbfbebebebebebebdbdbdbfbfbfbbbbbbb8b8b8b9b9b9b5b5b5b5b5b5b5b5b5b3b3b3b0b0b0
+afafafb0b0b0b1b1b1b0b0b0aaaaaaa7a7a7a9a9a9a7a7a7a1a1a19e9f9ef4f4f49a9b9adbdcdb
+dbdbdbc9c9c9c8c8c8c6c6c6c3c3c3c2c2c2c1c1c1c0c0c0c1c1c1bfbfbfbebebebebebebebebe
+c0c0c0b7b7b7b9b9b9b8b8b8b5b5b5b5b5b5b4b4b4b1b1b1b0b0b0b0b0b0b0b0b0b2b2b2acacac
+a9a9a9a8a8a8a9a9a9a6a6a6989998cccccccccdcca9aaa9f1f1f1c9c9c9c8c8c8acacac7f7f7f
+7d7d7d7d7d7d7c7c7c7c7c7c7c7c7c7a7a7a7b7b7b7878787b7b7b797979747474767676747474
+7373737272727272727272727272727171717171717171716e6e6e6c6c6ca3a3a3a8a8a8a2a2a2
+9a9b9af4f4f49e9f9ed7d8d7eaeaeac9c9c9c8c8c8c6c6c6c3c3c3c2c2c2c2c2c2c0c0c0c1c1c1
+bfbfbfbebebebebebebdbdbdc0c0c0bababab8b8b8b8b8b8b5b5b5b5b5b5b4b4b4b2b2b2b0b0b0
+afafafb0b0b0b2b2b2adadada9a9a9a7a7a7a9a9a9a7a7a7999999c8c8c8d0d1d0949594e9e9e9
+d5d5d5c8c8c8c7c7c7c5c5c5c2c2c2c2c2c2c1c1c1c0c0c0c1c1c1bebebebebebebdbdbdbebebe
+bfbfbfb7b7b7b9b9b9b6b6b6b5b5b5b5b5b5b4b4b4cbcbcbccccccbcbcbcb1b1b1b0b0b0ababab
+a8a8a8a8a8a8a8a8a8a2a3a2969796f4f4f4bfbfbfb7b8b7ebebebc9c9c9c8c8c8c7c7c7c5c5c5
+c2c2c2c2c2c2c0c0c0c1c1c1bfbfbfbebebebebebebdbdbdbfbfbfbbbbbbb8b8b8b8b8b8b5b5b5
+b5b5b5b4b4b4bebebecccccccacacab0b0b0b2b2b2afafafaaaaaaa7a7a7a9a9a9a7a7a7999a99
+a8a8a8f1f1f1949594e5e5e5d7d7d7c8c8c8c8c8c8c6c6c6c3c3c3c2c2c2c1c1c1c0c0c0c1c1c1
+bebebebebebebdbdbdbebebebfbfbfb7b7b7b9b9b9b8b8b8b5b5b5b5b5b5b4b4b4b1b1b1b0b0b0
+b0b0b0b0b0b0b2b2b2acacaca8a8a8a8a8a8a8a8a8a6a6a6969796d5d6d5ddddddc7c7c7c6c6c6
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c9c9c9c9c9c99fa09fb2b2b2
+eeeeeec8c8c8c8c8c8c6c6c6c4c4c4c3c3c3c3c3c3bfbfbfc0c0c0bebebebdbdbdbdbdbdbababa
+bfbfbfbababab6b6b6b7b7b7b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1b0b0b0adadadb0b0b0adadad
+aaaaaaa8a8a8a7a7a7a4a4a49a9a9abebfbef4f4f4969796dfe0dfd9d9d9c8c8c8c8c8c8c5c5c5
+c2c2c2c3c3c3c1c1c1bfbfbfc0c0c0bcbcbcbdbdbdbcbcbcbbbbbbc0c0c0b5b5b5b8b8b8b5b5b5
+b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1afafafaeaeaeb0b0b0acacaca9a9a9a7a7a7a6a6a6a2a2a2
+949594d0d0d0c8c9c8adaeadf0f0f0c8c8c8c8c8c8c6c6c6c5c5c5c2c2c2c3c3c3bfbfbfc0c0c0
+bebebebcbcbcbebebebabababfbfbfbbbbbbb6b6b6b8b8b8b3b3b3b2b2b2b2b2b2b1b1b1b1b1b1
+b0b0b0adadadafafafaeaeaeaaaaaaa8a8a8a7a7a7a5a5a59f9f9f9e9f9ef4f4f49a9b9adbdcdb
+dbdbdbc8c8c8c8c8c8c6c6c6c3c3c3c3c3c3c2c2c2bfbfbfc0c0c0bdbdbdbdbdbdbcbcbcbbbbbb
+c1c1c1b5b5b5b8b8b8b7b7b7b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1b0b0b0adadadb0b0b0acacac
+a9a9a9a7a7a7a7a7a7a4a4a4979897cccccccccdcca9aaa9f1f1f1c8c8c8c8c8c8c7c7c7c5c5c5
+c2c2c2c3c3c3c0c0c0bfbfbfbfbfbfbcbcbcbebebebabababebebebbbbbbb5b5b5b8b8b8b4b4b4
+b3b3b3b2b2b2b1b1b1b2b2b2b1b1b1aeaeaeaeaeaeafafafaaaaaaa8a8a8a7a7a7a5a5a5a0a0a0
+9a9b9af4f4f49e9f9ed7d8d7e9e9e9c8c8c8c8c8c8c6c6c6c3c3c3c3c3c3c3c3c3bfbfbfc0c0c0
+bdbdbdbdbdbdbcbcbcbbbbbbc1c1c1b9b9b9b7b7b7b7b7b7b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1
+b0b0b0adadadb0b0b0acacaca9a9a9a7a7a7a7a7a7a4a4a4989998c8c8c8d0d1d0949594e9e9e9
+d5d5d5c8c8c8c7c7c7c5c5c5c2c2c2c3c3c3c1c1c1bfbfbfbfbfbfbcbcbcbebebebabababcbcbc
+bfbfbfb5b5b5b8b8b8b4b4b4b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1aeaeaeaeaeaeafafafababab
+a8a8a8a7a7a7a6a6a6a0a1a0969796f4f4f4bfbfbfb7b8b7ebebebc8c8c8c8c8c8c6c6c6c4c4c4
+c2c2c2c3c3c3bfbfbfc0c0c0bdbdbdbdbdbdbebebebabababfbfbfb9b9b9b6b6b6b7b7b7b3b3b3
+b2b2b2b2b2b2b1b1b1b1b1b1b0b0b0adadadb0b0b0aeaeaeaaaaaaa7a7a7a7a7a7a4a4a4999999
+a8a8a8f1f1f1949594e5e5e5d7d7d7c8c8c8c8c8c8c6c6c6c3c3c3c3c3c3c1c1c1bfbfbfc0c0c0
+bcbcbcbdbdbdbcbcbcbcbcbcc0c0c0b5b5b5b8b8b8b6b6b6b3b3b3b2b2b2b1b1b1b1b1b1b1b1b1
+afafafadadadb0b0b0abababa8a8a8a7a7a7a6a6a6a4a4a4969796d5d6d5ddddddc8c8c8c7c7c7
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9c9c9c9cacaca9fa09fb2b2b2
+eeeeeec6c6c6c4c4c4c6c6c6c6c6c6c6c6c6c6c6c6bdbdbdbababab9b9b9b9b9b9babababababa
+b9b9b9b7b7b7b9b9b9bbbbbbb6b6b6b5b5b5b5b5b5b5b5b5b5b5b5afafafabababaaaaaaa8a8a8
+a7a7a7a8a8a8a3a3a3a5a5a59a9b9abebfbef4f4f4969796dfe0dfd8d8d8c5c5c5c4c4c4c6c6c6
+c6c6c6c6c6c6c2c2c2bcbcbcb9b9b9b9b9b9b9b9b9babababababab8b8b8b7b7b7bcbcbcb8b8b8
+b6b6b6b5b5b5b5b5b5b6b6b6b2b2b2aeaeaeabababaaaaaaa7a7a7a7a7a7a5a5a5a3a3a3a4a4a4
+949594d0d0d0c8c9c8adaeadefefefc7c7c7c4c4c4c6c6c6c6c6c6c6c6c6c6c6c6bdbdbdbababa
+b9b9b9b9b9b9babababababab9b9b9b7b7b7b9b9b9bcbcbcb7b7b7b6b6b6b5b5b5b5b5b5b6b6b6
+b0b0b0acacacabababa9a9a9a7a7a7a8a8a8a3a3a3a5a5a5a0a1a09e9f9ef4f4f49a9b9adbdcdb
+dadadac5c5c5c4c4c4c6c6c6c6c6c6c6c6c6c2c2c2bcbcbcbababab9b9b9b9b9b9babababababa
+b9b9b9b7b7b7bbbbbbbababab6b6b6b6b6b6b5b5b5b6b6b6b2b2b2afafafacacacaaaaaaa7a7a7
+a7a7a7a5a5a5a3a3a3a5a5a5989898cccccccccdcca9aaa9f1f1f1c6c6c6c5c5c5c5c5c5c6c6c6
+c6c6c6c6c6c6bebebebbbbbbb9b9b9b9b9b9babababababab9b9b9b8b8b8b7b7b7bdbdbdb8b8b8
+b6b6b6b5b5b5b5b5b5b7b7b7b1b1b1adadadabababa9a9a9a7a7a7a8a8a8a3a3a3a4a4a4a1a1a1
+9a9b9af4f4f49e9f9ed7d8d7e9e9e9c6c6c6c4c4c4c6c6c6c6c6c6c6c6c6c5c5c5bdbdbdbababa
+b9b9b9b9b9b9babababababab9b9b9b7b7b7b9b9b9bbbbbbb6b6b6b6b6b6b5b5b5b5b5b5b5b5b5
+afafafacacacaaaaaaa7a7a7a7a7a7a7a7a7a3a3a3a5a5a5989998c8c8c8d0d1d0949594e9e9e9
+d4d4d4c5c5c5c5c5c5c6c6c6c6c6c6c6c6c6c1c1c1bbbbbbb9b9b9b9b9b9b9b9b9babababababa
+b8b8b8b7b7b7bcbcbcb8b8b8b6b6b6b5b5b5b5b5b5b6b6b6b1b1b1adadadabababa9a9a9a7a7a7
+a7a7a7a5a5a5a4a4a4a2a2a2969796f4f4f4bfbfbfb7b8b7ebebebc6c6c6c4c4c4c6c6c6c6c6c6
+c6c6c6c6c6c6bdbdbdbababab9b9b9b9b9b9babababababab9b9b9b7b7b7b9b9b9bbbbbbb7b7b7
+b6b6b6b5b5b5b5b5b5b5b5b5afafafacacacaaaaaaa8a8a8a7a7a7a7a7a7a3a3a3a5a5a5999a99
+a8a8a8f1f1f1949594e5e5e5d5d5d5c5c5c5c4c4c4c7c7c7c6c6c6c6c6c6c1c1c1bcbcbcb9b9b9
+b9b9b9b9b9b9babababababab8b8b8b7b7b7bcbcbcbababab6b6b6b5b5b5b5b5b5b6b6b6b1b1b1
+adadadabababaaaaaaa7a7a7a7a7a7a5a5a5a4a4a4a6a6a6969796d5d6d5dfdfdfcacacac9c9c9
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cbcbcbcbcbcbcacaca9fa09f949594
+959695949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594bebfbef4f4f4969796949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594d0d0d0c8c9c8949594959695949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+9495949495949495949495949495949495949495949495949495949e9f9ef4f4f49a9b9a949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594cccccccccdcc949594959695949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+9a9b9af4f4f49e9f9e949594959595949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594c8c8c8d0d1d0949594959595
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594969796f4f4f4bfbfbf949594959695949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+a8a8a8f1f1f1949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594949594949594949594949594
+949594949594949594949594949594949594949594949594949594d5d6d5dfdfdfcbcbcbcbcbcb
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cbcbcbcbcbcbc9c9c9dcdcdce1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e9e9e9f4f4f4e2e2e2e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1edededebebebe1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e3e3e3f4f4f4e2e2e2e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ecececececece1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e2e2e2f4f4f4e3e3e3e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ebebebededede1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e2e1f4f4f4e9e9e9e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e5e5e5f3f3f3e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1
+e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1eeeeeedfdfdfcbcbcbcbcbcb
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cbcbcbcacacac9c9c9d3d3d3d6d6d6
+d5d5d5d5d5d5d7d7d7d7d7d7d8d8d8d8d8d8d7d7d7d7d7d7d6d6d6d6d6d6d7d7d7d9d9d9dadada
+d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d8d8d8d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d8d8d8d9d9d9
+dadadadadadad9d9d9d9d9d9dbdbdbdddddddedededcdcdcdadadad9d9d9d9d9d9d8d8d8d7d7d7
+d8d8d8d9d9d9dadadadadadadadadadadadadadadad9d9d9d8d8d8d8d8d8d9d9d9dadadadbdbdb
+dcdcdcdddddddddddddddddddddddddedededddddddcdcdcdbdbdbdadadadadadadadadadadada
+dadadad9d9d9d9d9d9d8d8d8d9d9d9d9d9d9dadadadbdbdbdcdcdcdddddddcdcdcdadadad9d9d9
+dadadadbdbdbdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdadadadadadad9d9d9dadadadadada
+dadadadadadadadadad9d9d9dadadadadadad9d9d9d9d9d9dadadadbdbdbdcdcdcdcdcdcdcdcdc
+dcdcdcdcdcdcdcdcdcdbdbdbdadadad7d7d7d6d6d6d5d5d5d7d7d7d8d8d8d9d9d9d9d9d9d9d9d9
+d9d9d9dadadad9d9d9d9d9d9d9d9d9d9d9d9dadadadadadadbdbdbdcdcdcdedededfdfdfdddddd
+dbdbdbdadadadadadadadadadbdbdbdcdcdcdbdbdbdadadadadadadadadadadadadadadadadada
+dadadadadadadadadadadadad9d9d9d9d9d9dadadadadadad9d9d9d9d9d9dadadad9d9d9d9d9d9
+d7d7d7d6d6d6d5d5d5d5d5d5d6d6d6d7d7d7d8d8d8d8d8d8d7d7d7d7d7d7d6d6d6d6d6d6d7d7d7
+d9d9d9dadadad9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d8d8d8d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7
+d8d8d8d9d9d9dadadadadadad9d9d9d9d9d9dadadadcdcdcdddddddcdcdcdadadadadadad9d9d9
+d8d8d8d7d7d7d8d8d8d9d9d9dadadadadadadadadadadadadadadad9d9d9d8d8d8d8d8d8d9d9d9
+d9d9d9dbdbdbdcdcdcdddddddddddddddddddddddddededededededcdcdcdadadadadadadadada
+dadadadadadadadadad9d9d9d8d8d8d8d8d8d9d9d9d9d9d9dadadadbdbdbdcdcdcdddddddcdcdc
+dadadad9d9d9dadadadbdbdbdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdadadad9d9d9d9d9d9
+d9d9d9dadadadadadadadadadadadad9d9d9dadadadadadad9d9d9d9d9d9dadadadbdbdbdcdcdc
+dcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdadadad9d9d9d8d8d8d6d6d6d5d5d5d7d7d7d8d8d8d9d9d9
+d9d9d9d9d9d9d9d9d9dadadad9d9d9d9d9d9d9d9d9d9d9d9dadadadadadadbdbdbdcdcdcdedede
+dfdfdfdedededcdcdcdadadadadadadadadadcdcdcdcdcdcdbdbdbdadadadadadadadadadadada
+dadadadadadadadadadadadadadadadadadad9d9d9d9d9d9dadadadadadad1d1d1cacacacbcbcb
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac9c9c9c9c9c9c6c6c6c5c5c5
+c4c4c4c5c5c5c6c6c6c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c5c5c5c4c4c4c6c6c6c9c9c9cacaca
+cacacacacacacacacacacacac8c8c8c7c7c7c7c7c7c6c6c6c6c6c6c6c6c6c6c6c6c7c7c7c9c9c9
+cbcbcbcdcdcdcbcbcbcbcbcbcccccccecececfcfcfcdcdcdcacacac9c9c9c8c8c8c6c6c6c6c6c6
+c6c6c6c7c7c7c9c9c9cacacacacacacacacacacacac9c9c9c9c9c9c9c9c9cacacacccccccdcdcd
+cececececececececececececfcfcfcfcfcfcfcfcfcecececccccccbcbcbcbcbcbcbcbcbcacaca
+cacacac9c9c9c8c8c8c7c7c7c7c7c7c8c8c8cacacacccccccdcdcdcfcfcfcecececdcdcdcccccc
+cccccccdcdcdcecececececececececececececececdcdcdcbcbcbcacacacacacacacacacbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcccccccacacac9c9c9cacacacccccccecececececececece
+cecececececececececccccccbcbcbc8c8c8c5c5c5c4c4c4c6c6c6c7c7c7c9c9c9cacacacacaca
+cacacacacacacacacacacacacacacacacacacacacacbcbcbcccccccdcdcdd0d0d0d2d2d2d1d1d1
+cfcfcfcdcdcdcccccccccccccdcdcdcdcdcdcbcbcbc9c9c9c9c9c9cbcbcbcbcbcbcbcbcbcbcbcb
+cccccccbcbcbcbcbcbcacacac9c9c9c9c9c9cbcbcbcbcbcbc9c9c9c9c9c9cacacac9c9c9c9c9c9
+c7c7c7c5c5c5c4c4c4c5c5c5c6c6c6c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c4c4c4c4c4c4c5c5c5
+c8c8c8cbcbcbcacacacacacacacacacacacac9c9c9c8c8c8c7c7c7c6c6c6c6c6c6c6c6c6c6c6c6
+c7c7c7c9c9c9cbcbcbcdcdcdcbcbcbcbcbcbcbcbcbcdcdcdcfcfcfcdcdcdcacacac9c9c9c8c8c8
+c7c7c7c6c6c6c6c6c6c8c8c8c9c9c9cacacacacacacacacacacacac9c9c9c9c9c9c9c9c9cacaca
+cbcbcbcdcdcdcececececececececececececfcfcfcfcfcfcfcfcfcecececccccccbcbcbcbcbcb
+cbcbcbcbcbcbcacacac9c9c9c8c8c8c7c7c7c7c7c7c8c8c8cacacacccccccdcdcdcfcfcfcecece
+cdcdcdcccccccccccccececececececececececececececececececdcdcdcbcbcbcacacacacaca
+cacacacbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcacacac9c9c9cacacacccccccecece
+cececececececececececececdcdcdcccccccbcbcbc8c8c8c5c5c5c3c3c3c6c6c6c8c8c8c9c9c9
+cacacacacacacacacacacacacacacacacacacacacacacacacacacacbcbcbcccccccececed0d0d0
+d2d2d2d1d1d1cfcfcfcdcdcdcccccccccccccdcdcdcdcdcdccccccc9c9c9c9c9c9cbcbcbcbcbcb
+cbcbcbcbcbcbcccccccbcbcbcbcbcbcacacac9c9c9c9c9c9cacacacbcbcbc9c9c9c9c9c9cacaca
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c8c8c8c8c8c8c9c9c9c7c7c7c6c6c6
+c6c6c6c6c6c6c7c7c7c7c7c7c7c7c7c8c8c8c9c9c9c8c8c8c5c5c5c4c4c4c6c6c6c8c8c8cacaca
+cbcbcbcccccccbcbcbcacacac8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c6c6c6c4c4c4c5c5c5c9c9c9
+cbcbcbd0d0d0cecececccccccccccccccccccecececcccccc9c9c9c8c8c8c7c7c7c5c5c5c5c5c5
+c5c5c5c6c6c6c7c7c7c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9cacacacccccccccccccdcdcdcecece
+cdcdcdcccccccccccccdcdcdcececececececececececececccccccccccccccccccbcbcbcacaca
+cacacac9c9c9c8c8c8c6c6c6c6c6c6c6c6c6c8c8c8cbcbcbcccccccececed0d0d0d0d0d0cecece
+cfcfcfd0d0d0d0d0d0cececececececececececececdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcccccccccccccccccccccccccacacac9c9c9c9c9c9cccccccecececececececece
+cececececececececececececcccccc9c9c9c6c6c6c5c5c5c6c6c6c7c7c7c9c9c9cacacacbcbcb
+cbcbcbcbcbcbcbcbcbcccccccccccccccccccbcbcbcacacacbcbcbccccccd0d0d0d1d1d1d2d2d2
+d0d0d0cfcfcfcecececececececececccccccacacac8c8c8c8c8c8cacacacbcbcbcccccccccccc
+cdcdcdcccccccbcbcbcacacac9c9c9c9c9c9cbcbcbcbcbcbc9c9c9c8c8c8c9c9c9c9c9c9c9c9c9
+c7c7c7c6c6c6c6c6c6c7c7c7c7c7c7c8c8c8c8c8c8c8c8c8c9c9c9c9c9c9c5c5c5c5c5c5c5c5c5
+c8c8c8cbcbcbcbcbcbcccccccbcbcbcacacac9c9c9c8c8c8c8c8c8c8c8c8c7c7c7c7c7c7c5c5c5
+c5c5c5c8c8c8cccccccfcfcfcecececccccccccccccccccccdcdcdccccccc9c9c9c8c8c8c7c7c7
+c5c5c5c5c5c5c5c5c5c6c6c6c8c8c8c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9cacacacccccccccccc
+cdcdcdcecececdcdcdcccccccccccccdcdcdcececececececececececececccccccccccccccccc
+cbcbcbcbcbcbcacacac9c9c9c7c7c7c6c6c6c6c6c6c6c6c6c8c8c8cacacacccccccececed0d0d0
+d0d0d0cecececececed0d0d0cfcfcfcececececececececececececdcdcdcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcccccccccccccccccccccccccacacac9c9c9cacacacccccccecece
+cececececececececececececececececececcccccc9c9c9c6c6c6c5c5c5c6c6c6c7c7c7c9c9c9
+cacacacbcbcbcbcbcbcbcbcbcbcbcbcccccccccccccccccccbcbcbcacacacacacacdcdcdd0d0d0
+d2d2d2d2d2d2d1d1d1cfcfcfcdcdcdcececececececdcdcdcacacac8c8c8c8c8c8cacacacbcbcb
+cccccccccccccecececccccccbcbcbc9c9c9c9c9c9c9c9c9cacacacbcbcbc9c9c9c8c8c8c9c9c9
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c7c7c7c8c8c8c8c8c8c8c8c8
+c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9c8c8c8c8c8c8c6c6c6c6c6c6c7c7c7c9c9c9
+cacacacbcbcbcbcbcbcacacac8c8c8c7c7c7c8c8c8c9c9c9c9c9c9c7c7c7c4c4c4c5c5c5c7c7c7
+cacacad0d0d0d3d3d3d2d2d2cecececccccccccccccbcbcbcacacac9c9c9c7c7c7c5c5c5c4c4c4
+c5c5c5c5c5c5c6c6c6c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8cacacacccccccdcdcdcccccccbcbcb
+cacacacacacacbcbcbcbcbcbcccccccccccccccccccccccccccccccbcbcbcacacac9c9c9c9c9c9
+c9c9c9c9c9c9c8c8c8c8c8c8c7c7c7c7c7c7c8c8c8cbcbcbcccccccececed0d0d0d2d2d2d3d3d3
+d3d3d3d3d3d3d1d1d1d1d1d1cecececccccccbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcacaca
+cacacacbcbcbcccccccecececfcfcfcdcdcdcbcbcbc8c8c8c8c8c8cacacacbcbcbcbcbcbcdcdcd
+cececececececfcfcfd0d0d0cecececbcbcbc8c8c8c6c6c6c6c6c6c7c7c7c8c8c8cacacacbcbcb
+cbcbcbcacacacacacacacacacacacacbcbcbcbcbcbcacacacbcbcbcccccccececed0d0d0d1d1d1
+d1d1d1d1d1d1cfcfcfcfcfcfcfcfcfcdcdcdcacacac7c7c7c7c7c7c8c8c8cacacacccccccecece
+cfcfcfcdcdcdcccccccbcbcbc9c9c9c9c9c9cacacacacacac8c8c8c7c7c7c7c7c7c7c7c7c7c7c7
+c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9c9c9c9c8c8c8c7c7c7c6c6c6
+c7c7c7c9c9c9cacacacbcbcbcbcbcbcacacac9c9c9c8c8c8c8c8c8c9c9c9c9c9c9c7c7c7c5c5c5
+c5c5c5c7c7c7cbcbcbd0d0d0d3d3d3d2d2d2cfcfcfcccccccbcbcbcbcbcbcacacac9c9c9c8c8c8
+c5c5c5c4c4c4c4c4c4c5c5c5c7c7c7c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9cacacacccccccdcdcd
+cccccccbcbcbcacacacacacacbcbcbcbcbcbcccccccccccccccccccccccccccccccbcbcbcacaca
+c9c9c9c9c9c9c9c9c9c9c9c9c8c8c8c8c8c8c7c7c7c7c7c7c8c8c8cacacacccccccececed0d0d0
+d2d2d2d3d3d3d3d3d3d3d3d3d1d1d1d0d0d0cfcfcfcdcdcdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcacacacbcbcbcdcdcdcecececfcfcfcdcdcdcbcbcbc9c9c9c8c8c8cacacacbcbcb
+cbcbcbcdcdcdcececececececfcfcfd0d0d0cecececcccccc9c9c9c6c6c6c6c6c6c7c7c7c9c9c9
+cacacacbcbcbcbcbcbcacacacacacacacacacacacacbcbcbcbcbcbcacacacacacacccccccecece
+d1d1d1d1d1d1d1d1d1d1d1d1cfcfcfcfcfcfcfcfcfcecececacacac7c7c7c7c7c7c7c7c7cacaca
+cdcdcdcecececfcfcfcecececccccccacacac9c9c9c9c9c9c9c9c9cacacac9c9c9c7c7c7c7c7c7
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8c6c6c6c7c7c7c9c9c9d6d6d6
+f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f2f2f2f3f3f3f3f3f3
+f3f3f3f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2f3f3f3
+f3f3f3f5f5f5f5f5f5f5f5f5f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2
+f2f2f2f2f2f2f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4
+f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3
+f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4f5f5f5f4f4f0f4f5f1
+f3f5f3f3f5f5f3f4f4f3f5f5f3f4f4f3f3f2f2f2f1f1f1f0f2f2f0f1f1eff1f0eff1f0eeefefed
+efefeef0f0f0f1f0f1f2f1f2f2f1f2efefefefeff0f1efeff1eeeff1edeef2f0eef1f3eef2f4f1
+f2f4f3f2f4f4f2f5f5f4f5f4f4f4f1f4f2f0f3f1f1f2f1f2f2f1f2f2f2f2f2f2f2f2f3f3f2f3f3
+f1f3f3f2f2f2f2f2f2f2f2f2f2f2f2f3f2f3f3f2f3f2f2f2f3f2f3f3f2f3f3f3f3f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f3f2f3f2f1f2f2f1f2f2f1f2f3f2f3f3f2f3f3f3f3
+f4f3f4f3f3f3f4f2f4f3f2f3f2f2f2f2f1f2f2f2f2f2f2f2f2f2f2f2f2f2f1f2f2f1f2f2f1f2f2
+f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2f1f2f2
+f2f2f2f2f1f2f3f2f3f3f2f3f3f2f3f3f2f3f2f1f2f2f1f2f2f0f0f2eff0f2eff0edf0f2e9edf0
+edeff0f1f1eff2f1eff3f2f1f2f4f2f2f4f1f1f3eff1f3eef0f3eef0f2eef1f2eef1f2eef0f2ef
+eff1efeff0eff0f1eff1f0eff0f0eff0f0f0f0f0f1eff0f1eef0f1eff0f1f1f0f1f2f1f1f2f1ef
+f1f2eff0f3f0f1f2f2f2f0f2f1f0f0f2f1f0f1f2f0f0f1f0eff1f0f0f2f1eff2f1eff2f1eef2f1
+edf1f2ecf0f1eef0eff0f0eff2f1f0f2f2f0f1f2f1f1f1f2f2f2f2f3f3f3f4f4f4f4f4f4f5f5f5
+f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f4f4f4
+f4f4f4f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f5f5f5f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3
+f4f4f4f4f4f4f4f4f4f4f4f4f5f5f5f5f5f5f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f3f3f3f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4
+f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f4f4f4f4f4f4f5f5f5f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3d7d7d7cacacac9c9c9c8c8c8
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c8c8c8c7c7c7c7c7c7c9c9c9dadada
+fefefefefefefefefefffffffefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefafdfefb
+fdfefdfdfefefdfefefdfefefefefdfefdfbfdfcf9fcfcf8fbfcf9f9fbf9f7fbfaf4fbfaf1fafa
+effafbebf7faecf6faedf6fbeef9fcf1fafcf2fafcf6fbfbf8fafbf9f9fafbfbfafcfefafdfefc
+fdfefefdfefffdfefffefefefffefbfffdfbfefdfcfefdfefefdfefefdfefefdfefdfefefdfefe
+fdfefefdfefefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefefe
+fefefefefefefefefefefefefefefefefdfefefdfefefdfefefdfefdfdfdfefdfefefdfefefdfe
+fefdfefefdfefefdfefefdfefefdfefefdfefefefefefefefefefefdfefefdfefefdfefefdfefe
+fdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefe
+fefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefdfbfcf9f8f9f5f5f8e9f3f8e6f5f9
+e9f7faebf8f9ecf7faeaf7fbeaf6fbedf4faeff4f9eff5f9f0f6f9f0f6faf0f5faf0f5faeff6fa
+edf8faebf9f9ecf8f9ecf8f9ecf8f8ebf7f8ecf7f9edf7f9f0f9faf6fbfbfbfbfcfdfbfbfdfcf9
+fafdf9fafefbfcfcfdfdfafdfdfafbfcfbfbf8fafaf2f8f9ecf5f7ebf8fae8f7fae7f7f9e7f6f8
+e8f5f7edf7f9f7fcfbfbfcfbfdfcfcfdfdfcfdfefdfbfdfdfdfdfefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcacacac8c8c8
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8c8c8c8c8c8c8c9c9c9dadada
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfefcfdfefd
+fefefdfefdfefefdfefefdfefefdfdfefdfafcfcf8fafcf8f6fcf9f0f9f9e0eff2cce2e7bad6dd
+abcbd5a6c6d2a6c6d2a7c5d1a8c6d0adc8d0b7d0d5c5d9ded2e1e6e7f1f4f5fcfcfbfdfdfdfdfe
+fdfdfefefdfefefdfefefdfdfefefbfefefbfefdfcfefdfefefdfefefdfefefdfefefefefefefe
+fefefefefefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefefefefefefefefefefe
+fefefefefefefefefefefefefefefefdfefefdfefefdfefefdfefefdfdfdfdfefefdfefefdfefe
+fdfdfefefdfefefdfefefdfefefdfefefefefefefefefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe
+fefdfefefdfefefdfefefdfefefdfefefdfefefdfefefdfefbfcfce7eff2d3e2e7a5c2cba1c6d0
+9fc6d09fc6cf9ec5cf9cc3d19cc2d2a1c1d1a4c2d2a6c3d3a7c4d4a7c4d4a6c3d3a5c3d2a4c3d2
+a1c5d29ec5d19ec5d19fc5cfa0c4cfa0c4cea3c4cda3c2cabacfd4e0eaecfafbfcfdfafbfdfcfa
+fbfdfafafefbfcfcfdfdfafdfdf9fafbfafbf3f8fadae8eeb5ccd5a8c5d0a2c4d09fc0cc9fbfc8
+a4c0c4bfd3d6f3fafbfbfbfdfdfcfdfdfcfdfdfefdf9fefdfcfefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcacacac8c8c8
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b414141c8c8c8c9c9c9c9c9c9c9c9c9dadada
+fffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fefefefffffffffffffefefefffffffefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfefefdfefe
+fefdfefefdfefefcfefefcfefefcfdfdfcfbf8fbfaeff9f9deeef0cae0e6a9c9d486b0c06a9baf
+5289a14f879f50879e50859c4f8398518294618e9d769dab8aabb9adc8d3d0e3e9eef5f8f8fafd
+fcfbfefdfbfefefcfdfefcfcfefefcfdfefcfdfefcfefefdfefefdfefefdfefefdfefefdfefefd
+fefefdfefefdfdfefdfdfefdfdfefdfdfefdfdfefdfdfefdfdfefdfdfefdfefefefefefefefefe
+fefefefefefefefefefefefefefefefdfefdfdfefdfdfefdfdfefdfdfdfdfdfefdfdfefdfdfefd
+fdfefdfefefefefefefefefefefefefefefefefefefefefefefefefefefdfefefdfefefdfefefd
+fefefdfefefdfefefdfefefdfefefdfefefdfefefdfefdfdfefdfdfefefdfefefdfefefdfefefd
+fefefdfefefefefefefdfdfdfdfdfdfefefefefefefefefef8fdfdd3e7e9aecfd45589974b899d
+43879a4084963f82963d80993d7f9a41819a45839b47849d48859f49869f47859d46849c44829b
+42829c3d7e993f819c40819b42809b43809a49809845788c6f929ec0d0d5f8fbfcfdfafbfdfcfb
+fcfdfbfbfefcfcfcfdfdfafdfdf9f9f9fbfceaf6f9bbd3de7197ab57869b50829a47798f457485
+4d767e8ba9adedf7fafafafdfdfbfdfdfcfdfdfefdf8fefdfbfefdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcacacac8c8c8
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9c9c9c9c9c9c9c8c8c8d9d9d9
+fffffffefefefffffffefefefffffffefefefffffffefefefefefefefefefffffffefefeffffff
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfefefdfefe
+fefdfefefcfdfefafdfdfafdfdfcfdfafbfdedf7fad1e9f0a3c2cf7199ab4f829a447f9c4281a2
+3c80a33d83a43e82a33e81a13e81a03e809c3c79933c758e3d728b44728a7093a7c8d6ddeaf2f5
+f7f9fcfbfafcfefcfcfefcfcfdfdfcfdfefdfdfefcfdfefcfdfefcfdfefcfdfefcfdfdfcfdfdfc
+fefefcfefdfcfefdfcfefdfdfefdfcfefdfcfefdfcfefdfcfefdfcfefdfdfefdfefefdfefefefe
+fefefefefefefefefefefefefefefefefdfdfefdfcfefdfcfefdfcfdfdfcfefdfcfefdfcfefdfc
+fdfdfcfdfefefdfefefdfefefdfefefdfefefefefefefefefefefefdfefdfdfefcfdfdfcfdfdfc
+fdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfdfcfdfefcfdfefc
+fdfefdfdfefefdfefefdfdfdfdfdfdfdfefefefefefefefef7fdfed2e9eeaed3dd528da13e89a2
+35849e317f99307a962e7896307696337896357997377b99387c9a3a7d9a3a7e9c387b99367897
+3477972a709232789e327aa1347aa2367aa13d7c9e2f688552798bb1c3caf7fbfdfcfbfdfdfbfc
+fdfdfcfcfefdfcfcfefdfbfdfdfbfcf6fbfddef0f7a7cada5e90ac4b86a4427f9c356e872d6276
+36606a99b6bbeaf6f9f8f9fcfcfbfdfdfcfdfdfefdf8fefdfbfefdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcacacac9c9c9
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b414141c8c8c8c9c9c9c9c9c9c9c9c9d9d9d9
+fefefefffffffefefefffffffefefefffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefefdfefe
+fefdfefefcfdfefafdfdfafdf8fafcedf6f9c5dbe581a8be5d8ca75185a4457e9f3d799b377397
+316a8e2e688830698a336d8e3571913575953a7a983b799a3b789a3b75963f6e8a607b8ac5d6dc
+eff6f9f9f9fafefcfbfefcfbfdfdfdfbfefefbfefefbfefefbfefefbfefefcfefefdfdfdfdfdfd
+fefefefefdfefefdfefefcfdfefcfdfefdfefefcfdfefcfdfefdfefefdfefefdfefefdfefefefe
+fefefefefefefefefefefefefefefefefdfefefcfdfefcfdfefcfdfdfbfdfefcfdfefcfdfefdfe
+fdfdfefdfefefcfefefcfefefdfefefdfefefefefefefefefefefefdfefefdfefefcfdfefcfdfe
+fbfcfcfbfcfcfcfcfdfcfcfdfcfcfdfdfdfdfdfdfdfcfdfdfcfdfdfcfdfdfcfdfdfdfefefdfefe
+fdfefefdfefefdfefefcfefdfcfefdfdfefefefefefefefefafcfed1dbe7a9bbd06186a6487ca0
+4077993f71913964852e5576335577345675355774355673355573375775355774345673345672
+36586f325768527f95497b9744779543759448748e34596d46616ea6b7bdf4fbfefbfbfefdfbfd
+fdfdfdfdfefdfdfdfefdfcfdfafbfdf0fafdbfd8e380aac2548cae4482a43b75902354672a5361
+5b787edff1f4f1f7faf8f9fbfcfbfdfdfcfdfdfefdfafefdfcfefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcacacac8c8c8
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8cacacacacacacacacadbdbdb
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefefefefe
+fefdfdfefcfcfefbfdfbfcfdf4fbfcd5e5eaa2bfcd6b98b15687a54c7f9f4478983c6f8e346180
+345d773a5f773b60793c637e3d6a853e708c4279964078973f789840789940728f4e70809bb1b9
+d9e4e7f9fbfafefcfafefcf9fcfdfcfafdfdf9fefef9fefef9fefef9fefefafdfefafdfdfbfdfd
+fcfefefbfdfefbfdfefbfdfdfbfdfdfbfdfefbfdfdfbfdfdfbfdfefbfdfefdfdfefdfdfefefefe
+fefefefefefefefefefefefefefefefcfdfefcfdfdfbfdfdfbfdfdfbfdfdfbfdfdfbfdfdfbfdfe
+fbfdfefbfefefbfefefbfefefcfefefdfefefefefefdfdfdfdfdfdfcfdfefafdfefafdfefafcfe
+fafdfdfafdfdfafdfdfafdfdfafcfdfbfdfdfbfdfdfbfdfdfbfdfdfafdfdfbfdfdfbfefefbfefe
+fbfdfdfbfdfdfcfdfdfcfdfdfcfefdfdfefefdfefefdfefefafcfecad3e09cacc3688cad4e7fa2
+467797416a873f5e78465d76596e865970855972845a73855b74865b74875b76875a74865a7384
+5e7581627b827ea0b05b859c4b79944977944f78913c5d7049636fa6b8bdf3fbfef9fafefdfbfd
+fdfdfdfdfefdfdfdfefcfcfdf7fafde2eff4aac7d5729eb9578eb14680a23c6c832a4e5b44606a
+95a4aaecf5f8f4f8faf9fafbfcfcfcfdfdfdfdfefdfbfdfdfdfdfefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdcdcdccccccccacacac8c8c8
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacaccccccccccccccccccdcdcdc
+fffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffefefeffffffffffff
+fffffffefefefffffffefefefffffffefefefffffffffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefdfefefd
+fefdfcfefcfbfcfcfcf6fcfde4f2f5b4cbd47ea2b45c8da84f819f497997416c883a5e77415b70
+6c7d8c85909d8591a08394a47e95a66a889c5179914c7994497997477a9a4679963e68786e8b94
+c1d0d3f7fbfafefdf9fefcf9f9fafaeff5f7e8f1f4e5f1f4e6f1f3e7f0f3e7f0f3edf4f7f7fcfd
+f7fdfdecf4f6e8f2f5e6f1f4e6f0f4e6f2f5e6f0f3e9f3f5eff8f9f3fbfcfafdfefcfdfcfdfdfc
+fdfdfcfdfdfcfcfdfdfbfdfdf8fcfcf2f8faecf5f8e8f3f6e5f0f3e6f1f3e6f0f3e6f0f3e6f1f4
+e7f3f5ecf5f6f0f7f8f3f9faf7fcfcfafcfdfcfdfdfcfcfcfcfbfbfafcfcf9fdfeecf1f4e4eaef
+e1e9ede1e9ede1e9eee1e9eee9f0f5f3f8fbf4fafceef4f7e5ecf0e2e9ede2eaeee2eaeee2eaee
+e3eaeeecf0f2f6f9fafbfcfdfcfdfdfdfefdfdfefdfcfefdf4f9fbbccbd88aa0b86993b24f84a2
+48799340677a4d66757f8c98a9b3bca8b5bca9b6bcaab8bdabb9beabb9beabbabfabb9beabb7bd
+abb8bbafbfc0a5c2ce6b93a852809b4f7e9b527e993f6379496674a5b9bff2fbfef9fafefdfbfd
+fefdfdfdfdfdfcfdfdfafcfdf1f9fcc7dae291b1c46794b1578cae4b7e9d395c6d455960747f84
+d6d7dcf9f8fcf9f9fbfbfcfbfcfdfcfcfefcfdfefefdfcfefdfdfefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdededececececbcbcbcacaca
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cdcdcdcdcdcdcdcdcdcdcdcddddddd
+fefefefefefefffffffffffffffffffefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffdfdfefb
+fefdfbfefdfbfafcfceffafbc7dde593b3c26b95aa5b8da54e7e974a73893f5f72475d6c77828c
+c7c8cdeae8eaeceaede9eaefdce2e8b2c0c9708b9c5e8197567e974e7d9a4e809c3d697a587881
+b1c2c4f3f8f6fefdf9fdfdfbf4f7f9d8e4e9bfd3dbb6cfd8b6cdd7b8cbd4b9c9d2c9d7dee6f1f5
+e8f3f5c5d6ddbad0dab6cedab4cddab6d0dbb3cbd7bacfd8c9dbe1d5e5e9edf5f7fafbfafcfbf7
+fdfcf8fafcfaf7fbfbedf6f8ddeaedcddfe5c0d7e0b9d1dcb5ccd6b8ced7b7cdd7b7ced7b7cfd8
+b8d2dac0d4dcc8d8ddcfdde2dce7eaebf1f3f9fbfcfbfbfafaf9f8fafafaf9fcfdd8e1e7b9c8d1
+afc1cdacc1ceabbfcfaabdccbbc9d6dae6eedfecf2cad8e1b4c5d0aec0cdaec1ceaec2ceadc1ce
+afc1ccbecbd1dae2e6f2f4f7fbfbfdfdfdfdfdfdfdfafdfde7f3f6acc6d37b9fb46597af50889f
+487b8d3f6672627b80c4d1d2f7fdfcf9fdfdf9fefdf9fefdfafefdfafefdf9fdfdfafdfdf9fdfc
+f6fcfceffdfeb3d2dc729db1578aa55387a552839f3f69814a697aa6bac1f2fbfdf9fbfdfdfbfb
+fdfcfafdfdfbfbfdfcf5fbfce2f1f6a9c0cd7fa1b66792ad5686a34e7790354c59778084acafb1
+faf6f9fefafefcfbfcfdfdfcfcfefcfcfefcfefefefefcfefefdfefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe0e0e0d0d0d0cecececdcdcd
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d1d1d1cecececccccccdcdcddddddd
+fefefefefefefefefefffffffefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfefefcfefc
+fdfefbfdfdfbf8fcfce2f2f5a6c3d17ca4ba6595ae588aa0568091436471475c64808c90e3e7e9
+f8f8f9fbfbfbfcfcfbfcfdfbfbfcfcf4fafcb1c1cd7692a561849b5783a05587a247718154707a
+a6b4b8ecf0effdfdfafbfdfcf2fafdbdd1d986a7b76e97ac6d92a66d8da06b8698889fabc0d4da
+c1d5db819dac7497ad7096ae6d96b06d95b0698ea868889c7792a28ca2afccd9def7f9f8fcf9f2
+fcfaf4f6faf7eef9f9c7e0e698b7bf7ca0af6e96ab6a92a96d92a77293a77395a87397a97098ab
+6c97ab6e93a57392a17c97a493a8b1c2ced4f5f9fbf9f9f8fbf9f7fbfaf9fbfafcd5e2ea8da8b7
+779cb1729bb46e95b16b8da9637d98a7bbcfb5cada8ca6b77897ac7397b07198b27198b27097b0
+6b91a66b86968e9faad9dde3f8f7fbfefafdfefcfef6fdfed9ecf1a2c0cf789eb46a93aa61889e
+5474874a626f79868eeaefeffefefcfdfefdfdfefefdfefefefefefefefefdfdfdfdfdfcfdfdfc
+fcfcfcf9fdfebed4db7d9fac638d9e5f8b9f5d86994a6b7e546b79adbbc1f6fcfdfbfcfcfdfcf9
+fdfaf6fbfbf7f8fcfbebf6f9c1d9e394b3c5769ab06990a65e85994364733c4d58b6bcc0e3e5e6
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe1e1e1d2d2d2d2d2d2d1d1d1
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d1d1d1d0d0d0cecececfcfcfdedede
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfefefdfefd
+fdfefbfcfdfbf5fcfdc3d5dc98b4c3779db2658fa75d849b486879415864829096d6dcdff8fafa
+f8f9fafafafafbfcfbfcfdfbfbfdfdf7fdffd0dee587a2b26d8ea3618ba55d8aa4517787536d76
+9fabaee6e9e8fdfdfafafdfdf4fdfec2d7e08dafc0729ab06c91a666869a5f7b8d7c94a4b3c9d4
+9db4bf87a4b57597ad6e93ac6a92ac6a93b0688ca768889e627e8f647c8a85949bf0f4f4fbfaf7
+fafbf8e9f0f3d4e3eb8faebb7ea2b0739bae6b93ab668ba56081985e7c915f7e93618297658a9f
+6c95a96e95a97192a46e8d9d69828f6a7a84ecf3f5f6f8f8f9f8f7f9f8f9f8fafcd5e3ea93afbd
+7a9fb46e97af668da664859f637b9589a0b58faabb7897a97094a96e95ac6a94ac6a94ac6995aa
+6790a560808e5b6e79b0b6bcdddde1fefafdfefcfef6fcfeccdde59dbacb80a5bc6c93aa6689a0
+587588566b778d989dfafdfcfefefcfefefdfdfefefdfefefefefefefefefefefdfefefcfdfdfb
+fcfcfafafdfec3d6dd85a5b26c94a56892a4688ca05472825b707cadb9c0f2f8faf9fbfafdfbf9
+fefcf9fbfdfbf2f9fbd9e7ee99b4c585a6ba7599af678ba0557588354e5b839096dfe2e4f9f9f9
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdededed1d1d1d2d2d2d1d1d1
+d0d0d0060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cdcdcdcecececfcfcfd1d1d1dfdfdf
+fefefefefefefffffffffffffefefefefefefffffffffffffefefefefefefefefefefefeffffff
+fffffffefefefefefefffffffffffffefefefefefefffffffefefefefefefefefeffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfdfdfdfd
+fcfefdfafdfdecf5f7acbfc790acbc799cb16a8ca4627e93485c6d667580b3babff3f5f6f7f7f7
+f7f8fafafcfcfbfdfcfdfdfbfafcfcf8fdffdbe8ef97afbd7c9bad6b94aa6490a7557888576f78
+a2aeb1e6eae8fafaf7fafdfeeff9fcbed2dc8dadbe779cb16c8ca16380945e788978909fa4bac8
+849aa76a859365839766859b688aa36a8ea9668aa36b8ca3617f915c77866a7a83dbdfe1f3f4f5
+f2f6f8d1dee6aabfce88a8bd7295aa6a8ca15e7e934e6a7f4a61745b6e7f5e7283617889647f91
+6a8a9b6c8ea27091a36c8b9c627d8b596f7ac0cbcfeff3f5fafafbf9fafcf8fbfdc6d5db97b1be
+7c9fb26f93aa6a8ba26c879d63798d687f8f677f8e5d788a5a798b67899f6c90a56e93a76e94a8
+6a91a4638391556973949ca2c1c3c8fefafdfefbfef3f8fdc3d1dc9ab5c886aac37195ad6c8ca2
+5e7a8c6b808ca4b0b6f5fafafcfefcfbfefdfafefefbfefefcfefefefefefdfdfcfdfdfcfdfdfb
+fcfcfaf9fcfdc9dadf8baab57398a87096a76f91a25b77855e717aabb6baeff4f4f9fbf8fcfbf7
+fdfcfaf8fcfce3eef4b9cddb8aa8bc7f9fb57595ab6483974d69784d606bd2d8dcf2f2f2fbfaf9
+fefefcfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcbcbcbcccccccdcdcd
+cecece060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacacbcbcbcdcdcdd0d0d0dfdfdf
+fefefefffffffefefefffffffefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfbfcfcfcfc
+fafdfdf7fbfce1ebf0a6bac38da9b87a9baf6c8ca161788b485867818c96cbd0d4fafbfbf9f9f9
+f8f9fbf9fcfcfbfdfcfcfdfcfbfdfdf8fdffdde9ee9bb1bf819eaf7097ab6992a85878885b717a
+a6b2b4e9edebfafaf7fafdfeebf5f9baced98dabbc7a9eb2708fa366819461798a7388978ea2b0
+758994667d8a657e8f65819468879e6d8fa86a8da56f8fa56582955e788963737dcfd4d7f0f2f4
+e9eff4c4d3df9eb5c883a3ba7193a9658397566f815266757382908d99a58e9ca78e9ea9899ca9
+7d95a26f8fa17191a36d8d9d637f8e566c78aebbc0ecf2f3fafbfcf9fbfcf7fcfdbecdd397b0bd
+7d9eb07193a86d8ba0688194596c7d657785718491738897718999708c9f728fa37392a57495a8
+7092a563828f54677098a0a5c6c8ccfdfbfdfcfafef2f6fcbeccd898b1c588aac27396ad708fa4
+657f91768b97abb8beedf3f5f1f6f7f1f6f8f1f7f8f3f7f8f3f6f7f4f6f6f5f5f5f5f5f4f7f7f5
+fbfbfaf9fcfdcddde291adb8789baa7498a87493a45f798661727aacb5b8eff3f2fafbf8fcfbf7
+fbfcfaf3f9fbd7e4eea8bfd188a7bb7f9eb37290a55e7a8c4e6573717f8ae7ebeef8f7f6fcfbf9
+fefefcfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdadadac8c8c8c8c8c8cacaca
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c7c7c7cacacacececededede
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfbfafbfcfb
+f8fbfcf3f9fbcdd9e0a1b6c18aa5b47d9bac708a9c5e6f7f4e5964abb1b8eaecedfefdfcfdfdfc
+fcfdfefafdfdfafdfcfcfefcfcfefef8fdffdbe6ea9fb2be87a0af7899ac7195a95c778761737b
+aeb7baeff2f1fbfcf9f8fdfde1eef2b4c8d38da9ba7c9eb07591a4688092677b8a74859183929d
+7d8c9481909a81939e7e929f7690a17391a67392a77593a86d889b677e8f616f7ac2c8ccecf1f3
+d8e2eab1c3d396aec57c9bb47290a55f7686586671767e85c6cbd1e3e5e8e2e5e7dde2e4cdd7da
+abb9bf7a96a37796a67391a1688493566c7b9baaafe9f0f1fafbfcf7fbfbf3fbfcb2c2c996aebb
+7f9dad7594a66e899a5d717f5967737e8994a1aab4b0b9c2afbac595a5b38093a47f94a67f97a9
+7a95a6627e8a53656da9b1b5d9dcddfdfbfdfafafeedf3f8b9c6d296adc089a7be7997ac7792a6
+728a9b8296a3a9b8bfd2dce1d2dce1d3dde3d5dfe4d7dfe3d7dee1d8dddfd8dadcd8d9dbe1e2e2
+fafafafbfefed5e2e89ab2bd809eac7a9baa7a97a6657c8865757baeb6b7f0f3f1fcfcf8fcfbf7
+f8fafae6f0f5c1d3e195afc488a7ba7e9cae6b8697576d7c5b6a75b4bbc3f7f7f9fcfbf9fdfcf9
+fefefcfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffd9d9d9c5c5c5c4c4c4c6c6c6
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b404040c4c4c4c4c4c4c6c6c6cacacadbdbdb
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefafcfdfc
+f8fdfdf2fafbb5c5cf9eb3bf8ba5b27f9aa97087955c6a77676f78c7cacef9f9f9fefdfafdfdfb
+fdfefdfbfefefbfefefbfefefcfefefbfeffd8e2e7a2b4be8da4b1819faf7998ab5f7484627179
+b5bcbff5f9f8fbfefbf7fdfcd7e3e9afc4d08eaaba7a98ab6d87985b6f7e68778298a2aad1d9de
+e6edeee7eeefe5edf0d5dfe4abbbc6788fa07994a87c94a8758c9e6f849465757ec0c8c9e6eef1
+c7d3dda3b7c797b1c67e9ab16e87975c6c76838a8fd3d5d8f7f6f7fbf8f8fbfaf8f9f9f7f4f7f5
+eaf2f391a9b287a4b07e9ba86d88955b728098a5aae8eef0fbfbfbf5f9f9edf7f8a7b9bf96aeba
+859faf7791a1677b894e5d65969fa4d9dce0f8f7fbf9f9fcf7fafce2e8ee9ca8b291a0ad899dac
+7e95a660768355646dbcc3c7eceff1fbfbfdf9fbfee6ebf2b6c2cf96aabd8ba4b9839bae8197a9
+8095a58194a2889aa695a6b097a7b099a9b49baab79caab69da9b2a4abb3969ca2979da1b3b8bb
+f7f8f8fbfdfed8e5e9a0b5c087a2b0829ead8099a66c7f896a787cb0b7b8f1f3f1fcfcfaf9f8f6
+f5f8f8d3dfe7aac0d190aec482a0b27a94a36479865b6b7580898feef1f5fcfbfcfbfaf8fbfbf8
+fefefdfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffd9d9d9c5c5c5c2c2c2c4c4c4
+c4c4c4060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c6c6c6c5c5c5c6c6c6c9c9c9dadada
+fffffffefefefffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fefefefefefefefefefefefefffffffefefefffffffffffffffffffffffffefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefcf8fbfcfb
+f3fafbe9f4f8aabdc99cb4c18fa7b4819aa66d838d61707898a1a5dadfe0fcfdfafffefafefefa
+fdfefdfbfefefbfefefbfefefbfefefbfeffd4dbe0a9b9c196abb5839fab7b97a7607282707d85
+c1c7cafafdfcfbfefcf3fcfcc9d7dfa9bdcb90abbb7c97a86c83925a6a75969fa5dee1e4f9f8f7
+f9f7f3f8f4f0f9f8f8f7f9fae6eef3aab9c58ca1b1879aab7c8e9e73859265757bbfc8c9d8e2e5
+bdccd59cb1c18ea7ba839baa6e7f89768388acb5b7edf2f4f5f7f8f9f8f8f9f9f9f7f9f9f4fbfa
+eef8f9a7bbc295aeb888a1ad7189965c707d9daab2ebeff0fbfaf9eff3f2e2ededa7b9bf98aeb9
+8ca4b17b909d65767f545f63c2c8c8f0f1edfcfbf5fbfbf6f6f8f3ebf2f1b2c0c4a3b6bd92aab5
+7d98a6617381707b85d0d6d9f8fbfcfafbfcf9fdfed5dfe6b2c1cd9eaebe96a7b98ea0b0889baa
+889baa859aa8839aa8859dac88a0ae8aa0b08ca1b28ea1b18fa0ad8e9ba66772797d888eb5bdc1
+fafdfefbfdfedde7eaa9bac590a6b589a1b1889faa788a92748084b3b8baeff0f0fcfcfafbfcfa
+e5eceebeced79ab5c689aac07f9baa6f848f596871767e86d1d4d8f9f8fbfbf9fbfcfbfbfcfcfb
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffddddddc9c9c9c6c6c6c6c6c6
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c5c5c5c6c6c6c7c7c7cacacadbdbdb
+fefefefffffffefefefffffffefefefefefefffffffffffffefefefefefefefefefefefeffffff
+fefefefffffffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfbf7fafcfa
+ebf4f5dce9eeafc2cea1b6c496abb98397a26b7d8569767bc3cbcee8ececfcfcf9fefdf9fefefa
+fdfefdfbfefefafdfdfafdfcfcfdfef8fcfecad2d8adbbc49dafba89a1ae7f97a5657481848d95
+ccd1d3f9fdfbf8fcfaf1fafbc6d4dcaabecb95adbd7d96a6687a89606d78aab1b6f1f3f4faf9f7
+fcf8f4fdf8f2fbfaf6f9fbf9edf4f6becdd599acb991a2af8494a17c8a966e7a80cdd6d7cfd9dd
+b9c7d0a2b4c297abba899faa7d8c94929fa4bcc8cce2ebf0e6edefebeff3ecf0f3ebf1f4e8f2f4
+e3f1f3b5c9d1a0b7bf90a6ae7487915c6c75bbc3c7eff2f2fbfbfaecf0f1d9e4e7afc0c69cb1bb
+92a7b27d909a69787e6d7878d5dad8f7f8f3fcfcf5fbfcf5f8fbf4e3ece9b5c4c7a7bac096aeb7
+8299a662717b889299d8dde0f8fbfcfafbfcf9fdfdccd5ddb5c2cda6b3c19eabba94a3b08b9ca6
+7d8f9872848e6b7f8b697f8c677d8c687d8b697b89697a87697883636e795c6770848e95c6cdd2
+fafcfcfbfcfae0e9ebaebdc697abb893a8b591a5ad8090957b8688b1b5b6e8e9eafafbfaf6f9fa
+d5dee2b6c7d09db5c48aa6b78398a464737c69737aa3a9aef3f5f7fcfbfcfcfafbfcfcfbfdfdfc
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfcdcdcdc9c9c9c6c6c6
+c6c6c6060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b414141c8c8c8c7c7c7c7c7c7cacacadbdbdb
+fefefefefefefefefefefefefefefefefefefffffffefefefffffffefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcf7f9fcfb
+e6f0f3d5e3e9b4c6d3a5b8c69faebb8996a0737e857d878be0e6e8f2f5f4fcfdfafefdfafefefb
+fdfefefbfefdfbfdfcfcfdfcfbfcfdf4f9fcc7d0d7b2bfc9a5b4bf91a3b18497a368757d969ea2
+d7dbdbfbfdfcf9fdfcedf6f8c5d4daadc0cb9bafbf8396a6667582717d85bac1c5f7fafafcfbfa
+fdfaf9fdfaf6fafbf8f7fcf9ebf5f7c1d2d8a4b7c299a9b58b98a4828d98737b82dce3e4cbd4d9
+bac5cea9b6c29dacb89aaab5919ea898a5adadb8c0c0cad2c2cbd3c9d0d8cad2d9cbd5dbccd6dd
+cad6ddb7cad4a1b5bd8ea0a8717e8460686ddadddef5f6f6fbfbfce9edf0d5dde3b7c5cda5b5bd
+99aab2808f96707d80868f8fe0e5e3fbfbf8fdfdf9fcfdfaf9fbf9dee5e6bec9ceb1bec69eadb8
+8694a0646f75a9afb3e4e7e9fafbfcfcfcfdf9fbfdcdd2dabbc3ceacb6c2a2adba9aa7ae7f8e90
+6776766d7d7d7d8d917e8e96818e99838e97848e96858f97868f97858d94899196a9b0b5dae0e3
+fbfdfbfbfcf8e4ecedb6c4cba2b3bd9db0ba99abb189979a838c8db2b6b7e5e7e9f8fbfceaeff3
+ccd5dbb3bfc99fafbc8d9fac75838c5f6a708d9599d5d9dcfbfdfdfdfdfdfdfcfcfdfdfbfdfdfc
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe1e1e1d1d1d1cdcdcdc8c8c8
+c7c7c7060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacac8c8c8c8c8c8cacacadbdbdb
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcf8f9fcfb
+e5eef2d3e0e7b8c9d6a9b9c6a4b0bb8d969e788085899194edf2f4f7f9f8fdfdfafefefafefefb
+fefefdfcfefdfcfdfcfcfdfcfafcfdf1f6f9c7d0d8b5c1cba9b7c295a5b28594a06a747aa5aaae
+dfe1e2fbfdfdfbfdfdeaf2f5c6d4dab0c1cc9eb0be8696a565727d7e8a90c4cccef9fdfcfcfcfc
+fefbfcfcfaf9f8fcf9f5fcfae9f5f6c1d4d8abbdc69dadb88e9ba5858f99787d85e4e8ebcbd3d8
+bcc5cdaeb8c2a2adb7a2afb997a4ae96a2ab9faab2aab4bdacb5beb1bac2b2bcc4b4bfc7b7c1ca
+b6c1caadbec998aab387969d6e767b666b6de9eaebf8f9f9fafbfce7ebefd2d9e0bcc7d0abb8bf
+9caab0818f9376818399a0a0e6ebe8fcfdfafdfdfbfdfefcf9fbfbdce1e3c4ccd2b8c1c9a2adb8
+87919c686f74bdc1c4eceeeffbfcfdfcfcfdf7f9fbcfd2dabec4cfafb8c3a5afbb9aa6aa778483
+6b7874828f8b9ca9a9a0abafa4acb3a6adb2a8aeb2a9afb4aab0b5acb1b6b1b6b9c7cccfe7ecee
+fbfdfbfcfcf7e7eeefbdc9cea9b9c1a5b6be9fafb4909c9f889192b3b8b8e4e7e8f7fbfde2e8ed
+c8d1d8b2bcc69facb78d9aa56a757c676f75a7adb1ecf0f2fbfdfdfefefefefefcfefefbfefefb
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe2e2e2d3d3d3cfcfcfcacaca
+c8c8c8060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444cfcfcfcbcbcbc8c8c8c8c8c8d9d9d9
+fffffffefefefffffffffffffffffffffffffffffffefefefffffffefefefffffffefefeffffff
+fffffffffffffffffffffffffffffffefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfefbfafdfd
+e5ebf0d2dce3c1cdd7aebac4aab3ba90969d7c8186969c9df9fcfcfbfcfbfdfdfafefefafefefc
+fefefcfcfefcfcfdfdfdfdfefafbfcecf0f3cad2d8b7c3c9adbac19baab37d8992696e76c1c3c7
+efeff1fbfafbfafafbe5eaeec9d3dcb3c2cda0afbb8896a066717996a0a5d5dbddfbfdfdfdfcfd
+fefcfdfbfafaf8fbfbf5fbfbe8f3f5c4d4d8b3c4caa3b0b9909ca4869199858a90e9ecefd0d3d9
+c0c5ccb4bbc2acb2baa3acb68f9aa589949d8c959d9099a1919aa28d979e9099a1939ca4959fa6
+949ca5818d9775828a6c767d656a6f7b7d7ff5f6f6fafbfaf9fbfbe4e8ecced4dac1c9d1b1bbc2
+9da7ae828b8f838a8cbfc3c4f0f2f1fcfdfcfcfdfcfcfdfcf8fbfad7dcdccad1d4bec5cca6adb7
+848c95727679d5d6d9f4f5f6fcfcfdfcfcfdf2f2f6d1d2dac3c7d0b6bdc6adb5be91989c6e7777
+aab2afdee5e2f2f9f9f5fbfcf8fcfdfafdfdfbfdfdf9fcfdf8fbfcf8fbfcf6f9f9f7fafafafcfc
+fbfcfbfdfdfbebf1f2c7d1d5b5c2c9b1bec6a9b3bb9ca5ab91989cb5babce0e4e6f2f7f9d8dfe3
+c6ced4b3bcc49ea8b1838f985b646a8f9499ced2d5f6f9fbfbfcfdfefefefefefcfefefbfefefb
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3d6d6d6d4d4d4cfcfcf
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b464646d5d5d5d0d0d0cbcbcbc9c9c9d9d9d9
+fefefefffffffffffffffffffefefefffffffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefffffffefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfafcfc
+e4e7e9d1d4d7c7cbceb3b6baacaeaf9495958e8e8fb6b8b8fbfcfbfbfbf9fcfcfafefefcfefefc
+fefefcfdfdfcfdfcfdfdfbfef9f7fae3e3e5d1d5d5b9c0c1aeb8b9a2aeb17d868a79797dd9d8da
+fbf9fafbf9fafaf8fadfe2e5ced2d9bac1c8a2abb18790966c7379b8bcc0eaedeefcfdfdfefdfd
+fefdfdfdfcfdfcfdfdf5f9f9e5ebecccd6d8bac5c8a5b0b3909b9e8993979ba1a4e6e5e7ceccce
+bfbdbfb5b3b7aeaeb2898f966f767f757c8480868c83888e868c918991958a90958a9095899095
+878f94858c9284888e878b8f94989ababcbbf9fbf9f9fbf9f4f6f3e0e3e3ced2d4bcc0c4b3b6ba
+999ba0828487939496ddddddf5f5f5fafbfcfafcfcfafcfaf6f7f4d3d4d0c8cac8bdbfc1a4a7ac
+828589858688e7e7e8f8f6f7faf8f9fbfbfbebebedd1d3d7c0c2c8b7b9beb3b5b98a8c8e7d7f7d
+cacbc9f4f6f4f9fbfafbfdfdfdfdfdfdfdfdfefefdfefefdfdfdfcfdfdfcfbfbfafbfbfafdfcfb
+fdfdfbfdfdfdeff1f4d1d5dcc0c5cdbabfc7b0b3bba7a7ad98989bb8babadddfdee6e9e9d2d6d8
+bfc3c8b0b5bb959aa26f757b6e7377c3c7c9f0f3f4f8fafbfafbfcfefefefefefcfefefcfefefc
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3d7d7d7d7d7d7d5d5d5
+d1d1d1070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b474747d8d8d8d5d5d5cdcdcdcacacadadada
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfdfdfbfbfa
+e3e2dfcecbc9c3bfbbb1aca7a6a19b928e8894918dc0c0bcfbfbf8fbfbf8fcfcfafdfdfbfefefc
+fefefcfdfdfcfdfcfbfcf9f9f6f1efd9d5d0cccac4bbbcb7b0b3af9ca4a1767c7c949397e2dfe3
+fbf8f9faf7f7faf7f5d2cfcfc8c6c6bababaa2a3a4868788797b7cc9cacbf4f4f5fdfdfdfefdfd
+fefdfdfdfdfcfbfbf8f0f0eddadad7d0d1cfb7bab9a2a8a7899090888f8fc8caccdedbdbc7c0be
+bbb2aeaea5a1a29a97807f82a6aaafccd1d4dee3e5e0e4e5e0e4e5e1e5e6e1e5e6e0e4e6e0e4e6
+e0e3e6e1e3e5e2e2e4e3e3e5e6e7e7eef0effcfdfafcfdf9f0f0ebdbd9d5cbc8c4b6b1aeadaaa6
+918d8b827e7da19e9df2f0f1faf8faf9fbfdf8fcfcf8f8f5edece5cdc9c0bdb9b2b4b0ab9d9a99
+7b797a9a9899f0efeffbfaf9fbfaf9faf9f7dfdddad3ceccbdb9b6b0aca9aaa7a37c7a76898784
+d7d6d4fcfcfafdfdfbfdfdfdfdfdfdfdfdfdfefefdfefefdfdfdfcfdfdfcfdfdfcfdfdfcfdfdfb
+fcfcfcfdfdfdf3f5f7d5d6dac4c3c8bebcc0b3aeb0aba6a49e9994b6b3acd1d0c9d7d6d0c4c3c1
+b8b7b8a3a3a784858a727479b1b3b6e0e2e3f8f9f9fbfbfbfcfcfcfefefefefefcfefefcfefefc
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3d7d7d7d7d7d7d8d8d8
+d5d5d5070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b474747d8d8d8d6d6d6d0d0d0ccccccdbdbdb
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfefcfaf9f4
+dfdad2c7bfb7bcb0a3ab9f91a1968891887b989288c6c3befcfbf6fcfbf8fcfcfafdfdfcfefefd
+fefefcfefdf9fefbf7f8f2ede6ddd5cdc1b7beb5a9b5b0a5a9a79d8d908a6c6e6cbbbabdece9eb
+faf7f6f7f3f0f2eee8c6beb7c0b7aeb5ada59c9790837f7b8c8986d8d6d5faf9f9fefefefdfefe
+fdfefefdfef8f6f4ebe8e3dacdc6bec6beb6b3aea89796927f827f858987ebebe9cfc9c5beb3aa
+b4a498a5968a988a8076706cc6c7c7edf0f1f8fafbf9fbfbf9fafbf9fbfbf9fbfbf9fafbf8fafb
+f8f9fbfbfaf9f9f8f7f8f8f7f8f9f7fbfcfafdfefbfdfcf7e8e5ded2cac1c5bbafafa196a59a8f
+897f7788807bb3aeacfaf8f8fbfbfcf8fbfdf8faf9f4f3ede3ddd1c7bcadb4a99baa9f94948a83
+77706db0b0aef3f3f2fbfaf8faf9f6f7f6f0d2ccc3cac0b5b6ad9fa69e8f9d9688766f669c9793
+e0dddcfdfdfcfdfefdfcfefdfdfefdfdfefdfefefdfefefdfefefdfefefdfefefdfefdfdfdfcfd
+fcfcfdfcfdfdf4f4f3d2d1cfc0bcb7bab4adaea69caa9f92a49889b0a696bfb5a7c3baaeb2aca4
+aaa4a1908c8e7b777c8a888de5e4e6f3f2f2fbfaf9fcfcfafcfcfbfefefcfefefcfefefcfefefc
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3d7d7d7d7d7d7d8d8d8
+d6d6d6070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b474747d7d7d7d6d6d6d2d2d2cdcdcddcdcdc
+fffffffefefefffffffffffffefefefefefefffffffffffffffffffefefefefefefefefeffffff
+fffffffefefefefefefefefefffffffefefefefefefffffffefefefefefefefefeffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfcf9faf8f0
+dcd5c8c2b7a7baaa93ac9b84a2947d9488739c9283c9c4bdfdfbf5fcfbf8fcfcfbfcfdfdfdfefd
+fdfdfbfdfcf6fcf8f0f2e8ddd9cabcc4b3a2b2a290ada1929e95887b786f71706cdcdcddf4f2f2
+faf7f4f4efe9ebe3dac3b5a8baa999ae9e8d968b7d847c74a29c97e3dfddfdfbfbfdfdfefdfefe
+fcfefefdfdf4ede8d9ddd5c6c4b7a9b9aa9da79a9188807a85837e989894f9f8f3c9c1b7bcad9f
+b39f8da48f7c94827171685ed5d5d1f8faf9fcfdfdfcfdfefcfdfefcfdfdfdfdfdfdfdfdfcfdfd
+fcfcfcfefdf8faf9f6faf9f6fafbf8fcfcfafefdfafbf9f4dfd8d0cabdafc3b19dae9a86a08e7b
+84756691877dc5c0bcfafafafafcfdf8fbfcf9faf7f2eee5d8cdbdc5b49fb2a08da492828c7c70
+796d65c8c9c6f5f6f3f9faf5f8f8f2f2f1e7c8bfb0c0b39eb2a38ba3957c988d75796f60b1aba3
+e8e5e3fdfdfcfbfefdf9fefdfafefdfcfefdfdfefefdfefefdfefefdfefefdfdfefcfdfefcfcfe
+fcfcfdfcfcfcf5f4f0cfcbc2bcb4a7b6ac9cab9f8aab9c82ab9980b09d85b4a28db5a592aa9d90
+988e877c73727f797cb7b4b8fbf8f9fbf9f8fcfaf8fcfbf9fdfdfbfefefcfefefcfefefcfefefc
+fefefdfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe2e2e2d6d6d6d7d7d7d7d7d7
+d6d6d6070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b464646d6d6d6d4d4d4d2d2d2cfcfcfdedede
+fffffffefefefefefefffffffefefefefefefffffffffffffefefefefefefffffffefefefefefe
+fefefefefefefefefefffffffefefefefefefffffffefefefefefefffffffefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafbf6faf8ee
+ddd4c4c2b5a0c1ad90b4a082ad9a7c9f8e73a29480c6bdb4fbf7f0fbf9f5fbfbf9fcfcfbfdfdfc
+fdfcfafdf9f2f9f1e5ecddcbd4c2acc0ab93ad9983a2917f8f82736e665b908e89eef0eff9f9f7
+fbf9f3f2ece1e4d8cacbb8a3baa48baa957c938370887e73bbb4adeae5e3fdfafbfdfcfdfcfdfc
+fcfefcfbf8ebe4dac5d7c9b3c2b19cb29e8b958377786c649c9691c0beb9faf7f0ccc2b3c2b09c
+bca38bad937b9d866f796c5ddbd8d0fbfbf7fdfdfbfefdfcfefdfcfdfdfcfefdfbfefdfafdfcfa
+fdfcf9fcf9f2f6f4eef7f6f0fafbf7fbfbf8fdfcf7f9f5eddacec4c8b5a2c6af94b59b819e886f
+82705d9d9285d9d5cef9faf9f8fcfcf8fcfbfafaf4f1ebddd1c2acc9b397b8a086a48e77877462
+807267e1e1def6f8f5f9faf4f6f6edede9dac5baa3bdab8eb4a080a694759a8b6d7f725fc9c1b8
+f0edeafdfcfcfafdfdf7fdfcf8fefcfbfdfdfdfdfdfdfdfdfcfdfdfcfcfcfafbfcfafbfcfafbfc
+fcfdfdfcfcfaf6f4edcec8b9bbb19bb7aa8fad9e7db19f7bb49e7bb69d7eb49c81b19b83a89685
+86786e736a66979092e6e2e6fdfafbfdfbfafdfbf9fcfbfafdfdfcfefefcfefefcfefefcfdfdfc
+fdfdfdfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe1e1e1d5d5d5d6d6d6d6d6d6
+d4d4d4070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d4d4d4d3d3d3d3d3d3d2d2d2e0e0e0
+fefefefefefefefefefffffffefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafbf6faf8ee
+dfd6c5c8b9a3ccb698c0a887bda481b19a78aa967dbbada0f6eee5f9f4edfcf8f5fdfaf8fdfbf9
+fefcf9fef5ecf5e7d6e8d3b8d9c2a4c1a98ab49d8396846f8071606b6056c4bfbbf4f4f3fafbf9
+fcfaf4f0e8dbddcebad7c0a3c3aa88ae977894826a8c8073d5cec7f0ebeafcf8f9fcfafafcfcf9
+fdfef7f8f1dce1d1b4d6c2a5c6b095b29b848572636d6157b6b0abe9e6e2fbf7edd2c4b3cbb49d
+c6a98dbb9d7fb194778d7a66dbd4c7f9f7effefcf6fefcf7fefcf7fdfbf6fefbf6fefaf5fefaf5
+fdf9f4f7f1e7e9e5dbecebe2f6f9f1f7fbf3fdfcf3f7efe3dcc8b9ceb49cceb394bca2839d856b
+826f5cada195f1ece6fbfbf9f7fafafafbf9fcfaf1f2e9d6d3bfa2d3b693c0a584a78f7186745e
+8a7f71f6f6f3f7faf7fafbf5f7f6ebe7e0cbcaba9bc0ab86bba681ab99769b8d6d80725de1d8cf
+faf4f2fdf9fbfafbfdf8fdfcf9fefcfbfdfcfdfdfdfdfcfcfcfbfafafaf7f8f9f7f7f8f7f8f9f9
+fcfdfdfcfcfaf8f4ecd1c8b4c1b294beac88b6a276baa57abea67dbea47fbaa080b59d81a28f79
+76685a837974beb9bafcfafdfefdfdfefdfcfefdfcfdfdfcfdfdfcfefefdfefefdfefefdfdfdfd
+fdfdfdfefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffe0e0e0d4d4d4d5d5d5d4d4d4
+d4d4d4070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d4d4d4d4d4d4d4d4d4d3d3d3e1e1e1
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9fbf7fafaf1
+e8e1d1d7cbb6c7b397c4aa88c4a782c0a37db99e7eb5a18bcbbca9e2d7c7f1eadcf7f1e4f7f1e5
+f1ebdcebdecae8d6bcdec6a5cdb491c1a886ad967a7d6c577466568d837bece7e5f8f8f8fafbf9
+faf9f1ede5d3dac9aed5bc97c6ac85b69e7aa69174a89783e5daccefe5ddf4ebe5f4ede5f4ede1
+f3ecd9e9dabbddc7a3d3bb97c0a888ab967b7566528c8479cfcdc8f6f5f2fcf8efd1c3afd0b89e
+cbab8cc4a280c09f7ead947bc4b3a0d8cebce5ddcbeae2d1eae3d2ece4d3ece5d4ebe3d1e7decd
+e5dacad2c5b7cfc8bcdedcd2f8fbf4f8fdf7fcfbeef5e9d6e3cbb3d4b697ccae8abca282967f67
+877565baaea5faf6f1fcfbf9fbfcfbfafaf7f9f5e9f0e3ccd9c09ed6b58bbda07aa68d6c8d7d64
+9b9485fafaf7fafdfbfbfcf5f7f4e7e5d9c0d2bc97c2ab81bda87db2a079a89974928369e8ddcd
+f8f0e6f8f2ebf8f3ebf7f4eaf7f5eaf8f5ebf9f4ebf8f3eaf8f3e9f6f1e7e7e4ddebeae4f5f5f1
+fcfdfbfdfcfcfaf4ecd7ccb6cbba95c9b588bea675c0a579c2a57ec1a680bda482b9a285907d68
+77695ca8a19be6e4e4fcfbfdfdfdfdfdfdfdfefdfdfdfdfdfdfdfdfefefdfefefdfefefdfdfdfd
+fdfdfdfefefefefefefefefefefefefdfdfdfdfdfdfdfdfdfefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd2d2d2d4d4d4d4d4d4
+d4d4d4070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b454545d4d4d4d5d5d5d7d7d7d6d6d6e3e3e3
+fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefeffffffffffffffffff
+fefefefefefefffffffffffffefefefefefefefefefffffffffffffffffffefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7faf8fafaf4
+f0ebdee3d9c9bba990bba284bea27ec1a47ebfa37eb9a080c1ac8ecdba9ed6c7acdccfb3dfd3b6
+dccfb2d9c8aad5c0a0cab190baa281a79070836f556e614f84796ccbc5bff9f5f5f7f6f7f7f7f6
+f5f1e8e7dbc7d5bfa1ceb28bc3a980bca47db89f7cbaa284d1bda4d6c4afd9c8b5dbc9b5dccab1
+deccacd8c29ccbb38dc3ab87b49d7c8c7a5f736653b9b3a9e7e6e1f9f9f6fdfaf2d2c6b3cab49a
+c5a685c2a07cc2a17bbaa07fbca88dc7b79ad3c4a4d8c9a9d7c7a7d9c9a9d7c8a8d5c5a4cfc09f
+c6b697ac9c8bcec5bbe2ded6f9fbf7fafdfafdfbeeeddfc7e1c7a7d2b48ec6a981b49a798c765e
+928171c7beb4fcfaf4fafbf8f9fcfafafbf6f6f0e4eadbc4d9bf9dceae85b1956f9a83628a7b63
+b1aa9afcfcf8fbfcfafbfaf2f6f0e2e1d1b6d8bd97c5a97ebea67ab7a378b2a076a69371d2c2a6
+dccdb5ded0b9dfd2bae0d5b9e1d4b8e1d4bae0d1b9dcceb6d9cbb5d0c4b2c2bcafd9d6caf6f5ee
+f9faf7fcfcfbf9f3ebd9cdb7cdbb96cbb688c0a775c0a277bfa27bbea27eb69d7caa9377796956
+8e8378c9c4c0f5f5f6f9fbfdfcfdfefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfbfbfbfbfbfb
+fafafaf9f9f9fafafafbfbfbfcfcfcfcfcfcfdfdfdfdfdfdfefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d2d2d2d4d4d4
+d5d5d5070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d3d3d3d5d5d5d8d8d8d8d8d8e4e4e4
+fffffffefefefffffffffffffefefefffffffffffffefefefefefefffffffefefefffffffefefe
+fefefefefefefffffffefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fbfbfafbf9
+f6f4ecefe9ddb7a995a89379a89171b19774b89c78b99e78bda37fbfa884c3ae89c7b38dc9b68f
+c6b28bbca883b29d7ca38d6f947f62806e52766953948b7db4ada4eae7e4efedefe9e9ebeae8e7
+e6ded4dac9b4ceb595c5a780bda27bbba27cbca27dbda17ec1a787c2aa8cc3ac8fc4ad8ec5ac89
+c7ac83bfa67cb29b76a893719480626c5e45958b7bd9d6cdeff0ecf4f5f2f9f7f0d5cababeab93
+b79d7db89a74b99b73b9a07ab8a380bda985c3b089c7b28bc5b089c6b18ac3ae87c0aa83b8a27b
+9d88638b7a68d7cec5ece6e2f7f6f6f8f8f9faf7eae1d3b8d6bf99c8ad84bb9f78a48a6c7f6b53
+9f9181d5cec4f7f7f1f2f6f3f2f5f4f5f5f0ede6daddceb8d2bb9bbea17c9f85638b7557887a64
+cac3b5f6f4f0f7f6f2f6f1e8efe5d6d9c4a9d4b690c0a178b99f75b59e74b29d72af9873bea885
+c5b08ec9b492cbb893cdba91ceb890cfb791ccb390c6ae8dbba587a3907aaba192cdc6baf3f1ea
+f2f3f0f5f5f4f4eee7d3c7b4c7b694c5b186bca274b99b73b79a76b49978a48c6f8b765d716455
+b0a9a0e2dfddf6f7f9f7fafcfbfcfdfbfbfcfafafafafafaf9f9f9f7f7f7f4f4f4f2f2f2f1f1f1
+efefefedededefefeff2f2f2f5f5f5f7f7f7fbfbfbfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d3d3d3
+d5d5d5070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444d1d1d1d4d4d4d8d8d8d7d7d7e3e3e3
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9fdfefafdfd
+fbfbf7f8f6eecac0b2a1927d958369988366a18869a88d6bab906dad9571b09873b09a73ae9870
+a59068927e5b8874567a685074644d786c569c9585d0ccc1dfddd6e0dfded6d5d9cdcdcfcdc9c6
+cbc0b4c9b49cc7aa89bc9b74b49974ae9774ab9472ad9372b09877ac9675aa9574aa9371a9906b
+a68a629a825c927d5d86745672634b6f6551c7c2b4e1e0d8e7e8e4e7e8e5eae8e3d5cbc0b0a18d
+a38f72a38b67a48a64a9916ba8936fab9573ae9675ae9675ad9574ad9674a99170a58b6b9a8060
+755d3e7c6c5ddcd3cdede6e5ede9ecedebedefe9dfcdc1a6c0ad85af9a71a28b6789735871604a
+aba091ddd7cee9eae5e2e6e4e0e4e3e6e4dfdcd4c8c8baa6bea98da1896a8670527a674d887b68
+d9d2c6e3e0dde6e4e0e4ddd3ddd1c2c9b298bfa07cad8f6ba78e6ba38d69a18b67a28b69aa9170
+af9774b39b76b69e76b8a075b89d73b89a72b69772ae906f9c81657d6954a99c91c8c0b8e9e6e3
+e8e8e7e7e9e7eae6e0c9beaeb9a88cb4a07da99069a48968a287699d836888715a6a58447e7369
+c8c4bfebeaeaf1f3f4f4f7f9f6f8f9f5f6f6f3f3f3f0f0f0ededede9e9e9e3e3e3dfdfdfdedede
+dcdcdcdcdcdce0e0e0e6e6e6ecececefefeff7f7f7fbfbfbfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d1d1d1
+d4d4d4070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444d1d1d1d3d3d3d5d5d5d5d5d5e2e2e2
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfdfefbfdfe
+fcfdfbfbfbf8f1ede5c0b7a99c907d897a64827059836d54887359877156867053846e517e6a4e
+7662466c5b426c5d48726656877d6fb9b3a5dcdad0dcdbd5d6d5d2c7c7c7b6b6b8a4a4a2a19c95
+ac9d8dbaa084c19f7bb08e67a98f6c96826589775e89775f84735b7e6f557c6d527a6c4f78684b
+7763467060456b5c456a5d48746a59aca69adcd9d2d4d3cdcfcfcbcdcdcacac7c5ccc5bda79d8d
+8c7f67817153816e4f85735386735787725b89715e897060866d5d866f5d8069587861506f5846
+634d3c8f847ad2cbc7dad5d5d5d2d4d5d2d3d6d0c7b1a790998b6a857453796649695843695b4c
+afa69bd4cfcacececbc5c8c7c1c6c3c9c8c2c3bab1ada09196867177664d6858406a5b47847a6b
+c6c2b7c2bfbcc3c1bec3bcb4bfb3a6b09b84967a5d8a7157867058836e57816d55806b55836c56
+856f568670558871528a72518c7251886c4e85684c7d6149705643685549b1a5a1c7bfbfdbd8db
+dadbdcd8dbd8e0ddd9c0b7aba4967f948467816d4e7e69507b6550745e4b675443574a3c948f88
+c2c1c0dcdddee7e9eaebedede9eaebe7e7e8e2e2e2dcdcdcd7d7d7d3d3d3cbcbcbc8c8c8c7c7c7
+c7c7c7cbcbcbd4d4d4dddddde5e5e5eaeaeaf4f4f4fafafafcfcfcfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d1d1d1
+d3d3d3070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d2d2d2d3d3d3d4d4d4d4d4d4e2e2e2
+fffffffffffffffffffffffffffffffffffffffffffefefefffffffefefefffffffefefeffffff
+fefefefefefefefefefefefefffffffefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfcfefdfcfe
+fafafcf7f8f8eaeae8e0ded9c7c3b8a6a092888072766d5f74685975665776675877695a7a6d61
+85796e978d86aca49dc7c4bcd6d5cddde0d9d4d7d2cdcecbc3c4c2afaead9796957e7c787f786b
+9a8872b29475b9936ea5805c93795c74624f685a4e75695f72685b716a5b716d5c7370607a7567
+847b708b8378999388a9a39ac3bfb9cecec9c0bfbdb5b4b0a6a3a09f9a989f9999a7a09fa49d96
+9990828b806f827765776c5b73665973655c74656075666275666276676375666272635f756662
+897a77bbb5b3c3c0bec1bfbdb9b8b6b5b4afbab6ac9a92848a7f6d8175637d716074695c766d64
+98928daaa7a4a4a4a39d9f9d9da09da9a7a4a8a19c978d84857b6c796e5f736a5b726a5d787169
+908a8591918e9595949d98949f948d9886778a7462817163786c6273675e71645a6e62576e6257
+6c60546c5f526e605171635376665977675979685a79695d786a5f867975cec6c6d3ced1d3d2d6
+d2d5d5d7dad6e2e0dcc4bfb79d9586867b68756a54665a4a6152455d4d425b4f465d554e8d8c8a
+adaeafc5c7c7d2d3d1d3d2cfd0cecccbcbcac6c6c6c2c2c2bfbfbfbdbdbdbebebec0c0c0c2c2c2
+c6c6c6d1d1d1dcdcdce3e3e3eaeaeaefefeff9f9f9fcfcfcfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d2d2d2
+d3d3d3070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d2d2d2d2d2d2d4d4d4d5d5d5e2e2e2
+fefefefefefefefefefffffffffffffefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfbfdfdfbfd
+f9f9fcf5f6f9e2e5e6c9cac8b1b2ab99988e84827878776c7b776c878075958c81a1988faaa39d
+b5afacbfbcbbc7c5c3d0d1ced5d8d4d0d6d2cbd0cec3c6c4bbbcbbaaaaa896949084847b8a8274
+9e8973ac8b6cae85619e7957876b526d5b4c70635c8b807c857d76837f748685798f8e849d9b94
+aba7a5b7b4b0bebcb8c2c0bdc5c5c3c2c3c4b4b5b6a7a6a49f9a989c96949c9597a49d9fa29c98
+9d98909690868f8980877f78857b77867c798b827e928a85978f8b9e9691a19a95a39b97a39c97
+ada6a2bfbcbcc1c1bfc0c0bdbdbdb8bbbbb3bdbbb2b3aea4afa79fada49baba399a39a9399928d
+9c97969d9a9a9b9a9a9b9b9aa4a5a2b3b1afbcb7b4bbb5aeb5aea4aaa4979a9589938f858a8881
+8986838a8a8a939494a4a09eaca5a0b4a69bb4a397ada39da19b9897918c918a83817a737b746c
+7a746c7f7870888078928b839a938ca09991a69f96aaa29aaea69fb6b0abd2d0cdd5d5d4d7dada
+dbdfdce0e3dde7e6e3dbd7d2beb8aea9a2938881726c645b6257505f524c61575367615e89898b
+a5a7a8b9babac5c4c1c9c6c1c6c3c1c5c4c3c5c5c5c6c6c6c6c6c6c9c9c9cdcdcdd2d2d2d4d4d4
+dadadae1e1e1e9e9e9eeeeeef3f3f3f7f7f7fcfcfcfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d2d2d2
+d3d3d3070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b3b1af9999994b4b4b454545d3d3d3d3d3d3d4d4d4d5d5d5e2e2e2
+fefefefefefefefefefffffffefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefcfdfdfbfd
+f8f9fbf3f5f8dee2e4bfc2c3a9aca9989b968d8f8a888b8690928ba2a19bb5b3adc5c2bed1cfcd
+dad9dbdcdde0dbdcded8dbdbd4d8d8cacfcec6cbcac0c2c2bbbcbcb3b2b1a8a5a1a09d939f9484
+a38b73a38062a17755926d4f755a4669574c7a6f6b9a93939a95929b9994a1a29caeb0abbfc0bf
+cecdd0d8d7d9d8d8d9d3d4d5c9caccc0c1c4b4b5b7abaaaaaaa5a4aba5a3ada8aab3aeb2b0acac
+aba8a6a5a3a0a09e9c9a95969a95989e9a9ba6a4a1b0afaabab7b4c1bfbbc6c4c0c9c8c4c9c8c4
+cccbc7cacacac9cac9cacbc8ccccc7cbcdc5cdcdc7ceccc8cecbcacdc9c7ccc7c4bfbab8b1adad
+a6a3a4a19fa1a5a3a4adababbbbab9cac8c7d6d3d2dcd8d5d9d6d0cdcac3b8b7b0aeaea8a0a09c
+969693999a9ba8a9aabab9b7c4c1bed1c8c3d4cac5cac6c6bdbcbeb0afafa9a6a396949192908b
+93938e9c9b98aaa8a6b7b6b5c0c0bec6c6c4ccccc9d1d0ccd6d4d0d9d8d4dadbd7dcdfdbe1e4e2
+e6ebe6eef0ebefefeeeceae7d7d4cfc4c2baa09d96827f7c797371776f6e7b7574828080959699
+a8aaacb8b9b8c3c1bec9c6c1c9c7c5cbcbcad0d0d0d5d5d5d8d8d8dddddde3e3e3e7e7e7eaeaea
+eeeeeef2f2f2f6f6f6f9f9f9fbfbfbfcfcfcfefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd1d1d1d1d1d1d3d3d3
+d3d3d3070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b454545d4d4d4d3d3d3d5d5d5d6d6d6e2e2e2
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefdfefefdfe
+f9f9faf5f6f6e5e6e7ced0d0bdbfbeb1b2b1aaabaaaaacaab2b4b1bfc0bdcdcdcad7d7d5dedede
+e4e4e5e2e3e5e1e2e4dedfe0d8d9dad1d2d2cdcfcfcbcdcccbcccbcbcbcacac9c6cac4bbb2a392
+a2876f987558936c4d805e44654b386d5e538c8480a8a5a5b0afadb6b6b3bfbfbdc9cac9d4d6d6
+dddddfe0e0e2dddedfd9dadbd2d2d4cdcdcfc7c7c8c6c6c6c8c7c6cac8c7d1cecfd4d2d4cecdcd
+c2c2c2b9b9b9b5b5b5b1afb1b3b2b4b9b8b9c1c1c0cacac8d1d1cfd4d4d2d5d5d3d7d7d6d9d9d8
+dadbd8dbdbdbdcdddcdedfdee2e2e0e3e4e0e6e6e4e3e3e2dddcddd7d6d6d3d2d2c4c3c3bdbbbc
+bbb9babdbcbdc5c4c5d0cfcfdbdbdbe5e5e4ebeaeaebeae9e4e3e0d5d3d2c6c6c4bfbfbdb9b9b7
+babab8c0c1c1cfd0d0dad9d9dfdddde3e0dedddad9d1d0d1c6c6c8bdbcbdb7b6b6afafadb1b1af
+b5b6b5bfbfbfcacacad3d3d5d9dadadadbdbdddedddfdfdee0e0dee1e1dfe5e6e3e8e9e7eceeec
+f1f3f1f9f9f8f8f7f7f1f0efdfdfddd1d1cfb9b9b7a9a9a9a6a5a4a6a4a3a8a7a6acacacb6b6b7
+bfbfc0cacacad3d2d1d8d7d5dddddbe0e0e0e6e6e6ebebebeeeeeef0f0f0f5f5f5f7f7f7f8f8f8
+f9f9f9fafafafcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfd0d0d0d1d1d1d4d4d4
+d3d3d3070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b444444d1d1d1d2d2d2d5d5d5d6d6d6e3e3e3
+fefefefffffffffffffffffffffffffefefefffffffffffffefefefefefefffffffefefeffffff
+fffffffffffffffffffefefefffffffefefefefefefefefefefefefffffffefefeffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fbfbfbf9f9f9f2f2f2e7e7e7e0e0e0dbdbdbd8d8d8d8d8d8dbdbdbe0e0e0e6e6e6eaeaeaededed
+eeeeeeedededecececeaeaeae7e7e7e3e3e3e3e3e3e5e5e5e7e7e7e9e9e8e9e9e6ebe6dbb2a290
+937b6286674b7e5d3f6b4d3456422c7f7365b5afaacececed7d7d7dcdcdce1e1e1e6e6e6eaeaea
+ececececececeaeaeae8e8e8e4e4e4e2e2e2e2e2e2e4e4e4e7e7e7eaeaeaeeeeeeeeeeeee9e9e9
+e2e2e2dcdcdcdadadad8d8d8dbdbdbdededee2e2e2e6e6e6e9e9e9e9e9e9eaeaeaebebebebebeb
+ebebebebebebeeeeeef0f0f0f4f4f4f6f6f6f6f6f6f4f4f4efefefeaeaeae6e6e6dedededcdcdc
+dddddde2e2e2e8e8e8eeeeeef3f3f3f7f7f7f8f8f8f6f6f6f0f0f0e7e7e7e1e1e1dedededddddd
+e0e0e0e6e6e6edededf2f2f2f3f3f3f2f2f2ededede5e5e5e0e0e0dcdcdcd9d9d9d7d7d7dadada
+dddddde2e2e2e7e7e7e9e9e9eaeaeaecececedededededededededeeeeeef1f1f1f3f3f3f7f7f7
+fafafafdfdfdfdfdfdf8f8f8eeeeeee7e7e7ddddddd9d9d9d8d8d8d6d6d6d6d6d6d7d7d7dcdcdc
+e0e0e0e6e6e6ecececefefeff2f2f2f4f4f4f7f7f7f9f9f9fbfbfbfafafafcfcfcfcfcfcfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdededecfcfcfd0d0d0d1d1d1
+d2d2d2070707646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b434343cecececfcfcfd2d2d2d4d4d4e2e2e2
+fefefefefefefefefefefefefffffffefefefffffffefefefefefefefefefffffffefefefefefe
+fefefefefefefffffffefefefefefefefefefefefefffffffefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fefefefdfdfdfcfcfcfafafaf9f9f9f7f7f7f7f7f7f7f7f7f8f8f8f8f8f8f9f9f9f9f9f9f9f9f9
+f9f9f9f9f9f9f9f9f9f9f9f9f8f8f8f7f7f7f7f7f7f8f8f8f9f9f9f9f9f9f9f9f6f4f1e79d9483
+6c5b44553f254a3317422e17574a36a59d90e5e3ddf5f5f5f6f6f6f7f7f7f9f9f9fafafafafafa
+fbfbfbfbfbfbfafafaf9f9f9f9f9f9f9f9f9f9f9f9fafafafbfbfbfcfcfcfdfdfdfcfcfcfafafa
+f8f8f8f7f7f7f7f7f7f7f7f7f7f7f7f8f8f8f8f8f8f9f9f9fbfbfbfafafafafafafafafafafafa
+fafafafbfbfbfbfbfbfcfcfcfefefefefefefefefefdfdfdfcfcfcfafafaf9f9f9f8f8f8f7f7f7
+f7f7f7f9f9f9fbfbfbfefefefefefefefefefdfdfdfdfdfdfdfdfdfafafaf8f8f8f7f7f7f7f7f7
+f9f9f9fafafafcfcfcfdfdfdfdfdfdfbfbfbf9f9f9f8f8f8f8f8f8f8f8f8f7f7f7f7f7f7f7f7f7
+f8f8f8f9f9f9fafafaf9f9f9fafafafafafaf9f9f9f9f9f9f9f9f9f9f9f9fafafafbfbfbfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfbfbfbf9f9f9f8f8f8f7f7f7f7f7f7f6f6f6f6f6f6f7f7f7f8f8f8
+f9f9f9fafafafbfbfbfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefefefefefefefefefe
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbcccccccccccccecece
+d0d0d0060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cbcbcbcececed0d0d0dfdfdf
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfcfcfc
+fcfcfcfbfbfbfcfcfcfdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfbfcfbf9f9f4cdc8bf
+999083796d5d73665672685b827c70c4c1b9f7f6f3fcfcfcfcfcfcfcfcfcfcfcfcfdfdfdfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfcfcfcfcfcfcfbfbfbfbfbfbfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfcfcfcfcfcfcfdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfdfdfdfdfdfdfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfdfdfdfdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfbfbfbfcfcfcfdfdfd
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfbfbfbfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfdfdfd
+fdfdfdfdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefefefefefefefefefe
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffdadadac8c8c8c8c8c8c9c9c9
+cbcbcb060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c9c9c9cccccccececedddddd
+fefefefefefefefefefefefefefefefefefefffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefefefe
+fefefefefefefefefefefefefefefefefefefdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+fdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefdfdfefcfcfbf1efed
+e2dedad8d3ced6d0cbd6d2cedbd8d5eeedeafdfcfbfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefe
+fefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefefefefefefefe
+fefefefdfdfdfdfdfdfcfcfcfcfcfcfcfcfcfdfdfdfdfdfdfefefefdfdfdfefefefefefefdfdfd
+fdfdfdfcfcfcfcfcfcfcfcfcfcfcfcfbfbfbfcfcfcfdfdfdfdfdfdfdfdfdfefefefefefefefefe
+fefefefcfcfcfbfbfbfdfdfdfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfefefefdfdfd
+fdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfdfdfdfdfdfdfdfdfdfdfdfdfefefefefefefefefefefefe
+fefefefefefefdfdfdfdfdfdfefefefdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfcfcfcfcfcfcfdfdfd
+fefefefefefefefefefefefefdfdfdfdfdfdfdfdfdfdfdfdfbfbfbfbfbfbfbfbfbfbfbfbfdfdfd
+fdfdfdfdfdfdfcfcfcfcfcfcfefefefefefefefefefefefefefefefefefefefefefefefefefefe
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefeffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffd8d8d8c7c7c7c7c7c7c7c7c7
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c7c7c7c9c9c9cbcbcbcdcdcddadada
+f4f4f4f5f5f5f5f5f5f5f5f5f5f5f5f4f4f4f4f4f4f3f3f3f3f3f3f2f2f2f2f2f2f2f2f2f2f2f2
+f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f3f3f3f3f3f3f2f2f2f2f2f2f1f1f1f1f1f1f1f1f1f2f2f2
+f2f2f2f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2f3f3f3f3f3f3f3f3f3f4f4f4f4f4f4
+f5f5f5f6f6f6f6f6f6f6f6f6f6f6f6f5f5f5f5f5f5f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f4f4f4
+f4f4f4f5f5f5f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f2f2f2f2f2f2f2f2f2f3f3f3f3f3f3f4f4f4
+f3f3f3f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2f3f3f3f3f3f3f3f3f3f3f3f3f2f2f3f2f2f3f4f3f3
+f4f3f3f4f2f1f4f2f1f4f3f3f5f4f4f5f4f4f4f4f4f3f3f3f2f2f2f2f2f2f1f1f1f1f1f1f1f1f1
+f1f1f1f0f0f0f1f1f1f2f2f2f2f2f2f3f3f3f3f3f3f2f2f2f2f2f2f1f1f1f1f1f1f1f1f1f1f1f1
+f1f1f1f1f1f1f1f1f1f1f1f1f0f0f0f1f1f1f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+f1f1f1f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f1f1f1f1f1f1f2f2f2f2f2f2f2f2f2
+f3f3f3f2f2f2f2f2f2f4f4f4f3f3f3f4f4f4f4f4f4f3f3f3f2f2f2f1f1f1f2f2f2f1f1f1f1f1f1
+f0f0f0f0f0f0f1f1f1f0f0f0f0f0f0f1f1f1f0f0f0f1f1f1f2f2f2f1f1f1f1f1f1f1f1f1f1f1f1
+f1f1f1f1f1f1f2f2f2f2f2f2f3f3f3f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f2f2f2f1f1f1f0f0f0f0f0f0f1f1f1f2f2f2
+f3f3f3f3f3f3f3f3f3f2f2f2f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f3f3f3
+f3f3f3f4f4f4f4f4f4f5f5f5f5f5f5f5f5f5f5f5f5f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+f4f4f4f4f4f4f4f4f4f5f5f5f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f3f3f3f4f4f4f4f4f4
+f4f4f4f4f4f4f5f5f5f5f5f5f5f5f5f4f4f4f4f4f4f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f5f5f5f5f5f5f5f5f5f4f4f4f3f3f3f2f2f2f2f2f2
+f2f2f2f2f2f2f2f2f2f2f2f2f3f3f3f3f3f3f4f4f4f4f4f4f4f4f4f3f3f3f3f3f3f2f2f2f2f2f2
+f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f3f3f3f2f2f2f2f2f2f3f3f3f3f3f3
+f3f3f3f3f3f3f3f3f3f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2d4d4d4c7c7c7c7c7c7c7c7c7
+c9c9c9060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b414141c8c8c8cacacacccccccdcdcdcecece
+d1d1d1d3d3d3d4d4d4d4d4d4d3d3d3d1d1d1cecececbcbcbc8c8c8c6c6c6c6c6c6c6c6c6c5c5c5
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c8c8c8c8c8c8c7c7c7c5c5c5c4c4c4c2c2c2c3c3c3c5c5c5
+c7c7c7c9c9c9cdcdcdcdcdcdcfcfcfcfcfcfcecececccccccccccccdcdcdcececececececfcfcf
+cfcfcfcfcfcfd0d0d0cfcfcfcdcdcdcccccccccccccccccccccccccdcdcdcdcdcdcfcfcfd0d0d0
+d0d0d0d0d0d0d0d0d0cccccccacacac9c9c9c8c8c8c8c8c8c9c9c9cbcbcbcccccccececed1d1d1
+d4d4d4d7d7d7d9d9d9d9d9d9d6d6d6d4d4d4d3d3d3d1d1d1d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0
+d1d1d1d2d2d2d1d1d1d0d0d0cecececececececececdcdcdcccccccdcdcdcfcfcfd0d0d0d1d1d1
+d3d3d3d3d3d3d2d2d2d0d0d0cdcdcdcccccccccccccccccccbcbcbcacacacbcbcbcdcdcdd0d0d0
+d0d0d0d0d0d0d0d0d0d1d1d1d1d1d1d2d2d2d1d1d1cfcfcfcbcbcbc7c7c7c5c5c5c5c5c5c4c4c4
+c4c4c4c5c5c5c9c9c9cbcbcbcecececfcfcfcecececacacac8c8c8c6c6c6c5c5c5c5c5c5c5c5c5
+c5c5c5c6c6c6c6c6c6c6c6c6c7c7c7c8c8c8c8c8c8c8c8c8c8c8c8cacacacbcbcbcbcbcbcbcbcb
+c9c9c9c8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c8c8c8c8c8c8cacacacbcbcb
+cdcdcdcfcfcfd1d1d1d3d3d3d4d4d4d5d5d5d4d4d4d1d1d1cdcdcdcbcbcbc8c8c8c7c7c7c6c6c6
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c8c8c8c8c8c8c7c7c7c6c6c6c4c4c4c3c3c3
+c3c3c3c5c5c5c7c7c7cacacacdcdcdcdcdcdcecececfcfcfcdcdcdcccccccccccccccccccecece
+cecececfcfcfcfcfcfcfcfcfd0d0d0cfcfcfcecececccccccccccccccccccccccccdcdcdcdcdcd
+cfcfcfd0d0d0d0d0d0d0d0d0d0d0d0cdcdcdcbcbcbc9c9c9c8c8c8c8c8c8c9c9c9cbcbcbcccccc
+cececed0d0d0d4d4d4d8d8d8d9d9d9d9d9d9d7d7d7d4d4d4d3d3d3d1d1d1d0d0d0d0d0d0d0d0d0
+d0d0d0d0d0d0d1d1d1d2d2d2d1d1d1d0d0d0cfcfcfcecececececececececccccccdcdcdcfcfcf
+d0d0d0d1d1d1d3d3d3d3d3d3d1d1d1cfcfcfcecececccccccccccccccccccbcbcbcacacacbcbcb
+cdcdcdcfcfcfd0d0d0d0d0d0d0d0d0d1d1d1d1d1d1d2d2d2d2d2d2d0d0d0cbcbcbc6c6c6c5c5c5
+c5c5c5c4c4c4c4c4c4c5c5c5c8c8c8cbcbcbcdcdcdcfcfcfcecececbcbcbc8c8c8c6c6c6c5c5c5
+c5c5c5c5c5c5c5c5c5c6c6c6c6c6c6c7c7c7c7c7c7c8c8c8c8c8c8c8c8c8c8c8c8cacacacbcbcb
+cbcbcbcbcbcbcacacac8c8c8c7c7c7c7c7c7c7c7c7c8c8c8c7c7c7c7c7c7c7c7c7c8c8c8c8c8c8
+cacaca060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242c9c9c9cbcbcbcdcdcdcdcdcdcecece
+d1d1d1d2d2d2d4d4d4d4d4d4d5d5d5d5d5d5d4d4d4d0d0d0ccccccc9c9c9c8c8c8c6c6c6c5c5c5
+c6c6c6c5c5c5c6c6c6c6c6c6c7c7c7c7c7c7c8c8c8c9c9c9c8c8c8c5c5c5c2c2c2c3c3c3c5c5c5
+c6c6c6c9c9c9cbcbcbcdcdcdcecececececececececccccccdcdcdcececececececececececece
+cecececfcfcfd0d0d0cfcfcfcececececececccccccccccccbcbcbcacacacacacacbcbcbcdcdcd
+cecececececed0d0d0d0d0d0cfcfcfcccccccacacac9c9c9c9c9c9cacacacbcbcbcccccccecece
+d2d2d2d5d5d5d9d9d9dcdcdcdbdbdbdadadad7d7d7d5d5d5d4d4d4d3d3d3d3d3d3d3d3d3d5d5d5
+d7d7d7d7d7d7d7d7d7d7d7d7d6d6d6d5d5d5d4d4d4d4d4d4d4d4d4d5d5d5d6d6d6d7d7d7d7d7d7
+d7d7d7d7d7d7d7d7d7d4d4d4d1d1d1d1d1d1d1d1d1d0d0d0cecececccccccececed0d0d0d2d2d2
+d3d3d3d4d4d4d5d5d5d4d4d4d1d1d1cecececbcbcbc9c9c9c8c8c8c7c7c7c6c6c6c5c5c5c4c4c4
+c4c4c4c4c4c4c5c5c5c7c7c7cacacacecececfcfcfcecececccccccacacac7c7c7c5c5c5c5c5c5
+c6c6c6c6c6c6c6c6c6c7c7c7c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9cacacacbcbcbcbcbcbcacaca
+c9c9c9c9c9c9c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c8c8c8c9c9c9c9c9c9cccccccdcdcd
+cecececfcfcfd1d1d1d3d3d3d4d4d4d5d5d5d5d5d5d5d5d5d3d3d3d0d0d0cbcbcbcacacac8c8c8
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c7c7c7c7c7c7c7c7c7c8c8c8c9c9c9c8c8c8c6c6c6c3c3c3
+c3c3c3c4c4c4c6c6c6c9c9c9cccccccdcdcdcececececececdcdcdcccccccdcdcdcececececece
+cecececececececececfcfcfd0d0d0cfcfcfcececececececccccccccccccbcbcbcbcbcbcacaca
+cbcbcbcdcdcdcecececececed0d0d0d0d0d0cfcfcfcccccccacacac9c9c9c9c9c9cacacacbcbcb
+cccccccececed1d1d1d6d6d6dadadadcdcdcdcdcdcdadadad7d7d7d5d5d5d4d4d4d3d3d3d3d3d3
+d3d3d3d5d5d5d6d6d6d7d7d7d7d7d7d7d7d7d6d6d6d5d5d5d4d4d4d4d4d4d4d4d4d5d5d5d6d6d6
+d7d7d7d7d7d7d7d7d7d7d7d7d6d6d6d4d4d4d2d2d2d1d1d1d1d1d1d0d0d0cecececccccccecece
+d0d0d0d2d2d2d3d3d3d4d4d4d4d4d4d4d4d4d1d1d1cecececbcbcbc9c9c9c8c8c8c7c7c7c6c6c6
+c5c5c5c4c4c4c4c4c4c4c4c4c5c5c5c7c7c7cacacacecececfcfcfcecececcccccc9c9c9c6c6c6
+c5c5c5c5c5c5c6c6c6c6c6c6c6c6c6c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9cacacacbcbcb
+cbcbcbcacacacacacac9c9c9c7c7c7c7c7c7c7c7c7c8c8c8c7c7c7c7c7c7c8c8c8c9c9c9c9c9c9
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b424242cacacacbcbcbcccccccccccccccccc
+cececed0d0d0d2d2d2d3d3d3d5d5d5d5d5d5d5d5d5d3d3d3cfcfcfcccccccbcbcbcacacac8c8c8
+c7c7c7c6c6c6c7c7c7c7c7c7c7c7c7c9c9c9cbcbcbcbcbcbcacacac8c8c8c6c6c6c5c5c5c5c5c5
+c6c6c6c9c9c9cbcbcbcdcdcdcecececececececececdcdcdcdcdcdcececececececececececece
+cecececfcfcfd0d0d0cfcfcfcfcfcfcecececdcdcdcdcdcdcbcbcbcacacac9c9c9c9c9c9cacaca
+cacacacbcbcbcececed1d1d1d3d3d3d2d2d2d1d1d1cfcfcfcdcdcdcccccccbcbcbcccccccccccc
+cececed2d2d2d7d7d7dadadadcdcdcdcdcdcdadadad7d7d7d6d6d6d4d4d4d3d3d3d4d4d4d5d5d5
+d6d6d6d6d6d6d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d5d5d5d8d8d8d9d9d9d8d8d8
+d7d7d7d7d7d7d7d7d7d6d6d6d4d4d4d4d4d4d5d5d5d3d3d3d2d2d2cfcfcfcececececececdcdcd
+cdcdcdcececed0d0d0d0d0d0cecececcccccc9c9c9c7c7c7c8c8c8c9c9c9cacacac9c9c9c6c6c6
+c4c4c4c4c4c4c4c4c4c5c5c5c8c8c8cbcbcbcececed1d1d1d1d1d1d0d0d0cbcbcbc7c7c7c7c7c7
+c6c6c6c6c6c6c6c6c6c7c7c7c8c8c8c8c8c8c8c8c8c9c9c9c9c9c9cacacacbcbcbcbcbcbcacaca
+cacacac9c9c9c8c8c8c7c7c7c7c7c7c7c7c7c7c7c7c8c8c8c8c8c8c9c9c9c9c9c9cccccccccccc
+cccccccdcdcdcececed0d0d0d2d2d2d3d3d3d4d4d4d5d5d5d5d5d5d3d3d3cecececccccccbcbcb
+cacacac8c8c8c7c7c7c6c6c6c7c7c7c7c7c7c7c7c7c9c9c9cbcbcbcbcbcbcacacac8c8c8c6c6c6
+c5c5c5c5c5c5c6c6c6c9c9c9cccccccdcdcdcececececececdcdcdcdcdcdcdcdcdcececececece
+cecececececececececfcfcfd0d0d0cfcfcfcfcfcfcecececdcdcdcccccccbcbcbcbcbcbc9c9c9
+c9c9c9cacacacacacacbcbcbcececed0d0d0d2d2d2d3d3d3d1d1d1cfcfcfcdcdcdcccccccbcbcb
+cccccccccccccececed3d3d3d8d8d8dadadadcdcdcdcdcdcdadadad8d8d8d5d5d5d4d4d4d3d3d3
+d4d4d4d5d5d5d6d6d6d5d5d5d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d6d6d6d7d7d7
+d9d9d9d8d8d8d7d7d7d7d7d7d6d6d6d5d5d5d4d4d4d4d4d4d5d5d5d4d4d4d1d1d1cfcfcfcecece
+cecececdcdcdcdcdcdcdcdcdd0d0d0d0d0d0cecececdcdcdcacacac7c7c7c8c8c8cacacacacaca
+c9c9c9c6c6c6c4c4c4c4c4c4c4c4c4c5c5c5c7c7c7cbcbcbcdcdcdd0d0d0d1d1d1cfcfcfcacaca
+c7c7c7c7c7c7c6c6c6c6c6c6c6c6c6c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c9c9c9cacacacbcbcb
+cbcbcbcacacacacacac9c9c9c8c8c8c7c7c7c7c7c7c8c8c8c7c7c7c8c8c8c8c8c8c9c9c9cacaca
+cccccc060606646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1af9999994b4b4b151515414141414141414141414141424242
+424242434343434343444444444444454545454545444444424242424242414141414141404040
+4040404040404040404040404040404141414141414141414141414040404040403f3f3f3f3f3f
+404040404040414141424242424242424242424242424242424242424242424242424242424242
+424242424242434343434343434343424242424242424242414141414141404040404040414141
+414141414141424242434343444444444444434343434343424242424242414141414141414141
+424242434343454545464646474747474747464646454545454545444444444444444444444444
+454545454545444444444444444444444444444444444444444444454545454545464646464646
+454545454545454545454545444444444444454545444444444444434343424242424242424242
+414141424242434343434343424242414141414141404040404040414141414141414141404040
+3f3f3f3f3f3f3f3f3f3f3f3f404040414141424242434343434343434343414141404040404040
+404040404040404040404040404040404040404040404040414141414141414141414141414141
+414141414141404040404040404040404040404040404040404040414141414141414141414141
+414141424242424242434343434343444444444444454545454545444444424242424242414141
+414141404040404040404040404040404040404040414141414141414141414141404040404040
+3f3f3f3f3f3f404040414141414141424242424242424242424242424242424242424242424242
+424242424242424242424242434343434343434343424242424242424242414141414141404040
+404040414141414141414141424242434343444444444444434343434343424242414141414141
+414141414141424242444444454545464646474747474747464646454545454545444444444444
+444444444444454545444444444444444444444444444444444444444444444444454545454545
+464646464646454545454545454545454545444444444444454545444444434343424242424242
+424242424242414141424242434343434343424242424242414141404040404040414141414141
+4141414040403f3f3f3f3f3f3f3f3f3f3f3f404040414141424242434343434343434343414141
+404040404040404040404040404040404040404040404040404040404040414141414141414141
+414141414141414141414141404040404040404040404040404040404040404040404040414141
+414141020202646464c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afa6a5a4848484656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565656565656565656565656565656565656565656565656565656565656565656565
+656565656565979797c4c3c3b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0bfbebdcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb
+cbcbcbcbcbcbcbcbcbc3c3c2b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585edededc7c7c7b2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb3b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb2b1afb2b1af
+b2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb2b1afb3b1afb2b1afb2b1afb3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b858585e6e5e5b6b5b3b3b1afb3b2b0b3b1afb3b1afb2b1afb2b1afb3b2b0b2b1afb3b1af
+b2b1afb2b1afb2b1afb3b1afb2b1afb2b1afb3b2b0b2b1afb2b1afb2b1afb2b1afb3b1afb2b1af
+b2b1afb2b1afb2b1afb3b1afb2b1afb3b1afb2b1afb2b1afb2b1afb3b1afb3b1afb2b1afb3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b2b1afb3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0
+b3b2b0b3b2b0b3b2b0b3b2b0b3b2b0b3b2b09a9a9a2323234b4b4b
+4b4b4b6b6b6abebdbca1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0
+a1a1a0a1a1a0a1a1a0a1a1a0a1a1a0a1a1a09999992323234b4b4b
+4b4b4b313030595858505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+505050505050505050505050505050505050505050505050505050505050505050505050505050
+5050505050505050505050505050505050505050501212124b4b4b
+8080804b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b
+4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b808080
+showpage
+%%Trailer
+end
+%%EOF
Added: packages/openev/branches/upstream/current/gextra.c
===================================================================
--- packages/openev/branches/upstream/current/gextra.c (rev 0)
+++ packages/openev/branches/upstream/current/gextra.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,76 @@
+/******************************************************************************
+ * $Id: gextra.c,v 1.4 2000/06/20 13:26:54 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Support functions that should have been in Glib.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gextra.c,v $
+ * Revision 1.4 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdlib.h>
+#include <glib.h>
+#include "gextra.h"
+
+gint
+g_compare_gint(gconstpointer a, gconstpointer b)
+{
+ return *(gint*)a - *(gint*)b;
+}
+
+void
+g_sort(gpointer mem, guint nmemb, gsize size, GCompareValFunc compare)
+{
+ qsort(mem, nmemb, size, compare);
+}
+
+void
+g_ptr_array_insert_fast(GPtrArray *array, guint index, gpointer data)
+{
+ g_return_if_fail(array);
+ g_return_if_fail(index <= array->len);
+
+ if (index == array->len)
+ {
+ g_ptr_array_add(array, data);
+ }
+ else
+ {
+ gpointer moved = g_ptr_array_index(array, index);
+ g_ptr_array_add(array, moved);
+ g_ptr_array_index(array, index) = data;
+ }
+}
+
+double g_get_current_time_as_double()
+
+{
+ GTimeVal cur_time;
+
+ g_get_current_time( &cur_time );
+
+ return cur_time.tv_sec + cur_time.tv_usec / 1000000.0;
+}
+
Added: packages/openev/branches/upstream/current/gextra.h
===================================================================
--- packages/openev/branches/upstream/current/gextra.h (rev 0)
+++ packages/openev/branches/upstream/current/gextra.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * $Id: gextra.h,v 1.4 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Support functions that should have been in Glib.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gextra.h,v $
+ * Revision 1.4 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __G_EXTRA_H__
+#define __G_EXTRA_H__
+
+#include <glib.h>
+
+/* Duplicates a memory buffer containing elements of homogeneous type */
+#define g_memdup_type(mem,type,count) \
+ ((type*)g_memdup((gconstpointer)mem, (unsigned)sizeof(type) * (count)))
+
+/* Sorts a buffer containing elements of homogeneous type */
+#define g_sort_type(mem,type,count) \
+ (g_sort((gpointer)mem, count, (gsize)sizeof(type), g_compare_##type))
+
+/* Comparison function for sorting (see qsort man page) */
+typedef gint (*GCompareValFunc) (gconstpointer a, gconstpointer b);
+
+/* General in-place sorting (uses qsort) */
+void g_sort(gpointer mem, guint nmemb, gsize size, GCompareValFunc compare);
+
+/* gint comparison for g_sort */
+gint g_compare_gint(gconstpointer a, gconstpointer b);
+
+void g_ptr_array_insert_fast(GPtrArray *array, guint index, gpointer data);
+
+#define g_list_push(list,data) g_list_prepend(list, data)
+#define g_list_pop(list) g_list_remove_link(list, list)
+
+double g_get_current_time_as_double();
+
+#endif /* __G_EXTRA_H__ */
Added: packages/openev/branches/upstream/current/gtkcolorwell.c
===================================================================
--- packages/openev/branches/upstream/current/gtkcolorwell.c (rev 0)
+++ packages/openev/branches/upstream/current/gtkcolorwell.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,700 @@
+/******************************************************************************
+ * $Id: gtkcolorwell.c,v 1.7 2001/09/27 00:39:14 pgs Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Color well button for GTK+
+ * Author: Federico Mena <federico at nuclecu.unam.mx>
+ * Paul J.Y. Lahaie <pjlahaie at atlsci.com>
+ *
+ ******************************************************************************
+ * Copyright (C) 1998 Red Hat Software, Inc.
+ * Copyright (C) 2000 Atlantis Scientific, Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gtkcolorwell.c,v $
+ * Revision 1.7 2001/09/27 00:39:14 pgs
+ * fixed initialization problem with resizing preview widget
+ *
+ * Revision 1.6 2001/09/26 20:28:52 pgs
+ * fixed bug in set functions that called gtk_widget_draw( cp->da ) - da is never
+ * initialized to anything and isn't used.
+ *
+ * Revision 1.5 2001/09/21 20:21:54 pgs
+ * tried to make it resizable but it didn't work.
+ *
+ * Revision 1.4 2001/09/17 03:38:06 pgs
+ * updated render to honour use_alpha setting and modified the set_ routines
+ * to only render/draw if the widget is realized (prevent Gtk-CRITICAL errors)
+ *
+ * Revision 1.3 2001/09/16 03:27:32 pgs
+ * Modified render code to render transparency. TODO: make it render not
+ * using transparency if this option is not set.
+ *
+ * Revision 1.2 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include <gtk/gtkalignment.h>
+#include <gtk/gtkcolorsel.h>
+#include <gtk/gtkdrawingarea.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkcompat.h>
+#include "gtkcolorwell.h"
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkbutton.h>
+
+/* These are the dimensions of the color sample in the color picker */
+#define COLOR_WELL_WIDTH 24
+#define COLOR_WELL_HEIGHT 16
+#define COLOR_WELL_PAD 1
+
+/* Size of checks and gray levels for alpha compositing checkerboard*/
+#define CHECK_SIZE 4
+#define CHECK_DARK (1.0 / 3.0)
+#define CHECK_LIGHT (2.0 / 3.0)
+
+enum {
+ COLOR_SET,
+ LAST_SIGNAL
+};
+
+static void gtk_color_well_class_init (GtkColorWellClass *class);
+static void gtk_color_well_init (GtkColorWell *cw);
+static void gtk_color_well_destroy (GtkObject *object);
+static void gtk_color_well_clicked (GtkButton *button);
+static void gtk_color_well_state_changed (GtkWidget *widget, GtkStateType previous_state);
+static void gtk_color_well_realize (GtkWidget *widget);
+static void gtk_color_well_style_set (GtkWidget *widget, GtkStyle *previous_style);
+
+
+static guint color_well_signals[LAST_SIGNAL] = { 0 };
+
+static GtkButtonClass *parent_class;
+
+
+GtkType
+gtk_color_well_get_type (void)
+{
+ static GtkType cp_type = 0;
+
+ if (!cp_type) {
+ GtkTypeInfo cp_info = {
+ "GtkColorWell",
+ sizeof (GtkColorWell),
+ sizeof (GtkColorWellClass),
+ (GtkClassInitFunc) gtk_color_well_class_init,
+ (GtkObjectInitFunc) gtk_color_well_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ cp_type = gtk_type_unique (gtk_button_get_type (), &cp_info);
+ }
+ return cp_type;
+}
+
+static void
+render(GtkColorWell *cw)
+{
+ int e;
+ guchar row[COLOR_WELL_WIDTH*3];
+ guchar red, green, blue, alpha;
+
+ gint x, y, f, n, width, height;
+ guchar c[3], cc[3 * 2], *cp = c;
+ gdouble o; //opacity ( 0 - 1 )
+
+ g_return_if_fail (cw != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cw));
+
+ //width = GTK_WIDGET(cw)->allocation.width;
+ //height = GTK_WIDGET(cw)->allocation.height;
+
+ width = COLOR_WELL_WIDTH;
+ height = COLOR_WELL_HEIGHT;
+
+ gtk_color_well_get_i8( cw, &red, &green, &blue, &alpha );
+
+ //g_message( "red=%d, green=%d, blue=%d, alpha=%d", red, green, blue, alpha);
+ c[0] = red;
+ c[1] = green;
+ c[2] = blue;
+ o = (gdouble)(alpha / 255.0);
+
+ //for alpha blending to create the gray checkerboard. The colors here are
+ //for either the dark or light areas of the checkerboard. A nifty
+ //calc below chooses between them.
+ if (cw->use_alpha)
+ {
+ for ( n=0; n < 3; n++ )
+ {
+ cc[n] = (guchar)((1.0 - o) * 255 + ( o * c[n] ));
+ cc[n+3] = (guchar)((1.0 - o) * 192 + ( o * c[n] ));
+ }
+ cp = cc;
+ }
+
+ for( y = 0; y < height; y++ )
+ {
+
+ for( x = 0, e = 0; x < width; x++ )
+ {
+ //this determines the size of the checkerboard. The result is
+ //either 0 or 3.
+ if (cw->use_alpha)
+ f = 3 * (((x % 12) < 6) ^ ((y % 12) < 6 ));
+ else
+ f = 0;
+
+ for ( n=0; n < 3; n++ )
+ row[e++] = cp[n+f];
+ }
+ gtk_preview_draw_row( GTK_PREVIEW( cw->preview ), row, 0, y, width );
+ }
+
+ gtk_widget_queue_draw( cw->preview );
+}
+
+static void
+gtk_color_well_class_init (GtkColorWellClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkButtonClass *button_class;
+
+
+ object_class = (GtkObjectClass *) class;
+ button_class = (GtkButtonClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ parent_class = gtk_type_class (gtk_button_get_type ());
+
+ color_well_signals[COLOR_SET] =
+ gtk_signal_new ("color_set",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkColorWellClass, color_set),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ gtk_object_class_add_signals (object_class, color_well_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_color_well_destroy;
+ widget_class->state_changed = gtk_color_well_state_changed;
+ widget_class->realize = gtk_color_well_realize;
+ widget_class->style_set = gtk_color_well_style_set;
+ button_class->clicked = gtk_color_well_clicked;
+
+
+ class->color_set = NULL;
+
+}
+
+static void
+gtk_color_well_realize (GtkWidget *widget)
+{
+ if (GTK_WIDGET_CLASS(parent_class)->realize)
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+ render (GTK_COLOR_WELL (widget));
+}
+static void
+gtk_color_well_style_set (GtkWidget *widget, GtkStyle *previous_style)
+{
+ if (GTK_WIDGET_CLASS(parent_class)->style_set)
+ GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
+ if (GTK_WIDGET_REALIZED (widget))
+ render (GTK_COLOR_WELL (widget));
+}
+
+static void
+gtk_color_well_state_changed (GtkWidget *widget, GtkStateType previous_state)
+{
+ if (widget->state == GTK_STATE_INSENSITIVE || previous_state == GTK_STATE_INSENSITIVE)
+ render (GTK_COLOR_WELL (widget));
+}
+static void
+gtk_color_well_init (GtkColorWell *cw)
+{
+ cw->continuous = 0;
+}
+
+GtkWidget *
+gtk_color_well_new(const gchar *title)
+{
+ GtkWidget *alignment;
+ GtkWidget *frame;
+ GtkColorWell *color_well;
+
+ color_well = GTK_COLOR_WELL(gtk_type_new (gtk_color_well_get_type () ));
+
+ /* Check to make sure we can init a color_well */
+
+ if( ( color_well->preview = gtk_preview_new( GTK_PREVIEW_COLOR ) ) == NULL )
+ {
+ /* We failed */
+ g_error( "failed to create preview in gtk_color_well_new" );
+
+ }
+
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0 );
+ gtk_container_set_border_width( GTK_CONTAINER(alignment), COLOR_WELL_PAD);
+ gtk_container_add (GTK_CONTAINER (color_well), alignment );
+ gtk_widget_show (alignment);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT );
+ gtk_container_add (GTK_CONTAINER (alignment), frame );
+ gtk_widget_show (frame);
+
+ gtk_preview_size( GTK_PREVIEW( color_well->preview ), COLOR_WELL_WIDTH, COLOR_WELL_HEIGHT );
+ gtk_container_add (GTK_CONTAINER(frame), color_well->preview );
+ gtk_widget_show(color_well->preview);
+
+ return GTK_WIDGET( color_well );
+
+
+}
+
+static void
+gtk_color_well_destroy (GtkObject *object)
+{
+ GtkColorWell *cw;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (object));
+
+ cw = GTK_COLOR_WELL (object);
+
+ if( cw->color_dialog )
+ gtk_widget_destroy( cw->color_dialog );
+
+ if( cw->preview )
+ gtk_widget_destroy( cw->preview );
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+/* Callback used when the color selection dialog is destroyed */
+static gboolean
+color_wheel_destroy(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ GtkColorSelectionDialog *cs = GTK_COLOR_SELECTION_DIALOG (data);
+
+ gtk_widget_hide( GTK_WIDGET( cs ) );
+
+ return TRUE;
+}
+
+static void
+cs_cancel_clicked (GtkWidget *widget, gpointer data)
+{
+ GtkColorSelectionDialog *cs = GTK_COLOR_SELECTION_DIALOG (data);
+
+ gtk_widget_hide( GTK_WIDGET( cs ) );
+}
+
+/* Callback for when the OK button in the color selection dialog is clicked */
+static void
+cs_ok_clicked (GtkWidget *widget, gpointer data)
+{
+ GtkColorWell *cp;
+ gdouble color[4];
+
+ cp = GTK_COLOR_WELL (data);
+
+ gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (cp->color_dialog)->colorsel),
+ color);
+ gtk_widget_hide(cp->color_dialog);
+
+ cp->r = color[0];
+ cp->g = color[1];
+ cp->b = color[2];
+ cp->a = cp->use_alpha ? color[3] : 1.0;
+
+ render (cp);
+
+ gtk_signal_emit (GTK_OBJECT (cp), color_well_signals[COLOR_SET] );
+}
+
+static void
+color_continuous_update( GtkWidget *widget, gpointer data )
+{
+ GtkColorWell *cp;
+ gdouble color[4];
+
+ cp = GTK_COLOR_WELL (data);
+
+ gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (cp->color_dialog)->colorsel),
+ color);
+
+ cp->r = color[0];
+ cp->g = color[1];
+ cp->b = color[2];
+ cp->a = cp->use_alpha ? color[3] : 1.0;
+
+ render (cp);
+
+ /* Notify the world that the color was set */
+
+ gtk_signal_emit (GTK_OBJECT (cp), color_well_signals[COLOR_SET] );
+
+}
+
+
+void
+gtk_color_well_set_continuous( GtkColorWell *cw, gboolean continuous )
+{
+ g_return_if_fail( cw != NULL );
+ g_return_if_fail( GTK_IS_COLOR_WELL( cw ) );
+
+ if( continuous == cw->continuous )
+ return;
+
+ if( continuous )
+ {
+ if( cw->color_dialog )
+ cw->cont_sig_id = gtk_signal_connect( GTK_OBJECT( GTK_COLOR_SELECTION_DIALOG( cw->color_dialog )->colorsel ),
+ "color-changed",
+ (GtkSignalFunc) color_continuous_update,
+ cw );
+ cw->continuous = 1;
+ } else {
+ if( cw->color_dialog )
+ gtk_signal_disconnect( GTK_OBJECT( GTK_COLOR_SELECTION_DIALOG( cw->color_dialog )->colorsel ), cw->cont_sig_id );
+
+ cw->continuous = 0;
+ }
+}
+
+
+static void
+gtk_color_well_clicked (GtkButton *button)
+{
+ GtkColorWell *cw;
+ GtkColorSelectionDialog *csd;
+ gdouble color[4];
+
+ g_return_if_fail (button != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (button));
+
+ cw = GTK_COLOR_WELL (button);
+
+ /*if dialog already exists, make sure it's shown and raised*/
+ if(cw->color_dialog) {
+ csd = GTK_COLOR_SELECTION_DIALOG (cw->color_dialog);
+ gtk_widget_show(cw->color_dialog);
+ if(cw->color_dialog->window)
+ gdk_window_raise(cw->color_dialog->window);
+ } else {
+ /* Create the dialog and connects its buttons */
+
+ cw->color_dialog = gtk_color_selection_dialog_new (cw->title);
+ csd = GTK_COLOR_SELECTION_DIALOG (cw->color_dialog);
+
+ gtk_signal_connect (GTK_OBJECT (cw->color_dialog), "delete-event",
+ (GtkSignalFunc) color_wheel_destroy,
+ cw->color_dialog );
+
+ gtk_signal_connect (GTK_OBJECT (csd->ok_button), "clicked",
+ (GtkSignalFunc) cs_ok_clicked,
+ cw);
+
+ gtk_signal_connect (GTK_OBJECT (csd->cancel_button), "clicked",
+ (GtkSignalFunc) cs_cancel_clicked,
+ cw->color_dialog);
+
+ if( cw->continuous )
+ cw->cont_sig_id = gtk_signal_connect (GTK_OBJECT (csd->colorsel), "color-changed",
+ (GtkSignalFunc) color_continuous_update,
+ cw);
+
+ /* FIXME: do something about the help button */
+
+ gtk_widget_hide( csd->help_button );
+
+ gtk_window_set_position (GTK_WINDOW (cw->color_dialog), GTK_WIN_POS_MOUSE);
+
+ /* If there is a grabed window, set new dialog as modal */
+ if (gtk_grab_get_current())
+ gtk_window_set_modal(GTK_WINDOW(cw->color_dialog),TRUE);
+ }
+ gtk_color_selection_set_opacity (GTK_COLOR_SELECTION (csd->colorsel), cw->use_alpha);
+
+ color[0] = cw->r;
+ color[1] = cw->g;
+ color[2] = cw->b;
+ color[3] = cw->use_alpha ? cw->a : 1.0;
+
+ /* Hack: we set the color twice so that GtkColorSelection will remember its history */
+ gtk_color_selection_set_color (GTK_COLOR_SELECTION (csd->colorsel), color);
+ gtk_color_selection_set_color (GTK_COLOR_SELECTION (csd->colorsel), color);
+
+ gtk_widget_show (cw->color_dialog);
+}
+
+
+/**
+ * gtk_color_well_set_d
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Red color component, values are in [0.0, 1.0]
+ * @g: Green color component, values are in [0.0, 1.0]
+ * @b: Blue color component, values are in [0.0, 1.0]
+ * @a: Alpha component, values are in [0.0, 1.0]
+ *
+ * Description:
+ * Set color shown in the color picker widget using floating point values.
+ */
+
+void
+gtk_color_well_set_d (GtkColorWell *cw, gdouble r, gdouble g, gdouble b, gdouble a)
+{
+ g_return_if_fail (cw != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cw));
+ g_return_if_fail ((r >= 0.0) && (r <= 1.0));
+ g_return_if_fail ((g >= 0.0) && (g <= 1.0));
+ g_return_if_fail ((b >= 0.0) && (b <= 1.0));
+ g_return_if_fail ((a >= 0.0) && (a <= 1.0));
+
+ cw->r = r;
+ cw->g = g;
+ cw->b = b;
+ cw->a = a;
+
+ if ( !GTK_WIDGET_REALIZED( cw ) ) return;
+
+ render( cw );
+}
+
+
+/**
+ * gtk_color_well_get_d
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Output location of red color component, values are in [0.0, 1.0]
+ * @g: Output location of green color component, values are in [0.0, 1.0]
+ * @b: Output location of blue color component, values are in [0.0, 1.0]
+ * @a: Output location of alpha color component, values are in [0.0, 1.0]
+ *
+ * Description:
+ * Retrieve color currently selected in the color picker widget in the form of floating point values.
+ */
+
+void
+gtk_color_well_get_d (GtkColorWell *cp, gdouble *r, gdouble *g, gdouble *b, gdouble *a)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+
+ if (r)
+ *r = cp->r;
+
+ if (g)
+ *g = cp->g;
+
+ if (b)
+ *b = cp->b;
+
+ if (a)
+ *a = cp->a;
+}
+
+
+/**
+ * gtk_color_well_set_i8
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Red color component, values are in [0, 255]
+ * @g: Green color component, values are in [0, 255]
+ * @b: Blue color component, values are in [0, 255]
+ * @a: Alpha component, values are in [0, 255]
+ *
+ * Description:
+ * Set color shown in the color picker widget using 8-bit integer values.
+ */
+
+void
+gtk_color_well_set_i8 (GtkColorWell *cp, guint8 r, guint8 g, guint8 b, guint8 a)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+ /* Don't check range of r,g,b,a since it's a 8 bit unsigned type. */
+
+ cp->r = r / 255.0;
+ cp->g = g / 255.0;
+ cp->b = b / 255.0;
+ cp->a = a / 255.0;
+
+ if ( !GTK_WIDGET_REALIZED( cp ) ) return;
+
+ render( cp );
+}
+
+
+/**
+ * gtk_color_well_get_i8
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Output location of red color component, values are in [0, 255]
+ * @g: Output location of green color component, values are in [0, 255]
+ * @b: Output location of blue color component, values are in [0, 255]
+ * @a: Output location of alpha color component, values are in [0, 255]
+ *
+ * Description:
+ * Retrieve color currently selected in the color picker widget in the form of 8-bit integer values.
+ */
+
+void
+gtk_color_well_get_i8 (GtkColorWell *cp, guint8 *r, guint8 *g, guint8 *b, guint8 *a)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+
+ if (r)
+ *r = (guint8) (cp->r * 255.0 + 0.5);
+
+ if (g)
+ *g = (guint8) (cp->g * 255.0 + 0.5);
+
+ if (b)
+ *b = (guint8) (cp->b * 255.0 + 0.5);
+
+ if (a)
+ *a = (guint8) (cp->a * 255.0 + 0.5);
+}
+
+
+/**
+ * gtk_color_well_set_i16
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Red color component, values are in [0, 65535]
+ * @g: Green color component, values are in [0, 65535]
+ * @b: Blue color component, values are in [0, 65535]
+ * @a: Alpha component, values are in [0, 65535]
+ *
+ * Description:
+ * Set color shown in the color picker widget using 16-bit integer values.
+ */
+
+void
+gtk_color_well_set_i16 (GtkColorWell *cp, gushort r, gushort g, gushort b, gushort a)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+ /* Don't check range of r,g,b,a since it's a 16 bit unsigned type. */
+
+ cp->r = r / 65535.0;
+ cp->g = g / 65535.0;
+ cp->b = b / 65535.0;
+ cp->a = a / 65535.0;
+
+ if ( !GTK_WIDGET_REALIZED( cp ) ) return;
+
+ render( cp );
+}
+
+
+/**
+ * gtk_color_well_get_i16
+ * @cp: Pointer to GNOME color picker widget.
+ * @r: Output location of red color component, values are in [0, 65535]
+ * @g: Output location of green color component, values are in [0, 65535]
+ * @b: Output location of blue color component, values are in [0, 65535]
+ * @a: Output location of alpha color component, values are in [0, 65535]
+ *
+ * Description:
+ * Retrieve color currently selected in the color picker widget in the form of 16-bit integer values.
+ */
+
+void
+gtk_color_well_get_i16 (GtkColorWell *cp, gushort *r, gushort *g, gushort *b, gushort *a)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+
+ if (r)
+ *r = (gushort) (cp->r * 65535.0 + 0.5);
+
+ if (g)
+ *g = (gushort) (cp->g * 65535.0 + 0.5);
+
+ if (b)
+ *b = (gushort) (cp->b * 65535.0 + 0.5);
+
+ if (a)
+ *a = (gushort) (cp->a * 65535.0 + 0.5);
+}
+
+
+/**
+ * gtk_color_well_set_dither
+ * @cp: Pointer to GNOME color picker widget.
+ * @dither: %TRUE if color sample should be dithered, %FALSE if not.
+ *
+ * Description:
+ * Sets whether the picker should dither the color sample or just paint
+ * a solid rectangle.
+ */
+
+/**
+ * gtk_color_well_set_use_alpha
+ * @cp: Pointer to GNOME color picker widget.
+ * @use_alpha: %TRUE if color sample should use alpha channel, %FALSE if not.
+ *
+ * Description:
+ * Sets whether or not the picker should use the alpha channel.
+ */
+
+void
+gtk_color_well_set_use_alpha (GtkColorWell *cp, gboolean use_alpha)
+{
+ g_return_if_fail (cp != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cp));
+
+ cp->use_alpha = use_alpha ? TRUE : FALSE;
+
+ if ( !GTK_WIDGET_REALIZED( cp ) ) return;
+
+ render( cp );
+}
+
+
+/**
+ * gtk_color_well_set_title
+ * @cp: Pointer to GNOME color picker widget.
+ * @title: String containing new window title.
+ *
+ * Description:
+ * Sets the title for the color selection dialog.
+ */
+
+void
+gtk_color_well_set_title (GtkColorWell *cw, const gchar *title)
+{
+ g_return_if_fail (cw != NULL);
+ g_return_if_fail (GTK_IS_COLOR_WELL (cw));
+
+ if (cw->title)
+ g_free (cw->title);
+
+ cw->title = g_strdup (title);
+
+ if (cw->color_dialog)
+ gtk_window_set_title (GTK_WINDOW (cw->color_dialog), cw->title);
+}
Added: packages/openev/branches/upstream/current/gtkcolorwell.h
===================================================================
--- packages/openev/branches/upstream/current/gtkcolorwell.h (rev 0)
+++ packages/openev/branches/upstream/current/gtkcolorwell.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * $Id: gtkcolorwell.h,v 1.3 2001/09/26 20:29:35 pgs Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Color well button for GTK+
+ * Author: Federico Mena <federico at nuclecu.unam.mx>
+ * Paul J.Y. Lahaie <pjlahaie at atlsci.com>
+ *
+ ******************************************************************************
+ * Copyright (C) 1998 Red Hat Software, Inc.
+ * Copyright (C) 2000 Atlantis Scientific, Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gtkcolorwell.h,v $
+ * Revision 1.3 2001/09/26 20:29:35 pgs
+ * removed extraneous variable da (unused)
+ *
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef GTK_COLOR_WELL_H
+#define GTK_COLOR_WELL_H
+
+#include <gtk/gtkbutton.h>
+
+#define GTK_TYPE_COLOR_WELL (gtk_color_well_get_type ())
+#define GTK_COLOR_WELL(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_COLOR_WELL, GtkColorWell))
+#define GTK_COLOR_WELL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_WELL, GtkColorWellClass))
+#define GTK_IS_COLOR_WELL(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_COLOR_WELL))
+#define GTK_IS_COLOR_WELL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_WELL))
+
+
+typedef struct _GtkColorWell GtkColorWell;
+typedef struct _GtkColorWellClass GtkColorWellClass;
+
+struct _GtkColorWell {
+ GtkButton button;
+
+ gdouble r, g, b, a; /* Red, green, blue, and alpha values */
+
+ GtkWidget *preview; /* Pixmap with the sample contents */
+
+ GtkWidget *color_dialog; /* Color selection dialog */
+
+ gchar *title; /* Title for the color selection window */
+ guint cont_sig_id;
+ guint use_alpha : 1; /* Use alpha or not */
+ guint continuous : 1;
+
+};
+
+struct _GtkColorWellClass {
+ GtkButtonClass parent_class;
+
+ /* Signal that is emitted when the color is set. The rgba values are in the [0, 65535]
+ * range. If you need a different color format, use the provided functions to get the
+ * values from the color picker.
+ */
+ /* (should be gushort, but Gtk can't marshal that.) */
+ void (* color_set) (GtkColorWell *cw, guint r, guint g, guint b, guint a);
+};
+
+
+/* Standard Gtk function */
+GtkType gtk_color_well_get_type (void);
+
+/* Creates a new color picker widget */
+GtkWidget *gtk_color_well_new (const gchar *title);
+
+/* Set/get the color in the picker. Values are in [0.0, 1.0] */
+void gtk_color_well_set_d (GtkColorWell *cp, gdouble r, gdouble g, gdouble b, gdouble a);
+void gtk_color_well_get_d (GtkColorWell *cp, gdouble *r, gdouble *g, gdouble *b, gdouble *a);
+
+/* Set/get the color in the picker. Values are in [0, 255] */
+void gtk_color_well_set_i8 (GtkColorWell *cp, guint8 r, guint8 g, guint8 b, guint8 a);
+void gtk_color_well_get_i8 (GtkColorWell *cp, guint8 *r, guint8 *g, guint8 *b, guint8 *a);
+
+/* Set/get the color in the picker. Values are in [0, 65535] */
+void gtk_color_well_set_i16 (GtkColorWell *cp, gushort r, gushort g, gushort b, gushort a);
+void gtk_color_well_get_i16 (GtkColorWell *cp, gushort *r, gushort *g, gushort *b, gushort *a);
+
+/* Sets whether the picker should use the alpha channel or not */
+void gtk_color_well_set_use_alpha (GtkColorWell *cp, gboolean use_alpha);
+
+/* Sets whether the picker should update the colors continuously */
+void gtk_color_well_set_continuous(GtkColorWell *cw, gboolean update_continuous );
+
+/* Sets the title for the color selection dialog */
+void gtk_color_well_set_title (GtkColorWell *cp, const gchar *title);
+
+
+#endif
Added: packages/openev/branches/upstream/current/gv_config.h.in
===================================================================
--- packages/openev/branches/upstream/current/gv_config.h.in (rev 0)
+++ packages/openev/branches/upstream/current/gv_config.h.in 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,25 @@
+/* Define if you don't have vprintf but do have _doprnt. */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function. */
+#undef HAVE_VPRINTF
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+#undef HAVE_LIBDL
+
+#undef HAVE_DLFCN_H
+#undef WORDS_BIGENDIAN
+
+#define HAVE_BROKEN_GL_POINTS 1
+
+#undef SHOW_TESS_LINES
+
+#undef HAVE_OGR
Added: packages/openev/branches/upstream/current/gv_config.h_win32
===================================================================
--- packages/openev/branches/upstream/current/gv_config.h_win32 (rev 0)
+++ packages/openev/branches/upstream/current/gv_config.h_win32 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* Define if you don't have vprintf but do have _doprnt. */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function. */
+#undef HAVE_VPRINTF
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+#undef HAVE_LIBDL
+
+#undef HAVE_DLFCN_H
+#undef WORDS_BIGENDIAN
+
+#define HAVE_BROKEN_GL_POINTS 1
+
+#undef SHOW_TESS_LINES
Added: packages/openev/branches/upstream/current/gvarealayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvarealayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvarealayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,556 @@
+/******************************************************************************
+ * $Id: gvarealayer.c,v 1.18 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer of GvAreas.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvarealayer.c,v $
+ * Revision 1.18 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.17 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvarealayer.h"
+#include <gtk/gtksignal.h>
+#include <GL/gl.h>
+
+static void gv_area_layer_class_init(GvAreaLayerClass *klass);
+static void gv_area_layer_init(GvAreaLayer *layer);
+static void gv_area_layer_draw(GvAreaLayer *layer, GvViewArea *view);
+static void gv_area_layer_extents(GvAreaLayer *layer, GvRect *rect);
+static void gv_area_layer_data_change(GvAreaLayer *layer, gpointer change_info);
+static void gv_area_layer_draw_selected(GvAreaLayer *layer, GvViewArea *view);
+static void gv_area_layer_delete_selected(GvAreaLayer *layer);
+static void gv_area_layer_translate_selected(GvAreaLayer *layer, GvVertex *delta);
+static void gv_area_layer_pick_shape(GvAreaLayer *layer);
+static void gv_area_layer_pick_node(GvAreaLayer *layer);
+static void gv_area_layer_get_node(GvAreaLayer *layer, GvNodeInfo *info);
+static void gv_area_layer_move_node(GvAreaLayer *layer, GvNodeInfo *info);
+static void gv_area_layer_insert_node(GvAreaLayer *layer, GvNodeInfo *info);
+static void gv_area_layer_delete_node(GvAreaLayer *layer, GvNodeInfo *info);
+static void gv_area_layer_node_motion(GvAreaLayer *layer, gint area_id);
+
+GtkType
+gv_area_layer_get_type(void)
+{
+ static GtkType area_layer_type = 0;
+
+ if (!area_layer_type)
+ {
+ static const GtkTypeInfo area_layer_info =
+ {
+ "GvAreaLayer",
+ sizeof(GvAreaLayer),
+ sizeof(GvAreaLayerClass),
+ (GtkClassInitFunc) gv_area_layer_class_init,
+ (GtkObjectInitFunc) gv_area_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ area_layer_type = gtk_type_unique(gv_shape_layer_get_type(),
+ &area_layer_info);
+ }
+ return area_layer_type;
+}
+
+static void
+gv_area_layer_class_init(GvAreaLayerClass *klass)
+{
+ GvDataClass *data_class;
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ data_class = (GvDataClass*) klass;
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ data_class->changed = (void (*)(GvData*,gpointer))
+ gv_area_layer_data_change;
+
+ layer_class->draw = (void (*)(GvLayer*,GvViewArea*)) gv_area_layer_draw;
+ layer_class->extents_request = (void (*)(GvLayer*,GvRect*))
+ gv_area_layer_extents;
+
+ shape_layer_class->draw_selected = (void (*)(GvShapeLayer*,GvViewArea*))
+ gv_area_layer_draw_selected;
+ shape_layer_class->delete_selected = (void (*)(GvShapeLayer*))
+ gv_area_layer_delete_selected;
+ shape_layer_class->translate_selected = (void (*)(GvShapeLayer*,GvVertex*))
+ gv_area_layer_translate_selected;
+ shape_layer_class->pick_shape = (void (*)(GvShapeLayer*))
+ gv_area_layer_pick_shape;
+ shape_layer_class->pick_node = (void (*)(GvShapeLayer*))
+ gv_area_layer_pick_node;
+ shape_layer_class->get_node = (void (*)(GvShapeLayer*,GvNodeInfo*))
+ gv_area_layer_get_node;
+ shape_layer_class->move_node = (void (*)(GvShapeLayer*,GvNodeInfo*))
+ gv_area_layer_move_node;
+ shape_layer_class->insert_node = (void (*)(GvShapeLayer*,GvNodeInfo*))
+ gv_area_layer_insert_node;
+ shape_layer_class->delete_node = (void (*)(GvShapeLayer*,GvNodeInfo*))
+ gv_area_layer_delete_node;
+ shape_layer_class->node_motion = (void (*)(GvShapeLayer*,gint))
+ gv_area_layer_node_motion;
+}
+
+static void
+gv_area_layer_init(GvAreaLayer *layer)
+{
+ GvColor default_area_color = {0.0, 1.0, 0.0, 0.3}; /* green */
+
+ layer->data = NULL;
+ layer->edit_ring = -1;
+ gv_color_copy(GV_SHAPE_LAYER(layer)->color, default_area_color);
+}
+
+GtkObject *
+gv_area_layer_new(GvAreas *data)
+{
+ GvAreaLayer *layer = GV_AREA_LAYER(gtk_type_new(gv_area_layer_get_type()));
+
+ if (data)
+ {
+ layer->data = data;
+ }
+ else
+ {
+ layer->data = GV_AREAS(gv_areas_new());
+ }
+
+ /* In case areas exist in data before layer is creatd */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_areas_num_areas(layer->data));
+
+ gv_data_set_parent(GV_DATA(layer), GV_DATA(layer->data));
+
+
+
+ return GTK_OBJECT(layer);
+}
+
+gint
+gv_area_layer_select_new_area(GvAreaLayer *layer)
+{
+ gint area_id;
+
+ layer->edit_ring = 0;
+ area_id = gv_areas_new_area(layer->data);
+
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_areas_num_areas(layer->data));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(layer), area_id);
+
+ return area_id;
+}
+
+gint
+gv_area_layer_select_new_ring(GvAreaLayer *layer, gint area_id)
+{
+ gint ring_id;
+
+ ring_id = gv_areas_new_ring(layer->data, area_id);
+ g_return_val_if_fail(ring_id > 0, 0);
+ layer->edit_ring = ring_id;
+
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(layer));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(layer), area_id);
+
+ return ring_id;
+}
+
+void
+gv_area_layer_edit_done(GvAreaLayer *layer)
+{
+ layer->edit_ring = -1;
+}
+
+/*******************************************************/
+
+static void
+gv_area_layer_draw(GvAreaLayer *layer, GvViewArea *view)
+{
+ gint i, r, areas, rings;
+ gint *selected, presentation;
+ gint hit_selected = FALSE;
+ GvArea *area;
+ GArray *ring;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ areas = gv_areas_num_areas(layer->data);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ for (i=0; i < areas; ++i)
+ {
+ int fill_object;
+
+ if (selected[i] && !presentation)
+ {
+ continue;
+ }
+
+ area = gv_areas_get_area(layer->data, i);
+
+ if( area->fill != NULL )
+ glVertexPointer(2, GL_GEOCOORD, 0, area->fill->data );
+ for( fill_object = 0; fill_object < area->fill_objects; fill_object++ )
+ {
+ int f_offset=g_array_index(area->mode_offset,gint,fill_object*2+1);
+ int f_mode = g_array_index(area->mode_offset,gint,fill_object*2);
+ int f_len;
+
+ if( fill_object == area->fill_objects-1 )
+ f_len = area->fill->len - f_offset;
+ else
+ f_len = g_array_index(area->mode_offset,gint,fill_object*2+3)
+ - f_offset;
+
+ glDrawArrays(f_mode, f_offset, f_len);
+ }
+ }
+ glDisable(GL_BLEND);
+
+ for (i=0; i < areas; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ area = gv_areas_get_area(layer->data, i);
+ rings = gv_areas_num_rings(area);
+
+ for (r=0; r < rings; ++r)
+ {
+ ring = gv_areas_get_ring(area, r);
+
+ glVertexPointer(2, GL_GEOCOORD, 0, ring->data);
+ glDrawArrays(GL_LINE_LOOP, 0, ring->len);
+ }
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ gv_area_layer_draw_selected(layer, view);
+ }
+}
+
+static void
+gv_area_layer_draw_selected(GvAreaLayer *layer, GvViewArea *view)
+{
+ gint i, r, areas, rings;
+ gint *selected;
+ GvArea *area;
+ GArray *ring;
+ GLenum mode;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ areas = gv_areas_num_areas(layer->data);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ for (i=0; i < areas; ++i)
+ {
+ if (selected[i])
+ {
+ int fill_object;
+
+ area = gv_areas_get_area(layer->data, i);
+ if( area->fill != NULL )
+ glVertexPointer(2, GL_GEOCOORD, 0, area->fill->data );
+
+ for( fill_object = 0;
+ fill_object < area->fill_objects;
+ fill_object++ )
+ {
+ int f_offset =
+ g_array_index(area->mode_offset,gint,fill_object*2+1);
+ int f_mode =
+ g_array_index(area->mode_offset,gint,fill_object*2);
+ int f_len;
+
+ if( fill_object == area->fill_objects-1 )
+ f_len = area->fill->len - f_offset;
+ else
+ f_len = g_array_index(area->mode_offset,gint,fill_object*2+3)
+ - f_offset;
+
+ glDrawArrays(f_mode, f_offset, f_len);
+
+#ifdef SHOW_TESS_LINES
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glColor4f(1.0,1.0,1.0,1.0);
+ glDrawArrays(f_mode, f_offset, f_len);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glColor4f(GV_SHAPE_LAYER(layer)->color);
+#endif /* SHOW_TESS_LINES */
+ }
+ }
+ }
+ glDisable(GL_BLEND);
+
+ glPointSize(3.0);
+ for (i=0; i < areas; ++i)
+ {
+ if (selected[i])
+ {
+ area = gv_areas_get_area(layer->data, i);
+ rings = gv_areas_num_rings(area);
+
+ for (r=0; r < rings; ++r)
+ {
+ if (r == layer->edit_ring)
+ {
+ mode = GL_LINE_STRIP;
+ }
+ else
+ {
+ mode = GL_LINE_LOOP;
+ }
+
+ ring = gv_areas_get_ring(area, r);
+
+ glVertexPointer(2, GL_GEOCOORD, 0, ring->data);
+ glDrawArrays(mode, 0, ring->len);
+
+#ifdef HAVE_BROKEN_GL_POINTS
+ {
+ int j;
+ for (j=0; j < ring->len; ++j)
+ {
+ glBegin(GL_POINTS);
+ glArrayElement(j);
+ glEnd();
+ }
+ }
+#else
+ glDrawArrays(GL_POINTS, 0, ring->len);
+#endif
+ }
+ }
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_area_layer_pick_shape(GvAreaLayer *layer)
+{
+ gint i, areas;
+ GvArea *area;
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+
+ areas = gv_areas_num_areas(layer->data);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ for (i=0; i < areas; ++i)
+ {
+ int fill_object;
+
+ glLoadName(i);
+ area = gv_areas_get_area(layer->data, i);
+
+ if( area->fill != NULL )
+ glVertexPointer(2, GL_GEOCOORD, 0, area->fill->data );
+ for( fill_object = 0; fill_object < area->fill_objects; fill_object++ )
+ {
+ int f_offset=g_array_index(area->mode_offset,gint,fill_object*2+1);
+ int f_mode = g_array_index(area->mode_offset,gint,fill_object*2);
+ int f_len;
+
+ if( fill_object == area->fill_objects-1 )
+ f_len = area->fill->len - f_offset;
+ else
+ f_len = g_array_index(area->mode_offset,gint,fill_object*2+3)
+ - f_offset;
+
+ glDrawArrays(f_mode, f_offset, f_len);
+ }
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_area_layer_pick_node(GvAreaLayer *layer)
+{
+ GvArea *area;
+ GArray *ring;
+ gint sel, rings, r, i;
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+
+ if (!gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_FIRST, &sel))
+ {
+ return;
+ }
+ area = gv_areas_get_area(layer->data, sel);
+ rings = gv_areas_num_rings(area);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ /* Nodes first */
+ glLoadName(0);
+ glPushName(-1);
+ glPointSize(1.0);
+ for (r=0; r < rings; ++r)
+ {
+ glLoadName(r);
+ glPushName(-1);
+
+ ring = gv_areas_get_ring(area, r);
+ glVertexPointer(2, GL_GEOCOORD, 0, ring->data);
+ for (i=0; i < ring->len; ++i)
+ {
+ glLoadName(i);
+ glBegin(GL_POINTS);
+ glArrayElement(i);
+ glEnd();
+ }
+ glPopName(); /* node id */
+ }
+ glPopName(); /* ring id */
+
+ /* Segments next */
+ glLoadName(1);
+ glPushName(-1);
+ for (r=0; r < rings; ++r)
+ {
+ glLoadName(r);
+
+ ring = gv_areas_get_ring(area, r);
+ glVertexPointer(2, GL_GEOCOORD, 0, ring->data);
+
+ /* First segment connects last vertex to first vertex:
+ "before" vertex zero */
+ glPushName(0);
+ glBegin(GL_LINES);
+ glArrayElement(ring->len - 1);
+ glArrayElement(0);
+ glEnd();
+ for (i=1; i < ring->len; ++i)
+ {
+ glLoadName(i);
+ glBegin(GL_LINES);
+ glArrayElement(i-1);
+ glArrayElement(i);
+ glEnd();
+ }
+ glPopName(); /* node id */
+ }
+ glPopName(); /* ring id */
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_area_layer_delete_selected(GvAreaLayer *layer)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_areas_delete_areas(layer->data, sel->len, (gint*)sel->data);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_area_layer_translate_selected(GvAreaLayer *layer, GvVertex *delta)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_areas_translate_areas(layer->data, sel->len, (gint*)sel->data,
+ delta->x, delta->y);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_area_layer_get_node(GvAreaLayer *layer, GvNodeInfo *info)
+{
+ info->vertex = gv_areas_get_node(layer->data, info->shape_id,
+ info->ring_id, info->node_id);
+}
+
+static void
+gv_area_layer_move_node(GvAreaLayer *layer, GvNodeInfo *info)
+{
+ gv_areas_move_node(layer->data, info->shape_id, info->ring_id,
+ info->node_id, info->vertex);
+}
+
+static void
+gv_area_layer_insert_node(GvAreaLayer *layer, GvNodeInfo *info)
+{
+ gv_areas_insert_nodes(layer->data, info->shape_id, info->ring_id,
+ info->node_id, 1, info->vertex);
+}
+
+static void
+gv_area_layer_delete_node(GvAreaLayer *layer, GvNodeInfo *info)
+{
+ gv_areas_clear_fill(layer->data, info->shape_id);
+ gv_areas_delete_nodes(layer->data, info->shape_id, info->ring_id,
+ 1, &info->node_id);
+}
+
+static void
+gv_area_layer_node_motion(GvAreaLayer *layer, gint area_id)
+{
+ gv_areas_clear_fill(layer->data, area_id);
+}
+
+static void
+gv_area_layer_extents(GvAreaLayer *layer, GvRect *rect)
+{
+ gv_areas_get_extents(layer->data, rect);
+}
+
+static void
+gv_area_layer_data_change(GvAreaLayer *layer, gpointer change_info)
+{
+ /* Reset the selected array to reflect the data length */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_areas_num_areas(layer->data));
+}
Added: packages/openev/branches/upstream/current/gvarealayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvarealayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvarealayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,68 @@
+/******************************************************************************
+ * $Id: gvarealayer.h,v 1.4 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer of GvAreas.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvarealayer.h,v $
+ * Revision 1.4 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_AREA_LAYER_H__
+#define __GV_AREA_LAYER_H__
+
+#include "gvshapelayer.h"
+#include "gvareas.h"
+
+#define GV_TYPE_AREA_LAYER (gv_area_layer_get_type ())
+#define GV_AREA_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_AREA_LAYER, GvAreaLayer))
+#define GV_AREA_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_AREA_LAYER, GvAreaLayerClass))
+#define GV_IS_AREA_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_AREA_LAYER))
+#define GV_IS_AREA_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_AREA_LAYER))
+
+typedef struct _GvAreaLayer GvAreaLayer;
+typedef struct _GvAreaLayerClass GvAreaLayerClass;
+
+struct _GvAreaLayer
+{
+ GvShapeLayer shape_layer;
+
+ GvAreas *data;
+ gint edit_ring;
+};
+
+struct _GvAreaLayerClass
+{
+ GvShapeLayerClass parent_class;
+};
+
+GtkType gv_area_layer_get_type(void);
+GtkObject* gv_area_layer_new(GvAreas *data);
+
+gint gv_area_layer_select_new_area(GvAreaLayer *layer);
+gint gv_area_layer_select_new_ring(GvAreaLayer *layer, gint area_id);
+void gv_area_layer_edit_done(GvAreaLayer *layer);
+
+#endif /* __GV_AREA_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvareas.c
===================================================================
--- packages/openev/branches/upstream/current/gvareas.c (rev 0)
+++ packages/openev/branches/upstream/current/gvareas.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,744 @@
+/******************************************************************************
+ * $Id: gvareas.c,v 1.15 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Data container of areas (superceeded by GvShapes-will be removed)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvareas.c,v $
+ * Revision 1.15 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.14 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gextra.h"
+#include "gvareas.h"
+#include "gvtess.h"
+
+typedef struct _GvAreasMemento GvAreasMemento;
+
+struct _GvAreasMemento
+{
+ GvDataMemento base;
+ GArray *area_ids;
+ GPtrArray *areas;
+};
+
+static void gv_areas_class_init(GvAreasClass *klass);
+static void gv_areas_init(GvAreas *pgdata);
+static void gv_areas_replace_areas(GvAreas *areas, gint num_areas, gint *area_id, GvArea **area);
+static void gv_areas_insert_areas(GvAreas *areas, gint num_areas, gint *area_ids, GvArea **area);
+static void gv_areas_get_memento(GvData *data, gpointer info, GvDataMemento **memento);
+static void gv_areas_set_memento(GvData *data, GvDataMemento *memento);
+static void gv_areas_del_memento(GvData *data, GvDataMemento *memento);
+static void gv_areas_changed(GvData *data, gpointer change_info);
+static void gv_areas_finalize(GtkObject *object);
+
+GtkType
+gv_areas_get_type(void)
+{
+ static GtkType areas_type = 0;
+
+ if (!areas_type)
+ {
+ static const GtkTypeInfo areas_info =
+ {
+ "GvAreas",
+ sizeof(GvAreas),
+ sizeof(GvAreasClass),
+ (GtkClassInitFunc) gv_areas_class_init,
+ (GtkObjectInitFunc) gv_areas_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ areas_type = gtk_type_unique(gv_data_get_type(), &areas_info);
+ }
+ return areas_type;
+}
+
+static void
+gv_areas_init(GvAreas *areas)
+{
+ areas->areas = g_ptr_array_new();
+ areas->extents_valid = FALSE;
+}
+
+static void
+gv_areas_class_init(GvAreasClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+ data_class = (GvDataClass*) klass;
+
+ object_class->finalize = gv_areas_finalize;
+
+ data_class->changed = gv_areas_changed;
+ data_class->get_memento = gv_areas_get_memento;
+ data_class->set_memento = gv_areas_set_memento;
+ data_class->del_memento = gv_areas_del_memento;
+}
+
+GvData *
+gv_areas_new(void)
+{
+ return GV_DATA(gtk_type_new(gv_areas_get_type()));
+}
+
+gint
+gv_areas_new_area(GvAreas *areas)
+{
+ return gv_areas_new_area_with_data(areas, NULL);
+}
+
+gint
+gv_areas_new_area_with_data(GvAreas *areas, GvArea *area_data)
+{
+ GvArea *area;
+ int area_id;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ area_id = areas->areas->len;
+ if (area_data)
+ {
+ area = gv_area_copy(area_data);
+ }
+ else
+ {
+ area = gv_area_new(TRUE);
+ }
+ g_return_val_if_fail(area, 0);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ g_ptr_array_add(areas->areas, area);
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+
+ /* Generate tesselation if necessary */
+ if (area_data)
+ {
+ gv_areas_tessellate_areas(areas, 1, &area_id);
+ }
+
+ return area_id;
+}
+
+void
+gv_areas_delete_areas(GvAreas *areas, gint num_areas, gint *area_id)
+{
+ GvArea *area;
+ GvShapeChangeInfo change_info = {GV_CHANGE_DELETE, 0, NULL};
+
+ change_info.num_shapes = num_areas;
+ change_info.shape_id = area_id;
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ if (num_areas == 1)
+ {
+ area = (GvArea*)g_ptr_array_remove_index_fast(areas->areas, *area_id);
+ if (area) gv_area_delete(area);
+ }
+ else
+ {
+ /* Strategy: sort the area_id buffer and delete lines in descending
+ order, so that indicies remain valid */
+ gint *id, i;
+
+ id = g_memdup_type(area_id, gint, num_areas);
+ g_sort_type(id, gint, num_areas);
+
+ for (i=num_areas-1; i >= 0; --i)
+ {
+ area = (GvArea*)g_ptr_array_remove_index_fast(areas->areas, id[i]);
+ if (area) gv_area_delete(area);
+ }
+ g_free(id);
+ }
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+void
+gv_areas_translate_areas(GvAreas *areas, gint num_areas, gint *area_id,
+ gvgeocoord dx, gvgeocoord dy)
+{
+ int i, j, k;
+ GArray *ring;
+ GvArea *area;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_areas;
+ change_info.shape_id = area_id;
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ for (k=0; k < num_areas; ++k)
+ {
+ g_return_if_fail(area_id[k] >= 0 && area_id[k] < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id[k]);
+
+ for (i=0; i < area->rings->len; ++i)
+ {
+ ring = gv_areas_get_ring(area, i);
+ for (j=0; j < ring->len; ++j)
+ {
+ g_array_index(ring, GvVertex, j).x += dx;
+ g_array_index(ring, GvVertex, j).y += dy;
+ }
+ }
+
+ if (area->fill_objects > 0)
+ {
+ for (i=0; i < area->fill->len; ++i)
+ {
+ g_array_index(area->fill, GvVertex, i).x += dx;
+ g_array_index(area->fill, GvVertex, i).y += dy;
+ }
+ }
+ }
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+gint
+gv_areas_new_ring(GvAreas *areas, gint area_id)
+{
+ GArray *ring;
+ GvArea *area;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ g_return_val_if_fail(area_id >= 0 && area_id < areas->areas->len, 0);
+ area = gv_areas_get_area(areas, area_id);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ ring = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_ptr_array_add(area->rings, ring);
+
+ gv_areas_clear_fill(areas, area_id);
+ area->fill_objects = -1;
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+
+ return area->rings->len - 1;
+}
+
+void
+gv_areas_delete_ring(GvAreas *areas, gint area_id, gint ring_id)
+{
+ GvArea *area;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ /* Can't delete ring 0 (outer ring) */
+ g_return_if_fail(ring_id > 0);
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ g_ptr_array_remove_index(area->rings, ring_id);
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+void
+gv_areas_append_nodes(GvAreas *areas, gint area_id, gint ring_id,
+ gint num_nodes, GvVertex *vertex)
+{
+ GvArea *area;
+ GArray *ring;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+ g_return_if_fail(ring_id >= 0 && ring_id < area->rings->len);
+ ring = gv_areas_get_ring(area, ring_id);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ g_array_append_vals(ring, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+GvVertex *
+gv_areas_get_node(GvAreas *areas, gint area_id, gint ring_id, gint node_id)
+{
+ GvArea *area;
+ GArray *ring;
+
+ g_return_val_if_fail(area_id >= 0 && area_id < areas->areas->len, NULL);
+ area = gv_areas_get_area(areas, area_id);
+ g_return_val_if_fail(ring_id >= 0 && ring_id < area->rings->len, NULL);
+ ring = gv_areas_get_ring(area, ring_id);
+ g_return_val_if_fail(node_id >= 0 && node_id < ring->len, NULL);
+
+ return &g_array_index(ring, GvVertex, node_id);
+}
+
+void
+gv_areas_move_node(GvAreas *areas, gint area_id, gint ring_id, gint node_id,
+ GvVertex *vertex)
+{
+ GvArea *area;
+ GArray *ring;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+ g_return_if_fail(ring_id >= 0 && ring_id < area->rings->len);
+ ring = gv_areas_get_ring(area, ring_id);
+ g_return_if_fail(node_id >= 0 && node_id < ring->len);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ g_array_index(ring, GvVertex, node_id).x = vertex->x;
+ g_array_index(ring, GvVertex, node_id).y = vertex->y;
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+void
+gv_areas_insert_nodes(GvAreas *areas, gint area_id, gint ring_id,
+ gint node_id, gint num_nodes, GvVertex *vertex)
+{
+ GvArea *area;
+ GArray *ring;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+ g_return_if_fail(ring_id >= 0 && ring_id < area->rings->len);
+ ring = gv_areas_get_ring(area, ring_id);
+ g_return_if_fail(node_id >= 0 && node_id < ring->len);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ g_array_insert_vals(ring, node_id, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+void
+gv_areas_delete_nodes(GvAreas *areas, gint area_id, gint ring_id,
+ gint num_nodes, gint *node_id)
+{
+ GvArea *area;
+ GArray *ring;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &area_id;
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+ g_return_if_fail(ring_id >= 0 && ring_id < area->rings->len);
+ ring = gv_areas_get_ring(area, ring_id);
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ if (num_nodes == 1)
+ {
+ /* Need to preserve node order, so we can't use *_remove_fast */
+ g_array_remove_index(ring, *node_id);
+ }
+ else
+ {
+ /* Strategy: sort the node_id buffer and delete nodes in desending
+ order, so that indicies remain valid */
+ gint *id, i;
+
+ id = g_memdup_type(node_id, gint, num_nodes);
+ g_sort_type(id, gint, num_nodes);
+
+ for (i=num_nodes-1; i >= 0; --i)
+ {
+ g_array_remove_index(ring, id[i]);
+ }
+ g_free(id);
+ }
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+gint
+gv_areas_tessellate_areas(GvAreas *areas, gint num_areas, gint *area_id)
+{
+ gint i, hit, ok;
+ GvArea *area;
+
+ hit = FALSE;
+ ok = TRUE;
+
+ for (i=0; i < num_areas; ++i)
+ {
+ area = gv_areas_get_area(areas, area_id[i]);
+ if (area->fill_objects == 0)
+ {
+ if (!gv_area_tessellate(area)) ok = FALSE;
+ hit = TRUE;
+ }
+ }
+
+ if (hit)
+ {
+ /* FIXME: need a change_info param which describes a
+ tesselation change. For now use NULL */
+ gv_data_changed(GV_DATA(areas), NULL);
+ }
+
+ return ok;
+}
+
+void
+gv_areas_clear_fill(GvAreas *areas, gint area_id)
+{
+ GvArea *area;
+
+ g_return_if_fail(area_id >= 0 && area_id < areas->areas->len);
+ area = gv_areas_get_area(areas, area_id);
+ area->fill_objects = 0;
+ if (area->mode_offset) g_array_set_size(area->mode_offset, 0);
+ if (area->fill) g_array_set_size(area->fill, 0);
+}
+
+void
+gv_areas_get_extents(GvAreas *areas, GvRect *rect)
+{
+ if (!areas->extents_valid)
+ {
+ gint i, j, num_areas;
+ GvArea *area;
+ GArray *ring = NULL;
+ GvVertex vmax, vmin, *v;
+
+ vmin.x = vmin.y = GV_MAXFLOAT;
+ vmax.x = vmax.y = -GV_MAXFLOAT;
+ num_areas = gv_areas_num_areas(areas);
+ for (i=0; i < num_areas; ++i)
+ {
+ area = gv_areas_get_area(areas, i);
+ ring = gv_areas_get_ring(area, 0);
+ for (j = 0; j < ring->len; ++j)
+ {
+ v = &g_array_index(ring, GvVertex, j);
+ if (v->x < vmin.x) vmin.x = v->x;
+ if (v->x > vmax.x) vmax.x = v->x;
+ if (v->y < vmin.y) vmin.y = v->y;
+ if (v->y > vmax.y) vmax.y = v->y;
+ }
+ }
+ if (num_areas == 0 || (num_areas == 1 && ring->len == 0))
+ {
+ areas->extents.x = 0;
+ areas->extents.y = 0;
+ areas->extents.width = 0;
+ areas->extents.height = 0;
+ }
+ else
+ {
+ areas->extents.x = vmin.x;
+ areas->extents.y = vmin.y;
+ areas->extents.width = vmax.x - vmin.x;
+ areas->extents.height = vmax.y - vmin.y;
+ }
+ areas->extents_valid = TRUE;
+ }
+ rect->x = areas->extents.x;
+ rect->y = areas->extents.y;
+ rect->width = areas->extents.width;
+ rect->height = areas->extents.height;
+}
+
+/***************************************************/
+
+GvArea *
+gv_area_new(gint alloc_outer_ring)
+{
+ GvArea *area;
+
+ area = g_new(GvArea, 1);
+ g_return_val_if_fail(area, NULL);
+
+ area->rings = g_ptr_array_new();
+ g_return_val_if_fail(area->rings, NULL);
+
+ if (alloc_outer_ring)
+ {
+ /* New area is created with ring 0 (outer ring) allocated, but empty */
+ GArray *ring = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_return_val_if_fail(ring, NULL);
+ g_ptr_array_add(area->rings, ring);
+ }
+
+ area->fill_objects = -1;
+ area->mode_offset = NULL;
+ area->fill = NULL;
+
+ return area;
+}
+
+GvArea *
+gv_area_copy(GvArea *area)
+{
+ GvArea *copyarea;
+ GArray *ring, *copyring;
+ gint rings, i;
+
+ copyarea = g_new(GvArea, 1);
+ g_return_val_if_fail(copyarea, NULL);
+
+ copyarea->rings = g_ptr_array_new();
+ g_return_val_if_fail(copyarea->rings, NULL);
+
+ rings = gv_areas_num_rings(area);
+ for (i=0; i < rings; ++i)
+ {
+ copyring = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_ptr_array_add(copyarea->rings, copyring);
+
+ ring = gv_areas_get_ring(area, i);
+ g_array_append_vals(copyring, ring->data, ring->len);
+ }
+
+ /* Don't bother to copy tessellation info, as this can be regenerated */
+ copyarea->fill_objects = 0;
+ copyarea->mode_offset = NULL;
+ copyarea->fill = NULL;
+
+ return copyarea;
+}
+
+void
+gv_area_delete(GvArea *area)
+{
+ int i;
+
+ for (i=0; i < area->rings->len; ++i)
+ {
+ g_array_free(gv_areas_get_ring(area, i), TRUE);
+ }
+ g_ptr_array_free(area->rings, TRUE);
+
+ if (area->fill)
+ {
+ g_array_free(area->fill, TRUE);
+ }
+
+ if (area->mode_offset)
+ {
+ g_array_free(area->mode_offset, TRUE);
+ }
+
+ g_free(area);
+}
+
+/***************************************************/
+
+static void
+gv_areas_replace_areas(GvAreas *areas, gint num_areas, gint *area_id,
+ GvArea **area)
+{
+ int i;
+
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_areas;
+ change_info.shape_id = area_id;
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ for (i=0; i < num_areas; ++i)
+ {
+ gv_area_delete(gv_areas_get_area(areas, area_id[i]));
+ g_ptr_array_index(areas->areas, area_id[i]) = area[i];
+ }
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+static void
+gv_areas_insert_areas(GvAreas *areas, gint num_areas, gint *area_ids,
+ GvArea **area)
+{
+ /* The area_id array must be in ascending order! */
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 0, NULL};
+
+ change_info.num_shapes = num_areas;
+ change_info.shape_id = area_ids;
+
+ gv_data_changing(GV_DATA(areas), &change_info);
+
+ for (i=0; i < num_areas; ++i)
+ {
+ g_ptr_array_insert_fast(areas->areas, area_ids[i], area[i]);
+ }
+
+ gv_data_changed(GV_DATA(areas), &change_info);
+}
+
+static void
+gv_areas_get_memento(GvData *data, gpointer change_info,
+ GvDataMemento **memento)
+{
+ GvAreas *areas = GV_AREAS(data);
+ GvShapeChangeInfo *info = (GvShapeChangeInfo *) change_info;
+ GvAreasMemento *mem;
+ int i;
+
+ mem = g_new(GvAreasMemento, 1);
+ mem->base.data = data;
+ mem->base.type = info->change_type;
+
+ mem->area_ids = g_array_new(FALSE, FALSE, sizeof(gint));
+ g_array_append_vals(mem->area_ids, info->shape_id, info->num_shapes);
+
+ /* Grab areas in ascending order */
+ if (info->num_shapes > 1)
+ {
+ g_sort_type(mem->area_ids->data, gint, mem->area_ids->len);
+ }
+
+ if (info->change_type == GV_CHANGE_ADD)
+ {
+ mem->areas = NULL;
+ }
+ else
+ {
+ mem->areas = g_ptr_array_new();
+ for (i=0; i < info->num_shapes; ++i)
+ {
+ GvArea *area = gv_area_copy(gv_areas_get_area(areas,
+ info->shape_id[i]));
+ g_ptr_array_add(mem->areas, area);
+ }
+ }
+
+ *memento = (GvDataMemento*)mem;
+}
+
+static void
+gv_areas_set_memento(GvData *data, GvDataMemento *data_memento)
+{
+ GvAreasMemento *memento = (GvAreasMemento *) data_memento;
+ GvAreas *areas = GV_AREAS(data);
+
+ switch (memento->base.type)
+ {
+ case GV_CHANGE_ADD:
+ gv_areas_delete_areas(areas, memento->area_ids->len,
+ (gint*)memento->area_ids->data);
+ break;
+
+ case GV_CHANGE_REPLACE:
+ gv_areas_replace_areas(areas, memento->area_ids->len,
+ (gint*)memento->area_ids->data,
+ (GvArea**)memento->areas->pdata);
+ break;
+
+ case GV_CHANGE_DELETE:
+ gv_areas_insert_areas(areas, memento->area_ids->len,
+ (gint*)memento->area_ids->data,
+ (GvArea**)memento->areas->pdata);
+ break;
+ }
+
+ if (memento->areas)
+ {
+ g_ptr_array_free(memento->areas, TRUE);
+ memento->areas = NULL;
+ }
+ gv_areas_del_memento(GV_DATA(areas), (GvDataMemento *) memento);
+}
+
+static void
+gv_areas_del_memento(GvData *data, GvDataMemento *data_memento)
+{
+ GvAreasMemento *memento = (GvAreasMemento *) data_memento;
+ int i;
+
+ if (memento->areas)
+ {
+ for (i=0; i < memento->areas->len; ++i)
+ {
+ gv_area_delete(g_ptr_array_index(memento->areas, i));
+ }
+ g_ptr_array_free(memento->areas, TRUE);
+ }
+ g_array_free(memento->area_ids, TRUE);
+ g_free(memento);
+}
+
+static void
+gv_areas_changed(GvData *data, gpointer change_info)
+{
+ GvAreas *areas = GV_AREAS(data);
+ GvShapeChangeInfo *info = (GvShapeChangeInfo *) change_info;
+
+ /* NULL info indicates change due to tesselation: ignore */
+ if (info && info->change_type == GV_CHANGE_REPLACE)
+ {
+ /* Retesselate changed areas if necessary */
+ gv_areas_tessellate_areas(areas, info->num_shapes, info->shape_id);
+ }
+ areas->extents_valid = FALSE;
+}
+
+static void
+gv_areas_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvAreas *areas;
+ int i;
+
+ areas = GV_AREAS(object);
+
+ for (i=0; i < gv_areas_num_areas(areas); i++)
+ {
+ gv_area_delete(gv_areas_get_area(areas, i));
+ }
+ g_ptr_array_free(areas->areas, TRUE);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
Added: packages/openev/branches/upstream/current/gvareas.h
===================================================================
--- packages/openev/branches/upstream/current/gvareas.h (rev 0)
+++ packages/openev/branches/upstream/current/gvareas.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,107 @@
+/******************************************************************************
+ * $Id: gvareas.h,v 1.11 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Data container of areas (superceeded by GvShapes-will be removed)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvareas.h,v $
+ * Revision 1.11 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.10 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_AREAS_H__
+#define __GV_AREAS_H__
+
+#include "gvdata.h"
+
+#define GV_TYPE_AREAS (gv_areas_get_type ())
+#define GV_AREAS(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_AREAS, GvAreas))
+#define GV_AREAS_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_AREAS, GvAreasClass))
+#define GV_IS_AREAS(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_AREAS))
+#define GV_IS_AREAS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_AREAS))
+
+typedef struct _GvArea GvArea;
+typedef struct _GvAreas GvAreas;
+typedef struct _GvAreasClass GvAreasClass;
+
+struct _GvArea
+{
+ GPtrArray *rings;
+ gint fill_objects;
+ GArray *mode_offset;
+ GArray *fill;
+};
+
+struct _GvAreas
+{
+ GvData data;
+
+ GPtrArray *areas;
+ GvRect extents;
+ guint extents_valid : 1;
+};
+
+struct _GvAreasClass
+{
+ GvDataClass parent_class;
+};
+
+GvArea* gv_area_new(gint alloc_outer_ring);
+GvArea* gv_area_copy(GvArea *area);
+void gv_area_delete(GvArea *area);
+
+GtkType gv_areas_get_type (void);
+
+GvData* gv_areas_new(void);
+gint gv_areas_new_area(GvAreas *areas);
+gint gv_areas_new_area_with_data(GvAreas *areas, GvArea *area_data);
+
+void gv_areas_delete_areas(GvAreas *areas, gint num_areas, gint *area_id);
+void gv_areas_translate_areas(GvAreas *areas, gint num_areas, gint *area_id, gvgeocoord dx, gvgeocoord dy);
+
+gint gv_areas_new_ring(GvAreas *areas, gint area_id);
+void gv_areas_delete_ring(GvAreas *areas, gint area_id, gint ring_id);
+void gv_areas_append_nodes(GvAreas *areas, gint area_id, gint ring_id, gint num_nodes, GvVertex *vertex);
+GvVertex* gv_areas_get_node(GvAreas *areas, gint area_id, gint ring_id, gint node_id);
+void gv_areas_move_node(GvAreas *areas, gint area_id, gint ring_id, gint node_id, GvVertex *vertex);
+void gv_areas_insert_nodes(GvAreas *areas, gint area_id, gint ring_id, gint node_id, gint num_nodes, GvVertex *vertex);
+void gv_areas_delete_nodes(GvAreas *areas, gint area_id, gint ring_id, gint num_nodes, gint *node_id);
+
+gint gv_areas_tessellate_areas(GvAreas *areas, gint num_areas, gint *area_id);
+void gv_areas_clear_fill(GvAreas *areas, gint area_id);
+void gv_areas_get_extents(GvAreas *areas, GvRect *rect);
+
+#define gv_areas_num_areas(adata) \
+ (adata->areas->len)
+#define gv_areas_get_area(adata,id) \
+ ((GvArea*)g_ptr_array_index(adata->areas, id))
+#define gv_areas_num_rings(area) \
+ (area->rings->len)
+#define gv_areas_get_ring(area,id) \
+ ((GArray*)g_ptr_array_index(area->rings, id))
+
+#endif /*__GV_AREAS_H__ */
Added: packages/openev/branches/upstream/current/gvareatool.c
===================================================================
--- packages/openev/branches/upstream/current/gvareatool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvareatool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,649 @@
+/******************************************************************************
+ * $Id: gvareatool.c,v 1.25 2004/10/28 21:59:52 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Area (Polygon) editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvareatool.c,v $
+ * Revision 1.25 2004/10/28 21:59:52 gmwalter
+ * Send a changed signal when editing finishes.
+ *
+ * Revision 1.24 2004/01/27 19:51:34 gmwalter
+ * Make sure memento pointers are set to NULL
+ * after being freed.
+ *
+ * Revision 1.23 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.22 2002/10/01 15:06:38 warmerda
+ * ensure old selection clear when selecting new object
+ *
+ * Revision 1.21 2002/09/30 13:24:54 warmerda
+ * ensure areas are closed properly
+ *
+ * Revision 1.20 2001/08/08 17:44:12 warmerda
+ * use gv_shape_type() macro
+ *
+ * Revision 1.19 2001/04/09 18:13:51 warmerda
+ * improved warning
+ *
+ * Revision 1.18 2000/08/10 15:47:35 warmerda
+ * fixed one-off undo quirk when adding rings to existing area
+ *
+ * Revision 1.17 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.16 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.15 2000/07/24 14:00:24 warmerda
+ * set_layer with NULL should be allowed
+ *
+ * Revision 1.14 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.13 2000/07/17 20:20:32 warmerda
+ * enable delete-last-vertex
+ *
+ * Revision 1.12 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtksignal.h>
+#include "gvareatool.h"
+#include "gvundo.h"
+#include "gvshapeslayer.h"
+#include <GL/gl.h>
+
+static void gv_area_tool_class_init(GvAreaToolClass *klass);
+static void gv_area_tool_init(GvAreaTool *tool);
+static void gv_area_tool_draw(GvAreaTool *tool);
+static void gv_area_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_area_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_area_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_area_tool_deactivate(GvTool *tool, GvViewArea *view);
+static void gv_area_tool_stop_drawing(GvAreaTool *tool);
+static gint gv_area_tool_configure(GvAreaTool *tool);
+
+GtkType
+gv_area_tool_get_type(void)
+{
+ static GtkType area_tool_type = 0;
+
+ if (!area_tool_type)
+ {
+ static const GtkTypeInfo area_tool_info =
+ {
+ "GvAreaTool",
+ sizeof(GvAreaTool),
+ sizeof(GvAreaToolClass),
+ (GtkClassInitFunc) gv_area_tool_class_init,
+ (GtkObjectInitFunc) gv_area_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ area_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &area_tool_info);
+ }
+ return area_tool_type;
+}
+
+static void
+gv_area_tool_class_init(GvAreaToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_area_tool_deactivate;
+ tool_class->button_press = gv_area_tool_button_press;
+ tool_class->motion_notify = gv_area_tool_motion_notify;
+ tool_class->key_press = gv_area_tool_key_press;
+}
+
+static void
+gv_area_tool_init(GvAreaTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->layer = NULL;
+ tool->named_layer = NULL;
+ tool->drawing = FALSE;
+ tool->ring_id = 0;
+ tool->memento = NULL;
+}
+
+GvTool *
+gv_area_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_AREA_TOOL));
+}
+
+static gint gv_area_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvAreaTool *tool = (GvAreaTool *) data;
+
+ if( tool->layer == GV_SHAPE_LAYER(layer) )
+ gv_area_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_area_tool_set_layer(GvAreaTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_area_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_area_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ if (tool->drawing)
+ {
+ gv_area_tool_stop_drawing(tool);
+ }
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+
+ tool->layer = layer;
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_area_tool_draw),
+ GTK_OBJECT(tool));
+
+ /* recover if layer destroyed */
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_area_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+void
+gv_area_tool_set_named_layer(GvAreaTool *tool, gchar *name)
+{
+ if (tool->named_layer)
+ {
+ g_free(tool->named_layer);
+ tool->named_layer = NULL;
+ }
+ if (name)
+ {
+ tool->named_layer = g_strdup(name);
+ }
+ /* Tool layer will be updated next time it is configured */
+}
+
+static void
+gv_area_tool_draw(GvAreaTool *tool)
+{
+ if (tool->drawing)
+ {
+ /* Color is set when the layer is drawn,
+ so we don't need to repeat it here */
+
+ glBegin(GL_LINES);
+ glVertex2v((GLgeocoord*)&tool->v_head);
+ glVertex2v((GLgeocoord*)&tool->v_tail);
+ glEnd();
+ }
+}
+
+static void
+gv_area_tool_button_press(GvTool *rtool, GdkEventButton *event)
+{
+ GvAreaTool *tool = GV_AREA_TOOL(rtool);
+
+ /* ignore control corded buttons -- these are for zooming and panning */
+ if( event->state & GDK_CONTROL_MASK )
+ return;
+
+ if (event->button == 1)
+ {
+ gint area_id = -1;
+
+ if (!gv_area_tool_configure(tool)) return;
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ if (tool->drawing)
+ {
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ /* Filter out duplicate verticies */
+ if (tool->v_head.x == tool->v_tail.x &&
+ tool->v_head.y == tool->v_tail.y)
+ {
+ return;
+ }
+
+ /* Add a new vertex to the area */
+ gv_shape_layer_selected(GV_SHAPE_LAYER(tool->layer), GV_FIRST,
+ &area_id);
+ if( area_id == -1 )
+ {
+ g_warning( "gv_area_tool_button_press: get selection failed.");
+ return;
+ }
+ }
+ else
+ {
+ if( !gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_tail.x, tool->v_tail.y ) )
+ return;
+
+ /* Start a new ring */
+ tool->drawing = TRUE;
+
+ /* Close down undo. We don't want undos pushed for each vertex */
+ gv_undo_close();
+ gv_undo_disable();
+
+ /* If the first click is inside an existing area,
+ start a hole ring */
+ if (gv_shape_layer_pick_shape(GV_SHAPE_LAYER(tool->layer),
+ GV_TOOL(tool)->view,
+ event->x, event->y, &area_id))
+ {
+ if( GV_IS_AREA_LAYER(tool->layer) )
+ tool->ring_id =
+ gv_area_layer_select_new_ring(
+ GV_AREA_LAYER(tool->layer), area_id);
+ else
+ {
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE,1,NULL};
+
+ GvShape *area;
+ GvShapes *shapes;
+
+ gv_shape_layer_clear_selection(
+ GV_SHAPE_LAYER(tool->layer));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(tool->layer),
+ area_id);
+
+ shapes = GV_SHAPES_LAYER(tool->layer)->data;
+ area = gv_shapes_get_shape( shapes, area_id );
+ tool->ring_id = gv_shape_get_rings( area );
+
+ /* force a changing() signal for the shape */
+ area = gv_shape_copy(area);
+ gv_shapes_replace_shapes( shapes, 1, &area_id, &area,
+ FALSE );
+
+ change_info.shape_id = &area_id;
+ if( tool->memento != NULL )
+ gv_data_del_memento( GV_DATA(shapes), tool->memento );
+ tool->memento = gv_data_get_memento( GV_DATA(shapes),
+ &change_info );
+ }
+ }
+ else
+ {
+ /* Start a new area */
+ if( GV_IS_AREA_LAYER(tool->layer) )
+ {
+ area_id = gv_area_layer_select_new_area(
+ GV_AREA_LAYER(tool->layer));
+ tool->ring_id = 0;
+ }
+ else
+ {
+ GvShape *area = gv_shape_new( GVSHAPE_AREA );
+
+ area_id = gv_shapes_layer_select_new_shape(
+ GV_SHAPES_LAYER(tool->layer), area );
+ tool->ring_id = 0;
+ }
+ }
+ }
+
+ tool->v_head = tool->v_tail;
+ if( GV_IS_AREA_LAYER(tool->layer) )
+ gv_areas_append_nodes(GV_AREA_LAYER(tool->layer)->data, area_id,
+ tool->ring_id, 1, &tool->v_tail);
+ else
+ {
+ GvShapes *shapes = GV_SHAPES_LAYER(tool->layer)->data;
+ GvShape *area = gv_shapes_get_shape(shapes, area_id );
+
+ if( gv_shape_type(area) == GVSHAPE_AREA )
+ {
+ gv_shape_add_node(area, tool->ring_id,
+ tool->v_tail.x, tool->v_tail.y, 0);
+ ((GvAreaShape *) area)->fill_objects = -2;
+ }
+ else
+ g_warning( "selected object not area in gvareatool mode!\n" );
+ }
+ }
+ else if (event->button == 3 && tool->drawing)
+ {
+ gv_area_tool_stop_drawing(tool);
+ }
+}
+
+static void
+gv_area_tool_motion_notify(GvTool *rtool, GdkEventMotion *event)
+{
+ GvAreaTool *tool = GV_AREA_TOOL(rtool);
+
+ if (tool->drawing)
+ {
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_area_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvAreaTool *tool = GV_AREA_TOOL(rtool);
+
+ if (!gv_area_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ if( tool->drawing && !GV_IS_AREA_LAYER(tool->layer) )
+ {
+ gint line_id;
+ GvNodeInfo node_info;
+ GvShape *shape;
+ GvShapes *shapes = GV_SHAPES_LAYER(tool->layer)->data;
+
+ gv_shape_layer_selected(GV_SHAPE_LAYER(tool->layer), GV_FIRST,
+ &line_id);
+
+ shape = gv_shapes_get_shape( shapes, line_id );
+
+ node_info.shape_id = line_id;
+ node_info.ring_id = MAX(0,gv_shape_get_rings(shape) - 1);
+ node_info.node_id = gv_shape_get_nodes( shape,
+ node_info.ring_id) - 1;
+
+ if( gv_shape_get_nodes( shape, node_info.ring_id ) > 1 )
+ {
+ tool->v_head.x = gv_shape_get_x( shape,
+ node_info.ring_id,
+ node_info.node_id-1);
+ tool->v_head.y = gv_shape_get_y( shape,
+ node_info.ring_id,
+ node_info.node_id-1);
+ }
+ else
+ {
+ tool->drawing = FALSE;
+ }
+
+ gv_shape_layer_delete_node(tool->layer, &node_info );
+
+
+ if( !tool->drawing )
+ gv_area_tool_stop_drawing( tool );
+ else
+ {
+ shape = gv_shapes_get_shape( shapes, line_id );
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_AREA )
+ ((GvAreaShape *) shape)->fill_objects = -2;
+ }
+ }
+ break;
+ }
+}
+
+static void
+gv_area_tool_deactivate(GvTool *rtool, GvViewArea *view)
+{
+ GvAreaTool *tool = GV_AREA_TOOL(rtool);
+
+ /* Disconnect from layer */
+ if (tool->layer)
+ {
+ gv_area_tool_set_layer(tool, NULL);
+ }
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static void
+gv_area_tool_stop_drawing(GvAreaTool *tool)
+{
+ gint sel, push_undo = TRUE;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ if( GV_IS_AREA_LAYER(tool->layer) )
+ {
+ GvAreaLayer *alayer = GV_AREA_LAYER(tool->layer);
+
+ change_info.shape_id = &sel;
+
+ tool->drawing = FALSE;
+ gv_area_layer_edit_done(alayer);
+
+ gv_shape_layer_selected(GV_SHAPE_LAYER(alayer), GV_FIRST, &sel);
+ gv_areas_clear_fill(alayer->data, sel);
+ if (!gv_areas_tessellate_areas(alayer->data, 1, &sel))
+ {
+ g_warning("Invalid area drawn");
+ if(tool->ring_id != 0 )
+ {
+ gv_areas_delete_ring(alayer->data,sel,tool->ring_id);
+ gv_areas_clear_fill(alayer->data, sel);
+ gv_areas_tessellate_areas(alayer->data, 1, &sel);
+ }
+ else
+ {
+ gv_shape_layer_delete_selected(GV_SHAPE_LAYER(alayer));
+ }
+ push_undo = FALSE;
+ }
+
+ /* Reopen undo. Push a memento describing the ring addition */
+ gv_undo_enable();
+ gv_undo_open();
+ if (push_undo)
+ {
+ if (tool->ring_id > 0)
+ {
+ if( tool->memento != NULL )
+ {
+ gv_undo_push(tool->memento);
+ tool->memento = NULL;
+ }
+ }
+ else
+ {
+ gv_undo_push(gv_data_get_memento(GV_DATA(alayer->data),
+ &change_info));
+ }
+ }
+
+ if( tool->memento != NULL )
+ {
+ gv_data_del_memento( GV_DATA(alayer->data), tool->memento );
+ tool->memento = NULL;
+ }
+ }
+ else /* GV_IS_SHAPES_LAYER(tool->layer) */
+ {
+ GvShapesLayer *slayer = GV_SHAPES_LAYER(tool->layer);
+ GvShapes *shapes = slayer->data;
+ GvAreaShape *area;
+ GvShapeChangeInfo sent_change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &sel;
+
+ tool->drawing = FALSE;
+
+ if( gv_shape_layer_selected(GV_SHAPE_LAYER(slayer), GV_FIRST, &sel) )
+ area = (GvAreaShape *) gv_shapes_get_shape(shapes, sel);
+ else
+ area = NULL;
+
+ if( area != NULL && gv_shape_type(area) == GVSHAPE_AREA )
+ {
+ GvShape *shape = (GvShape *) area;
+ int vert_count = gv_shape_get_nodes( shape, tool->ring_id );
+ /* If the ring isn't properly closed, do now. */
+ if( gv_shape_get_x( shape, tool->ring_id, 0 )
+ != gv_shape_get_x( shape, tool->ring_id, vert_count-1 )
+ || gv_shape_get_y( shape, tool->ring_id, 0 )
+ != gv_shape_get_y( shape, tool->ring_id, vert_count-1 )
+ || gv_shape_get_z( shape, tool->ring_id, 0 )
+ != gv_shape_get_z( shape, tool->ring_id, vert_count-1 ) )
+ {
+ gv_shape_add_node(shape, tool->ring_id,
+ gv_shape_get_x( shape, tool->ring_id, 0 ),
+ gv_shape_get_y( shape, tool->ring_id, 0 ),
+ gv_shape_get_z( shape, tool->ring_id, 0 ) );
+ }
+
+ area->fill_objects = -1;
+
+ if (!gv_area_shape_tessellate(area))
+ {
+ g_warning("Invalid area drawn");
+ if(tool->ring_id != 0 )
+ {
+ gv_shape_delete_ring((GvShape *) area,tool->ring_id);
+ gv_area_shape_tessellate(area);
+ }
+ else
+ {
+ gv_shape_layer_delete_selected(GV_SHAPE_LAYER(slayer));
+ }
+ push_undo = FALSE;
+ }
+
+ /* Reopen undo. Push a memento describing the ring addition */
+ gv_undo_enable();
+ gv_undo_open();
+ if (push_undo)
+ {
+ if (tool->ring_id > 0)
+ {
+ if( tool->memento != NULL )
+ {
+ gv_undo_push(tool->memento);
+ tool->memento = NULL;
+ }
+ }
+ else
+ {
+ gv_undo_push(gv_data_get_memento(GV_DATA(shapes),
+ &change_info));
+ }
+
+ /* Force a changed() signal for the finalized shape,
+ but send it as a "replace" signal, since "add"
+ was already sent if necessary when first node
+ was created. */
+ sent_change_info.shape_id = &sel;
+ gv_data_changed(GV_DATA(shapes), &sent_change_info);
+ }
+ }
+ else
+ {
+ gv_undo_enable();
+ gv_undo_open();
+ }
+
+ if( tool->memento != NULL )
+ {
+ gv_data_del_memento( GV_DATA(shapes), tool->memento );
+ tool->memento = NULL;
+ }
+
+ }
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+}
+
+static gint
+gv_area_tool_configure(GvAreaTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ if (tool->named_layer)
+ {
+ /* Look for named layer if given */
+ layer = gv_view_area_get_named_layer(GV_TOOL(tool)->view,
+ tool->named_layer);
+ }
+ else
+ {
+ /* Attempt to find a area layer to edit */
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_AREA_LAYER,
+ FALSE);
+ if( layer == NULL )
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPES_LAYER,
+ FALSE);
+ }
+ if (!layer)
+ {
+ g_warning("gv_area_tool_configure(): no editable area layer in view");
+ return FALSE;
+ }
+
+ gv_area_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+
+ return tool->layer != NULL;
+}
Added: packages/openev/branches/upstream/current/gvareatool.h
===================================================================
--- packages/openev/branches/upstream/current/gvareatool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvareatool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * $Id: gvareatool.h,v 1.7 2000/08/10 15:56:53 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Area (Polygon) editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvareatool.h,v $
+ * Revision 1.7 2000/08/10 15:56:53 warmerda
+ * added memento
+ *
+ * Revision 1.6 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_AREA_TOOL_H__
+#define __GV_AREA_TOOL_H__
+
+#include "gvtool.h"
+#include "gvarealayer.h"
+
+#define GV_TYPE_AREA_TOOL (gv_area_tool_get_type ())
+#define GV_AREA_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_AREA_TOOL, GvAreaTool))
+#define GV_AREA_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_AREA_TOOL, GvAreaToolClass))
+#define GV_IS_AREA_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_AREA_TOOL))
+#define GV_IS_AREA_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_AREA_TOOL))
+
+typedef struct _GvAreaTool GvAreaTool;
+typedef struct _GvAreaToolClass GvAreaToolClass;
+
+struct _GvAreaTool
+{
+ GvTool tool;
+
+ GvShapeLayer *layer;
+ gchar *named_layer;
+ guint drawing : 1;
+ gint ring_id;
+ GvVertex v_head, v_tail;
+ GvDataMemento *memento;
+};
+
+struct _GvAreaToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_area_tool_get_type(void);
+GvTool* gv_area_tool_new(void);
+void gv_area_tool_set_layer(GvAreaTool *tool, GvShapeLayer *layer);
+void gv_area_tool_set_named_layer(GvAreaTool *tool, gchar *name);
+
+#endif /* __GV_AREA_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvautopan.c
===================================================================
--- packages/openev/branches/upstream/current/gvautopan.c (rev 0)
+++ packages/openev/branches/upstream/current/gvautopan.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2416 @@
+/******************************************************************************
+ * $Id: gvautopan.c,v 1.3 2005/09/12 15:33:10 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Auto-panning tool. Scans systematically over an area or along
+ * a preset path.
+ * Author: Gillian Walter
+ *
+ * Developed by Atlantis Scientific Inc. (www.atlantis-scientific.com) for
+ * DRDC Ottawa.
+ *
+ ******************************************************************************
+ * Copyright (c) Her majesty the Queen in right of Canada as represented
+ * by the Minister of National Defence, 2004.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvautopan.c,v $
+ * Revision 1.3 2005/09/12 15:33:10 gmwalter
+ * Update autopan tool for line paths.
+ *
+ * Revision 1.2 2005/02/22 13:22:27 gmwalter
+ * Add autopan tool.
+ *
+ * Revision 1.1.2.9 2005/02/04 19:18:45 gmwalter
+ * Updated rectangle merging.
+ *
+ * Revision 1.1.2.8 2005/01/31 21:17:16 gmwalter
+ * First pass at merging rectangles.
+ *
+ * Revision 1.1.2.7 2005/01/29 04:01:11 gmwalter
+ * Initial support for autopan trail.
+ *
+ * Revision 1.1.2.6 2005/01/21 15:38:53 gmwalter
+ * Fix some problems with speed.
+ *
+ * Revision 1.1.2.5 2005/01/20 15:20:07 gmwalter
+ * Add ability to change standard path.
+ *
+ * Revision 1.1.2.4 2005/01/17 21:27:19 gmwalter
+ * Add ability to cope with raw/georef
+ * mismatch beteen main and secondary
+ * view.
+ *
+ * Revision 1.1.2.3 2005/01/05 21:22:22 gmwalter
+ * Updated autopan tool to add more functions.
+ *
+ * Revision 1.1.2.2 2004/12/21 15:10:26 gmwalter
+ * Add ability to relocate zoomed region by
+ * dragging in secondary view.
+ *
+ * Revision 1.1.2.1 2004/12/09 16:58:28 gmwalter
+ * Add initial autopan support.
+ *
+ *
+ *
+ */
+
+/* TODO:
+ * - If more than one overview is ever used and cache becomes a problem, may want
+ * to consider context-sharing textures instead of different textures for each
+ * secondary view. Might also want to consider resident textures, though not
+ * sure what this would do to the performance of the rest of the application...
+ * - need to test with main view in georef mode and overview window in pixel/line
+ * mode, and vice versa.
+ * - extension: reset high-res window zoom level from overview window (resize)
+ */
+
+/* Notes:
+ * - It should be possible to have more than one overview window, with trails, but
+ * this has never been tested, so likely bugs would need to be worked out if
+ * anyone actually tried this...
+ * - When overlap and boundaries are set, the tool will not follow them exactly
+ * because in order to have constant speed, it must step over regions of
+ * constant size. Boundaries and overlap are rounded to the nearest allowable
+ * increment. Likewise, with repositioning, zoom area will snap to the closest
+ * valid location.
+ *
+ * - Currently all translated locations (centers) are pre-calculated and stored
+ * in the "centers" array. This might occupy too much memory for large panning
+ * areas at high resolution. If this turns out to be the case, the
+ * compute_locations_and_zoom function should be replaced with a new function
+ * that gets called at every zoom iteration and avoids storage.
+ *
+ */
+
+#include "gvautopan.h"
+#include <gtk/gtksignal.h>
+#include <gtk/gtkmain.h>
+#include <stdio.h>
+#include <math.h>
+#include "gvutils.h"
+
+#define LOG2(x) (log(x) / 0.69314718056)
+
+#define PICK_SIZE 6.0
+
+#ifndef MAX
+#define MAX(a,b) ((a>b) ? a:b)
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a<b) ? a:b)
+#endif
+
+enum
+{
+ PICK_NONE = 0,
+ PICK_TOP,
+ PICK_RIGHT,
+ PICK_BOTTOM,
+ PICK_LEFT,
+ PICK_CENTER
+};
+
+/* Ideas for future:
+ *
+ * - Ability to step between frames instead of panning
+ *
+ */
+
+
+/* Signals */
+enum
+{
+ ZOOMEXTENTS_CHANGED, /* for when extents are reset by secondary views */
+ ZOOMEXTENTS_CHANGING,
+ LAST_SIGNAL
+};
+
+static void gv_autopan_tool_class_init(GvAutopanToolClass *klass);
+static void gv_autopan_tool_init(GvAutopanTool *tool);
+
+static void gv_autopan_tool_activate(GvTool *tool, GvViewArea *view);
+static void gv_autopan_tool_deactivate(GvTool *tool, GvViewArea *view);
+static void gv_autopan_tool_destroy(GtkObject *object);
+
+static void gv_autopan_tool_sv_draw(GvTool *tool, GvViewArea *view);
+
+static void gv_autopan_tool_sv_button_press(GtkWidget *view,
+ GdkEventButton *event,
+ gpointer *data_tool);
+
+static void gv_autopan_tool_sv_button_release(GtkWidget *view,
+ GdkEventButton *event,
+ gpointer *data_tool);
+
+static void gv_autopan_tool_sv_motion_notify(GtkWidget *view,
+ GdkEventMotion *event,
+ gpointer *data_tool);
+static gint
+gv_autopan_tool_pick(GvAutopanTool *tool, GvViewArea *view,
+ gvgeocoord x, gvgeocoord y);
+
+static gint gv_autopan_tool_quit(gpointer data);
+
+static void compute_locations_and_zoom(GvAutopanTool *tool);
+
+static gint map_view_to_view_xy(GvViewArea *view1, GvViewArea *view2, gvgeocoord *x, gvgeocoord *y);
+
+static void new_trail_tile( GvAutopanTool *tool, gint xindex, gint yindex);
+static void update_trail( GvAutopanTool *tool, gvgeocoord xmin, gvgeocoord ymin,
+ gvgeocoord width, gvgeocoord height );
+
+static void create_trail_textures( GvAutopanTool *tool, GvAutopanViewItem *item );
+
+
+static guint autopantool_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_autopan_tool_get_type(void)
+{
+ static GtkType autopan_tool_type = 0;
+
+ if (!autopan_tool_type)
+ {
+ static const GtkTypeInfo autopan_tool_info =
+ {
+ "GvAutopanTool",
+ sizeof(GvAutopanTool),
+ sizeof(GvAutopanToolClass),
+ (GtkClassInitFunc) gv_autopan_tool_class_init,
+ (GtkObjectInitFunc) gv_autopan_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ autopan_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &autopan_tool_info);
+ }
+ return autopan_tool_type;
+}
+
+static void
+gv_autopan_tool_class_init(GvAutopanToolClass *klass)
+{
+ GvToolClass *tool_class;
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+ tool_class = (GvToolClass*)klass;
+
+ autopantool_signals[ZOOMEXTENTS_CHANGED] =
+ gtk_signal_new ("zoomextents_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvAutopanToolClass,
+ zoomextents_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ autopantool_signals[ZOOMEXTENTS_CHANGING] =
+ gtk_signal_new ("zoomextents_changing",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvAutopanToolClass,
+ zoomextents_changing),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ gtk_object_class_add_signals(object_class,
+ autopantool_signals, LAST_SIGNAL);
+
+ object_class->destroy = gv_autopan_tool_destroy;
+
+ klass->zoomextents_changed = NULL;
+ klass->zoomextents_changing = NULL;
+
+ tool_class->activate = gv_autopan_tool_activate;
+ tool_class->deactivate = gv_autopan_tool_deactivate;
+
+ /* NOTE: Currently, no gtk events are connected to, so
+ * the parent gvtool deactivation function is not
+ * called in gv_autopan_tool_deactivate. If any
+ * gtk events do end up being connected to, then
+ * gv_autopan_tool_deactivate should be updated to
+ * uncomment this call (it was commented out because
+ * gtk gives a warning message if you disconnect
+ * and there were no handlers connected)
+ */
+}
+
+static void
+gv_autopan_tool_init(GvAutopanTool *tool)
+{
+ int i;
+
+ tool->path_type = TL_R_D_L_D;
+
+ tool->nonstandard_path_shapes = NULL;
+
+ tool->play_flag = 0;
+
+ tool->win_width = 0;
+ tool->win_height = 0;
+ tool->win_zoom = 0;
+
+ tool->pan_region.x = 0;
+ tool->pan_region.y = 0;
+ tool->pan_region.width = -1;
+ tool->pan_region.height = -1;
+
+ tool->overlap = 0.1;
+ tool->speed = 0.01;
+
+ tool->block_size_mode = 0;
+ tool->block_x_size = 0;
+ tool->resolution = 0;
+
+ tool->centers = NULL;
+ tool->view_items = NULL;
+ tool->num_views = 0;
+
+ tool->trail_overview_region.x = 0;
+ tool->trail_overview_region.y = 0;
+ tool->trail_overview_region.width = -1;
+ tool->trail_overview_region.height = -1;
+
+ tool->trail_overview_width_pixels = 256;
+ tool->trail_tile_pixels = 256;
+ tool->trail_tile_lines = 256;
+
+ tool->trail_x0 = 0.0;
+ tool->trail_y0 = 0.0;
+ tool->trail_tile_xsize = 0.0;
+ tool->trail_tile_ysize = 0.0;
+
+ tool->trail = NULL;
+ tool->num_trail_tiles = 0;
+ tool->trail_mode = 0;
+ tool->trail_block = g_malloc(
+ tool->trail_tile_pixels*tool->trail_tile_lines*2);
+
+ for (i=0; i<tool->trail_tile_pixels*tool->trail_tile_lines*2; i++)
+ ((unsigned char *) tool->trail_block)[i] = 255;
+
+ /* make sure panning stops when application is signalled to quit- */
+ /* gtk won't quit until play function exits */
+ tool->quit_handler_id = gtk_quit_add(0, gv_autopan_tool_quit,
+ (gpointer) tool);
+}
+
+GvTool *
+gv_autopan_tool_new(void)
+{
+ GvTool *tool;
+
+ tool = GV_TOOL(gtk_type_new(GV_TYPE_AUTOPAN_TOOL));
+
+ return tool;
+}
+
+/**************************************************************/
+
+
+static void
+gv_autopan_tool_activate(GvTool *rtool, GvViewArea *view)
+{
+ GvAutopanTool *tool = GV_AUTOPAN_TOOL(rtool);
+
+ /* Call the parent class func */
+ GV_TOOL_ACTIVATE(tool, view);
+
+ /* TODO:
+ * - get current view extents
+ * - store window size parameters
+ * - calculate locations for default speed, block size,
+ * overlap.
+ * - calculate view zoom level
+ * - connect view window's resize event to resize function
+ * - activate secondary view signals, if there are any
+ */
+ gv_view_area_get_extents(view,
+ &tool->pan_region.x,
+ &tool->pan_region.y,
+ &tool->pan_region.width,
+ &tool->pan_region.height);
+ tool->pan_region.width -= tool->pan_region.x;
+ tool->pan_region.height -= tool->pan_region.y;
+
+ tool->win_width = view->state.shape_x;
+ tool->win_height = view->state.shape_y;
+
+ /* default: use first standard path, 10% overlap at each
+ * edge between successive passes, zoomed in at 8 times
+ * the regular extents.
+ */
+ tool->block_size_mode = 0;
+ tool->block_x_size = 1.0/8.0;
+
+ tool->overlap = 0.1;
+ tool->speed = 0.01;
+
+ tool->current_index = 0;
+}
+
+
+
+static void
+gv_autopan_tool_deactivate(GvTool *rtool, GvViewArea *view)
+{
+ GvAutopanTool *tool = GV_AUTOPAN_TOOL(rtool);
+ GvAutopanViewItem *sv;
+ int sv_idx;
+
+ /* Call the parent class func- uncomment the line below
+ * and remove the 3 lines following it if any gtk events
+ * are connected to in future.
+ */
+ /*GV_TOOL_DEACTIVATE(tool, view); */
+ g_return_if_fail(GV_TOOL(tool)->view == view);
+ GV_TOOL(tool)->view = NULL;
+ gtk_object_unref(GTK_OBJECT(view));
+
+
+ gv_autopan_tool_stop(tool);
+ if (tool->centers != NULL)
+ {
+ g_array_free(tool->centers, TRUE);
+ tool->centers = NULL;
+ }
+
+ /* TODO:
+ * - clear extent settings, zoom, block size
+ * - disconnect secondary views
+ */
+
+ gv_view_area_queue_draw(view);
+ if (tool->num_views > 0)
+ {
+ for (sv_idx = tool->num_views-1; sv_idx >= 0; sv_idx--)
+ {
+ sv = &(g_array_index(tool->view_items, GvAutopanViewItem,
+ sv_idx));
+ gv_autopan_tool_remove_view( tool, sv->view);
+ }
+ }
+}
+
+static void gv_autopan_tool_destroy(GtkObject *object)
+{
+ gv_autopan_tool_clear_trail(GV_AUTOPAN_TOOL(object));
+ g_free(GV_AUTOPAN_TOOL(object)->trail_block);
+ gtk_quit_remove(GV_AUTOPAN_TOOL(object)->quit_handler_id);
+}
+
+/* Start panning */
+gint gv_autopan_tool_play(GvAutopanTool *tool)
+{
+ /* TODO:
+ * - Set zoom level and initial translation
+ * - While tool is not paused:
+ * - translate to next position in list.
+ * - If secondary views are present, trigger
+ * a redraw (maybe not every time- if not
+ * then make sure one is at least triggered
+ * at the end
+ * - do a while loop of gtk_main_iterations
+ * on gtk_events_pending, limited by a timer.
+ * If panning has reached the very end, maybe
+ * allow a little more time?
+ * Is there any way to set a priority on
+ * an event (eg. if left click used to pause)?
+ */
+ GvVertex3d *nloc;
+ GTimer *timer;
+ int sv_idx;
+ GvAutopanViewItem *sv;
+ gvgeocoord xmin, ymin, xmax, ymax;
+
+ /* Avoid recursive plays */
+ if (tool->play_flag == 1)
+ return TRUE;
+
+ /* If tool is not just paused, compute zoom locations */
+ if (tool->play_flag == 0)
+ {
+ compute_locations_and_zoom(tool);
+
+ if (tool->num_centers < 1)
+ return FALSE;
+
+ gv_view_area_zoom(GV_TOOL(tool)->view,
+ -1*gv_view_area_get_zoom(GV_TOOL(tool)->view));
+ gv_view_area_zoom(GV_TOOL(tool)->view, tool->win_zoom);
+ }
+ else if (tool->num_centers < 1)
+ return FALSE;
+
+ tool->play_flag = 1;
+ while (tool->play_flag == 1)
+ {
+ /* check if user has resized window; update if they have */
+ if ((tool->win_width != GV_TOOL(tool)->view->state.shape_x) ||
+ (tool->win_height != GV_TOOL(tool)->view->state.shape_y))
+ compute_locations_and_zoom(tool);
+
+ /* check if user has zoomed; reset if they have */
+ if (gv_view_area_get_zoom(GV_TOOL(tool)->view) != tool->win_zoom)
+ {
+ gv_view_area_zoom(GV_TOOL(tool)->view,
+ -1*gv_view_area_get_zoom(GV_TOOL(tool)->view));
+ gv_view_area_zoom(GV_TOOL(tool)->view,tool->win_zoom);
+ }
+
+ nloc = &( g_array_index( tool->centers, GvVertex3d,
+ tool->current_index) );
+
+ gv_view_area_set_translation(GV_TOOL(tool)->view, nloc->x, nloc->y);
+
+ if ( tool->trail_mode > 0 )
+ {
+ gv_view_area_get_extents( GV_TOOL(tool)->view, &xmin, &ymin,
+ &xmax, &ymax );
+ update_trail( tool, xmin, ymin, xmax-xmin, ymax-ymin );
+ }
+
+ if (tool->speed > 0)
+ {
+ tool->current_index++;
+ if (tool->current_index >= tool->num_centers)
+ tool->current_index = 0;
+ }
+ else
+ {
+ tool->current_index--;
+ if (tool->current_index < 0)
+ tool->current_index = tool->num_centers;
+
+ }
+
+ if (tool->num_views > 0)
+ {
+ for (sv_idx = 0; sv_idx < tool->num_views; sv_idx++)
+ {
+ sv = &(g_array_index(tool->view_items, GvAutopanViewItem,
+ sv_idx));
+ gv_view_area_queue_draw(sv->view);
+ }
+ }
+ /* continue to be interactive */
+ timer = g_timer_new();
+ g_timer_start(timer);
+ while(gtk_events_pending() &&
+ (g_timer_elapsed(timer,NULL) < 2.0))
+ gtk_main_iteration();
+ g_timer_destroy(timer);
+ }
+
+ return TRUE;
+}
+
+/* Pause the tool, but maintain current position, resolution, and
+ * speed settings.
+ */
+
+static gint gv_autopan_tool_quit(gpointer data)
+{
+ gv_autopan_tool_stop(GV_AUTOPAN_TOOL(data));
+ return 0;
+}
+
+gint gv_autopan_tool_pause(GvAutopanTool *tool)
+{
+
+ if (tool->play_flag == 0)
+ compute_locations_and_zoom(tool);
+
+ tool->play_flag = 2;
+
+ return TRUE;
+}
+
+gint gv_autopan_tool_stop(GvAutopanTool *tool)
+{
+ int sv_idx;
+ GvAutopanViewItem *sv;
+
+ if (tool->play_flag == 0)
+ return TRUE;
+
+ /* Same as pause, except that secondary views will be
+ * refreshed without the current region drawn.
+ */
+ if (tool->num_views > 0)
+ {
+ /* If tool is not playing, force redraw of secondary views */
+ for (sv_idx = 0; sv_idx < tool->num_views; sv_idx++)
+ {
+ sv = &(g_array_index(tool->view_items, GvAutopanViewItem,
+ sv_idx));
+ gv_view_area_queue_draw(sv->view);
+ }
+ }
+
+ if (tool->centers != NULL)
+ {
+ g_array_free(tool->centers, TRUE);
+ tool->centers = NULL;
+ tool->current_index = 0;
+ }
+ tool->play_flag = 0;
+
+ return TRUE;
+}
+
+/* Speed is adjusted by placing successive locations closer or
+ * further apart in the direction of panning. Function returns
+ * the final speed setting (speed is forced to be between
+ * -1.0 and 1.0, with an absolute value of at least 0.000001).
+ */
+double gv_autopan_tool_set_speed(GvAutopanTool *tool, gvgeocoord speed)
+{
+ /* TODO:
+ * - if playing, set pause flag
+ * - recalculate locations and zoom, and reset current position
+ * to equivalent point in new list
+ * - if tool was playing, restart
+ * - warn if speed is out of bounds
+ */
+ if (tool->speed == speed)
+ return tool->speed;
+
+ if (tool->speed == -1*speed)
+ {
+ tool->speed = speed;
+ return tool->speed;
+ }
+
+ if (speed > 0)
+ {
+ if (speed < 0.000001)
+ tool->speed = 0.000001;
+ else if (speed > 1.0)
+ tool->speed = 1.0;
+ else
+ tool->speed = speed;
+ }
+ else
+ {
+ if (speed < -1.0)
+ tool->speed = -1.0;
+ else if (speed > -0.000001)
+ tool->speed = -0.000001;
+ else
+ tool->speed = speed;
+ }
+
+ /* If tool is stopped, don't recompute locations just yet in
+ * case other things (eg. extents) also need to be reset.
+ */
+ if (tool->play_flag != 0)
+ compute_locations_and_zoom(tool);
+
+ return (double) tool->speed;
+}
+
+double gv_autopan_tool_get_speed(GvAutopanTool *tool)
+{
+ return (double) tool->speed;
+}
+
+gint gv_autopan_tool_set_standard_path(GvAutopanTool *tool, gint path_type)
+{
+ gint playing;
+
+ if ( ( path_type < 0 ) || ( path_type >= STANDARD_PATHS ) )
+ {
+ g_error("GvAutopan: invalid value for standard path setting");
+ return FALSE;
+ }
+
+ playing = tool->play_flag;
+ if ( playing == 1 )
+ gv_autopan_tool_pause(tool);
+
+ tool->path_type = path_type;
+
+ if ( playing != 0 )
+ compute_locations_and_zoom(tool);
+
+ if ( playing == 1 )
+ gv_autopan_tool_play(tool);
+
+ return TRUE;
+}
+
+gint gv_autopan_tool_set_lines_path( GvAutopanTool *tool, GvShapes *lines)
+{
+ int idx;
+ GvShape *shp;
+
+ if (tool->nonstandard_path_shapes != NULL)
+ {
+ /* clear old shapes; free space associated with them */
+ gtk_object_unref( GTK_OBJECT(tool->nonstandard_path_shapes) );
+ tool->nonstandard_path_shapes = NULL;
+ }
+ tool->nonstandard_path_shapes = (GvShapes *) gv_shapes_new();
+
+ for (idx = 0; idx<lines->shapes->len; idx++)
+ {
+ shp = gv_shapes_get_shape(lines, idx);
+ if ( ( shp != NULL ) &&
+ ( gv_shape_type( shp ) == GVSHAPE_LINE ) )
+ {
+ gv_shapes_add_shape(tool->nonstandard_path_shapes, gv_shape_copy(shp));
+ }
+ }
+ tool->path_type = LINES_PATH;
+ compute_locations_and_zoom(tool);
+
+ return TRUE;
+}
+
+/* Set the extents of the full panning region */
+/* Returns TRUE for success; FALSE for failure */
+/* (eg. if panning extents parameter doesn't */
+/* apply for the current path type) */
+gint gv_autopan_tool_new_rect(GvAutopanTool *tool, GvRect *rect)
+{
+
+
+ tool->pan_region.x = rect->x;
+ tool->pan_region.y = rect->y;
+ tool->pan_region.width = rect->width;
+ tool->pan_region.height = rect->height;
+
+ if ( ( tool->trail_overview_region.width <= 0 ) && (tool->num_trail_tiles < 1) )
+ {
+ gv_autopan_tool_set_trail_parameters( tool, rect, tool->trail_overview_width_pixels );
+ tool->trail_tile_ysize = tool->trail_tile_xsize;
+ }
+
+ /* If path is non-standard, region can be set, but won't be used */
+ if ( tool->path_type < 0 )
+ return TRUE;
+
+ if (tool->centers != NULL)
+ {
+ g_array_free(tool->centers, TRUE);
+ tool->centers = NULL;
+ }
+
+ if (tool->play_flag != 0)
+ compute_locations_and_zoom(tool);
+
+ return TRUE;
+}
+gint gv_autopan_tool_get_rect(GvAutopanTool *tool, GvRect *rect)
+{
+ if ( tool->path_type < 0 )
+ return FALSE;
+
+ rect->x = tool->pan_region.x;
+ rect->y = tool->pan_region.y;
+ rect->width = tool->pan_region.width;
+ rect->height = tool->pan_region.height;
+
+ return TRUE;
+}
+
+/* Reset the current position of the primary view window. Snaps
+ * to the closest listed location.
+ */
+gint gv_autopan_tool_set_location(GvAutopanTool *tool, gvgeocoord x,
+ gvgeocoord y, gvgeocoord z)
+{
+ /* TODO:
+ * - if playing, set pause flag
+ * - find closest position in list and set new current position to it
+ * - if tool was playing, restart
+ */
+ gvgeocoord mindiff, cdiff, cx, cy, cz;
+ gint cidx=0, i;
+ GvVertex3d *loc;
+
+ if (GV_TOOL(tool)->view == NULL)
+ return FALSE;
+
+ if (tool->centers == NULL)
+ compute_locations_and_zoom(tool);
+
+ if (tool->num_centers < 1)
+ return FALSE;
+
+ loc = &(g_array_index( tool->centers, GvVertex3d, 0) );
+ cx = -1*loc->x;
+ cy = -1*loc->y;
+ cz = -1*loc->z;
+ cdiff = sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z));
+ mindiff = cdiff;
+ for (i=1; i < tool->num_centers; i++)
+ {
+ loc = &(g_array_index( tool->centers, GvVertex3d, i) );
+ cx = -1*loc->x;
+ cy = -1*loc->y;
+ cz = -1*loc->z;
+ cdiff = sqrt((cx-x)*(cx-x)+(cy-y)*(cy-y)+(cz-z)*(cz-z));
+ if (cdiff < mindiff)
+ {
+ mindiff = cdiff;
+ cidx = i;
+ }
+ }
+
+ tool->current_index = cidx;
+
+ return TRUE;
+}
+
+/*
+ * Get the current position. Returns FALSE if there is no
+ * current position; TRUE if the position is valid.
+ */
+gint gv_autopan_tool_get_location(GvAutopanTool *tool, gvgeocoord *x,
+ gvgeocoord *y, gvgeocoord *z)
+{
+ GvVertex3d *oloc;
+
+ /* If tool is deactivated or stopped, return FALSE because
+ * there is no "current location".
+ */
+
+ *x = 0;
+ *y = 0;
+ *z = 0;
+
+ if (GV_TOOL(tool)->view == NULL)
+ return FALSE;
+
+ if (tool->play_flag == 0)
+ return FALSE;
+
+ if (tool->centers == NULL)
+ return FALSE;
+
+ if (tool->current_index < tool->num_centers)
+ {
+ oloc = &(g_array_index(tool->centers, GvVertex3d,
+ tool->current_index));
+ *x = -1*oloc->x;
+ *y = -1*oloc->y;
+ }
+ else
+ return FALSE;
+
+
+ return TRUE;
+}
+
+/* Overlap is only relevant for standard paths covering the whole
+ * panning region. It determines the overlap between successive
+ * passes perpendicular to the direction of panning.
+ */
+
+gint gv_autopan_tool_set_overlap(GvAutopanTool *tool, gvgeocoord overlap)
+{
+
+ tool->overlap = overlap;
+ if ( (tool->play_flag != 0) && (tool->path_type >= 0) )
+ compute_locations_and_zoom(tool);
+
+ return TRUE;
+
+}
+
+double gv_autopan_tool_get_overlap(GvAutopanTool *tool)
+{
+ return (double) tool->overlap;
+}
+
+/* Either the size of the block in the x dimension OR the x resolution of
+ * the view in terms of the pixels of a reference raster may be used to
+ * determine the panning zoom level.
+ */
+
+gint gv_autopan_tool_set_block_x_size(GvAutopanTool *tool,
+ gvgeocoord block_x_size,
+ gint mode)
+{
+ /* mode 0: block size is a fraction of panning extents
+ * - block size will change depending on panning extents
+ * - zoom level will change when window is resized
+ * 1: block size is in view coordinates
+ * - block size will not change with different panning extents
+ * - zoom level will change when window is resized
+ */
+ if ((mode != 0) && (mode != 1))
+ {
+ g_error("mode must be 0 or 1");
+ return FALSE;
+ }
+ tool->block_size_mode = mode;
+ tool->block_x_size = block_x_size;
+ if (tool->play_flag != 0)
+ compute_locations_and_zoom(tool);
+
+ return TRUE;
+
+}
+
+gint gv_autopan_tool_set_x_resolution(GvAutopanTool *tool,
+ gvgeocoord resolution)
+{
+ /* mode 2: block size is set so that the current layer resolution
+ * will remain constant.
+ * - block size will change when window is resized, and
+ * has no dependence on panning extents
+ * - zoom level will not change when window is resized
+ */
+ tool->block_size_mode = 2;
+ tool->resolution = resolution;
+ if (tool->play_flag != 0)
+ compute_locations_and_zoom(tool);
+
+ return TRUE;
+}
+
+/* Get state information about the tool */
+void gv_autopan_tool_get_state(GvAutopanTool *tool,
+ gint *play_flag,
+ gint *path_type,
+ gint *block_size_mode,
+ gvgeocoord *block_x_size,
+ gvgeocoord *x_resolution,
+ gint *num_views)
+{
+ *play_flag = tool->play_flag;
+ *path_type = tool->path_type;
+ *block_size_mode = tool->block_size_mode;
+ *block_x_size = tool->block_x_size;
+ *x_resolution = tool->resolution;
+ *num_views = tool->num_views;
+}
+
+void gv_autopan_tool_clear_trail( GvAutopanTool *tool )
+{
+ int i, j, tnum;
+ GvAutopanViewItem *item;
+ GvAutopanTrailTile *tile;
+ GLuint *texName;
+
+ /* Note below: should context be set before texture deleted? */
+ if ( tool->trail != NULL )
+ {
+ tnum = tool->num_trail_tiles;
+
+ while ( tool->num_trail_tiles > 0 )
+ {
+ tile = &(g_array_index(tool->trail, GvAutopanTrailTile, tool->num_trail_tiles - 1 ));
+ g_free(tile->mask);
+ g_array_remove_index(tool->trail, tool->num_trail_tiles-1);
+ tool->num_trail_tiles--;
+ }
+
+ g_array_free(tool->trail, TRUE);
+ tool->trail = NULL;
+
+ for( i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if ( item->trail_mode > 0)
+ {
+ for ( j = tnum-1; j >= 0; j-- )
+ {
+ texName = &(g_array_index(item->trail_textures, GLuint, j));
+ glDeleteTextures(1,texName);
+ }
+ g_array_free(item->trail_textures,TRUE);
+ item->trail_textures = NULL;
+ gv_view_area_queue_draw(item->view);
+ }
+ }
+ /* Force tool to reset panning region next time trail comes on */
+ tool->trail_overview_region.width = -1;
+ }
+
+}
+
+gint gv_autopan_tool_set_trail_color(GvAutopanTool *tool, GvViewArea *view,
+ float red, float green, float blue,
+ float alpha)
+{
+ int i, viewidx;
+ GvAutopanViewItem *item;
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if (item->view == view)
+ viewidx = i;
+ }
+ if (viewidx < 0)
+ {
+ g_error("View not registered with autopan tool!");
+ return FALSE;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+ item->trail_color[0] = red;
+ item->trail_color[1] = green;
+ item->trail_color[2] = blue;
+ item->trail_color[3] = alpha;
+ if ( tool->num_trail_tiles > 0 )
+ gv_view_area_queue_draw( view );
+
+ return TRUE;
+
+}
+
+gint gv_autopan_tool_set_trail_mode( GvAutopanTool *tool, GvViewArea *view,
+ gint trail_mode )
+{
+ int i, j, viewidx, omode;
+ GvAutopanViewItem *item;
+ GLuint *texName;
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if (item->view == view)
+ viewidx = i;
+ }
+ if (viewidx < 0)
+ {
+ g_error("View not registered with autopan tool!");
+ return FALSE;
+ }
+
+ if ( (trail_mode != 0) && (trail_mode != 1) )
+ {
+ g_warning("gvautopan: trail_mode must be 0 or 1- leaving alone");
+ return FALSE;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+ tool->trail_mode = tool->trail_mode - item->trail_mode + trail_mode;
+ omode = item->trail_mode;
+ item->trail_mode = trail_mode;
+
+ /* Make sure trail is properly initialized if mode is turning on: set to pan_region region */
+ if (( tool->trail_mode > 0 ) && ( tool->trail_overview_region.width < 0 ) && ( tool->pan_region.width > 0 ) )
+ gv_autopan_tool_set_trail_parameters( tool, &tool->pan_region, tool->trail_overview_width_pixels );
+
+ if ( ( omode == 1 ) && ( trail_mode == 0 ) && ( item->trail_textures != NULL ) )
+ {
+ for ( j = tool->num_trail_tiles-1; j >= 0; j-- )
+ {
+ texName = &(g_array_index(item->trail_textures, GLuint, j));
+ glDeleteTextures(1,texName);
+ }
+ g_array_free(item->trail_textures,TRUE);
+ item->trail_textures = NULL;
+ }
+ else if ( ( omode == 0 ) && ( trail_mode == 1 ) )
+ create_trail_textures( tool, item );
+
+ if ( tool->num_trail_tiles > 0 )
+ gv_view_area_queue_draw( view );
+
+ return TRUE;
+}
+
+
+/* Compute the zoom level and populate the list of locations to translate to */
+
+static void compute_locations_and_zoom(GvAutopanTool *tool)
+{
+ gvgeocoord cx=0, cy=0, mindiff=-1, cdiff;
+ gint reset_position=0, cidx=0;
+ GvVertex3d nloc;
+ GvVertex3d *oloc;
+
+ tool->win_width = GV_TOOL(tool)->view->state.shape_x;
+ tool->win_height = GV_TOOL(tool)->view->state.shape_y;
+
+ if (tool->centers != NULL)
+ {
+ if (tool->current_index < tool->num_centers)
+ {
+ oloc = &(g_array_index(tool->centers, GvVertex3d,
+ tool->current_index));
+ cx = oloc->x;
+ cy = oloc->y;
+ reset_position=1;
+ }
+ g_array_free(tool->centers, TRUE);
+ }
+
+ if ((tool->play_flag == 0) ||
+ (( tool->path_type > -1 ) &&
+ ((-1*cx < tool->pan_region.x) ||
+ (-1*cy < tool->pan_region.y) ||
+ (-1*cx > tool->pan_region.x + tool->pan_region.width) ||
+ (-1*cy > tool->pan_region.y + tool->pan_region.height))))
+ reset_position = 0;
+
+ tool->centers = g_array_new(FALSE, FALSE, sizeof(GvVertex3d));
+
+ nloc.z = 0.0;
+
+ /* TODO: see comment above */
+ if (tool->path_type < LINES_PATH)
+ {
+ g_error("non-standard paths other than lines not implemented");
+ }
+ else if ( tool->path_type == LINES_PATH )
+ {
+ GvShape *line;
+ gvgeocoord bsx, delta, x1, y1, x2, y2, dist, dx, dy, doff;
+ gint i, j, k, nnodes, nstop;
+
+ if (tool->block_size_mode == 2)
+ tool->block_x_size = tool->resolution * tool->win_width;
+
+ bsx = tool->block_x_size;
+ /* For now, ignore case where block size mode is 0; eventually
+ * might make it related to total line length, or something
+ * like that. Here, block size modes 0 and 1 will both behave
+ * the same way as block size mode 1 does in the standard path case.
+ */
+
+ delta = fabs(tool->speed*bsx);
+
+ tool->num_centers = 0;
+
+ for ( i = 0; i < tool->nonstandard_path_shapes->shapes->len; i++ )
+ {
+ line = gv_shapes_get_shape(tool->nonstandard_path_shapes, i);
+
+ if (( line != NULL ) && ( gv_shape_get_nodes( line, 0 ) > 1 ))
+ {
+ nnodes = gv_shape_get_nodes( line, 0 );
+ for ( j = 0 ; j < nnodes - 1; j++ )
+ {
+ x1 = gv_shape_get_x( line, 0, j );
+ y1 = gv_shape_get_y( line, 0, j );
+ x2 = gv_shape_get_x( line, 0, j+1 );
+ y2 = gv_shape_get_y( line, 0, j+1 );
+
+ dx = x2-x1;
+ dy = y2-y1;
+ dist = sqrt(dx*dx + dy*dy);
+ nstop = (int) ceil(dist/delta) + 1;
+ /* offset ensures that centers calculated in one direction
+ * are same as the centers calculated if the speed is reversed.
+ */
+ doff = ( ceil(dist/delta) - dist/delta )/2;
+ if (nstop > 1)
+ {
+ dx = dx/(nstop-1);
+ dy = dy/(nstop-1);
+ }
+ else
+ doff = 0.0;
+
+ for ( k = 0; k < nstop; k++ )
+ {
+ nloc.x = -1*(dx*(k-doff) + x1);
+ nloc.y = -1*(dy*(k-doff) + y1);
+ g_array_append_val(tool->centers, nloc);
+ if (reset_position == 1)
+ {
+ cdiff = sqrt((nloc.x-cx)*(nloc.x-cx) +
+ (nloc.y-cy)*(nloc.y-cy));
+ if ((mindiff == -1) || (cdiff < mindiff))
+ {
+ cidx = tool->num_centers;
+ mindiff = cdiff;
+ }
+ }
+ tool->num_centers += 1;
+ }
+ }
+ }
+ else if (( line != NULL ) && ( gv_shape_get_nodes( line, 0 ) == 1 ))
+ {
+ /* line only has a single node- set path so that node
+ * gets visited once.
+ */
+ nloc.x = -1*gv_shape_get_x(line,0,0);
+ nloc.y = -1*gv_shape_get_y(line,0,0);
+ g_array_append_val(tool->centers, nloc);
+ if (reset_position == 1)
+ {
+ cdiff = sqrt((nloc.x-cx)*(nloc.x-cx) +
+ (nloc.y-cy)*(nloc.y-cy));
+ if ((mindiff == -1) || (cdiff < mindiff))
+ {
+ cidx = tool->num_centers;
+ mindiff = cdiff;
+ }
+ }
+ tool->num_centers += 1;
+ }
+ }
+
+ tool->win_zoom = LOG2(tool->win_width/tool->block_x_size);
+
+ }
+ else if ((tool->path_type == TL_R_D_L_D) ||
+ (tool->path_type == BL_R_U_L_U) ||
+ (tool->path_type == TR_L_D_R_D) ||
+ (tool->path_type == BR_L_U_R_U))
+ {
+ /* Note: currently overlap is dealt with by showing extra
+ along the last (bottom) pass if the blocks don't fit
+ evenly into the panning extents. May want to do this
+ a bit differently later.
+ */
+
+ gvgeocoord bsx, bsy, delta, xoff, yoff;
+ gint nxloc, npasses, nvert, i, j;
+
+ if (tool->block_size_mode == 2)
+ tool->block_x_size = tool->resolution * tool->win_width;
+
+ bsx = tool->block_x_size;
+ if (tool->block_size_mode == 0)
+ bsx = bsx * tool->pan_region.width;
+
+ bsy = bsx * tool->win_height/tool->win_width;
+
+ npasses = (int) ceil(
+ (tool->pan_region.height - (tool->overlap*bsy))/
+ ((1.0 - tool->overlap)*bsy));
+
+ if (tool->speed < 0)
+ delta = -1*tool->speed*bsx;
+ else
+ delta = tool->speed*bsx;
+
+ nxloc = (int) ceil((tool->pan_region.width - bsx)/delta) + 1;
+ nvert = (int) ceil(bsy*(1.0 - tool->overlap)/delta);
+
+ /* NOTE: in order to keep speed constant for different
+ * sizes of panning region, the panning region is
+ * rounded to the nearest multiple of delta
+ * (otherwise delta would have to be modified
+ * to fit evenly into the panning region, which
+ * results in noticeable speed changes between
+ * small and large regions. Likewise, the
+ * overlap is also rounded.
+ */
+
+ if (((tool->path_type == TL_R_D_L_D) &&
+ (GV_TOOL(tool)->view->state.flip_y > 0)) ||
+ ((tool->path_type == BL_R_U_L_U) &&
+ (GV_TOOL(tool)->view->state.flip_y < 0)) ||
+ ((tool->path_type == TR_L_D_R_D) &&
+ (GV_TOOL(tool)->view->state.flip_y > 0)) ||
+ ((tool->path_type == BR_L_U_R_U) &&
+ (GV_TOOL(tool)->view->state.flip_y < 0)))
+ bsy=-1*bsy;
+
+ if ((tool->path_type == TR_L_D_R_D) ||
+ (tool->path_type == BR_L_U_R_U))
+ xoff = tool->pan_region.x + tool->pan_region.width - bsx/2.0;
+ else
+ xoff = tool->pan_region.x + bsx/2.0;
+
+ if ( tool->pan_region.width < bsx )
+ {
+ /* Very narrow panning region- only one x location */
+ xoff = tool->pan_region.x + tool->pan_region.width/2.0;
+ nxloc = 1;
+ }
+
+ if (bsy > 0)
+ yoff = tool->pan_region.y + bsy/2.0;
+ else
+ yoff = tool->pan_region.y + tool->pan_region.height + bsy/2.0;
+
+ if ((tool->path_type == TR_L_D_R_D) ||
+ (tool->path_type == BR_L_U_R_U))
+ delta = -1.0*delta;
+
+ tool->num_centers = 0;
+ for ( i = 0; i < npasses; i++ )
+ {
+ for ( j = 0; j < nxloc; j++ )
+ {
+ if (nxloc > 1)
+ {
+ if ( (i % 2) == 0)
+ nloc.x = -1*(xoff + j*delta);
+ else
+ nloc.x = -1*(xoff + (nxloc-1-j)*delta);
+ }
+ else
+ nloc.x = -1*xoff;
+
+ nloc.y = -1*(yoff + i*bsy*(1.0 - tool->overlap));
+
+ g_array_append_val(tool->centers, nloc);
+ if (reset_position == 1)
+ {
+ cdiff = sqrt((nloc.x-cx)*(nloc.x-cx) +
+ (nloc.y-cy)*(nloc.y-cy));
+ if ((mindiff == -1) || (cdiff < mindiff))
+ {
+ cidx = tool->num_centers;
+ mindiff = cdiff;
+ }
+ }
+ tool->num_centers += 1;
+ }
+
+ if (nxloc > 1)
+ {
+ nloc.x = -1*xoff;
+ if ( (i % 2) == 0)
+ nloc.x -= (nxloc-1)*delta;
+ }
+
+ if ( i != npasses - 1)
+ {
+ for ( j = 1; j < nvert; j++ )
+ {
+ nloc.y = -1*(yoff+(i+j*1.0/nvert)*bsy*(1.0-tool->overlap));
+ g_array_append_val(tool->centers, nloc);
+ if (reset_position == 1)
+ {
+ cdiff = sqrt((nloc.x-cx)*(nloc.x-cx) +
+ (nloc.y-cy)*(nloc.y-cy));
+ if ((mindiff == -1) || (cdiff < mindiff))
+ {
+ cidx = tool->num_centers;
+ mindiff = cdiff;
+ }
+ }
+ tool->num_centers += 1;
+ }
+ }
+ }
+ if (tool->block_size_mode == 0)
+ {
+ tool->win_zoom = LOG2(tool->win_width/
+ (tool->block_x_size*tool->pan_region.width));
+ }
+ else
+ tool->win_zoom = LOG2(tool->win_width/tool->block_x_size);
+
+ }
+ else if (tool->path_type == TL_R_D_R_D)
+ {
+ gvgeocoord bsx, bsy, delta, xoff, yoff;
+ gint nxloc, npasses, i, j;
+
+ if (tool->block_size_mode == 2)
+ tool->block_x_size = tool->resolution * tool->win_width;
+
+ bsx = tool->block_x_size;
+ if (tool->block_size_mode == 0)
+ bsx = bsx * tool->pan_region.width;
+
+ bsy = bsx * tool->win_height/tool->win_width;
+
+ npasses = (int) ceil(
+ (tool->pan_region.height - (tool->overlap*bsy))/
+ ((1.0 - tool->overlap)*bsy));
+
+ if (tool->speed < 0)
+ delta = -1*tool->speed*bsx;
+ else
+ delta = tool->speed*bsx;
+
+ nxloc = (int) ceil((tool->pan_region.width - bsx)/delta) + 1;
+
+ if (GV_TOOL(tool)->view->state.flip_y > 0)
+ bsy=-1*bsy;
+
+
+ xoff = tool->pan_region.x + bsx/2.0;
+
+ if ( tool->pan_region.width < bsx )
+ {
+ xoff = tool->pan_region.x + tool->pan_region.width/2.0;
+ nxloc = 1;
+ }
+
+ if (bsy > 0)
+ yoff = tool->pan_region.y + bsy/2.0;
+ else
+ yoff = tool->pan_region.y + tool->pan_region.height + bsy/2.0;
+
+
+ tool->num_centers = 0;
+ for ( i = 0; i < npasses; i++ )
+ {
+ for ( j = 0; j < nxloc; j++ )
+ {
+ if (nxloc > 1)
+ nloc.x = -1*(xoff + j*delta);
+ else
+ nloc.x = -1*xoff;
+
+ nloc.y = -1*(yoff + i*bsy*(1.0 - tool->overlap));
+
+ g_array_append_val(tool->centers, nloc);
+ if (reset_position == 1)
+ {
+ cdiff = sqrt((nloc.x-cx)*(nloc.x-cx) +
+ (nloc.y-cy)*(nloc.y-cy));
+ if ((mindiff == -1) || (cdiff < mindiff))
+ {
+ cidx = tool->num_centers;
+ mindiff = cdiff;
+ }
+ }
+ tool->num_centers += 1;
+ }
+ }
+ if (tool->block_size_mode == 0)
+ {
+ tool->win_zoom = LOG2(tool->win_width/
+ (tool->block_x_size*tool->pan_region.width));
+ }
+ else
+ tool->win_zoom = LOG2(tool->win_width/tool->block_x_size);
+
+ }
+ else
+ {
+ g_error("path not implemented");
+ }
+
+ tool->current_index = cidx;
+}
+
+
+/* When the tool is panning, optional secondary views can be associated
+ * with the primary view. In these views, the area currently
+ * covered by the primary view is drawn as a blue-green rectangle
+ * in each secondary view. The secondary views can be configured
+ * so that the primary view resolution and location can be updated
+ * by dragging the rectangle in the secondary view.
+ *
+ * can_resize: 0 if resetting the resolution is disabled; 1 if it
+ * is enabled. If resizing is on, corners can be
+ * selected and dragged. The shape of the rectangle
+ * must always be dictated by the aspect ratio of the
+ * primary view though, so dragging will snap to
+ * a rectangle of the appropriate shape at the end.
+ *
+ * can_reposition: 0 if resetting the position is disabled; 1 if it
+ * is enabled. If repositioning is on, borders
+ * can be selected and dragged (whole box will move).
+ *
+ * trail_mode: 0 if secondary view should not indicate where tool
+ * has already travelled; 1 if it should display the trail.
+ *
+ */
+
+gint gv_autopan_tool_register_view(GvAutopanTool *tool, GvViewArea *view,
+ gint can_resize, gint can_reposition,
+ gint trail_mode)
+{
+ GvAutopanViewItem newview;
+
+ /* TODO:
+ * - if playing, pause
+ * - add view to list of secondary views
+ * - connect the view's gldraw event to gv_autopan_tool_sv_draw
+ * - if can_resize or can_reposition is 1, connect to button-press,
+ * button-release, and motion-notify events for that view.
+ * Note: if things are too slow or flashy using the gldraw event,
+ * could do something similar to what was done for the
+ * ghost cursor. Probably could avoid changes to gvviewarea
+ * by storing more parameters in the autopan tool and just
+ * calling gv_manager_set_busy, gtk_widget_queue draw, then
+ * connecting the view to GLCURSOR instead of GLDRAW.
+ */
+
+ /* First, make sure this is not the main panning view */
+ if (view == GV_TOOL(tool)->view)
+ {
+ g_error("Autopan: Cannot register main view as a secondary view!");
+ return FALSE;
+ }
+
+ if (can_resize != 0)
+ g_warning("gvautopan: Secondary view resize not implemented yet!");
+
+ if ( (trail_mode != 0) && (trail_mode != 1) )
+ {
+ g_warning("gvautopan: trail_mode must be 0 or 1");
+ return FALSE;
+ }
+
+ newview.can_resize = 0;
+ newview.can_reposition = can_reposition;
+ newview.trail_mode = trail_mode;
+
+ tool->trail_mode = tool->trail_mode + trail_mode;
+
+ newview.trail_color[0] = 1.0;
+ newview.trail_color[1] = 0.75;
+ newview.trail_color[2] = 0.0;
+ newview.trail_color[3] = 0.5;
+
+ newview.banding = 0;
+ newview.translating = 0;
+ newview.play_flag = 0;
+
+ /* Add a reference to this view */
+ gtk_object_ref(GTK_OBJECT(view));
+
+ newview.view = view;
+ newview.tool = tool;
+ newview.trail_textures = NULL;
+
+ if (tool->view_items == NULL)
+ tool->view_items = g_array_new(FALSE, FALSE, sizeof(GvAutopanViewItem));
+
+ /* Connect to view area delete event */
+ gtk_signal_connect_object(GTK_OBJECT(view), "destroy",
+ GTK_SIGNAL_FUNC(gv_autopan_tool_remove_view),
+ GTK_OBJECT(tool));
+
+ /* Connect to view area gldraw signal so that current region
+ * can be drawn in the view whenever the view is refreshed.
+ */
+ gtk_signal_connect_object(GTK_OBJECT(view), "gldraw",
+ GTK_SIGNAL_FUNC(gv_autopan_tool_sv_draw),
+ GTK_OBJECT(tool));
+
+ /* Connect to button-press and button-release signals so that
+ * translating/resizing can be detected.
+ */
+ newview.press_id = \
+ gtk_signal_connect(GTK_OBJECT(view), "button-press-event",
+ GTK_SIGNAL_FUNC(gv_autopan_tool_sv_button_press),
+ (gpointer *) tool);
+
+ newview.release_id = \
+ gtk_signal_connect(GTK_OBJECT(view), "button-release-event",
+ GTK_SIGNAL_FUNC(gv_autopan_tool_sv_button_release),
+ (gpointer *) tool);
+
+ newview.motion_id = \
+ gtk_signal_connect(GTK_OBJECT(view), "motion-notify-event",
+ GTK_SIGNAL_FUNC(gv_autopan_tool_sv_motion_notify),
+ (gpointer *) tool);
+
+
+ g_array_append_val(tool->view_items, newview);
+
+
+ tool->num_views = tool->num_views + 1;
+
+ if ( newview.trail_mode > 0 )
+ {
+ create_trail_textures( tool, &newview );
+ gv_view_area_queue_draw( newview.view );
+ }
+
+ return TRUE;
+}
+
+gint gv_autopan_tool_remove_view(GvAutopanTool *tool, GvViewArea *view)
+{
+ int i, j, viewidx;
+ GvAutopanViewItem *item;
+ GLuint *texName;
+
+ /* TODO:
+ * - disconnect from view's gldraw event
+ * - disconnect view from button-press/button-release/motion-notify
+ * events if necessary
+ * - remove view from list
+ * - redraw the view to get rid of trail artifact
+ */
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if (item->view == view)
+ viewidx = i;
+ }
+ if (viewidx < 0)
+ {
+ g_error("View not registered for removal!");
+ return FALSE;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+
+ tool->trail_mode = tool->trail_mode - item->trail_mode;
+
+ if ( item->trail_textures != NULL )
+ {
+ for ( j = tool->num_trail_tiles-1; j >= 0; j-- )
+ {
+ texName = &(g_array_index(item->trail_textures, GLuint, j));
+ glDeleteTextures(1,texName);
+ }
+ g_array_free(item->trail_textures,TRUE);
+ item->trail_textures = NULL;
+ }
+
+ gtk_signal_disconnect(GTK_OBJECT(view), item->press_id);
+ gtk_signal_disconnect(GTK_OBJECT(view), item->release_id);
+ gtk_signal_disconnect(GTK_OBJECT(view), item->motion_id);
+
+ g_array_remove_index(tool->view_items, viewidx);
+
+ gtk_signal_disconnect_by_data(GTK_OBJECT(view), GTK_OBJECT(tool));
+ gtk_object_unref(GTK_OBJECT(view));
+ tool->num_views = tool->num_views - 1;
+ if (tool->num_views == 0)
+ {
+ g_array_free(tool->view_items, TRUE);
+ tool->view_items = NULL;
+ }
+ return TRUE;
+}
+
+
+static void gv_autopan_tool_sv_draw(GvTool *tool, GvViewArea *view)
+{
+ int i;
+ GvAutopanViewItem *item;
+ GvAutopanTrailTile *tile;
+ GLuint texName;
+ gvgeocoord xmin, xmax, ymin, ymax;
+ gvgeocoord x1, y1, x2, y2, x3, y3, x4, y4;
+ gvgeocoord dx=6.0, dy=0.0, xc=0.0, yc=0.0;
+
+ if (GV_AUTOPAN_TOOL(tool)->play_flag == 0)
+ return;
+
+ item = &(g_array_index(GV_AUTOPAN_TOOL(tool)->view_items,
+ GvAutopanViewItem, 0));
+ for (i=0; i<GV_AUTOPAN_TOOL(tool)->num_views; i++)
+ {
+ item = &(g_array_index(GV_AUTOPAN_TOOL(tool)->view_items,
+ GvAutopanViewItem, i));
+ if (item->view == view)
+ break;
+ }
+
+ if (( item->trail_mode > 0 ) &&
+ (GV_AUTOPAN_TOOL(tool)->num_trail_tiles > 0))
+ {
+ glColor4fv( item->trail_color );
+
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ glEnable( GL_TEXTURE_2D );
+
+ // May need to uncomment the next four lines at some point-
+ // gvrasterlayer.c does in its draw function...not sure why...
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+
+ glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ for (i=0; i<GV_AUTOPAN_TOOL(tool)->num_trail_tiles; i++)
+ {
+ tile = (GvAutopanTrailTile *) &g_array_index(
+ GV_AUTOPAN_TOOL(tool)->trail,
+ GvAutopanTrailTile, i);
+ texName = g_array_index(item->trail_textures, GLuint, i);
+ glBindTexture(GL_TEXTURE_2D, texName);
+
+ xmin = tile->x0;
+ ymin = tile->y0;
+ xmax = tile->xf;
+ ymax = tile->yf;
+
+ x1 = x4 = xmin;
+ y3 = y4 = ymin;
+ x2 = x3 = xmax;
+ y1 = y2 = ymax;
+
+ if ( map_view_to_view_xy(tool->view, view, &x1, &y1) &&
+ map_view_to_view_xy(tool->view, view, &x2, &y2) &&
+ map_view_to_view_xy(tool->view, view, &x3, &y3) &&
+ map_view_to_view_xy(tool->view, view, &x4, &y4) )
+ {
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0,1.0); glVertex2f(x1,y1);
+ glTexCoord2f(1.0,1.0); glVertex2f(x2,y2);
+ glTexCoord2f(1.0,0.0); glVertex2f(x3,y3);
+ glTexCoord2f(0.0,0.0); glVertex2f(x4,y4);
+ glEnd();
+ }
+ }
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_BLEND );
+ }
+
+ gv_view_area_get_extents(tool->view, &xmin, &ymin, &xmax, &ymax);
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ x1 = xmin;
+ y1 = ymin;
+ x2 = xmin;
+ y2 = ymax;
+ x3 = xmax;
+ y3 = ymax;
+ x4 = xmax;
+ y4 = ymin;
+
+ xc = (xmin + xmax)/2.0;
+ yc = (ymin + ymax)/2.0;
+
+ if ( !map_view_to_view_xy(tool->view, view, &x1, &y1) ||
+ !map_view_to_view_xy(tool->view, view, &x2, &y2) ||
+ !map_view_to_view_xy(tool->view, view, &x3, &y3) ||
+ !map_view_to_view_xy(tool->view, view, &x4, &y4) ||
+ !map_view_to_view_xy(tool->view, view, &xc, &yc) )
+ {
+ CPLDebug( "GvAutopan", "gv_reproject_points(%s,%s) failed.",
+ gv_view_area_get_projection(tool->view),
+ gv_view_area_get_projection(view) );
+ return;
+ }
+
+
+ glColor3f(0.0,0.5,1.0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x1, y1);
+ glVertex2(x2, y2);
+ glVertex2(x3, y3);
+ glVertex2(x4, y4);
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex3(xc-dx, yc,0.0);
+ glVertex3( xc+dx, yc,0.0);
+ glVertex3( xc, yc-dx,0.0);
+ glVertex3( xc, yc+dx,0.0);
+ glEnd();
+
+}
+
+static void gv_autopan_tool_sv_button_press(GtkWidget *view,
+ GdkEventButton *event,
+ gpointer *data_tool)
+{
+ int i, viewidx;
+ GvAutopanViewItem *item;
+ GvAutopanTool *tool;
+ gint pick;
+
+ /* TODO:
+ * - try to select a border (can_resize=1) and/or
+ * the center (can_reposition=1). If neither is
+ * selected, return.
+ * - record whether or not tool is playing
+ * - if it is playing, pause
+ * - send a zoomextents-changing signal
+ */
+
+ if ( (event->type != GDK_BUTTON_PRESS) ||
+ (event->button != 1) )
+ return;
+
+
+ tool = (GvAutopanTool *) data_tool;
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if ( item->view == (GvViewArea *) view)
+ viewidx = i;
+ }
+
+ if (viewidx < 0)
+ {
+ g_error("View not found in autopan tool list!");
+ return;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+
+ if ((item->can_resize == 0) && (item->can_reposition == 0))
+ return;
+
+ pick = gv_autopan_tool_pick(tool, (GvViewArea *) view, event->x, event->y);
+ if (( pick == PICK_CENTER ) && ( item->can_reposition == 1 ) )
+ {
+ item->translating = 1;
+ item->play_flag = tool->play_flag;
+ gv_autopan_tool_pause(tool);
+ }
+}
+
+static void gv_autopan_tool_sv_button_release(GtkWidget *view,
+ GdkEventButton *event,
+ gpointer *data_tool)
+{
+ int i, viewidx;
+ GvAutopanViewItem *item;
+ GvAutopanTool *tool;
+ gvgeocoord gx=0.0, gy=0.0;
+
+ /* TODO:
+ * - reset extents
+ * - send a zoomextents-changed signal
+ * - if tool was playing, restart
+ */
+
+ tool = (GvAutopanTool *) data_tool;
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if (item->view == (GvViewArea *) view)
+ viewidx = i;
+ }
+
+ if (viewidx < 0)
+ {
+ g_error("View not found in autopan tool list!");
+ return;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+
+ if ((item->can_resize == 0) && (item->can_reposition == 0))
+ return;
+
+ if (item->translating == 1)
+ {
+ gv_view_area_map_pointer(item->view, event->x, event->y, &gx, &gy);
+ map_view_to_view_xy(item->view, ((GvTool *) tool)->view, &gx, &gy);
+ gv_autopan_tool_set_location(tool, gx, gy, 0);
+
+ if ( item->play_flag == 1 )
+ {
+ item->play_flag = 0;
+ item->translating = 0;
+ gv_autopan_tool_play(tool);
+ }
+ else
+ {
+ item->play_flag = 0;
+ item->translating = 0;
+ }
+ }
+
+}
+
+static void gv_autopan_tool_sv_motion_notify(GtkWidget *view,
+ GdkEventMotion *event,
+ gpointer *data_tool)
+{
+ int i, viewidx, sv_idx;
+ GvVertex3d *nloc;
+ GvAutopanViewItem *item;
+ GvAutopanViewItem *sv;
+ GvAutopanTool *tool;
+ gvgeocoord gx=0.0, gy=0.0;
+
+ /* TODO:
+ * - redraw the box in the view and in other secondary views,
+ * making sure that box is snapped to correct aspect ratio.
+ */
+
+ tool = (GvAutopanTool *) data_tool;
+
+ viewidx = -1;
+ for (i=0; i<tool->num_views; i++)
+ {
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, i));
+ if (item->view == (GvViewArea *) view)
+ viewidx = i;
+ }
+
+ if (viewidx < 0)
+ {
+ g_error("View not found in autopan tool list!");
+ return;
+ }
+
+ item = &(g_array_index(tool->view_items, GvAutopanViewItem, viewidx));
+
+ if ((item->can_resize == 0) && (item->can_reposition == 0))
+ return;
+
+ if ( item->translating == 1 )
+ {
+ gv_view_area_map_pointer(item->view, event->x, event->y, &gx, &gy);
+ map_view_to_view_xy(item->view, ((GvTool *) tool)->view, &gx, &gy);
+ gv_autopan_tool_set_location(tool, gx, gy, 0);
+ nloc = &( g_array_index( tool->centers, GvVertex3d,
+ tool->current_index) );
+
+ gv_view_area_set_translation(GV_TOOL(tool)->view, nloc->x, nloc->y);
+ for (sv_idx = 0; sv_idx < tool->num_views; sv_idx++)
+ {
+ sv = &(g_array_index(tool->view_items, GvAutopanViewItem,
+ sv_idx));
+ gv_view_area_queue_draw(sv->view);
+ }
+ }
+
+}
+
+static gint
+gv_autopan_tool_pick(GvAutopanTool *tool, GvViewArea *view,
+ gvgeocoord x, gvgeocoord y)
+{
+ gvgeocoord xmin, xmax, ymin, ymax;
+ gvgeocoord dx=6.0, dy=0.0, xc=0.0, yc=0.0;
+ gvgeocoord x1, y1, x2, y2, x3, y3, x4, y4;
+
+ GLuint buf[20];
+ GLint hits;
+ GLint vp[4];
+
+ gv_view_area_get_extents(((GvTool *) tool)->view, &xmin, &ymin, &xmax, &ymax);
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ x1 = xmin;
+ y1 = ymin;
+ x2 = xmin;
+ y2 = ymax;
+ x3 = xmax;
+ y3 = ymax;
+ x4 = xmax;
+ y4 = ymin;
+
+ xc = (xmin + xmax)/2.0;
+ yc = (ymin + ymax)/2.0;
+
+ if ( !map_view_to_view_xy(((GvTool *) tool)->view, view, &x1, &y1) ||
+ !map_view_to_view_xy(((GvTool *) tool)->view, view, &x2, &y2) ||
+ !map_view_to_view_xy(((GvTool *) tool)->view, view, &x3, &y3) ||
+ !map_view_to_view_xy(((GvTool *) tool)->view, view, &x4, &y4) ||
+ !map_view_to_view_xy(((GvTool *) tool)->view, view, &xc, &yc) )
+ {
+ CPLDebug( "GvAutopan", "gv_reproject_points(%s,%s) failed.",
+ gv_view_area_get_projection(((GvTool *) tool)->view),
+ gv_view_area_get_projection(view) );
+ }
+
+ vp[0] = vp[1] = 0;
+ vp[2] = (GLint)view->state.shape_x;
+ vp[3] = (GLint)view->state.shape_y;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPickMatrix(x, vp[3]-y, PICK_SIZE, PICK_SIZE, vp);
+ gluOrtho2D(-vp[2]/2.0, vp[2]/2.0, -vp[3]/2.0, vp[3]/2.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+
+ glSelectBuffer(20, buf);
+ glRenderMode(GL_SELECT);
+
+ glInitNames();
+ glPushName(-1);
+
+ /* Center */
+ glLoadName(4);
+ glBegin(GL_LINES);
+ glVertex2(xc-dx, yc);
+ glVertex2(xc+dx, yc);
+ glVertex2(xc, yc-dx);
+ glVertex2(xc, yc+dx);
+ glEnd();
+
+ /* Top */
+ glLoadName(0);
+ glBegin(GL_LINES);
+ glVertex2(x1, y1);
+ glVertex2(x4, y4);
+ glEnd();
+
+ /* Right */
+ glLoadName(1);
+ glBegin(GL_LINES);
+ glVertex2(x4, y4);
+ glVertex2(x3, y3);
+ glEnd();
+
+ /* Bottom */
+ glLoadName(2);
+ glBegin(GL_LINES);
+ glVertex2(x2, y2);
+ glVertex2(x3, y3);
+ glEnd();
+
+ /* Left */
+ glLoadName(3);
+ glBegin(GL_LINES);
+ glVertex2(x1, y1);
+ glVertex2(x2, y2);
+ glEnd();
+
+
+ hits = glRenderMode(GL_RENDER);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ /* We're only concerned with the first hit */
+ if (hits >= 1)
+ return buf[3]+1;
+
+ /* No hits */
+ return PICK_NONE;
+}
+
+/* Map xy in view1 to xy in view2. Returns TRUE if
+ * successful; FALSE otherwise.
+ */
+
+static gint map_view_to_view_xy(GvViewArea *view1, GvViewArea *view2,
+ gvgeocoord *x, gvgeocoord *y)
+{
+ GvRasterLayer *rst1, *rst2;
+ double xd, yd;
+
+ xd = (double) *x;
+ yd = (double) *y;
+
+ if (gv_view_area_get_primary_raster(view1) != NULL)
+ {
+ rst1 = GV_RASTER_LAYER(gv_view_area_get_primary_raster(view1));
+
+ if( gv_view_area_get_raw(view1,NULL) )
+ gv_raster_pixel_to_georef( rst1->prototype_data, &xd, &yd, NULL );
+ }
+
+ if( gv_view_area_get_projection(view1) != NULL
+ && gv_view_area_get_projection(view2) != NULL
+ && !EQUAL(gv_view_area_get_projection(view1),
+ gv_view_area_get_projection(view2))
+ && !EQUAL(gv_view_area_get_projection(view1),"PIXEL")
+ && !EQUAL(gv_view_area_get_projection(view2),"PIXEL") )
+ {
+ if( !gv_reproject_points( gv_view_area_get_projection(view1),
+ gv_view_area_get_projection(view2),
+ 1, &xd, &yd, NULL )
+ )
+ return FALSE;
+ }
+
+ if (gv_view_area_get_primary_raster(view2) != NULL)
+ {
+ rst2 = GV_RASTER_LAYER(gv_view_area_get_primary_raster(view2));
+
+ if( gv_view_area_get_raw(view2,NULL) )
+ gv_raster_georef_to_pixel( rst2->prototype_data, &xd, &yd, NULL );
+ }
+
+ *x = (gvgeocoord) xd;
+ *y = (gvgeocoord) yd;
+
+ return TRUE;
+
+}
+
+/* Trail-related functions */
+gint gv_autopan_tool_set_trail_parameters(GvAutopanTool *tool,
+ GvRect *overview_extents,
+ int overview_width_pixels)
+{
+ gint i,j, xnum, ynum;
+
+ gv_autopan_tool_clear_trail( tool );
+
+ /* set extents */
+ tool->trail_overview_region.x = overview_extents->x;
+ tool->trail_overview_region.y = overview_extents->y;
+ tool->trail_overview_region.width = overview_extents->width;
+ tool->trail_overview_region.height = overview_extents->height;
+ tool->trail_overview_width_pixels = overview_width_pixels;
+
+ tool->trail_x0 = overview_extents->x;
+ tool->trail_y0 = overview_extents->y;
+ tool->trail_tile_xsize = overview_extents->width*tool->trail_tile_pixels/overview_width_pixels;
+ tool->trail_tile_ysize = tool->trail_tile_xsize;
+
+ /* initialize new tiles */
+ xnum = (int) ceil(overview_width_pixels/tool->trail_tile_pixels);
+ ynum = (int) ceil((overview_width_pixels/tool->trail_tile_lines)*
+ (overview_extents->height/overview_extents->width));
+
+ for ( i = 0; i < xnum; i++ )
+ {
+ for ( j = 0; j < ynum; j++ )
+ new_trail_tile( tool, i, j );
+ }
+
+ return TRUE;
+}
+
+void gv_autopan_tool_get_trail_parameters(GvAutopanTool *tool,
+ GvRect *overview_extents,
+ int *overview_width_pixels,
+ int *num_trail_tiles)
+{
+ overview_extents->x = tool->trail_overview_region.x;
+ overview_extents->y = tool->trail_overview_region.y;
+ overview_extents->width = tool->trail_overview_region.width;
+ overview_extents->height = tool->trail_overview_region.height;
+ *overview_width_pixels = tool->trail_overview_width_pixels;
+ *num_trail_tiles = tool->num_trail_tiles;
+}
+
+gint gv_autopan_tool_save_trail_tiles(GvAutopanTool *tool,
+ const char *basename)
+{
+ GvAutopanTrailTile *tile;
+ GDALDriverH driver;
+ GDALDatasetH dataset;
+ GDALRasterBandH band;
+ double gt[6];
+
+ int i, blen;
+ char *name_buf;
+ char xindex[25];
+ char yindex[25];
+
+ if (tool->num_trail_tiles < 1)
+ return 0;
+
+ driver = GDALGetDriverByName( "GTiff" );
+ if( driver == NULL )
+ return -1;
+
+ blen = strlen(basename);
+ name_buf = (char *) malloc( sizeof(char)*(blen+10) );
+
+ for ( i = 0; i < tool->num_trail_tiles; i++ )
+ {
+ tile = &(g_array_index(tool->trail, GvAutopanTrailTile, i ));
+ sprintf(name_buf,"%s%d",basename,i);
+ sprintf(xindex,"%d",tile->xindex);
+ sprintf(yindex,"%d",tile->yindex);
+ //dataset = GDALCreate( driver, name_buf,
+ // tile->pixels,
+ dataset = GDALCreate( driver, name_buf,
+ 2*tile->pixels, tile->lines, 1, GDT_Byte,
+ NULL );
+ GDALSetMetadataItem( dataset, "xindex", xindex, NULL );
+ GDALSetMetadataItem( dataset, "yindex", yindex, NULL );
+ gt[0] = tile->x0;
+ gt[1] = (tile->xf - tile->x0)/tile->pixels;
+ gt[2] = 0;
+ gt[3] = tile->y0;
+ gt[4] = 0;
+ gt[5] = (tile->yf - tile->y0)/tile->lines;
+ GDALSetGeoTransform( dataset, gt );
+ band = GDALGetRasterBand( dataset, 1 );
+ //GDALRasterIO( band, GF_Write, 0, 0, tile->pixels, tile->lines,
+ // tile->mask, tile->pixels, tile->lines, GDT_Byte,
+ // 2, 2*tile->pixels );
+ GDALRasterIO( band, GF_Write, 0, 0, 2*tile->pixels, tile->lines,
+ tile->mask, 2*tile->pixels, tile->lines, GDT_Byte,
+ 1, 2*tile->pixels );
+
+ GDALClose( dataset );
+ }
+
+ free(name_buf);
+
+ return tool->num_trail_tiles;
+
+}
+
+gint gv_autopan_tool_load_trail_tiles(GvAutopanTool *tool,
+ const char *basename,
+ int num_trail_tiles)
+{
+ /*
+ * Note: trail parameters (overview region, overview width in pixels)
+ * must be set properly before this function is called.
+ */
+
+ GvAutopanTrailTile *tile;
+ GvAutopanViewItem *item;
+ GLuint texName;
+ GDALDatasetH dataset;
+ GDALRasterBandH band;
+ int i, blen, xindex, yindex, idx;
+ char *name_buf;
+
+ gv_autopan_tool_clear_trail( tool );
+
+ if (num_trail_tiles < 1)
+ return 0;
+
+ blen = strlen(basename);
+ name_buf = (char *) malloc( sizeof(char)*(blen+10) );
+
+ for ( i = 0; i < num_trail_tiles; i++ )
+ {
+ sprintf(name_buf,"%s%d",basename,i);
+ dataset = GDALOpen( name_buf, GA_ReadOnly);
+ xindex = atoi(GDALGetMetadataItem( dataset, "xindex", NULL ));
+ yindex = atoi(GDALGetMetadataItem( dataset, "yindex", NULL ));
+ new_trail_tile(tool,xindex,yindex);
+ tile = &(g_array_index(tool->trail, GvAutopanTrailTile, tool->num_trail_tiles - 1 ));
+ band = GDALGetRasterBand( dataset, 1 );
+ //GDALRasterIO( band, GF_Read, 0, 0, tile->pixels, tile->lines,
+ // tile->mask, 2*tile->pixels, tile->lines, GDT_Byte,
+ // 1, tile->pixels );
+ GDALRasterIO( band, GF_Read, 0, 0, 2*tile->pixels, tile->lines,
+ tile->mask, 2*tile->pixels, tile->lines, GDT_Byte,
+ 1, 2*tile->pixels );
+ GDALClose( dataset );
+
+ // update textures for views
+ for ( idx = 0; idx < tool->num_views; idx++ )
+ {
+ item = &(g_array_index(tool->view_items,
+ GvAutopanViewItem, idx));
+
+ if ( item->trail_mode < 1 )
+ continue;
+
+ /* Appropriate view must be active in order to update texture; */
+ /* otherwise changes won't show up. */
+ if (!gtk_gl_area_make_current( GTK_GL_AREA(item->view) ))
+ g_warning("gv_autopan_tool_load_trail_tiles: Unable to make view current, trail may not update properly!");
+
+ texName = g_array_index( item->trail_textures, GLuint, tool->num_trail_tiles - 1 );
+ glBindTexture(GL_TEXTURE_2D,texName);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tile->pixels, tile->lines,
+ GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tile->mask);
+ }
+ }
+
+ free(name_buf);
+
+ return num_trail_tiles;
+}
+
+static void new_trail_tile( GvAutopanTool *tool, gint xindex, gint yindex)
+{
+ GvAutopanTrailTile newtile;
+ int idx;
+ int pixel_count = tool->trail_tile_pixels*tool->trail_tile_lines;
+ GvAutopanViewItem *item;
+ GLuint texName;
+
+
+ newtile.xindex = xindex;
+ newtile.yindex = yindex;
+ newtile.pixels = tool->trail_tile_pixels;
+ newtile.lines = tool->trail_tile_lines;
+ newtile.x0 = tool->trail_x0 + tool->trail_tile_xsize*xindex;
+ newtile.y0 = tool->trail_y0 + tool->trail_tile_ysize*yindex;
+ newtile.xf = tool->trail_x0 + tool->trail_tile_xsize*(xindex + 1);
+ newtile.yf = tool->trail_y0 + tool->trail_tile_ysize*(yindex + 1);
+
+ newtile.mask = (unsigned char *) g_malloc( pixel_count*2 );
+ memset( newtile.mask, 0, pixel_count*2 );
+
+ if ( tool->trail == NULL )
+ tool->trail = g_array_new(FALSE,FALSE, sizeof(GvAutopanTrailTile));
+
+ g_array_append_val( tool->trail, newtile);
+ tool->num_trail_tiles = tool->num_trail_tiles + 1;
+
+ for (idx = 0; idx < tool->num_views; idx++)
+ {
+ item = &(g_array_index(tool->view_items,
+ GvAutopanViewItem, 0));
+
+ if ( item->trail_mode < 1 )
+ continue;
+
+ if (item->trail_textures == NULL)
+ {
+ create_trail_textures( tool, item );
+ }
+ else
+ {
+ /* View that texture is going to be displayed in must be the */
+ /* current context when that texture is generated or updated */
+ /* There is supposedly a way to share contexts between views, */
+ /* but that hasn't been used here... */
+ if (!gtk_gl_area_make_current( GTK_GL_AREA(item->view) ))
+ g_warning("new_trail_tile: Unable to make view current, trail may not update properly!");
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glGenTextures(1,&texName);
+ glBindTexture(GL_TEXTURE_2D, texName);
+ /* The next parameters need to be set whenever a texture is
+ * created (tried just putting them in draw function;
+ * things didn't work- entire rectangle goes solid-coloured)
+ */
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE_ALPHA,newtile.pixels,
+ newtile.lines, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, newtile.mask);
+ g_array_append_val( item->trail_textures, texName);
+ }
+
+ }
+}
+
+
+static void update_trail( GvAutopanTool *tool, gvgeocoord xmin, gvgeocoord ymin,
+ gvgeocoord width, gvgeocoord height )
+{
+ int xs,xe,ys,ye, i, j, k, p1, p2, l1, l2, offset, pd, tidx;
+ GvAutopanTrailTile *tile;
+ GvAutopanViewItem *item;
+ GLuint texName;
+
+
+ xs = (int) floor((xmin - tool->trail_x0)/tool->trail_tile_xsize);
+ xe = (int) floor((xmin + width - tool->trail_x0)/tool->trail_tile_xsize);
+ ys = (int) floor((ymin - tool->trail_y0)/tool->trail_tile_ysize);
+ ye = (int) floor((ymin + height - tool->trail_y0)/tool->trail_tile_ysize);
+
+ /* Note: tiles currently aren't indexed/sorted because it is assumed there
+ won't be very many, so the search time shouldn't significantly
+ slow things down.
+ */
+ for ( i = xs; i <= xe; i++ )
+ {
+ for ( j = ys; j <= ye; j++ )
+ {
+ tile = NULL;
+ for (k = 0; k < tool->num_trail_tiles; k++)
+ {
+ tile = &(g_array_index(tool->trail, GvAutopanTrailTile, k));
+ if ((i == tile->xindex) && (j == tile->yindex))
+ break;
+ tile = NULL;
+ }
+ tidx = k;
+ if (tile == NULL)
+ {
+ new_trail_tile( tool, i, j );
+ tile = &(g_array_index(tool->trail, GvAutopanTrailTile,
+ tool->num_trail_tiles - 1 ));
+ tidx = tool->num_trail_tiles - 1;
+ }
+ p1 = (int) floor(((xmin - tile->x0)*
+ tool->trail_tile_pixels/tool->trail_tile_xsize) + 0.5);
+ p2 = (int) floor(((xmin + width - tile->x0)*
+ tool->trail_tile_pixels/tool->trail_tile_xsize) + 0.5);
+ l1 = (int) floor(((ymin - tile->y0)*
+ tool->trail_tile_lines/tool->trail_tile_ysize) + 0.5);
+ l2 = (int) floor(((ymin + height - tile->y0)*
+ tool->trail_tile_lines/tool->trail_tile_ysize) + 0.5);
+
+ p1 = MIN(tool->trail_tile_pixels-1,MAX(p1,0));
+ p2 = MIN(tool->trail_tile_pixels-1,MAX(p2,0));
+ l1 = MIN(tool->trail_tile_lines-1,MAX(l1,0));
+ l2 = MIN(tool->trail_tile_lines-1,MAX(l2,0));
+
+ if ((l1 >= l2) || (p1 >= p2))
+ continue;
+ pd = (p2-p1+1)*2;
+ /* If saving wasn't needed, could use mask only for initializing
+ * and work with textures only after that point, I think.
+ */
+ for (k = l1; k<=l2; k++)
+ {
+ offset = p1*2 + k*tool->trail_tile_pixels*2;
+ memset(tile->mask + offset, 255, pd);
+ }
+
+ for ( k = 0; k < tool->num_views; k++ )
+ {
+ item = &(g_array_index(tool->view_items,
+ GvAutopanViewItem, k));
+
+ if ( item->trail_mode < 1 )
+ continue;
+
+ /* Appropriate view must be active in order to update texture; */
+ /* otherwise changes won't show up. */
+ if (!gtk_gl_area_make_current( GTK_GL_AREA(item->view) ))
+ g_warning("update_trail: Unable to make view current, trail may not update properly!");
+
+ texName = g_array_index( item->trail_textures, GLuint, tidx );
+ glBindTexture(GL_TEXTURE_2D,texName);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, p1, l1, p2-p1+1, l2-l1+1,
+ GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tool->trail_block);
+ }
+ }
+ }
+}
+
+static void create_trail_textures(GvAutopanTool *tool, GvAutopanViewItem *item)
+{
+ int i;
+ GvAutopanTrailTile *tile;
+ GLuint texName;
+
+ if ( item->trail_textures != NULL )
+ g_warning("create_trail_textures: textures unexpectedly not null!");
+
+ item->trail_textures = g_array_new(FALSE,FALSE,sizeof(GLuint));
+
+ if (!gtk_gl_area_make_current( GTK_GL_AREA(item->view) ))
+ g_warning("new_trail_tile: Unable to make view current, trail may not update properly!");
+
+ for ( i = 0; i < tool->num_trail_tiles; i++ )
+ {
+ tile = &(g_array_index(tool->trail,
+ GvAutopanTrailTile, i));
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ glGenTextures(1,&texName);
+ glBindTexture(GL_TEXTURE_2D, texName);
+ /* The next parameters need to be set whenever a texture is
+ * created (tried just putting them in draw function;
+ * things didn't work- entire rectangle goes solid-coloured)
+ */
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE_ALPHA,tile->pixels,
+ tile->lines, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tile->mask);
+ g_array_append_val( item->trail_textures, texName);
+ }
+}
Added: packages/openev/branches/upstream/current/gvautopan.h
===================================================================
--- packages/openev/branches/upstream/current/gvautopan.h (rev 0)
+++ packages/openev/branches/upstream/current/gvautopan.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,335 @@
+/******************************************************************************
+ * $Id: gvautopan.h,v 1.3 2005/09/12 15:33:10 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Auto-panning tool. Scans systematically over an area or along
+ * a preset path.
+ * Author: Gillian Walter
+ *
+ * Developed by Atlantis Scientific Inc. (www.atlantis-scientific.com) for
+ * DRDC Ottawa.
+ *
+ ******************************************************************************
+ * Copyright (c) Her majesty the Queen in right of Canada as represented
+ * by the Minister of National Defence, 2004.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvautopan.h,v $
+ * Revision 1.3 2005/09/12 15:33:10 gmwalter
+ * Update autopan tool for line paths.
+ *
+ * Revision 1.2 2005/02/22 13:22:36 gmwalter
+ * Add autopan tool.
+ *
+ * Revision 1.1.2.5 2005/01/29 04:01:11 gmwalter
+ * Initial support for autopan trail.
+ *
+ * Revision 1.1.2.4 2005/01/20 15:20:08 gmwalter
+ * Add ability to change standard path.
+ *
+ * Revision 1.1.2.3 2005/01/05 21:22:23 gmwalter
+ * Updated autopan tool to add more functions.
+ *
+ * Revision 1.1.2.2 2004/12/21 15:10:26 gmwalter
+ * Add ability to relocate zoomed region by
+ * dragging in secondary view.
+ *
+ * Revision 1.1.2.1 2004/12/09 16:58:28 gmwalter
+ * Add initial autopan support.
+ *
+ *
+ *
+ */
+
+
+#ifndef __GV_AUTOPAN_TOOL_H__
+#define __GV_AUTOPAN_TOOL_H__
+
+#include "gvtypes.h"
+#include "gvtool.h"
+#include "gvrasterlayer.h"
+#include "gvshapes.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#define GV_TYPE_AUTOPAN_TOOL (gv_autopan_tool_get_type ())
+#define GV_AUTOPAN_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_AUTOPAN_TOOL, GvAutopanTool))
+#define GV_AUTOPAN_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_AUTOPAN_TOOL, GvAutopanToolClass))
+#define GV_IS_AUTOPAN_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_AUTOPAN_TOOL))
+#define GV_IS_AUTOPAN_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_AUTOPAN_TOOL))
+
+typedef struct _GvAutopanTool GvAutopanTool;
+typedef struct _GvAutopanToolClass GvAutopanToolClass;
+typedef struct _GvAutopanViewItem GvAutopanViewItem;
+typedef struct _GvAutopanTrailTile GvAutopanTrailTile;
+
+
+
+enum
+{
+ TL_R_D_L_D = 0, /* Start top left, go right, down, left, down, right... */
+ BL_R_U_L_U, /* Start bottom left, go right, up, left, up, right... */
+ TR_L_D_R_D,
+ BR_L_U_R_U,
+ TL_R_D_R_D, /* Start top left, go right, jump down and to left edge, go right... */
+ /* TL_D_R_D_R, Start top left, go down, jump right and to top edge, go down... */
+ STANDARD_PATHS
+};
+
+#define LINES_PATH -1
+
+struct _GvAutopanTool
+{
+ GvTool tool;
+
+ guint quit_handler_id;
+
+ /* play_flag: 0- not playing, 1- playing, 2- paused */
+ gint play_flag;
+
+ /* Route to follow in panning: -1 for non-standard, 0...STANDARD_PATHS-1
+ * for preset path coverage. non-standard is not implemented yet.
+ *
+ * standard paths cover the tool's current extents completely in a
+ * regular fashion.
+ *
+ * non-standard will allow the user to provide a set of points that
+ * define a path to follow: the locations will be interpolated from
+ * this path (the number of locations between points will depend on
+ * the current speed settings).
+ */
+
+ gint path_type;
+
+ GvShapes *nonstandard_path_shapes;
+
+ /* Track changes that user makes to window size and zoom level,
+ * and reset accordingly.
+ */
+
+ gvgeocoord win_width, win_height, win_zoom;
+
+ /* Default settings:
+ * - pan_region: extents (can't just use tool boundaries
+ * because locations have to be recalculated when extents are
+ * reset). Only used for standard paths.
+ * - overlap (perpendicular to path direction, as a fraction
+ * of the extents in that direction)
+ * - speed (panning speed- appropriate values will be machine
+ * dependent- set negative to go in reverse direction)
+ */
+
+ GvRect pan_region;
+ gvgeocoord overlap; /* only used for standard paths */
+ gvgeocoord speed;
+
+
+ /* Block size mode: user has different options in how block
+ * size is set.
+ *
+ * block_size_mode = 0:
+ * - user sets block_x_size to a float between 0 and 1,
+ * corresponding to the block size as a fraction of the
+ * total x extents (block_y_size will be determined by
+ * block_x_size and the window's aspect ratio). resolution
+ * is ignored in this mode.
+ *
+ * block_size_mode = 1:
+ * - same as mode 0, except that block_x_size is in view
+ * coordinates rather than a fraction of total x extents
+ * to be panned.
+ *
+ * block_size_mode = 2:
+ * - block size is set so that the size of pixels in the
+ * view will be constant at "resolution".
+ */
+
+ gint block_size_mode;
+
+ gvgeocoord block_x_size;
+
+ gvgeocoord resolution;
+
+ gint current_index;
+
+ /* list of sequential translates for panning */
+ GArray *centers;
+ gint num_centers;
+
+ /* trail info */
+ /* Predicted region that trail will cover: can go outside; just */
+ /* used in resolution calculations. */
+ /* Overview_width_pixels should correspond to maximum resoluiont */
+ /* required by all overview windows. */
+ GvRect trail_overview_region;
+ gint trail_overview_width_pixels;
+
+ gint trail_tile_pixels;
+ gint trail_tile_lines;
+
+ /* Next four parameters are calculated based on overview info */
+ gvgeocoord trail_x0;
+ gvgeocoord trail_y0;
+ gvgeocoord trail_tile_xsize;
+ gvgeocoord trail_tile_ysize;
+
+ GArray *trail;
+ gint num_trail_tiles;
+ gint trail_mode; /* Number of views showing a trail */
+ GLuint *trail_block; /* Used to selectively replace parts of a texture */
+
+
+
+ /* optional secondary views in which to draw a box
+ indicating current location.
+ view- gvviewarea
+ can_resize- whether or not the current panning
+ resolution can be reset by dragging
+ a corner of the box in the view.
+ can_relocate- whether or not the current position
+ can be reset by selecting a boundary
+ of the box and dragging the box in
+ the view.
+ trail_mode- whether or not the view should display a
+ trail where user has already panned.
+ */
+ GArray *view_items;
+
+ gint num_views;
+
+};
+
+
+struct _GvAutopanTrailTile
+{
+ gint xindex;
+ gint yindex;
+ gint pixels;
+ gint lines;
+
+ gvgeocoord x0;
+ gvgeocoord y0;
+ gvgeocoord xf;
+ gvgeocoord yf;
+
+ unsigned char *mask;
+};
+
+struct _GvAutopanViewItem
+{
+ GvViewArea *view;
+ GvAutopanTool *tool;
+
+ gint can_resize;
+ gint can_reposition;
+ gint trail_mode;
+
+ gint banding;
+ gint translating;
+ gint play_flag;
+ GvColor trail_color;
+ GArray *trail_textures;
+
+ /* Store connections for later disconnect */
+ gint press_id;
+ gint release_id;
+ gint motion_id;
+};
+
+struct _GvAutopanToolClass
+{
+ GvToolClass parent_class;
+
+ void (* zoomextents_changed)(GvAutopanTool *tool);
+ void (* zoomextents_changing)(GvAutopanTool *tool);
+};
+
+
+GtkType gv_autopan_tool_get_type(void);
+GvTool* gv_autopan_tool_new(void);
+
+gint gv_autopan_tool_play(GvAutopanTool *tool);
+gint gv_autopan_tool_pause(GvAutopanTool *tool);
+gint gv_autopan_tool_stop(GvAutopanTool *tool);
+
+double gv_autopan_tool_set_speed(GvAutopanTool *tool, gvgeocoord speed);
+double gv_autopan_tool_get_speed(GvAutopanTool *tool);
+
+gint gv_autopan_tool_new_rect(GvAutopanTool *tool, GvRect *rect);
+gint gv_autopan_tool_get_rect(GvAutopanTool *tool, GvRect *rect);
+
+gint gv_autopan_tool_set_location(GvAutopanTool *tool, gvgeocoord x,
+ gvgeocoord y, gvgeocoord z);
+gint gv_autopan_tool_get_location(GvAutopanTool *tool, gvgeocoord *x,
+ gvgeocoord *y, gvgeocoord *z);
+
+gint gv_autopan_tool_set_overlap(GvAutopanTool *tool, gvgeocoord overlap);
+double gv_autopan_tool_get_overlap(GvAutopanTool *tool);
+
+gint gv_autopan_tool_set_block_x_size(GvAutopanTool *tool,
+ gvgeocoord block_x_size,
+ gint mode);
+gint gv_autopan_tool_set_x_resolution(GvAutopanTool *tool,
+ gvgeocoord resolution);
+
+gint gv_autopan_tool_set_standard_path(GvAutopanTool *tool, gint path_type);
+
+void gv_autopan_tool_get_state(GvAutopanTool *tool,
+ gint *play_flag,
+ gint *path_type,
+ gint *block_size_mode,
+ gvgeocoord *block_x_size,
+ gvgeocoord *x_resolution,
+ gint *num_views);
+
+void gv_autopan_tool_clear_trail(GvAutopanTool *tool);
+
+gint gv_autopan_tool_set_trail_color(GvAutopanTool *tool, GvViewArea *view,
+ float red, float green, float blue,
+ float alpha);
+
+gint gv_autopan_tool_set_trail_mode( GvAutopanTool *tool, GvViewArea *view,
+ gint trail_mode);
+
+gint gv_autopan_tool_register_view(GvAutopanTool *tool, GvViewArea *view,
+ gint can_resize, gint can_reposition,
+ gint trail_mode);
+
+gint gv_autopan_tool_remove_view(GvAutopanTool *tool, GvViewArea *view);
+
+gint gv_autopan_tool_set_lines_path(GvAutopanTool *tool, GvShapes *lines);
+
+gint gv_autopan_tool_set_trail_parameters(GvAutopanTool *tool,
+ GvRect *overview_extents,
+ int overview_width_pixels);
+
+void gv_autopan_tool_get_trail_parameters(GvAutopanTool *tool,
+ GvRect *overview_extents,
+ int *overview_width_pixels,
+ int *num_trail_tiles);
+
+gint gv_autopan_tool_save_trail_tiles(GvAutopanTool *tool,
+ const char *basename);
+
+gint gv_autopan_tool_load_trail_tiles(GvAutopanTool *tool,
+ const char *basename,
+ int num_trail_tiles);
+
+
+
+#endif /* __GV_AUTOPAN_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvdata.c
===================================================================
--- packages/openev/branches/upstream/current/gvdata.c (rev 0)
+++ packages/openev/branches/upstream/current/gvdata.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,457 @@
+/******************************************************************************
+ * $Id: gvdata.c,v 1.15 2003/02/07 20:06:49 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for raster, vector and layer data containers.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvdata.c,v $
+ * Revision 1.15 2003/02/07 20:06:49 andrey_kiselev
+ * Memory leaks fixed.
+ *
+ * Revision 1.14 2001/08/08 02:57:03 warmerda
+ * implemented support for gv_data_registry_dump()
+ *
+ * Revision 1.13 2001/06/20 14:02:45 warmerda
+ * avoid emitting signal in gv_data_set_name if object is destroyed
+ *
+ * Revision 1.12 2001/05/15 16:22:13 pgs
+ * added meta-changed signal for notification of\nchanges to meta data
+ *
+ * Revision 1.11 2000/08/08 20:09:06 warmerda
+ * cleanup properties and parents
+ *
+ * Revision 1.10 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.9 2000/06/20 13:26:54 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvdata.h"
+#include <gtk/gtksignal.h>
+#include <stdio.h>
+
+enum
+{
+ CHANGING,
+ CHANGED,
+ META_CHANGED,
+ LAST_SIGNAL
+};
+
+static void gv_data_class_init(GvDataClass *klass);
+static void gv_data_init(GvData *data);
+static void gv_data_parent_changed(GvData *data, gpointer change_info);
+static void gv_data_child_changed(GvData *data, GvData *child, gpointer change_info);
+static void gv_data_destroy(GtkObject *object);
+static void gv_data_finalize(GtkObject *object);
+
+static guint data_signals[LAST_SIGNAL] = { 0 };
+
+static GPtrArray *live_datasets = NULL;
+
+GtkType
+gv_data_get_type(void)
+{
+ static GtkType data_type = 0;
+
+ if (!data_type)
+ {
+ static const GtkTypeInfo data_info =
+ {
+ "GvData",
+ sizeof(GvData),
+ sizeof(GvDataClass),
+ (GtkClassInitFunc) gv_data_class_init,
+ (GtkObjectInitFunc) gv_data_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ data_type = gtk_type_unique(gtk_data_get_type(), &data_info);
+ }
+ return data_type;
+}
+
+static void
+gv_data_class_init(GvDataClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ data_signals[CHANGING] =
+ gtk_signal_new ("changing",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvDataClass, changing),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ data_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvDataClass, changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ data_signals[META_CHANGED] =
+ gtk_signal_new ("meta-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvDataClass, meta_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals(object_class, data_signals, LAST_SIGNAL);
+
+ object_class->destroy = gv_data_destroy;
+ object_class->finalize = gv_data_finalize;
+
+ klass->changing = NULL;
+ klass->changed = NULL;
+ klass->meta_changed = NULL;
+ klass->child_changed = NULL;
+ klass->get_memento = NULL;
+ klass->set_memento = NULL;
+ klass->del_memento = NULL;
+}
+
+void gv_data_registry_dump()
+
+{
+ int i;
+
+ printf( "gv_data registry dump\n" );
+ printf( "=====================\n" );
+
+ if( live_datasets == NULL )
+ {
+ printf( "no GvDatas created yet\n" );
+ return;
+ }
+
+ for( i = 0; i < live_datasets->len; i++ )
+ {
+ GvData *data = GV_DATA(g_ptr_array_index(live_datasets,i));
+
+ printf( " %-24s %p/%s\n",
+ gtk_type_name(GTK_OBJECT_TYPE( GTK_OBJECT(data) )),
+ data,
+ gv_data_get_name( data ) );
+ }
+
+ printf( "\n" );
+}
+
+static void
+gv_data_init(GvData *data)
+{
+ data->parent = NULL;
+ data->name = NULL;
+ data->frozen = FALSE;
+ data->changed_while_frozen = FALSE;
+ data->read_only = FALSE;
+ data->projection = NULL;
+ data->properties = NULL;
+
+
+ if( live_datasets == NULL )
+ live_datasets = g_ptr_array_new();
+
+ g_ptr_array_add( live_datasets, data );
+}
+
+GvData *
+gv_data_get_parent(GvData *data)
+{
+ return data->parent;
+}
+
+void
+gv_data_set_parent(GvData *data, GvData *parent)
+{
+ if (data->parent)
+ {
+ /* Remove reference to parent */
+ gtk_signal_disconnect_by_data(GTK_OBJECT(data->parent),
+ GTK_OBJECT(data));
+ gtk_object_unref(GTK_OBJECT(data->parent));
+ }
+
+ data->parent = parent;
+
+ if (parent)
+ {
+ /* Each GvData maintains a reference to its parent */
+ gtk_object_ref(GTK_OBJECT(parent));
+ gtk_object_sink(GTK_OBJECT(parent));
+
+ gtk_signal_connect_object(GTK_OBJECT(parent), "changed",
+ GTK_SIGNAL_FUNC(gv_data_parent_changed),
+ GTK_OBJECT(data));
+ if (!data->name)
+ {
+ gv_data_set_name(data, parent->name);
+ }
+ }
+}
+
+void
+gv_data_set_name(GvData *data, const gchar *name)
+{
+ if (data->name)
+ {
+ g_free(data->name);
+ }
+ if (name)
+ {
+ data->name = g_strdup(name);
+ }
+ else
+ {
+ data->name = NULL;
+ }
+
+ if( !GTK_OBJECT_DESTROYED(data) )
+ gv_data_meta_changed(data);
+}
+
+const gchar *
+gv_data_get_name(GvData *data)
+{
+ return (const gchar *)data->name;
+}
+
+const char *
+gv_data_get_property(GvData *data, const char *name)
+{
+ return gv_properties_get( &(data->properties), name );
+}
+
+void
+gv_data_set_property(GvData *data, const char *name, const char *value)
+{
+ gv_properties_set( &(data->properties), name, value );
+}
+
+GvProperties *
+gv_data_get_properties(GvData *data)
+{
+ return &(data->properties);
+}
+
+void
+gv_data_changing(GvData *data, gpointer change_info)
+{
+ if (!data->frozen)
+ {
+ if (data->parent)
+ {
+ gv_data_changing(data->parent, change_info);
+ }
+ else
+ {
+ gtk_signal_emit(GTK_OBJECT(data), data_signals[CHANGING],
+ change_info);
+ }
+ }
+}
+
+void
+gv_data_changed(GvData *data, gpointer change_info)
+{
+ if (data->frozen)
+ {
+ data->changed_while_frozen = TRUE;
+ }
+ else
+ {
+ if (data->parent)
+ {
+ gv_data_child_changed(data->parent, data, change_info);
+ }
+ else
+ {
+ gtk_signal_emit(GTK_OBJECT(data), data_signals[CHANGED],
+ change_info);
+ }
+ }
+}
+
+void
+gv_data_meta_changed(GvData *data)
+{
+ //do we need to any tests at this point?
+
+ gtk_signal_emit(GTK_OBJECT(data), data_signals[META_CHANGED]);
+}
+
+void
+gv_data_freeze(GvData *data)
+{
+ data->frozen = TRUE;
+ data->changed_while_frozen = FALSE;
+}
+
+void
+gv_data_thaw(GvData *data)
+{
+ if (data->frozen)
+ {
+ data->frozen = FALSE;
+ if (data->changed_while_frozen)
+ {
+ gv_data_changed(data, NULL);
+ }
+ }
+}
+
+GvDataMemento *
+gv_data_get_memento(GvData *data, gpointer change_info)
+{
+ GvDataClass *klass = GV_DATA_CLASS(((GtkObject*)data)->klass);
+ GvDataMemento *memento = NULL;
+
+ if (klass->get_memento)
+ {
+ klass->get_memento(data, change_info, &memento);
+ }
+ return memento;
+}
+
+void
+gv_data_set_memento(GvData *data, GvDataMemento *memento)
+{
+ GvDataClass *klass = GV_DATA_CLASS(((GtkObject*)data)->klass);
+ g_return_if_fail(memento);
+
+ if (klass->set_memento)
+ {
+ klass->set_memento(data, memento);
+ }
+}
+
+void
+gv_data_del_memento(GvData *data, GvDataMemento *memento)
+{
+ GvDataClass *klass = GV_DATA_CLASS(((GtkObject*)data)->klass);
+ g_return_if_fail(memento);
+
+ if (klass->del_memento)
+ {
+ klass->del_memento(data, memento);
+ }
+}
+
+static void
+gv_data_parent_changed(GvData *data, gpointer change_info)
+{
+ if (data->frozen)
+ {
+ data->changed_while_frozen = TRUE;
+ }
+ else
+ {
+ gtk_signal_emit(GTK_OBJECT(data), data_signals[CHANGED],
+ change_info);
+ }
+}
+
+static void
+gv_data_child_changed(GvData *data, GvData *child, gpointer change_info)
+{
+ GvDataClass *klass = GV_DATA_CLASS(((GtkObject*)data)->klass);
+ if (klass->child_changed)
+ {
+ klass->child_changed(data, child, change_info);
+ }
+
+ gv_data_changed(data, change_info);
+}
+
+static void
+gv_data_destroy(GtkObject *object)
+{
+ GtkDataClass *parent_class;
+
+ /* Remove reference to parent */
+ gv_data_set_parent(GV_DATA(object), NULL);
+
+ parent_class = gtk_type_class(gtk_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(object);
+}
+
+static void
+gv_data_finalize(GtkObject *object)
+{
+ GtkDataClass *parent_class;
+
+ gv_data_set_name(GV_DATA(object), NULL);
+ gv_data_set_projection(GV_DATA(object), NULL);
+ gv_properties_destroy(&(GV_DATA(object)->properties));
+ gv_data_set_parent(GV_DATA(object), NULL);
+
+ parent_class = gtk_type_class(gtk_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+
+ g_ptr_array_remove( live_datasets, object );
+}
+
+const char *
+gv_data_get_projection(GvData *data)
+{
+ return data->projection;
+}
+
+void
+gv_data_set_projection(GvData *data, const char *projection)
+
+{
+ if( data->projection != NULL )
+ {
+ g_free( data->projection );
+ data->projection = NULL;
+ }
+
+ if( projection != NULL )
+ data->projection = g_strdup(projection);
+}
+
+gint
+gv_data_is_read_only(GvData *data)
+{
+ return data->read_only;
+}
+
+void
+gv_data_set_read_only(GvData *data, int read_only)
+{
+ data->read_only = read_only;
+}
+
Added: packages/openev/branches/upstream/current/gvdata.h
===================================================================
--- packages/openev/branches/upstream/current/gvdata.h (rev 0)
+++ packages/openev/branches/upstream/current/gvdata.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,127 @@
+/******************************************************************************
+ * $Id: gvdata.h,v 1.13 2003/02/07 20:06:49 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for raster, vector and layer data containers.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvdata.h,v $
+ * Revision 1.13 2003/02/07 20:06:49 andrey_kiselev
+ * Memory leaks fixed.
+ *
+ * Revision 1.12 2001/08/08 02:57:03 warmerda
+ * implemented support for gv_data_registry_dump()
+ *
+ * Revision 1.11 2001/05/15 16:22:13 pgs
+ * added meta-changed signal for notification of\nchanges to meta data
+ *
+ * Revision 1.10 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.9 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_DATA_H__
+#define __GV_DATA_H__
+
+#include <gtk/gtkdata.h>
+#include "gvtypes.h"
+#include "gvproperties.h"
+
+#define GV_TYPE_DATA (gv_data_get_type ())
+#define GV_DATA(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_DATA, GvData))
+#define GV_DATA_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_DATA, GvDataClass))
+#define GV_IS_DATA(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_DATA))
+#define GV_IS_DATA_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_DATA))
+
+typedef struct _GvData GvData;
+typedef struct _GvDataClass GvDataClass;
+typedef struct _GvDataMemento GvDataMemento;
+
+struct _GvData
+{
+ GtkData data;
+
+ GvData *parent;
+ gchar *name;
+
+ guint frozen : 1;
+ guint changed_while_frozen : 1;
+ gint read_only;
+
+ char *projection;
+
+ GvProperties properties;
+};
+
+struct _GvDataClass
+{
+ GtkDataClass parent_class;
+
+ void (* changing) (GvData *data, gpointer change_info);
+ void (* changed) (GvData *data, gpointer change_info);
+ void (* meta_changed) (GvData *data);
+ void (* child_changed) (GvData *data, GvData *child, gpointer change_info);
+ void (* get_memento) (GvData *data, gpointer change_info,
+ GvDataMemento **memento);
+ void (* set_memento) (GvData *data, GvDataMemento *memento);
+ void (* del_memento) (GvData *data, GvDataMemento *memento);
+};
+
+struct _GvDataMemento
+{
+ GvData *data;
+ gint type;
+ gint group;
+};
+
+GtkType gv_data_get_type (void);
+
+void gv_data_set_parent(GvData *data, GvData *parent);
+GvData *gv_data_get_parent(GvData *data);
+void gv_data_set_name(GvData *data, const gchar *name);
+const gchar* gv_data_get_name(GvData *data);
+
+void gv_data_changing(GvData *data, gpointer change_info);
+void gv_data_changed(GvData *data, gpointer change_info);
+void gv_data_meta_changed(GvData *data);
+void gv_data_freeze(GvData *data);
+void gv_data_thaw(GvData *data);
+GvDataMemento* gv_data_get_memento(GvData *data, gpointer change_info);
+void gv_data_set_memento(GvData *data, GvDataMemento *memento);
+void gv_data_del_memento(GvData *data, GvDataMemento *memento);
+const char *gv_data_get_projection(GvData *data);
+void gv_data_set_projection(GvData *data, const char *projection);
+void gv_data_set_read_only(GvData *data, gint read_only );
+gint gv_data_is_read_only(GvData *data );
+
+void gv_data_set_property(GvData *data, const char *name, const char *value);
+const char *gv_data_get_property(GvData *data, const char *name);
+GvProperties *gv_data_get_properties(GvData *data);
+
+void gv_data_registry_dump( void );
+
+#endif /*__GV_DATA_H__ */
+
+
Added: packages/openev/branches/upstream/current/gview.h
===================================================================
--- packages/openev/branches/upstream/current/gview.h (rev 0)
+++ packages/openev/branches/upstream/current/gview.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * $Id: gview.h,v 1.16 2005/02/22 13:22:36 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Primary OpenEV include file.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gview.h,v $
+ * Revision 1.16 2005/02/22 13:22:36 gmwalter
+ * Add autopan tool.
+ *
+ * Revision 1.15 2003/06/25 16:43:24 warmerda
+ * added gvrotatetool.h
+ *
+ * Revision 1.14 2003/05/23 16:18:17 warmerda
+ * added GvRecords for CIETMap
+ *
+ * Revision 1.13 2003/02/28 16:47:48 warmerda
+ * added gvsymbolmanager.h
+ *
+ * Revision 1.12 2002/02/28 18:52:22 gmwalter
+ * Added a point-of-interest tool similar to the region-of-interest
+ * tool (allows a user to select a temporary point without having to add a
+ * new layer). Added a mechanism to allow some customization of openev
+ * via a textfile defining external modules.
+ *
+ * Revision 1.11 2000/08/25 20:05:34 warmerda
+ * added appcurlayer
+ *
+ * Revision 1.10 2000/07/25 23:33:04 warmerda
+ * added rectangle tool
+ *
+ * Revision 1.9 2000/07/14 18:25:53 warmerda
+ * added ipgcplayer
+ *
+ * Revision 1.8 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GVIEW_H__
+#define __GVIEW_H__
+
+#include "gvtypes.h"
+#include "gvmanager.h"
+#include "gvdata.h"
+#include "gvundo.h"
+#include "gvviewarea.h"
+#include "gvviewlink.h"
+#include "gvpointlayer.h"
+#include "gvlinelayer.h"
+#include "gvarealayer.h"
+#include "gvpquerylayer.h"
+#include "ipgcplayer.h"
+#include "appcurlayer.h"
+#include "gvrecords.h"
+#include "gvrasterlayer.h"
+#include "gvrasterlut.h"
+#include "gvselecttool.h"
+#include "gvpointtool.h"
+#include "gvlinetool.h"
+#include "gvrecttool.h"
+#include "gvrotatetool.h"
+#include "gvareatool.h"
+#include "gvnodetool.h"
+#include "gvroitool.h"
+#include "gvpoitool.h"
+#include "gvtracktool.h"
+#include "gvzoompantool.h"
+#include "gvtoolbox.h"
+#include "gvsymbolmanager.h"
+#include "gvautopan.h"
+
+#endif /*__GVIEW_H__*/
Added: packages/openev/branches/upstream/current/gvlayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvlayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvlayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,263 @@
+/******************************************************************************
+ * $Id: gvlayer.c,v 1.13 2001/10/12 17:44:18 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for all display layers.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlayer.c,v $
+ * Revision 1.13 2001/10/12 17:44:18 warmerda
+ * avoid extra redraws when many raster layers displayed
+ *
+ * Revision 1.12 2001/04/09 18:14:49 warmerda
+ * added view field to GvLayer
+ *
+ * Revision 1.11 2001/03/28 15:13:59 warmerda
+ * added view to GvLayer
+ *
+ * Revision 1.10 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvlayer.h"
+#include <gtk/gtksignal.h>
+
+/** FIXME: we are currently leaking the projection string. Should
+ add a finalize function. **/
+
+enum
+{
+ SETUP,
+ TEARDOWN,
+ DRAW,
+ EXTENTS_REQUEST,
+ DISPLAY_CHANGE,
+ LAST_SIGNAL
+};
+
+static void gv_layer_class_init(GvLayerClass *klass);
+static void gv_layer_init(GvLayer *layer);
+
+static guint layer_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_layer_get_type(void)
+{
+ static GtkType layer_type = 0;
+
+ if (!layer_type)
+ {
+ static const GtkTypeInfo layer_info =
+ {
+ "GvLayer",
+ sizeof(GvLayer),
+ sizeof(GvLayerClass),
+ (GtkClassInitFunc) gv_layer_class_init,
+ (GtkObjectInitFunc) gv_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ layer_type = gtk_type_unique(gv_data_get_type(), &layer_info);
+ }
+ return layer_type;
+}
+
+static void
+gv_layer_class_init(GvLayerClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ layer_signals[SETUP] =
+ gtk_signal_new ("setup",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvLayerClass, setup),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ layer_signals[TEARDOWN] =
+ gtk_signal_new ("teardown",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvLayerClass, teardown),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ layer_signals[DRAW] =
+ gtk_signal_new ("draw",
+ GTK_RUN_FIRST | GTK_RUN_NO_RECURSE,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvLayerClass, draw),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ layer_signals[EXTENTS_REQUEST] =
+ gtk_signal_new ("get-extents",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvLayerClass, extents_request),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ layer_signals[DISPLAY_CHANGE] =
+ gtk_signal_new ("display-change",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvLayerClass, display_change),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ gtk_object_class_add_signals(object_class, layer_signals, LAST_SIGNAL);
+
+ klass->setup = NULL;
+ klass->teardown = NULL;
+ klass->draw = NULL;
+ klass->extents_request = NULL;
+ klass->reproject = NULL;
+ klass->display_change = NULL;
+}
+
+void
+gv_layer_init(GvLayer *layer)
+{
+ layer->setup_count = 0;
+ layer->invisible = FALSE;
+ layer->presentation = FALSE;
+ layer->projection = NULL;
+ layer->view = NULL;
+ layer->pending_idle = FALSE;
+}
+
+void
+gv_layer_setup(GvLayer *layer, GvViewArea *view)
+{
+ if (++layer->setup_count == 1)
+ {
+ gtk_signal_emit(GTK_OBJECT(layer), layer_signals[SETUP], view);
+ }
+}
+
+void
+gv_layer_teardown(GvLayer *layer, GvViewArea *view)
+{
+ if (--layer->setup_count < 1)
+ {
+ gtk_signal_emit(GTK_OBJECT(layer), layer_signals[TEARDOWN], view);
+ }
+}
+
+void
+gv_layer_draw(GvLayer *layer, GvViewArea *view)
+{
+ g_assert( view == layer->view );
+
+ if (!layer->invisible)
+ {
+ if (layer->presentation)
+ {
+ /* Avoid triggering tool drawing by not emitting a signal */
+ GvLayerClass *klass = GV_LAYER_CLASS(GTK_OBJECT(layer)->klass);
+ if (klass->draw)
+ {
+ klass->draw(layer, view);
+ }
+ }
+ else
+ {
+ gtk_signal_emit(GTK_OBJECT(layer), layer_signals[DRAW], view);
+ }
+ }
+}
+
+
+void
+gv_layer_extents(GvLayer *layer, GvRect *rect)
+{
+ rect->x = rect->y = rect->width = rect->height = 0.0;
+ gtk_signal_emit(GTK_OBJECT(layer), layer_signals[EXTENTS_REQUEST], rect);
+}
+
+void
+gv_layer_display_change(GvLayer *layer, gpointer change_info)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), layer_signals[DISPLAY_CHANGE],
+ change_info);
+}
+
+gint
+gv_layer_is_visible(GvLayer *layer)
+{
+ return (layer->invisible == FALSE);
+}
+
+void
+gv_layer_set_visible(GvLayer *layer, gint visible)
+{
+ gint invisible = !visible;
+ if (invisible != layer->invisible)
+ {
+ layer->invisible = invisible;
+ gv_layer_display_change(layer, NULL);
+ }
+}
+
+gint
+gv_layer_set_visible_temp(GvLayer *layer, gint visible)
+{
+ gint old_visible = !layer->invisible;
+ layer->invisible = !visible;
+ return old_visible;
+}
+
+void
+gv_layer_set_presentation(GvLayer *layer, gint presentation)
+{
+ layer->presentation = presentation;
+}
+
+gint
+gv_layer_reproject(GvLayer *layer, const char *projection)
+{
+ GvLayerClass *klass = GV_LAYER_CLASS(((GtkObject*)layer)->klass);
+
+ if (klass->reproject)
+ return klass->reproject(layer, projection);
+ else
+ return FALSE;
+}
+
+GvViewArea *
+gv_layer_get_view(GvLayer *layer)
+{
+ return GV_LAYER(layer)->view;
+}
+
Added: packages/openev/branches/upstream/current/gvlayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvlayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvlayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * $Id: gvlayer.h,v 1.13 2001/10/12 17:44:18 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for all display layers.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlayer.h,v $
+ * Revision 1.13 2001/10/12 17:44:18 warmerda
+ * avoid extra redraws when many raster layers displayed
+ *
+ * Revision 1.12 2001/04/09 18:14:49 warmerda
+ * added view field to GvLayer
+ *
+ * Revision 1.11 2001/03/28 15:13:59 warmerda
+ * added view to GvLayer
+ *
+ * Revision 1.10 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_LAYER_H__
+#define __GV_LAYER_H__
+
+#include <gdk/gdk.h>
+#include "gvdata.h"
+#include "gvviewarea.h"
+
+#define GV_TYPE_LAYER (gv_layer_get_type ())
+#define GV_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_LAYER, GvLayer))
+#define GV_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_LAYER, GvLayerClass))
+#define GV_IS_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_LAYER))
+#define GV_IS_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_LAYER))
+
+typedef struct _GvLayer GvLayer;
+typedef struct _GvLayerClass GvLayerClass;
+
+struct _GvLayer
+{
+ GvData data;
+
+ gint setup_count; /* Prevents multiple setup/teardown events */
+ guint invisible : 1;
+ guint presentation : 1; /* Presentation mode drawing (e.g. printing) */
+
+ char *projection; /* in WKT format */
+
+ GvViewArea *view;
+
+ int pending_idle;/* Is there pending idle work for this layer? */
+};
+
+struct _GvLayerClass
+{
+ GvDataClass parent_class;
+
+ /* the following are signals */
+ void (* setup) (GvLayer *layer, GvViewArea *view);
+ void (* teardown) (GvLayer *layer, GvViewArea *view);
+ void (* draw) (GvLayer *layer, GvViewArea *view);
+ void (* extents_request) (GvLayer *layer, GvRect *rect);
+ void (* display_change) (GvLayer *layer, gpointer change_info);
+
+ /* this is just a hook function, not a signal */
+ gint (* reproject) (GvLayer *layer, const char *);
+};
+
+GtkType gv_layer_get_type (void);
+
+void gv_layer_setup(GvLayer *layer, GvViewArea *view);
+void gv_layer_teardown(GvLayer *layer, GvViewArea *view);
+void gv_layer_draw(GvLayer *layer, GvViewArea *view);
+void gv_layer_extents(GvLayer *layer, GvRect *rect);
+void gv_layer_display_change(GvLayer *layer, gpointer change_info);
+gint gv_layer_is_visible(GvLayer *layer);
+void gv_layer_set_visible(GvLayer *layer, gint visible);
+gint gv_layer_set_visible_temp(GvLayer *layer, gint visible);
+void gv_layer_set_presentation(GvLayer *layer, gint presentation);
+GvViewArea *gv_layer_get_view(GvLayer *layer);
+gint gv_layer_reproject(GvLayer *layer, const char *projection);
+
+#endif /*__GV_LAYER_H__ */
+
Added: packages/openev/branches/upstream/current/gvlinelayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvlinelayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvlinelayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,375 @@
+/******************************************************************************
+ * $Id: gvlinelayer.c,v 1.12 2002/11/05 18:56:24 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for GvLines.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlinelayer.c,v $
+ * Revision 1.12 2002/11/05 18:56:24 sduclos
+ * fix gcc warning
+ *
+ * Revision 1.11 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.10 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvlinelayer.h"
+#include <gtk/gtksignal.h>
+#include <GL/gl.h>
+
+static void gv_line_layer_class_init(GvLineLayerClass *klass);
+static void gv_line_layer_init(GvLineLayer *layer);
+static void gv_line_layer_draw(GvLineLayer *layer, GvViewArea *view);
+static void gv_line_layer_extents(GvLineLayer *layer, GvRect *rect);
+static void gv_line_layer_data_change(GvLineLayer *layer, gpointer change_info);
+static void gv_line_layer_draw_selected(GvLineLayer *layer, GvViewArea *view);
+static void gv_line_layer_delete_selected(GvLineLayer *layer);
+static void gv_line_layer_translate_selected(GvLineLayer *layer, GvVertex *delta);
+static void gv_line_layer_pick_shape(GvLineLayer *layer);
+static void gv_line_layer_pick_node(GvLineLayer *layer);
+static void gv_line_layer_get_node(GvLineLayer *layer, GvNodeInfo *info);
+static void gv_line_layer_move_node(GvLineLayer *layer, GvNodeInfo *info);
+static void gv_line_layer_insert_node(GvLineLayer *layer, GvNodeInfo *info);
+static void gv_line_layer_delete_node(GvLineLayer *layer, GvNodeInfo *info);
+
+GtkType
+gv_line_layer_get_type(void)
+{
+ static GtkType line_layer_type = 0;
+
+ if (!line_layer_type)
+ {
+ static const GtkTypeInfo line_layer_info =
+ {
+ "GvLineLayer",
+ sizeof(GvLineLayer),
+ sizeof(GvLineLayerClass),
+ (GtkClassInitFunc) gv_line_layer_class_init,
+ (GtkObjectInitFunc) gv_line_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ line_layer_type = gtk_type_unique(gv_shape_layer_get_type(),
+ &line_layer_info);
+ }
+ return line_layer_type;
+}
+
+static void
+gv_line_layer_class_init(GvLineLayerClass *klass)
+{
+ typedef void (*f)();
+ GvDataClass *data_class;
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ data_class = (GvDataClass*) klass;
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ data_class->changed = (f) gv_line_layer_data_change;
+
+ layer_class->draw = (f) gv_line_layer_draw;
+ layer_class->extents_request = (f) gv_line_layer_extents;
+
+ shape_layer_class->draw_selected = (f) gv_line_layer_draw_selected;
+ shape_layer_class->delete_selected = (f) gv_line_layer_delete_selected;
+ shape_layer_class->translate_selected = (f) gv_line_layer_translate_selected;
+ shape_layer_class->pick_shape = (f) gv_line_layer_pick_shape;
+ shape_layer_class->pick_node = (f) gv_line_layer_pick_node;
+ shape_layer_class->get_node = (f) gv_line_layer_get_node;
+ shape_layer_class->move_node = (f) gv_line_layer_move_node;
+ shape_layer_class->insert_node = (f) gv_line_layer_insert_node;
+ shape_layer_class->delete_node = (f) gv_line_layer_delete_node;
+}
+
+static void
+gv_line_layer_init(GvLineLayer *layer)
+{
+ GvColor default_line_color = {1.0, 1.0, 0.0, 1.0}; /* yellow */
+
+ layer->data = NULL;
+ gv_color_copy(GV_SHAPE_LAYER(layer)->color, default_line_color);
+
+
+}
+
+GtkObject *
+gv_line_layer_new(GvPolylines *data)
+{
+ GvLineLayer *layer = GV_LINE_LAYER(gtk_type_new(gv_line_layer_get_type()));
+
+ if (data)
+ {
+ layer->data = data;
+ }
+ else
+ {
+ layer->data = GV_POLYLINES(gv_polylines_new());
+ }
+
+ /* Set the number of shapes - case where data exists before layer was created */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_polylines_num_lines(layer->data));
+
+ gv_data_set_parent(GV_DATA(layer), GV_DATA(layer->data));
+
+ return GTK_OBJECT(layer);
+}
+
+gint
+gv_line_layer_select_new_line(GvLineLayer *layer)
+{
+ gint line_id;
+
+ line_id = gv_polylines_new_line(layer->data);
+
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_polylines_num_lines(layer->data));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(layer), line_id);
+
+ return line_id;
+}
+
+/*******************************************************/
+
+static void
+gv_line_layer_draw(GvLineLayer *layer, GvViewArea *view)
+{
+ gint i, lines;
+ GArray *line;
+ gint *selected, presentation;
+ gint hit_selected = FALSE;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ lines = gv_polylines_num_lines(layer->data);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ for (i=0; i < lines; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ line = gv_polylines_get_line(layer->data, i);
+
+ glVertexPointer(2, GL_GEOCOORD, 0, line->data);
+ glDrawArrays(GL_LINE_STRIP, 0, line->len);
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ gv_line_layer_draw_selected(layer, view);
+ }
+}
+
+static void
+gv_line_layer_draw_selected(GvLineLayer *layer, GvViewArea *view)
+{
+ gint i, lines;
+ GArray *line;
+ gint *selected;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ lines = gv_polylines_num_lines(layer->data);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+ glPointSize(3.0);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ for (i=0; i < lines; ++i)
+ {
+ if (selected[i])
+ {
+ line = gv_polylines_get_line(layer->data, i);
+
+ glVertexPointer(2, GL_GEOCOORD, 0, line->data);
+ glDrawArrays(GL_LINE_STRIP, 0, line->len);
+
+#ifdef HAVE_BROKEN_GL_POINTS
+ {
+ int j;
+ for (j=0; j < line->len; ++j)
+ {
+ glBegin(GL_POINTS);
+ glArrayElement(j);
+ glEnd();
+ }
+ }
+#else
+ glDrawArrays(GL_POINTS, 0, line->len);
+#endif /* HAVE_BROKEN_GL_POINTS */
+ }
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_line_layer_pick_shape(GvLineLayer *layer)
+{
+ gint i, lines;
+ GArray *line;
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+
+ lines = gv_polylines_num_lines(layer->data);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ for (i=0; i < lines; ++i)
+ {
+ line = gv_polylines_get_line(layer->data, i);
+
+ glLoadName(i);
+ glVertexPointer(2, GL_GEOCOORD, 0, line->data);
+ glDrawArrays(GL_LINE_STRIP, 0, line->len);
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_line_layer_pick_node(GvLineLayer *layer)
+{
+ GArray *line;
+ gint sel, i;
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+
+ if (!gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_FIRST, &sel))
+ {
+ return;
+ }
+ line = gv_polylines_get_line(layer->data, sel);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_GEOCOORD, 0, line->data);
+
+ /* Nodes first */
+ glLoadName(0);
+ glPushName(0); /* Ring id is always zero */
+ glPushName(-1);
+ glPointSize(1.0);
+ for (i=0; i < line->len; ++i)
+ {
+ glLoadName(i);
+ glBegin(GL_POINTS);
+ glArrayElement(i);
+ glEnd();
+ }
+ glPopName(); /* node id */
+ glPopName(); /* ring id */
+
+ /* Segments next */
+ glLoadName(1);
+ glPushName(0); /* Ring id is always zero */
+ glPushName(-1);
+ for (i=1; i < line->len; ++i)
+ {
+ glLoadName(i);
+ glBegin(GL_LINES);
+ glArrayElement(i-1);
+ glArrayElement(i);
+ glEnd();
+ }
+ glPopName(); /* node id */
+ glPopName(); /* ring id */
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void
+gv_line_layer_delete_selected(GvLineLayer *layer)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_polylines_delete_lines(layer->data, sel->len, (gint*)sel->data);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_line_layer_translate_selected(GvLineLayer *layer, GvVertex *delta)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ gv_polylines_translate_lines(layer->data, sel->len, (gint*)sel->data,
+ delta->x, delta->y);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_line_layer_get_node(GvLineLayer *layer, GvNodeInfo *info)
+{
+ info->vertex = gv_polylines_get_node(layer->data, info->shape_id,
+ info->node_id);
+}
+
+static void
+gv_line_layer_move_node(GvLineLayer *layer, GvNodeInfo *info)
+{
+ gv_polylines_move_node(layer->data, info->shape_id, info->node_id,
+ info->vertex);
+}
+
+static void
+gv_line_layer_insert_node(GvLineLayer *layer, GvNodeInfo *info)
+{
+ gv_polylines_insert_nodes(layer->data, info->shape_id, info->node_id,
+ 1, info->vertex);
+}
+
+static void
+gv_line_layer_delete_node(GvLineLayer *layer, GvNodeInfo *info)
+{
+ gv_polylines_delete_nodes(layer->data, info->shape_id, 1, &info->node_id);
+}
+
+static void
+gv_line_layer_extents(GvLineLayer *layer, GvRect *rect)
+{
+ gv_polylines_get_extents(layer->data, rect);
+}
+
+static void
+gv_line_layer_data_change(GvLineLayer *layer, gpointer change_info)
+{
+ /* Reset the selected array to reflect the data length */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_polylines_num_lines(layer->data));
+}
+
Added: packages/openev/branches/upstream/current/gvlinelayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvlinelayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvlinelayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * $Id: gvlinelayer.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for GvLines.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlinelayer.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_LINE_LAYER_H__
+#define __GV_LINE_LAYER_H__
+
+#include "gvshapelayer.h"
+#include "gvpolylines.h"
+
+#define GV_TYPE_LINE_LAYER (gv_line_layer_get_type ())
+#define GV_LINE_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_LINE_LAYER, GvLineLayer))
+#define GV_LINE_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_LINE_LAYER, GvLineLayerClass))
+#define GV_IS_LINE_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_LINE_LAYER))
+#define GV_IS_LINE_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_LINE_LAYER))
+
+typedef struct _GvLineLayer GvLineLayer;
+typedef struct _GvLineLayerClass GvLineLayerClass;
+
+struct _GvLineLayer
+{
+ GvShapeLayer shape_layer;
+
+ GvPolylines *data;
+};
+
+struct _GvLineLayerClass
+{
+ GvShapeLayerClass parent_class;
+};
+
+GtkType gv_line_layer_get_type(void);
+GtkObject* gv_line_layer_new(GvPolylines *data);
+
+gint gv_line_layer_select_new_line(GvLineLayer *layer);
+
+#endif /* __GV_LINE_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvlinetool.c
===================================================================
--- packages/openev/branches/upstream/current/gvlinetool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvlinetool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,469 @@
+/******************************************************************************
+ * $Id: gvlinetool.c,v 1.19 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Polyline editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlinetool.c,v $
+ * Revision 1.19 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.18 2001/08/08 17:44:12 warmerda
+ * use gv_shape_type() macro
+ *
+ * Revision 1.17 2001/04/09 18:15:20 warmerda
+ * improved warning
+ *
+ * Revision 1.16 2000/08/09 14:40:16 warmerda
+ * escape also termintes digitization mode
+ *
+ * Revision 1.15 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.14 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.13 2000/07/24 14:00:24 warmerda
+ * set_layer with NULL should be allowed
+ *
+ * Revision 1.12 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.11 2000/07/17 19:20:21 warmerda
+ * avoid putting gl.h ahead of openev include files: windows problem
+ *
+ * Revision 1.10 2000/07/17 17:11:09 warmerda
+ * added delete key support
+ *
+ * Revision 1.9 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include "gvlinetool.h"
+#include "gvundo.h"
+#include <GL/gl.h>
+
+static void gv_line_tool_class_init(GvLineToolClass *klass);
+static void gv_line_tool_init(GvLineTool *tool);
+static void gv_line_tool_draw(GvLineTool *tool);
+static void gv_line_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_line_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_line_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_line_tool_deactivate(GvTool *tool, GvViewArea *view);
+static void gv_line_tool_stop_drawing(GvLineTool *tool);
+static gint gv_line_tool_configure(GvLineTool *tool);
+
+GtkType
+gv_line_tool_get_type(void)
+{
+ static GtkType line_tool_type = 0;
+
+ if (!line_tool_type)
+ {
+ static const GtkTypeInfo line_tool_info =
+ {
+ "GvLineTool",
+ sizeof(GvLineTool),
+ sizeof(GvLineToolClass),
+ (GtkClassInitFunc) gv_line_tool_class_init,
+ (GtkObjectInitFunc) gv_line_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ line_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &line_tool_info);
+ }
+ return line_tool_type;
+}
+
+static void
+gv_line_tool_class_init(GvLineToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_line_tool_deactivate;
+ tool_class->button_press = gv_line_tool_button_press;
+ tool_class->motion_notify = gv_line_tool_motion_notify;
+ tool_class->key_press = gv_line_tool_key_press;
+}
+
+static void
+gv_line_tool_init(GvLineTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->layer = NULL;
+ tool->named_layer = NULL;
+ tool->drawing = FALSE;
+}
+
+GvTool *
+gv_line_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_LINE_TOOL));
+}
+
+static gint gv_line_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvLineTool *tool = (GvLineTool *) data;
+
+ if( tool->layer == GV_SHAPE_LAYER(layer) )
+ gv_line_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_line_tool_set_layer(GvLineTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_line_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_line_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ if (tool->drawing)
+ {
+ gv_line_tool_stop_drawing(tool);
+ }
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+
+ tool->layer = layer;
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_line_tool_draw),
+ GTK_OBJECT(tool));
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_line_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+void
+gv_line_tool_set_named_layer(GvLineTool *tool, gchar *name)
+{
+ if (tool->named_layer)
+ {
+ g_free(tool->named_layer);
+ tool->named_layer = NULL;
+ }
+ if (name)
+ {
+ tool->named_layer = g_strdup(name);
+ }
+ /* Tool layer will be updated next time it is configured */
+}
+
+/********************************************************/
+
+static void
+gv_line_tool_draw(GvLineTool *tool)
+{
+ if (tool->drawing)
+ {
+ /* Color is set when the layer is drawn,
+ so we don't need to repeat it here */
+
+ glBegin(GL_LINES);
+ glVertex2v((GLgeocoord*)&tool->v_head);
+ glVertex2v((GLgeocoord*)&tool->v_tail);
+ glEnd();
+ }
+}
+
+static void
+gv_line_tool_button_press(GvTool *r_tool, GdkEventButton *event)
+{
+ GvLineTool *tool = GV_LINE_TOOL(r_tool);
+
+ if (event->button == 1)
+ {
+ gint line_id;
+
+ if (!gv_line_tool_configure(tool)) return;
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ if (tool->drawing)
+ {
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ /* Filter out duplicate verticies */
+ if (tool->v_head.x == tool->v_tail.x &&
+ tool->v_head.y == tool->v_tail.y)
+ {
+ return;
+ }
+
+ /* Add a new vertex to the line */
+ gv_shape_layer_selected(GV_SHAPE_LAYER(tool->layer), GV_FIRST,
+ &line_id);
+ }
+ else
+ {
+ if( !gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_tail.x, tool->v_tail.y ) )
+ return;
+
+ /* Start a new line */
+ tool->drawing = TRUE;
+
+ /* Close down undo. A single operation describing the new
+ line will be pushed to undo when drawing stops. */
+ gv_undo_close();
+ gv_undo_disable();
+
+ if( GV_IS_LINE_LAYER(tool->layer) )
+ {
+ line_id = gv_line_layer_select_new_line(
+ GV_LINE_LAYER(tool->layer));
+ }
+ else
+ {
+ GvShape *line = gv_shape_new( GVSHAPE_LINE );
+
+ line_id = gv_shapes_layer_select_new_shape(
+ GV_SHAPES_LAYER(tool->layer), line );
+ }
+ }
+
+ tool->v_head = tool->v_tail;
+
+ if( GV_IS_LINE_LAYER(tool->layer) )
+ gv_polylines_append_nodes(GV_LINE_LAYER(tool->layer)->data,
+ line_id, 1, &tool->v_tail);
+ else
+ {
+ GvShapes *shapes = GV_SHAPES_LAYER(tool->layer)->data;
+ GvShape *line = gv_shapes_get_shape(shapes, line_id );
+
+ if( gv_shape_type(line) == GVSHAPE_LINE )
+ gv_shape_add_node(line, 0, tool->v_tail.x, tool->v_tail.y, 0);
+ else
+ g_warning( "selected object not line in gvlinetool mode!\n" );
+ }
+ }
+ else if (event->button == 3 && tool->drawing)
+ {
+ gv_line_tool_stop_drawing(tool);
+ }
+}
+
+static void
+gv_line_tool_motion_notify(GvTool *r_tool, GdkEventMotion *event)
+{
+ GvLineTool *tool = GV_LINE_TOOL(r_tool);
+
+ if (tool->drawing)
+ {
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_line_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvLineTool *tool = GV_LINE_TOOL(rtool);
+
+ if (!gv_line_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Escape:
+ gv_line_tool_stop_drawing(tool);
+ break;
+
+ case GDK_Delete:
+ case GDK_BackSpace:
+ if( tool->drawing && !GV_IS_LINE_LAYER(tool->layer) )
+ {
+ gint line_id;
+ GvNodeInfo node_info;
+ GvShape *shape;
+ GvShapes *shapes = GV_SHAPES_LAYER(tool->layer)->data;
+
+ gv_shape_layer_selected(GV_SHAPE_LAYER(tool->layer), GV_FIRST,
+ &line_id);
+
+ shape = gv_shapes_get_shape( shapes, line_id );
+
+ node_info.shape_id = line_id;
+ node_info.ring_id = 0;
+ node_info.node_id = gv_shape_get_nodes( shape, 0 ) - 1;
+
+ if( gv_shape_get_nodes( shape, 0 ) > 1 )
+ {
+ tool->v_head.x = gv_shape_get_x( shape, 0,
+ node_info.node_id-1);
+ tool->v_head.y = gv_shape_get_y( shape, 0,
+ node_info.node_id-1);
+ }
+ else
+ {
+ tool->drawing = FALSE;
+ }
+
+ gv_shape_layer_delete_node(tool->layer, &node_info );
+
+ if( !tool->drawing )
+ gv_line_tool_stop_drawing( tool );
+ }
+ break;
+ }
+}
+
+static void
+gv_line_tool_deactivate(GvTool *r_tool, GvViewArea *view)
+{
+ GvLineTool *tool = GV_LINE_TOOL(r_tool);
+
+ /* Disconnect from layer */
+ if (tool->layer)
+ {
+ gv_line_tool_set_layer(tool, NULL);
+ }
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static void
+gv_line_tool_stop_drawing(GvLineTool *tool)
+{
+ gint sel, push_undo = TRUE;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ change_info.shape_id = &sel;
+
+ tool->drawing = FALSE;
+
+ /* Reject lines with only one node */
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(tool->layer), GV_FIRST, &sel))
+ {
+ if( GV_IS_LINE_LAYER(tool->layer) )
+ {
+ if (gv_polylines_get_line(GV_LINE_LAYER(tool->layer)->data,
+ sel)->len < 2)
+ {
+ gv_shape_layer_delete_selected(GV_SHAPE_LAYER(tool->layer));
+ push_undo = FALSE;
+ }
+ }
+ else
+ {
+ GvShapes *shapes = GV_SHAPES_LAYER(tool->layer)->data;
+ GvShape *shape = gv_shapes_get_shape(shapes, sel);
+
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_LINE
+ && gv_shape_get_nodes(shape,0) < 2 )
+ {
+ gv_shape_layer_delete_selected(GV_SHAPE_LAYER(tool->layer));
+ push_undo = FALSE;
+ }
+ }
+ }
+
+ /* Reopen undo. Push a memento describing the line addition. */
+ gv_undo_enable();
+ gv_undo_open();
+ if (push_undo)
+ {
+ gv_undo_push(
+ gv_data_get_memento(gv_data_get_parent(GV_DATA(tool->layer)),
+ &change_info));
+ }
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+}
+
+static gint
+gv_line_tool_configure(GvLineTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ if (tool->named_layer)
+ {
+ /* Look for named layer if given */
+ layer = gv_view_area_get_named_layer(GV_TOOL(tool)->view,
+ tool->named_layer);
+ }
+ else
+ {
+ /* Attempt to find a line layer to edit */
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_LINE_LAYER,
+ FALSE);
+ if( layer == NULL )
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPES_LAYER,
+ FALSE);
+ }
+ if (!layer)
+ {
+ g_warning("gv_line_tool_configure(): no editable line layer in view");
+ return FALSE;
+ }
+
+ gv_line_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+ return tool->layer != NULL;
+}
Added: packages/openev/branches/upstream/current/gvlinetool.h
===================================================================
--- packages/openev/branches/upstream/current/gvlinetool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvlinetool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * $Id: gvlinetool.h,v 1.6 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Polyline editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvlinetool.h,v $
+ * Revision 1.6 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_LINE_TOOL_H__
+#define __GV_LINE_TOOL_H__
+
+#include "gvtool.h"
+#include "gvlinelayer.h"
+#include "gvshapeslayer.h"
+
+#define GV_TYPE_LINE_TOOL (gv_line_tool_get_type ())
+#define GV_LINE_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_LINE_TOOL, GvLineTool))
+#define GV_LINE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_LINE_TOOL, GvLineToolClass))
+#define GV_IS_LINE_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_LINE_TOOL))
+#define GV_IS_LINE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_LINE_TOOL))
+
+typedef struct _GvLineTool GvLineTool;
+typedef struct _GvLineToolClass GvLineToolClass;
+
+struct _GvLineTool
+{
+ GvTool tool;
+
+ GvShapeLayer *layer;
+ gchar *named_layer;
+ guint drawing : 1;
+ GvVertex v_head, v_tail;
+};
+
+struct _GvLineToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_line_tool_get_type(void);
+GvTool* gv_line_tool_new(void);
+void gv_line_tool_set_layer(GvLineTool *tool, GvShapeLayer *layer);
+void gv_line_tool_set_named_layer(GvLineTool *tool, gchar *name);
+
+#endif /* __GV_LINE_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvmanager.c
===================================================================
--- packages/openev/branches/upstream/current/gvmanager.c (rev 0)
+++ packages/openev/branches/upstream/current/gvmanager.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,571 @@
+/******************************************************************************
+ * $Id: gvmanager.c,v 1.14 2004/02/10 15:38:30 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Preferences (and other?) manager. Singleton object.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvmanager.c,v $
+ * Revision 1.14 2004/02/10 15:38:30 andrey_kiselev
+ * Added gv_manager_add_dataset() function.
+ *
+ * Revision 1.13 2001/07/24 02:21:54 warmerda
+ * added 8bit phase averaging
+ *
+ * Revision 1.12 2001/01/30 14:29:33 warmerda
+ * added gv_manager_dump
+ *
+ * Revision 1.11 2000/09/29 20:32:27 warmerda
+ * made decimation the default instead of averaging
+ *
+ * Revision 1.10 2000/09/27 19:17:13 warmerda
+ * use prefs for GvRaster sample method
+ *
+ * Revision 1.9 2000/08/23 14:16:06 warmerda
+ * avoid error message opening for update
+ *
+ * Revision 1.8 2000/08/09 17:36:50 warmerda
+ * update lists when GvRaster destroyed
+ *
+ * Revision 1.7 2000/07/25 14:18:19 warmerda
+ * added task dequeuing support
+ *
+ * Revision 1.6 2000/06/29 19:50:17 warmerda
+ * Initialize busy_changed signal handler.
+ *
+ * Revision 1.5 2000/06/29 14:38:22 warmerda
+ * added busy status, and idle task list
+ *
+ * Revision 1.4 2000/06/26 15:12:00 warmerda
+ * Added dataset/gvraster management
+ *
+ * Revision 1.3 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvmanager.h"
+#include <gtk/gtksignal.h>
+#include <stdio.h>
+#include <string.h>
+
+
+enum
+{
+ PREFERENCES_CHANGED,
+ BUSY_CHANGED,
+ LAST_SIGNAL
+};
+
+static void gv_manager_class_init(GvManagerClass *klass);
+
+static guint manager_signals[LAST_SIGNAL] = { 0 };
+static void gv_manager_init( GvManager *manager );
+static gint gv_manager_idle_handler( gpointer );
+
+GtkType
+gv_manager_get_type(void)
+{
+ static GtkType manager_type = 0;
+
+ if (!manager_type)
+ {
+ static const GtkTypeInfo manager_info =
+ {
+ "GvManager",
+ sizeof(GvManager),
+ sizeof(GvManagerClass),
+ (GtkClassInitFunc) gv_manager_class_init,
+ (GtkObjectInitFunc) gv_manager_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ manager_type = gtk_type_unique(gtk_object_get_type(),
+ &manager_info);
+ }
+ return manager_type;
+}
+
+static void
+gv_manager_class_init(GvManagerClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ manager_signals[PREFERENCES_CHANGED] =
+ gtk_signal_new ("preferences-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvManagerClass,preferences_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ manager_signals[BUSY_CHANGED] =
+ gtk_signal_new ("busy-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvManagerClass,busy_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ gtk_object_class_add_signals(object_class, manager_signals, LAST_SIGNAL);
+
+ klass->preferences_changed = NULL;
+ klass->busy_changed = NULL;
+}
+
+static void
+gv_manager_init( GvManager *manager )
+
+{
+ manager->preferences = NULL;
+ manager->datasets = g_ptr_array_new();
+ manager->idle_tasks = NULL;
+ manager->busy_flag = FALSE;
+ GDALAllRegister();
+}
+
+GvManager *gv_manager_new()
+{
+ return GV_MANAGER(gtk_type_new(GV_TYPE_MANAGER));
+}
+
+GvManager *gv_get_manager()
+
+{
+ static GvManager *main_manager = NULL;
+
+ if( main_manager == NULL )
+ main_manager = gv_manager_new();
+
+ return main_manager;
+}
+
+void gv_manager_dump( GvManager *manager )
+{
+ FILE *fp = stderr;
+ int i;
+ GvIdleTask *task;
+
+ fprintf( fp, "GvManager Status Report\n" );
+ fprintf( fp, "=======================\n" );
+
+ fprintf( fp, "\n" );
+ fprintf( fp, "Preferences:\n" );
+ for( i = 0; i < gv_properties_count( &(manager->preferences) ); i++ )
+ {
+ fprintf( fp, " %s=%s\n",
+ gv_properties_get_name_by_index( &(manager->preferences), i),
+ gv_properties_get_value_by_index( &(manager->preferences),i));
+ }
+
+ fprintf( fp, "\n" );
+ fprintf( fp, "Datasets:\n" );
+ for( i = 0; i < manager->datasets->len; i++ )
+ {
+ GvDataset *ds = (GvDataset *) g_ptr_array_index(manager->datasets,i);
+ int band;
+
+ fprintf( fp, " %s:", GDALGetDescription( ds->dataset ) );
+
+ for( band = 0; band < GDALGetRasterCount(ds->dataset); band++ )
+ {
+ if( ds->rasters[band] != NULL )
+ fprintf( fp, "R" );
+ else
+ fprintf( fp, "_" );
+ }
+ fprintf( fp, "\n" );
+ }
+
+ fprintf( fp, "\n" );
+ fprintf( fp, "Idle Tasks:\n" );
+
+ for( task = manager->idle_tasks; task != NULL; task = task->next )
+ {
+ fprintf( fp, " %s: priority=%d, cb=%p, cb_data=%p\n",
+ task->name, task->priority, task->callback, task->task_info );
+ }
+}
+
+GvProperties *gv_manager_get_preferences(GvManager *manager)
+
+{
+ return &(manager->preferences);
+}
+
+const char *gv_manager_get_preference(GvManager *manager, const char *name)
+
+{
+ return gv_properties_get(&(manager->preferences),name);
+}
+
+void gv_manager_set_preference(GvManager *manager,
+ const char *name, const char *value )
+
+{
+ /* don't do anything if it is already set */
+
+ if( gv_properties_get( &(manager->preferences), name ) != NULL
+ && strcmp(gv_properties_get(&(manager->preferences),name),value) == 0 )
+ return;
+
+ gv_properties_set( &(manager->preferences), name, value );
+
+ gtk_signal_emit(GTK_OBJECT(manager),
+ manager_signals[PREFERENCES_CHANGED]);
+}
+
+/************************************************************************/
+/* gv_manager_add_dataset() */
+/************************************************************************/
+
+/**
+ * Adds GDALDatasetH object instance to the list of managed datasets.
+ *
+ * This method adds given GDALDatasetH object instance to the list of
+ * managed datasets. Does nothing if this dataset already listed.
+ *
+ * @param manager Pointer to GvManager object.
+ * @param dataset GDALDatasetH dataset handler.
+ *
+ * @return Handler for added GDALDatasetH object (the same as supplied in
+ * dataset parameter) or NULL if parameters are wrong.
+ */
+
+GDALDatasetH gv_manager_add_dataset( GvManager *manager, GDALDatasetH dataset )
+
+{
+ int i;
+ GvDataset *ds;
+
+ if( dataset == NULL || manager == NULL )
+ return NULL;
+
+ /*
+ * Check for dataset in existing list of open files. Note that our
+ * filename check does not account for different possible names for
+ * one dataset.
+ */
+ for( i = 0; i < manager->datasets->len; i++ )
+ {
+ ds = (GvDataset *) g_ptr_array_index(manager->datasets, i);
+
+ if( EQUAL(GDALGetDescription(ds->dataset),GDALGetDescription(dataset)) )
+ {
+ return ds->dataset;
+ }
+ }
+
+ /*
+ * Add the dataset to the list of managed datasets.
+ */
+ GDALReferenceDataset(dataset);
+ ds = g_new(GvDataset,1);
+ ds->dataset = dataset;
+ ds->rasters = g_new0(GvRaster *, GDALGetRasterCount(dataset));
+
+ g_ptr_array_add( manager->datasets, ds );
+
+ return dataset;
+}
+
+GDALDatasetH gv_manager_get_dataset( GvManager *manager, const char * filename)
+
+{
+ int i;
+ GvDataset *ds;
+ GDALDatasetH dataset;
+
+ /*
+ * Check for dataset in existing list of open files. Note that our
+ * filename check does not account for different possible names for
+ * one dataset.
+ */
+ for( i = 0; i < manager->datasets->len; i++ )
+ {
+ ds = (GvDataset *) g_ptr_array_index(manager->datasets, i);
+
+ if( EQUAL(GDALGetDescription(ds->dataset),filename) )
+ {
+ return ds->dataset;
+ }
+ }
+
+ /*
+ * Try to open the dataset, preferably with update access. We don't
+ * want to report update access errors so we supress error reporting
+ * temporarily.
+ */
+
+ CPLErrorReset();
+ CPLPushErrorHandler( CPLQuietErrorHandler );
+ dataset = GDALOpen( filename, GA_Update );
+ CPLPopErrorHandler();
+
+ if( dataset == NULL )
+ {
+ dataset = GDALOpen( filename, GA_ReadOnly );
+ }
+
+ if( dataset == NULL )
+ return NULL;
+
+ /*
+ * Add the dataset to the list of managed datasets.
+ */
+ ds = g_new(GvDataset,1);
+ ds->dataset = dataset;
+ ds->rasters = g_new0(GvRaster *, GDALGetRasterCount(dataset));
+
+ g_ptr_array_add( manager->datasets, ds );
+
+ return dataset;
+}
+
+static gint gv_manager_raster_destroy_cb( GtkObject * raster_in,
+ gpointer cb_data )
+
+{
+ GvManager *manager = GV_MANAGER(cb_data);
+ GvRaster *raster = GV_RASTER(raster_in);
+ GvDataset *ds = NULL;
+ int i, active_rasters = 0;
+
+ /*
+ * Find in our list. The dataset must already be "under management".
+ */
+ for( i = 0; i < manager->datasets->len; i++ )
+ {
+ ds = (GvDataset *) g_ptr_array_index(manager->datasets, i);
+
+ if( raster->dataset == ds->dataset )
+ break;
+ }
+
+ if( i == manager->datasets->len )
+ {
+ g_warning( "gv_manager_raster_destroy_cb(): can't find dataset." );
+ return FALSE;
+ }
+
+ /*
+ * Find our GvRaster.
+ */
+
+ for( i = 0; i < GDALGetRasterCount(ds->dataset); i++ )
+ {
+ if( ds->rasters[i] == raster )
+ ds->rasters[i] = NULL;
+ else if( ds->rasters[i] != NULL )
+ active_rasters++;
+ }
+
+ /*
+ * We apparently no longer need this GDALDataset. Dereference it, and
+ * remove from the list.
+ */
+ if( active_rasters == 0 )
+ {
+ if( GDALDereferenceDataset( ds->dataset ) < 1 )
+ GDALClose( ds->dataset );
+
+ g_free( ds->rasters );
+ g_free( ds );
+ g_ptr_array_remove_fast( manager->datasets, ds );
+ }
+
+ return FALSE;
+}
+
+GvRaster *gv_manager_get_dataset_raster( GvManager *manager,
+ GDALDatasetH dataset, int band )
+
+{
+ int i;
+ GvDataset *ds = NULL;
+ GvSampleMethod sm;
+ const char *sm_pref;
+
+ if( band < 1 || band > GDALGetRasterCount(dataset) )
+ return NULL;
+
+ /*
+ * Find in our list. The dataset must already be "under management".
+ */
+ for( i = 0; i < manager->datasets->len; i++ )
+ {
+ ds = (GvDataset *) g_ptr_array_index(manager->datasets, i);
+
+ if( dataset == ds->dataset )
+ break;
+ }
+
+ if( i == manager->datasets->len )
+ {
+ g_warning( "gv_manager_get_dataset_raster called with unmanaged dataset" );
+ return NULL;
+ }
+
+ /*
+ * Figure out the sample method to use from the preferences.
+ */
+ sm_pref = gv_manager_get_preference( manager, "default_raster_sample");
+ if( sm_pref != NULL && EQUAL(sm_pref,"average") )
+ sm = GvSMAverage;
+ else if( sm_pref != NULL && EQUAL(sm_pref,"average_8bit_phase") )
+ sm = GvSMAverage8bitPhase;
+ else
+ sm = GvSMSample;
+
+ /*
+ * Create a new GvRaster if it doesn't already exist.
+ */
+
+ if( ds->rasters[band-1] == NULL )
+ {
+ GDALRasterBandH gdal_band;
+
+ gdal_band = GDALGetRasterBand( ds->dataset, band );
+ if( GDALGetRasterColorInterpretation(gdal_band) == GCI_PaletteIndex )
+ sm = GvSMSample;
+
+ ds->rasters[band-1] = GV_RASTER(gv_raster_new( ds->dataset, band, sm));
+ gtk_signal_connect(
+ GTK_OBJECT(ds->rasters[band-1]), "destroy",
+ GTK_SIGNAL_FUNC(gv_manager_raster_destroy_cb),
+ GTK_OBJECT(manager));
+ }
+
+ return ds->rasters[band-1];
+}
+
+void gv_manager_set_busy( GvManager *manager, int busy_flag )
+
+{
+ if( !manager->busy_flag == !busy_flag )
+ return;
+
+ if( !manager->busy_flag )
+ gtk_idle_add( gv_manager_idle_handler, NULL );
+
+ manager->busy_flag = busy_flag;
+
+ gtk_signal_emit(GTK_OBJECT(manager),
+ manager_signals[BUSY_CHANGED]);
+}
+
+int gv_manager_get_busy( GvManager *manager )
+
+{
+ return manager->busy_flag;
+}
+
+static gint gv_manager_idle_handler( gpointer cb_data )
+
+{
+ GvManager *manager = gv_get_manager();
+ GvIdleTask *task;
+
+ if( manager->idle_tasks == NULL )
+ {
+ gv_manager_set_busy( manager, FALSE );
+ return FALSE;
+ }
+
+ /* remove task from list for now */
+ task = manager->idle_tasks;
+ manager->idle_tasks = task->next;
+ task->next = NULL;
+
+ if( task->callback( task->task_info ) )
+ gv_manager_queue_task( manager, task->name, task->priority,
+ task->callback, task->task_info );
+
+ g_free( task->name );
+ g_free( task );
+
+ return TRUE;
+}
+
+void gv_manager_queue_task( GvManager *manager, const char *task_name,
+ int priority, GtkFunction callback,
+ void *task_info)
+
+{
+ GvIdleTask *task = g_new0( GvIdleTask, 1 );
+
+ task->name = g_strdup( task_name );
+ task->priority = priority;
+ task->callback = callback;
+ task->task_info = task_info;
+
+ if( manager->idle_tasks == NULL
+ || manager->idle_tasks->priority > task->priority )
+ {
+ task->next = manager->idle_tasks;
+ manager->idle_tasks = task;
+ }
+ else
+ {
+ GvIdleTask *link;
+
+ for( link = manager->idle_tasks; link != NULL; link = link->next )
+ {
+ if( link->next == NULL )
+ {
+ link->next = task;
+ break;
+ }
+ else if( link->next->priority > task->priority )
+ {
+ task->next = link->next;
+ link->next = task;
+ break;
+ }
+ }
+ }
+
+ gv_manager_set_busy( manager, TRUE );
+}
+
+void gv_manager_dequeue_task( GvManager *manager, GvIdleTask *task )
+
+{
+ GvIdleTask **prev_ptr = &(manager->idle_tasks);
+
+ while( *prev_ptr != NULL )
+ {
+ if( *prev_ptr == task )
+ {
+ *prev_ptr = task->next;
+
+ g_free( task->name );
+ g_free( task );
+ }
+ else
+ prev_ptr = &((*prev_ptr)->next);
+ }
+}
Added: packages/openev/branches/upstream/current/gvmanager.h
===================================================================
--- packages/openev/branches/upstream/current/gvmanager.h (rev 0)
+++ packages/openev/branches/upstream/current/gvmanager.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,118 @@
+/******************************************************************************
+ * $Id: gvmanager.h,v 1.6 2004/02/10 15:38:31 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Preferences (and other?) manager. Singleton object.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvmanager.h,v $
+ * Revision 1.6 2004/02/10 15:38:31 andrey_kiselev
+ * Added gv_manager_add_dataset() function.
+ *
+ * Revision 1.5 2001/01/30 14:29:33 warmerda
+ * added gv_manager_dump
+ *
+ * Revision 1.4 2000/06/29 14:38:22 warmerda
+ * added busy status, and idle task list
+ *
+ * Revision 1.3 2000/06/26 15:12:00 warmerda
+ * Added dataset/gvraster management
+ *
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_MANAGER_H__
+#define __GV_MANAGER_H__
+
+#include <gtk/gtkobject.h>
+#include "gvtypes.h"
+#include "gvproperties.h"
+#include "gvraster.h"
+
+#define GV_TYPE_MANAGER (gv_manager_get_type ())
+#define GV_MANAGER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_MANAGER, GvManager))
+#define GV_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_MANAGER, GvManagerClass))
+#define GV_IS_MANAGER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_MANAGER))
+#define GV_IS_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_MANAGER))
+
+typedef struct _GvManager GvManager;
+typedef struct _GvManagerClass GvManagerClass;
+
+typedef struct {
+ GDALDatasetH dataset;
+
+ GvRaster **rasters;
+} GvDataset;
+
+typedef struct _idle_task {
+ struct _idle_task *next;
+ char *name;
+ int priority;
+ GtkFunction callback;
+ void *task_info;
+} GvIdleTask;
+
+struct _GvManager
+{
+ GtkObject object;
+
+ GvProperties preferences;
+
+ GPtrArray *datasets;
+
+ int busy_flag; /* TRUE if busy */
+
+ GvIdleTask*idle_tasks;
+};
+
+struct _GvManagerClass
+{
+ GtkObjectClass parent_class;
+
+ void (* preferences_changed)(GvManager *man);
+ void (* busy_changed)(GvManager *man);
+};
+
+GtkType gv_manager_get_type (void);
+GvManager* gv_manager_new (void);
+GvManager* gv_get_manager (void);
+
+void gv_manager_dump( GvManager * );
+const char* gv_manager_get_preference(GvManager *, const char *);
+GvProperties* gv_manager_get_preferences(GvManager *);
+void gv_manager_set_preference(GvManager *, const char *, const char *);
+
+GDALDatasetH gv_manager_add_dataset( GvManager *, GDALDatasetH );
+GDALDatasetH gv_manager_get_dataset( GvManager *, const char * );
+GvRaster *gv_manager_get_dataset_raster( GvManager *manager,
+ GDALDatasetH dataset, int band );
+
+void gv_manager_set_busy( GvManager *manager, int busy_flag );
+int gv_manager_get_busy( GvManager *manager );
+void gv_manager_queue_task( GvManager *manager,
+ const char *task_name, int priority,
+ GtkFunction callback, void *task_info );
+void gv_manager_dequeue_task( GvManager *manager, GvIdleTask *task );
+
+#endif /* __GV_MANAGER_H__ */
Added: packages/openev/branches/upstream/current/gvmesh.c
===================================================================
--- packages/openev/branches/upstream/current/gvmesh.c (rev 0)
+++ packages/openev/branches/upstream/current/gvmesh.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1165 @@
+/******************************************************************************
+ * $Id: gvmesh.c,v 1.37 2005/08/30 12:31:32 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Geometric mesh mapping tile s/t coordinates to display x/y/z
+ * coordinates.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvmesh.c,v $
+ * Revision 1.37 2005/08/30 12:31:32 andrey_kiselev
+ * Avoid initialization warnings in gv_mesh_extents().
+ *
+ * Revision 1.36 2004/02/18 16:07:27 andrey_kiselev
+ * Use gv_raster_get_nodata() instead of GDALGetRasterNoDataValue().
+ *
+ * Revision 1.35 2002/09/11 18:24:28 warmerda
+ * fixed serious hosing in gv_mesh_get_height() for multi tile meshes
+ *
+ * Revision 1.34 2002/09/10 21:13:49 warmerda
+ * fixed serious bugs in gv_mesh_get_height() esp for partial tiles
+ *
+ * Revision 1.33 2002/04/12 14:40:35 gmwalter
+ * Removed the gvmesh rescale function (not needed because of view area
+ * rescaling).
+ *
+ * Revision 1.31 2002/03/07 02:33:45 warmerda
+ * Fixed add_height() function so that mesh nodes for which no value is ever
+ * found are set to default_height instead of 1000.0. Also, values falling
+ * outside the source height raster are now set to default_height instead of 0.0.
+ *
+ * Revision 1.30 2001/08/22 16:20:38 warmerda
+ * use gv_mesh_reset_to_identity for setting to raw
+ *
+ * Revision 1.29 2001/08/08 13:18:08 warmerda
+ * fixed case of edge tiles not of reduced size
+ *
+ * Revision 1.28 2001/08/08 02:57:38 warmerda
+ * implement gv_mesh_finalize(), remove unused normals code
+ *
+ * Revision 1.27 2001/07/13 22:13:35 warmerda
+ * added function to get height from mesh
+ *
+ * Revision 1.26 2001/03/29 03:53:18 warmerda
+ * use three iterations in nodata fill-in
+ *
+ * Revision 1.25 2001/03/29 03:38:58 warmerda
+ * improved nodata propagation to go two steps
+ *
+ * Revision 1.24 2001/03/28 22:38:16 warmerda
+ * fill in mesh nodata values with average of ajacent real mesh points
+ *
+ * Revision 1.23 2000/08/23 19:06:42 warmerda
+ * fixed problems with overly large levels of detail
+ *
+ * Revision 1.22 2000/08/23 18:35:11 warmerda
+ * avoid off-by-one errors and honour nodata in setting mesh from dem file
+ *
+ * Revision 1.21 2000/08/18 20:33:56 warmerda
+ * don't return a mesh that is more resolved than the raster
+ *
+ * Revision 1.20 2000/08/16 20:28:31 warmerda
+ * fixed calculation of corner tiles in get extents
+ *
+ * Revision 1.19 2000/07/03 20:57:32 warmerda
+ * moved tile selection for draw to gvrasterlayer
+ *
+ * Revision 1.18 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "gvviewarea.h"
+#include <GL/gl.h>
+#include "gvmesh.h"
+#include "gvraster.h"
+#include "gvrasterlayer.h"
+#include "gvmanager.h"
+
+static void gv_mesh_class_init(GvMeshClass *klass);
+static void gv_mesh_init(GvMesh *mesh);
+static void gv_mesh_finalize(GtkObject *object);
+
+#define GV_MESH_RIGHT_X_BIT 1
+#define GV_MESH_LEFT_X_BIT 2
+#define GV_MESH_TOP_Y_BIT 4
+#define GV_MESH_BOT_Y_BIT 8
+
+#define DEG2RAD 0.01745329252
+#define RAD2DEG 57.2986885
+
+GtkType
+gv_mesh_get_type(void)
+{
+ static GtkType mesh_type = 0;
+
+ if (!mesh_type)
+ {
+ static const GtkTypeInfo mesh_info =
+ {
+ "GvMesh",
+ sizeof(GvMesh),
+ sizeof(GvMeshClass),
+ (GtkClassInitFunc) gv_mesh_class_init,
+ (GtkObjectInitFunc) gv_mesh_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ mesh_type = gtk_type_unique(gv_data_get_type(), &mesh_info);
+ }
+ return mesh_type;
+}
+
+static void
+gv_mesh_init(GvMesh *mesh)
+{
+
+ mesh->vertices = NULL;
+ mesh->tex_coords = NULL;
+
+}
+
+static void
+gv_mesh_class_init(GvMeshClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ data_class = (GvDataClass*) klass;
+
+ object_class = (GtkObjectClass*) klass;
+ object_class->finalize = gv_mesh_finalize;
+}
+
+static GArray *
+gv_mesh_get_tile_tex_coords( GvMesh *mesh, int tile, int lod )
+
+{
+ gint tiles_across, tiles_down;
+ GPtrArray *parray;
+
+ if( lod >= mesh->raster->max_lod )
+ lod = mesh->raster->max_lod - 1;
+ else if( lod < 0 )
+ lod = 0;
+
+ tiles_across = mesh->raster->tiles_across;
+ tiles_down = mesh->raster->tiles_down;
+
+ if( tile >= tiles_across * (tiles_down-1) )
+ {
+ if( (tile % tiles_across) == (tiles_across-1) )
+ parray = mesh->tex_coords_bottom_right;
+ else
+ parray = mesh->tex_coords_bottom;
+ }
+ else if( (tile % tiles_across) == (tiles_across-1) )
+ parray = mesh->tex_coords_right;
+ else
+ parray = mesh->tex_coords;
+
+ return (GArray *) g_ptr_array_index(parray,lod);
+}
+
+gint *
+gv_mesh_get_tile_corner_coords( GvMesh *mesh, int tile)
+{
+ gint tiles_across = mesh->raster->tiles_across;
+ /* gint tiles_down = mesh->raster->tiles_down; */
+
+ gint tile_x = mesh->raster->tile_x;
+ gint tile_y = mesh->raster->tile_y;
+
+ gint *coords = (gint *)malloc( 8*sizeof(gint) );
+ if(coords == NULL)
+ {
+ g_error("Out of memory!!!");
+ return NULL;
+ }
+
+ /* top left corner */
+ coords[0] = tile_x * (tile % tiles_across);
+ coords[1] = tile_y * (tile / tiles_across);
+
+ /* top right corner */
+ coords[2] = coords[0] + tile_x;
+ coords[3] = coords[1];
+
+ /* bottom left corner */
+ coords[4] = coords[0];
+ coords[5] = coords[1] + tile_y;
+
+ /* bottom right corner */
+ coords[6] = coords[0] + tile_x;
+ coords[7] = coords[1] + tile_y;
+
+ /* Check that aren't past edge of image on far right and bottom */
+ if ( coords[2] >= mesh->raster->width)
+ {
+ coords[2] = mesh->raster->width - 1;
+ coords[6] = mesh->raster->width - 1;
+ }
+
+ if ( coords[5] >= mesh->raster->height)
+ {
+ coords[5] = mesh->raster->height - 1;
+ coords[7] = mesh->raster->height - 1;
+ }
+
+ return coords;
+
+}
+
+static void
+gv_mesh_build_tex_coord( GvMesh *mesh, GArray *tex_coords, gint lod,
+ gint ds_x, gint ds_y,
+ gint stride_x, gint stride_y )
+
+{
+ gint i, e;
+ gint tile_x = mesh->tile_x;
+ gint tile_y = mesh->tile_y;
+ gint edge_width;
+
+ /*
+ ** Edge mesh tiles (bottom, right and bottom/right) that are not a
+ ** reduced size, will be computed as having a remainder of zero, and
+ ** given a size of 2. Adjust these.
+ */
+
+ if( ds_x == 2 )
+ ds_x += mesh->tile_x-GV_TILE_OVERLAP;
+
+ if( ds_y == 2 )
+ ds_y += mesh->tile_y-GV_TILE_OVERLAP;
+
+ /* Compute */
+
+ edge_width = (1 << lod) * GV_TILE_OVERLAP/2;
+
+ for( i = 0; i <= tile_y; i += stride_y )
+ {
+ for( e = 0; e <= tile_x; e += stride_x )
+ {
+ float s, t;
+
+ s = (float) e / (float) tile_x;
+ t = (float) i / (float) tile_y;
+
+ s = (s * (ds_x-edge_width*2) + edge_width) / tile_x;
+ t = (t * (ds_y-edge_width*2) + edge_width) / tile_y;
+
+ g_array_append_val( tex_coords, s );
+ g_array_append_val( tex_coords, t );
+ }
+ }
+}
+
+
+GvMesh *
+gv_mesh_new_identity( GvRaster *raster, gint detail )
+{
+ gint begin_x, begin_y;
+ gint stride_x, stride_y;
+ gint i, e, j, k, mesh_lod;
+ gint tiles_down, tiles_across, tile;
+ gint tile_x = raster->tile_x;
+ gint tile_y = raster->tile_y;
+ gint x = raster->width;
+ gint y = raster->height;
+ GArray *tex_coords;
+
+ GvMesh *mesh = (GvMesh *) GV_DATA(gtk_type_new(gv_mesh_get_type()));
+
+ mesh->raster = raster;
+
+ while( (tile_x >> detail) == 0 || (tile_y >> detail) == 0 )
+ detail--;
+
+ stride_x = tile_x >> detail;
+ stride_y = tile_y >> detail;
+
+ mesh->detail = detail;
+ mesh->tile_x = tile_x;
+ mesh->tile_y = tile_y;
+ mesh->width = x;
+ mesh->height = y;
+
+ tiles_across = raster->tiles_across;
+ tiles_down = raster->tiles_down;
+
+ mesh->max_tiles = tiles_across * tiles_down;
+ mesh->vertices = g_array_new( FALSE, FALSE, sizeof( GArray *) );
+
+ /* Set top left coords */
+
+ mesh->corner_coords[0] = 0.0;
+ mesh->corner_coords[1] = (float) y;
+
+ /* Set top right coords */
+
+ mesh->corner_coords[2] = (float) x;
+ mesh->corner_coords[3] = (float) y;
+
+ /* Set bottom left coords */
+
+ mesh->corner_coords[4] = 0.0;
+ mesh->corner_coords[5] = 0.0;
+
+ /* Set bottom right coords */
+
+ mesh->corner_coords[6] = (float) x;
+ mesh->corner_coords[7] = 0.0;
+
+ /* prepare meshes for each level of detail */
+
+ mesh->tex_coords = g_ptr_array_new();
+ mesh->tex_coords_right = g_ptr_array_new();
+ mesh->tex_coords_bottom = g_ptr_array_new();
+ mesh->tex_coords_bottom_right = g_ptr_array_new();
+
+ for( mesh_lod = 0; mesh_lod < raster->max_lod; mesh_lod++ )
+ {
+ /* First we set the full tile s/t coordinate mappings */
+ tex_coords = g_array_new( FALSE, FALSE, sizeof( float ) );
+ g_ptr_array_add(mesh->tex_coords, tex_coords );
+ gv_mesh_build_tex_coord( mesh, tex_coords, mesh_lod,
+ tile_x, tile_y, stride_x, stride_y );
+
+ /* Generate right hand side partial tile s/t coordinates */
+ tex_coords = g_array_new( FALSE, FALSE, sizeof( float ) );;
+ g_ptr_array_add(mesh->tex_coords_right, tex_coords );
+ gv_mesh_build_tex_coord( mesh, tex_coords, mesh_lod,
+ (mesh->width % (tile_x-GV_TILE_OVERLAP)) + 2,
+ tile_y,
+ stride_x, stride_y );
+ /* Generate bottom side partial tile s/t coordinates */
+ tex_coords = g_array_new( FALSE, FALSE, sizeof( float ) );;
+ g_ptr_array_add(mesh->tex_coords_bottom, tex_coords );
+ gv_mesh_build_tex_coord( mesh, tex_coords, mesh_lod,
+ tile_x,
+ (mesh->height % (tile_y-GV_TILE_OVERLAP)) + 2,
+ stride_x, stride_y );
+
+ /* Generate bottom/right partial tile s/t coordinates */
+ tex_coords = g_array_new( FALSE, FALSE, sizeof( float ) );;
+ g_ptr_array_add(mesh->tex_coords_bottom_right, tex_coords );
+ gv_mesh_build_tex_coord( mesh, tex_coords, mesh_lod,
+ (mesh->width % (tile_x-GV_TILE_OVERLAP)) + 2,
+ (mesh->height % (tile_y-GV_TILE_OVERLAP)) + 2,
+ stride_x, stride_y );
+ }
+
+ /* generate output raster coordinates for every tile */
+ tile = 0;
+ for( i = 0; i < tiles_down; i++ )
+ {
+ for( e = 0; e < tiles_across; e++ )
+ {
+ GArray *tile_vertices;
+ int tex_index = 0;
+
+ tex_coords = gv_mesh_get_tile_tex_coords( mesh, tile, 0 );
+
+ begin_x = e * (tile_x-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2;
+ begin_y = i * (tile_y-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2;
+
+ tile_vertices = g_array_new( FALSE, FALSE, sizeof( float ) );
+
+ for( j = 0; j <= tile_y; j += stride_y )
+ {
+ for( k = 0; k <= tile_x; k += stride_x )
+ {
+ float t_x, t_y, t_z;
+ float s, t;
+
+ s = g_array_index( tex_coords, float, 2*tex_index );
+ t = g_array_index( tex_coords, float, 2*tex_index+1);
+ tex_index++;
+
+ t_x = begin_x + s*tile_x;
+ t_y = y - (begin_y + t*tile_y);
+ t_z = 0.0;
+
+ g_array_append_val( tile_vertices, t_x );
+ g_array_append_val( tile_vertices, t_y );
+ g_array_append_val( tile_vertices, t_z );
+ }
+ }
+
+ g_array_append_val( mesh->vertices, tile_vertices );
+ tile++;
+ }
+ }
+
+ return mesh;
+}
+
+void
+gv_mesh_reset_to_identity( GvMesh *mesh )
+
+{
+ int i, e, tile, tiles_across, tiles_down, stride_x, stride_y;
+ int begin_x, begin_y;
+ gint tile_x = mesh->tile_x;
+ gint tile_y = mesh->tile_y;
+
+ stride_x = mesh->tile_x >> mesh->detail;
+ stride_y = mesh->tile_y >> mesh->detail;
+
+ tiles_across = mesh->raster->tiles_across;
+ tiles_down = mesh->raster->tiles_down;
+
+ /* generate output raster coordinates for every tile */
+ tile = 0;
+ for( i = 0; i < tiles_down; i++ )
+ {
+ for( e = 0; e < tiles_across; e++ )
+ {
+ GArray *tex_coords;
+ GArray *tile_vertices;
+ int tex_index = 0, out_vert = 0, j, k;
+
+ tex_coords = gv_mesh_get_tile_tex_coords( mesh, tile, 0 );
+
+ begin_x = e * (tile_x-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2;
+ begin_y = i * (tile_y-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2;
+
+ tile_vertices = g_array_index( mesh->vertices, GArray *, tile );
+
+ for( j = 0; j <= tile_y; j += stride_y )
+ {
+ for( k = 0; k <= tile_x; k += stride_x )
+ {
+ float t_x, t_y;
+ float s, t;
+
+ s = g_array_index( tex_coords, float, 2*tex_index );
+ t = g_array_index( tex_coords, float, 2*tex_index+1);
+ tex_index++;
+
+ t_x = begin_x + s*tile_x;
+ t_y = begin_y + t*tile_y;
+
+ g_array_index(tile_vertices, float, out_vert++) = t_x;
+ g_array_index(tile_vertices, float, out_vert++) = t_y;
+ out_vert++;
+ }
+ }
+
+ tile++;
+ }
+ }
+}
+
+
+/* Add height values to mesh based on provided hight raster
+ - go through mesh->vertices and for every x-y co-ord transform back to image co-ordinates
+ - query height raster at x-y point and set mesh->verticies z value to it
+ */
+void
+gv_mesh_add_height( GvMesh *mesh, GvRaster *raster,
+ double default_height )
+{
+ int i, j, success, iteration, max_iteration;
+ float z_float;
+ double x, y, z, imaginary;
+ double nodata_value;
+
+ success = gv_raster_get_nodata( raster, &nodata_value );
+ if( !success )
+ nodata_value = -1e8;
+
+ /* number of tiles */
+ for( i=0; i < mesh->vertices->len; i++)
+ {
+ GArray *tile_vertices;
+
+ tile_vertices = g_array_index( mesh->vertices, GArray *, i);
+
+ /* Vertices in tile */
+ for( j=0; j < (tile_vertices->len/3); j++)
+ {
+ /* get xy in image space */
+ x = (float) g_array_index( tile_vertices, float, 3*j);
+ y = (float) g_array_index( tile_vertices, float, 3*j+1);
+ z = (float) g_array_index( tile_vertices, float, 3*j+2);
+
+ /* printf("x y z %f %f %f", x, y, z); */
+
+ if (!gv_raster_georef_to_pixel(raster, &x, &y, &z))
+ {
+ fprintf(stderr, "ERROR raster_georef_to_pixel failed!!!\n");
+ break;
+ }
+
+ if( x > -1.0 && x < 0.0 )
+ x = 0.0;
+ if( y > -1.0 && y < 0.0 )
+ y = 0.0;
+ if( x >= raster->width && x < raster->width+1 )
+ x = raster->width - 0.01;
+ if( y >= raster->height && y < raster->height+1 )
+ y = raster->height - 0.01;
+
+ /* Check if mesh xy values outside of height raster - leave as 0 */
+ if( x >= 0.0 && x < raster->width
+ && y >= 0.0 && y < raster->height )
+ {
+ if (!gv_raster_get_sample(raster, x, y, &z, &imaginary))
+ {
+ fprintf(stderr,
+ "ERROR raster_get_sample failed for (x y z) %f %f\n",
+ x, y);
+ z_float = (float)nodata_value;
+ }
+ else
+ {
+ z_float = z;
+ }
+ }
+ else
+ z_float = (float)nodata_value;
+
+ g_array_index( tile_vertices, float, 3*j+2) = z_float;
+ }
+
+ mesh->vertices = g_array_remove_index(mesh->vertices, i);
+ g_array_insert_val(mesh->vertices, i, tile_vertices);
+ }
+
+ /*
+ * Make another pass, trying to fill in mesh elevations for vertices
+ * where we got nodata, or fell off the available data.
+ *
+ * We run this twice to propagate out values an extra step.
+ */
+
+ max_iteration = 3;
+ for( iteration = 0; iteration < max_iteration; iteration++ )
+ {
+ /* number of tiles */
+ for( i=0; i < mesh->vertices->len; i++)
+ {
+ GArray *tile_vertices;
+ int j, k;
+ int mesh_xsize, mesh_ysize;
+ float *data;
+
+ tile_vertices = g_array_index( mesh->vertices, GArray *, i);
+ data = (float *) tile_vertices->data;
+
+ mesh_xsize = (1 << mesh->detail) + 1;
+ mesh_ysize = (1 << mesh->detail) + 1;
+
+ g_assert( mesh_xsize * mesh_ysize * 3 == tile_vertices->len );
+
+ for( j = 0; j < mesh_ysize; j++ )
+ {
+ for( k = 0; k < mesh_xsize; k++ )
+ {
+ float sum = 0;
+ int count = 0;
+ int t_i;
+
+ t_i = j * mesh_xsize + k;
+
+ /* skip entries with an OK value */
+ if( data[3*t_i+2] != (float)nodata_value )
+ continue;
+
+ /* check mesh entry to left */
+ if( k > 0 && data[3*(t_i-1)+2] != (float)nodata_value )
+ {
+ sum += data[3*(t_i-1)+2];
+ count++;
+ }
+
+ /* check mesh entry to right */
+ if( k+1 < mesh_xsize && data[3*(t_i+1)+2] != (float)nodata_value )
+ {
+ sum += data[3*(t_i+1)+2];
+ count++;
+ }
+
+ /* check mesh entry above */
+ if( j > 0
+ && data[3*(t_i-mesh_xsize)+2] != (float)nodata_value )
+ {
+ sum += data[3*(t_i-mesh_xsize)+2];
+ count++;
+ }
+
+ /* check mesh entry below */
+ if( j+1 < mesh_ysize
+ && data[3*(t_i+mesh_xsize)+2] != (float)nodata_value )
+ {
+ sum += data[3*(t_i+mesh_xsize)+2];
+ count++;
+ }
+
+ /* if we got hits, average them and assign */
+ if( count > 0 )
+ {
+ data[3*t_i+2] = sum / count;
+ }
+ else if( iteration == max_iteration-1 )
+ {
+ data[3*t_i+2] = default_height;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Set upper/lower bounds for the height (eg. if a DEM
+ * defaults to -32767 for patches of missing data within
+ * the image, gv_mesh_add_height will treat it as valid data.
+ * This function takes a pass through the vertices
+ * and clamps if necessary). This will also get rid of the
+ * effects of a very low nodata_value (when the DEM doesn't
+ * cover the full area of the raster being draped atop it).
+ */
+
+void
+gv_mesh_clamp_height( GvMesh *mesh, int bclamp_min, int bclamp_max,
+ double min_height, double max_height )
+{
+
+ int i;
+
+ /*
+ * Clamp minimum z value to min_height if bclamp_min = 1
+ * Clamp maximum z value to max_height if bclamp_max = 1
+ */
+
+ /* number of tiles */
+ for( i=0; i < mesh->vertices->len; i++)
+ {
+ GArray *tile_vertices;
+ int j, k;
+ int mesh_xsize, mesh_ysize;
+ float *data;
+
+ tile_vertices = g_array_index( mesh->vertices, GArray *, i);
+ data = (float *) tile_vertices->data;
+
+ mesh_xsize = (1 << mesh->detail) + 1;
+ mesh_ysize = (1 << mesh->detail) + 1;
+
+ g_assert( mesh_xsize * mesh_ysize * 3 == tile_vertices->len );
+
+
+ for( j = 0; j < mesh_ysize; j++ )
+ {
+ for( k = 0; k < mesh_xsize; k++ )
+ {
+ int t_i;
+
+ t_i = j * mesh_xsize + k;
+
+ if (( bclamp_min == 1 ) && ( data[3*t_i+2] < min_height ))
+ data[3*t_i+2] = min_height;
+
+ if (( bclamp_max == 1 ) && ( data[3*t_i+2] > max_height ))
+ data[3*t_i+2] = max_height;
+
+ }
+ }
+ }
+}
+
+
+/*
+ * This function assumes the mesh is the result of gv_mesh_new_identity, and
+ * maps a raw raster space into an equivelent OpenGL model space. Now
+ * transform the model space outputs to be georeferenced coordinates instead
+ * of pixel/line identity values.
+ *
+ * The "geotransform" is the usual six word affine transform.
+ */
+
+void
+gv_mesh_set_transform( GvMesh *mesh, gint xsize, gint ysize,
+ double *geotransform )
+{
+ int tile;
+
+ for( tile = 0; tile < mesh->max_tiles; tile++ )
+ {
+ GArray *verts;
+ float *xyz_verts;
+ int xyz_offset;
+
+ verts = g_array_index( mesh->vertices, GArray *, tile );
+
+ xyz_verts = (float *) verts->data;
+ for( xyz_offset = 0; xyz_offset < verts->len; xyz_offset += 3 )
+ {
+ float x_out, y_out;
+
+ x_out = geotransform[0]
+ + xyz_verts[0] * geotransform[1]
+ + (ysize - xyz_verts[1]) * geotransform[2];
+ y_out = geotransform[3]
+ + xyz_verts[0] * geotransform[4]
+ + (ysize - xyz_verts[1]) * geotransform[5];
+
+ xyz_verts[0] = x_out;
+ xyz_verts[1] = y_out;
+
+ xyz_verts += 3;
+ }
+ }
+}
+
+
+
+GvMeshTile *
+gv_mesh_get( GvMesh *mesh, gint tile, gint raster_lod, gint detail,
+ GvMeshTile *tile_info )
+{
+ gint i, e, step;
+ gint dimensions = (1 << mesh->detail) + 1;
+ GArray *verts;
+ static GArray *g_indices = NULL;
+
+ if( tile_info == NULL )
+ {
+ if( ( tile_info = g_new( GvMeshTile, 1 ) ) == NULL )
+ {
+ return NULL;
+ }
+ }
+
+ if( detail < raster_lod )
+ detail = raster_lod;
+
+ if( tile < mesh->max_tiles )
+ {
+ if( mesh->tex_coords )
+ {
+ GArray *tex_coords;
+
+ tex_coords = gv_mesh_get_tile_tex_coords( mesh, tile, detail );
+ tile_info->tex_coords = (float *) tex_coords->data;
+ }
+ else
+ tile_info->tex_coords = NULL;
+
+ verts = g_array_index( mesh->vertices, GArray *, tile );
+
+ if( verts == NULL )
+ {
+ fprintf( stderr, "Missing vertices information\n" );
+ }
+
+ tile_info->vertices = (float *)verts->data;
+
+ /* Figure out the spacing for the index */
+
+ /* What does this do ??? */
+ if( detail >= mesh->detail )
+ {
+ /* Use mesh spacing */
+ step = 1;
+ detail = mesh->detail;
+ } else {
+ /* Use raster spacing */
+ step = 1 << (mesh->detail - detail);
+ }
+
+ /* Note: overwrites above calculations */
+ step = 1;
+ detail = mesh->detail;
+
+
+ /* Now we build the indices and get ready to return the tile */
+
+ tile_info->restarts = 0;
+ tile_info->list_type = GL_TRIANGLE_STRIP;
+
+ if( g_indices )
+ {
+ g_array_set_size( g_indices, 0 );
+ } else {
+ g_indices = g_array_new( FALSE, FALSE, sizeof( int ) );
+ }
+
+ for( i = 0; i < dimensions-1; i += step )
+ {
+ for( e = 0; e < dimensions; e += step )
+ {
+ gint val;
+
+ val = i * dimensions + e;
+
+ g_array_append_val( g_indices, val );
+
+ val = (i+step) * dimensions + e;
+
+ g_array_append_val( g_indices, val );
+ }
+ tile_info->restarts++;
+ }
+
+ switch( tile_info->list_type )
+ {
+ case 0:
+ tile_info->range = dimensions*4;
+ break;
+ case GL_TRIANGLE_STRIP:
+ /* Only this case works right now */
+ tile_info->range = ( (1 << detail ) + 1 ) * 2;
+ break;
+ case 2:
+ tile_info->range = 2+dimensions;
+ break;
+ case 3:
+ tile_info->range = dimensions*2;
+ break;
+ }
+
+ tile_info->restarts--;
+ tile_info->indices = (gint *) g_indices->data;
+ } else {
+ return NULL;
+ }
+ return tile_info;
+
+}
+
+void gv_mesh_extents( GvMesh *mesh, GvRect *rect )
+{
+ float x[4], y[4];
+ int dimensions;
+ int tile;
+ GArray *verts;
+
+ if( mesh )
+ {
+ gint tiles_per_row;
+
+ /* First we get the top left tile */
+
+ if( ( verts = g_array_index( mesh->vertices, GArray *, 0 ) ) == NULL )
+ {
+ return;
+ }
+
+ dimensions = ( 1 << mesh->detail ) + 1;
+
+ x[0] = g_array_index( verts, float, 0 );
+ y[0] = g_array_index( verts, float, 1 );
+
+ /* The we do the top right tile */
+
+ tiles_per_row = mesh->raster->tiles_across;
+ tile = tiles_per_row - 1;
+
+ if( ( verts = g_array_index( mesh->vertices, GArray *, tile ) ) == NULL )
+ {
+ return;
+ }
+
+ x[1] = g_array_index( verts, float, 3*(dimensions-1) );
+ y[1] = g_array_index( verts, float, 3*(dimensions-1)+1 );
+
+ /* The we do the bottom left tile */
+
+ tile = mesh->raster->tiles_across * (mesh->raster->tiles_down-1);
+
+ if( ( verts = g_array_index( mesh->vertices, GArray *, tile ) ) == NULL )
+ {
+ return;
+ }
+
+ x[2] = g_array_index( verts, float, 3*(dimensions*(dimensions-1)) );
+ y[2] = g_array_index( verts, float, 3*(dimensions*(dimensions-1))+1);
+
+ /* The we do the last tile */
+
+ if( ( verts = g_array_index( mesh->vertices, GArray *, mesh->max_tiles-1 ) ) == NULL )
+ {
+ return;
+ }
+
+ x[3] = g_array_index( verts, float, 3*(dimensions*dimensions-1) );
+ y[3] = g_array_index( verts, float, 3*(dimensions*dimensions-1)+1 );
+
+ /* Return results */
+
+ rect->x = MIN( MIN( MIN( x[0], x[1] ), x[2] ), x[3] );
+ rect->y = MIN( MIN( MIN( y[0], y[1] ), y[2] ), y[3] );
+
+ rect->width = MAX( MAX( MAX( x[0], x[1] ), x[2] ), x[3] ) - rect->x;
+ rect->height = MAX( MAX( MAX( y[0], y[1] ), y[2] ), y[3] ) - rect->y;
+ }
+
+ return;
+}
+
+/************************************************************************/
+/* gv_mesh_get_height() */
+/* */
+/* Fetch the mesh height at the indicated location. */
+/************************************************************************/
+
+float gv_mesh_get_height( GvMesh *mesh,
+ double x, double y, int *success )
+
+{
+ int tile, tile_in_x, tile_in_y, vert_off;
+ int mesh_pnts_per_line, mesh_pnts_per_column, vert_x, vert_y;
+ int factor;
+ double stride_x, stride_y;
+ GvRaster *raster = mesh->raster;
+ double pl_x, pl_y;
+ GArray *tile_vertices;
+ float x_vert[4], y_vert[4], z_vert[4], u, v;
+ int tile_width, tile_height;
+
+ if( success != NULL )
+ *success = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* What pixel/line location are we looking for. Provide a */
+/* little bit of fudging if necessary to avoid stuff on the */
+/* edge falling out of bounds. */
+/* -------------------------------------------------------------------- */
+
+ pl_x = x;
+ pl_y = y;
+
+ gv_raster_georef_to_pixel( raster, &pl_x, &pl_y, NULL );
+
+ if( pl_x < 0.0 && pl_x > -0.01 )
+ pl_x += 0.01;
+ if( pl_y < 0.0 && pl_y > -0.01 )
+ pl_y += 0.01;
+ if( pl_x >= raster->width && pl_x < raster->width + 0.01 )
+ pl_x -= 0.01;
+ if( pl_y >= raster->height && pl_y < raster->height + 0.01 )
+ pl_y -= 0.01;
+
+ if( pl_x < 0 || pl_x >= raster->width
+ || pl_y < 0 || pl_y >= raster->height )
+ {
+ CPLDebug( "OpenEV",
+ "Didn't get a value (1) for location Geo:(%g,%g) PL:(%g,%g) Size:(%d,%d)",
+ x, y, pl_x, pl_y, raster->width, raster->height );
+ return 0.0;
+ }
+
+/* -------------------------------------------------------------------- */
+/* What tile does this fall in. */
+/* -------------------------------------------------------------------- */
+ tile_in_x = ((int) pl_x) / (raster->tile_x-GV_TILE_OVERLAP);
+ tile_in_y = ((int) pl_y) / (raster->tile_y-GV_TILE_OVERLAP);
+
+ tile = tile_in_x + tile_in_y * raster->tiles_across;
+
+/* -------------------------------------------------------------------- */
+/* Where does our request fall within the tile. */
+/* -------------------------------------------------------------------- */
+ factor = 1 << mesh->detail;
+
+ mesh_pnts_per_line = factor + 1;
+ mesh_pnts_per_column = factor + 1;
+
+ if( tile_in_x == raster->tiles_across - 1 )
+ tile_width = mesh->width
+ - (raster->tile_x - GV_TILE_OVERLAP) * tile_in_x;
+ else
+ tile_width = mesh->tile_x;
+
+ if( tile_in_y == raster->tiles_down - 1 )
+ tile_height = mesh->height
+ - (raster->tile_y - GV_TILE_OVERLAP) * tile_in_y;
+ else
+ tile_height = mesh->tile_y;
+
+ stride_x = tile_width / (float) factor;
+ stride_y = tile_height / (float) factor;
+
+ pl_x -= tile_in_x * (raster->tile_x - GV_TILE_OVERLAP);
+ pl_y -= tile_in_y * (raster->tile_y - GV_TILE_OVERLAP);
+
+ vert_x = (int) (pl_x / stride_x);
+ vert_y = (int) (pl_y / stride_y);
+
+ vert_off = vert_x + vert_y * mesh_pnts_per_line;
+
+/* -------------------------------------------------------------------- */
+/* Find the neighbouring vertices. */
+/* -------------------------------------------------------------------- */
+ g_assert( tile >= 0 && tile < mesh->vertices->len );
+ tile_vertices = g_array_index( mesh->vertices, GArray *, tile );
+
+ if( vert_off < 0 || vert_off*3 >= tile_vertices->len )
+ {
+ CPLDebug( "OpenEV",
+ "Didn't get a value for location (%g,%g), vert_off=%d\n",
+ x, y, vert_off );
+ return 0.0;
+ }
+
+ x_vert[0] = g_array_index( tile_vertices, float, 3*vert_off );
+ y_vert[0] = g_array_index( tile_vertices, float, 3*vert_off+1 );
+ z_vert[0] = g_array_index( tile_vertices, float, 3*vert_off+2 );
+
+ if( vert_x+1 < mesh_pnts_per_line )
+ {
+ x_vert[1] = g_array_index( tile_vertices, float, 3*(vert_off+1) );
+ y_vert[1] = g_array_index( tile_vertices, float, 3*(vert_off+1)+1 );
+ z_vert[1] = g_array_index( tile_vertices, float, 3*(vert_off+1)+2 );
+ }
+ else
+ {
+ x_vert[1] = x_vert[0];
+ y_vert[1] = y_vert[0];
+ z_vert[1] = z_vert[0];
+ }
+
+ if( vert_y+1 < mesh_pnts_per_column )
+ {
+ int off = vert_off + mesh_pnts_per_line;
+
+ x_vert[2] = g_array_index( tile_vertices, float, 3*off );
+ y_vert[2] = g_array_index( tile_vertices, float, 3*off + 1 );
+ z_vert[2] = g_array_index( tile_vertices, float, 3*off + 2 );
+ }
+ else
+ {
+ x_vert[2] = x_vert[0];
+ y_vert[2] = y_vert[0];
+ z_vert[2] = z_vert[0];
+ }
+
+ if( vert_y+1 < mesh_pnts_per_column && vert_x+1 < mesh_pnts_per_line )
+ {
+ int off = vert_off + mesh_pnts_per_line + 1;
+
+ x_vert[3] = g_array_index( tile_vertices, float, 3*off );
+ y_vert[3] = g_array_index( tile_vertices, float, 3*off + 1 );
+ z_vert[3] = g_array_index( tile_vertices, float, 3*off + 2 );
+ }
+ else if( vert_y+1 < mesh_pnts_per_column )
+ {
+ x_vert[3] = x_vert[2];
+ y_vert[3] = y_vert[2];
+ z_vert[3] = z_vert[2];
+ }
+ else
+ {
+ x_vert[3] = x_vert[1];
+ y_vert[3] = y_vert[1];
+ z_vert[3] = z_vert[1];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Interpolate the value within this grid square. */
+/* -------------------------------------------------------------------- */
+ u = (pl_x - vert_x * stride_x) / (float) stride_x;
+ v = (pl_y - vert_y * stride_y) / (float) stride_y;
+
+ if( u < -0.0001 || u > 1.0001 || v < -0.0001 || v > 1.0001 )
+ g_warning( "illegal u or v in gv_mesh_get_height()" );
+
+#ifdef notdef
+ /* Note: this will produce false positives for "on the edges" conditions*/
+ if( x < MIN(x_vert[0],x_vert[1])
+ || x > MAX(x_vert[0],x_vert[1])
+ || y < MIN(y_vert[0],y_vert[2])
+ || y > MAX(y_vert[0],y_vert[2]) )
+ {
+ CPLDebug( "OpenEV",
+ "x/y outside of quadrant in gv_mesh_get_height(), uv=%g,%g\n"
+ " x,y=%g,%g quad=(%g,%g),(%g,%g),(%g,%g),(%g,%g)",
+ u, v,
+ x, y,
+ x_vert[0], y_vert[0],
+ x_vert[1], y_vert[1],
+ x_vert[2], y_vert[2],
+ x_vert[3], y_vert[3] );
+ }
+#endif
+
+ if( success != NULL )
+ *success = TRUE;
+
+ return z_vert[0] * (1.0-u) * (1.0-v)
+ + z_vert[1] * (u) * (1.0-v)
+ + z_vert[2] * (1.0-u) * (v)
+ + z_vert[3] * (u) * (v);
+}
+
+/************************************************************************/
+/* gv_mesh_finalize() */
+/* */
+/* Final destruction of GvMesh. */
+/************************************************************************/
+
+static void
+gv_mesh_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvMesh *mesh = GV_MESH(object);
+ int i;
+ GPtrArray *tex_coords;
+
+ CPLDebug( "OpenEV", "gv_mesh_finalize(%s)\n",
+ gv_data_get_name(GV_DATA(object)) );
+
+ /* free all vertices */
+ for( i = 0; i < mesh->vertices->len; i++ )
+ g_array_free( g_array_index( mesh->vertices, GArray *, i ), TRUE );
+
+ g_array_free( mesh->vertices, TRUE );
+
+ /* free texture coordinates */
+ tex_coords = mesh->tex_coords;
+ for( i = 0; i < tex_coords->len; i++ )
+ g_array_free( (GArray *) g_ptr_array_index(tex_coords,i), TRUE );
+
+ tex_coords = mesh->tex_coords_right;
+ for( i = 0; i < tex_coords->len; i++ )
+ g_array_free( (GArray *) g_ptr_array_index(tex_coords,i), TRUE );
+
+ tex_coords = mesh->tex_coords_bottom_right;
+ for( i = 0; i < tex_coords->len; i++ )
+ g_array_free( (GArray *) g_ptr_array_index(tex_coords,i), TRUE );
+
+ tex_coords = mesh->tex_coords_bottom;
+ for( i = 0; i < tex_coords->len; i++ )
+ g_array_free( (GArray *) g_ptr_array_index(tex_coords,i), TRUE );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
Added: packages/openev/branches/upstream/current/gvmesh.h
===================================================================
--- packages/openev/branches/upstream/current/gvmesh.h (rev 0)
+++ packages/openev/branches/upstream/current/gvmesh.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,125 @@
+/******************************************************************************
+ * $Id: gvmesh.h,v 1.19 2002/04/12 14:40:36 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Geometric mesh mapping tile s/t coordinates to display x/y/z
+ * coordinates.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvmesh.h,v $
+ * Revision 1.19 2002/04/12 14:40:36 gmwalter
+ * Removed the gvmesh rescale function (not needed because of view area
+ * rescaling).
+ *
+ * Revision 1.17 2002/03/07 02:31:56 warmerda
+ * added default_height to add_height functions
+ *
+ * Revision 1.16 2001/08/22 16:20:38 warmerda
+ * use gv_mesh_reset_to_identity for setting to raw
+ *
+ * Revision 1.15 2001/08/08 02:57:38 warmerda
+ * implement gv_mesh_finalize(), remove unused normals code
+ *
+ * Revision 1.14 2001/07/13 22:13:35 warmerda
+ * added function to get height from mesh
+ *
+ * Revision 1.13 2001/04/19 21:46:35 warmerda
+ * don't include ourself
+ *
+ * Revision 1.12 2000/07/03 20:57:32 warmerda
+ * moved tile selection for draw to gvrasterlayer
+ *
+ * Revision 1.11 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_MESH_H__
+#define __GV_MESH_H__
+
+#include "gvdata.h"
+#include "gvviewarea.h"
+#include "gvraster.h"
+
+#define GV_TYPE_MESH (gv_mesh_get_type ())
+#define GV_MESH(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_MESH, GvMesh))
+#define GV_MESH_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_MESH, GvMeshClass))
+#define GV_IS_MESH(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_MESH))
+#define GV_IS_MESH_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_MESH))
+
+typedef struct _GvMesh GvMesh;
+typedef struct _GvMeshClass GvMeshClass;
+typedef struct _GvMeshTile GvMeshTile;
+
+struct _GvMeshTile {
+ gint list_type; /* 0 = TRIANGLES, 1 = TRISTRIPS, 2 = QUADS, 3 = QUADSTRIPGS */
+ gint range; /* Only used for "strip" processing */
+ gint restarts;
+ gint *indices;
+ gfloat *vertices;
+ gfloat *tex_coords;
+};
+
+struct _GvMesh
+{
+ GvData data;
+
+ struct _GvRaster *raster;
+
+ gint max_tiles;
+ gint tile_x, tile_y;
+ gint width, height;
+ gint detail;
+ gfloat corner_coords[8];
+
+ GArray *vertices;
+
+ GPtrArray *tex_coords;
+ GPtrArray *tex_coords_right;
+ GPtrArray *tex_coords_bottom;
+ GPtrArray *tex_coords_bottom_right;
+};
+
+struct _GvMeshClass
+{
+ GvDataClass parent_class;
+};
+
+struct _GvRaster;
+
+GtkType gv_mesh_get_type(void);
+
+GvMeshTile *gv_mesh_get(GvMesh *mesh, gint tile, gint raster_lod, gint detail,
+ GvMeshTile *tile_info );
+gint * gv_mesh_get_tile_corner_coords( GvMesh *mesh, int tile);
+GvMesh *gv_mesh_new_identity( struct _GvRaster *raster, gint detail );
+void gv_mesh_reset_to_identity( GvMesh * );
+void gv_mesh_add_height(GvMesh *mesh, struct _GvRaster *raster,
+ double default_height );
+void gv_mesh_clamp_height(GvMesh *mesh, int bclamp_min, int bclamp_max,
+ double min_height, double max_height);
+void gv_mesh_set_transform( GvMesh *mesh, gint xsize, gint ysize,
+ double *geotransform );
+void gv_mesh_extents( GvMesh *mesh, GvRect *rect );
+float gv_mesh_get_height( GvMesh *mesh, double x, double y, int *success );
+
+#endif /* __GV_RASTER_H__ */
Added: packages/openev/branches/upstream/current/gvnodetool.c
===================================================================
--- packages/openev/branches/upstream/current/gvnodetool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvnodetool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,537 @@
+/******************************************************************************
+ * $Id: gvnodetool.c,v 1.13 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Node editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvnodetool.c,v $
+ * Revision 1.13 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.12 2002/09/30 20:49:35 warmerda
+ * maintain ring integrity when deleting a node
+ *
+ * Revision 1.11 2002/09/30 20:09:27 warmerda
+ * Ensure that first/last vertex of closed rings are kept in sync. Added
+ * "track_node" concept. Only works for GvShapesLayer areas, not the old
+ * GvAreaLayer.
+ *
+ * Revision 1.10 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.9 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.8 2000/07/24 14:00:24 warmerda
+ * set_layer with NULL should be allowed
+ *
+ * Revision 1.7 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvnodetool.h"
+#include "gvshapeslayer.h"
+#include "gvundo.h"
+#include "cpl_error.h"
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <GL/gl.h>
+
+static void gv_node_tool_class_init(GvNodeToolClass *klass);
+static void gv_node_tool_init(GvNodeTool *tool);
+static void gv_node_tool_draw(GvTool *tool);
+static void gv_node_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_node_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_node_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_node_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_node_tool_deactivate(GvTool *tool, GvViewArea *view);
+static void gv_node_tool_layer_change(GvNodeTool *tool, gpointer info);
+static gint gv_node_tool_configure(GvNodeTool *tool);
+static GdkCursor* gv_node_tool_make_cursor(void);
+
+GtkType
+gv_node_tool_get_type(void)
+{
+ static GtkType node_tool_type = 0;
+
+ if (!node_tool_type)
+ {
+ static const GtkTypeInfo node_tool_info =
+ {
+ "GvNodeTool",
+ sizeof(GvNodeTool),
+ sizeof(GvNodeToolClass),
+ (GtkClassInitFunc) gv_node_tool_class_init,
+ (GtkObjectInitFunc) gv_node_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ node_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &node_tool_info);
+ }
+ return node_tool_type;
+}
+
+static void
+gv_node_tool_class_init(GvNodeToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_node_tool_deactivate;
+ tool_class->button_press = gv_node_tool_button_press;
+ tool_class->button_release = gv_node_tool_button_release;
+ tool_class->motion_notify = gv_node_tool_motion_notify;
+ tool_class->key_press = gv_node_tool_key_press;
+}
+static void
+gv_node_tool_init(GvNodeTool *tool)
+{
+ GV_TOOL(tool)->cursor = gv_node_tool_make_cursor();
+ tool->layer = NULL;
+ tool->node_selected = FALSE;
+ tool->dragging = FALSE;
+ tool->tracking_node.shape_id = -1;
+}
+
+GvTool *
+gv_node_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_NODE_TOOL));
+}
+
+static gint gv_node_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvNodeTool *tool = (GvNodeTool *) data;
+
+ if( tool->layer == GV_SHAPE_LAYER(layer) )
+ gv_node_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_node_tool_set_layer(GvNodeTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_node_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_node_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ }
+
+ tool->layer = layer;
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_node_tool_draw),
+ GTK_OBJECT(tool));
+
+ /* Trap changes to the layer (e.g. undo) and clear node selection */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "changed",
+ GTK_SIGNAL_FUNC(
+ gv_node_tool_layer_change),
+ GTK_OBJECT(tool));
+
+ /* Recover if layer destroyed */
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_node_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+/**************************************************************/
+
+static void
+gv_node_tool_button_press(GvTool *rtool, GdkEventButton *event)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ if (event->button == 1)
+ {
+ gint shape_id, before;
+
+ if (!gv_node_tool_configure(tool)) return;
+
+ if (gv_shape_layer_pick_shape(tool->layer, GV_TOOL(tool)->view,
+ event->x, event->y, &shape_id))
+ {
+ if (!gv_shape_layer_is_selected(tool->layer, shape_id))
+ {
+ /* Select this shape (and only this shape) */
+ gv_shape_layer_clear_selection(tool->layer);
+ gv_shape_layer_select_shape(tool->layer, shape_id);
+
+ /* New shape: deselect current node */
+ tool->node_selected = FALSE;
+ tool->tracking_node.shape_id = -1;
+ }
+ else
+ {
+ if (gv_shape_layer_pick_node(tool->layer, GV_TOOL(tool)->view,
+ event->x, event->y, &before,
+ &tool->edit_node))
+ {
+ /* Capture pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view,
+ event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ tool->v_head = tool->v_tail;
+
+ if( !gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_tail.x,
+ tool->v_tail.y ) )
+ return;
+
+ /* Select the node for edit and start dragging */
+ tool->node_selected = TRUE;
+ tool->dragging = TRUE;
+
+ /* If this node is the first in a ring of an area and
+ the last vertex of the ring matches it, capture that
+ node for "tracking" purposes. */
+
+ tool->tracking_node.shape_id = -1;
+ if( GV_IS_SHAPES_LAYER(tool->layer)
+ && tool->edit_node.node_id == 0 )
+ {
+ GvShape *shape;
+ int ring = tool->edit_node.ring_id;
+ int last_node;
+
+ shape = gv_shapes_get_shape(
+ GV_SHAPES_LAYER(tool->layer)->data,
+ tool->edit_node.shape_id );
+ last_node = gv_shape_get_nodes( shape, ring ) - 1;
+
+ if( gv_shape_type(shape) == GVSHAPE_AREA
+ && gv_shape_get_x( shape, ring, 0 )
+ == gv_shape_get_x( shape, ring, last_node )
+ && gv_shape_get_y( shape, ring, 0 )
+ == gv_shape_get_y( shape, ring, last_node )
+ && gv_shape_get_z( shape, ring, 0 )
+ == gv_shape_get_z( shape, ring, last_node ) )
+ {
+ tool->tracking_node.shape_id =
+ tool->edit_node.shape_id;
+ tool->tracking_node.ring_id =
+ tool->edit_node.ring_id;
+ tool->tracking_node.node_id = last_node;
+ gv_shape_layer_get_node( tool->layer,
+ &tool->tracking_node );
+ tool->v_orig_tracking =
+ *(tool->tracking_node.vertex);
+ }
+ }
+
+ if (before)
+ {
+ /* Insert a new node */
+ tool->edit_node.vertex = &tool->v_tail;
+ tool->changing = TRUE;
+ gv_shape_layer_insert_node(tool->layer,
+ &tool->edit_node);
+ tool->changing = FALSE;
+ }
+
+ /* Get pointer to vertex */
+ gv_shape_layer_get_node(tool->layer, &tool->edit_node);
+
+ /* Snapshot the original node position */
+ tool->v_orig = *(tool->edit_node.vertex);
+ }
+ else
+ {
+ /* Click away from a node: deselect the current node */
+ tool->node_selected = FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* Click away from shape: deselect the current node,
+ but not the current shape */
+ tool->node_selected = FALSE;
+ tool->tracking_node.shape_id = -1;
+ }
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_node_tool_button_release(GvTool *rtool, GdkEventButton *event)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ if (tool->dragging && event->button == 1)
+ {
+ /* End dragging */
+ tool->dragging = FALSE;
+
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &tool->v_tail.x, &tool->v_tail.y );
+
+ /* Filter out clicks that wern't really drags */
+ if (tool->v_tail.x != tool->v_head.x ||
+ tool->v_tail.y != tool->v_head.y)
+ {
+ GvVertex temp;
+ GvVertex temp_tracking;
+ gint undo_group;
+
+ /* Actually the node is already moved, but the layer doesn't
+ know this, so we put back the original vertex position
+ and move it properly */
+ temp.x = tool->v_orig.x + (tool->v_tail.x - tool->v_head.x);
+ temp.y = tool->v_orig.y + (tool->v_tail.y - tool->v_head.y);
+
+ *(tool->edit_node.vertex) = tool->v_orig;
+ tool->edit_node.vertex = &temp;
+
+ if( tool->tracking_node.shape_id != -1 )
+ {
+ temp_tracking = temp;
+ *(tool->tracking_node.vertex) = tool->v_orig_tracking;
+ tool->tracking_node.vertex = &temp_tracking;
+ }
+
+ tool->changing = TRUE;
+ undo_group = gv_undo_start_group();
+
+ gv_shape_layer_move_node(tool->layer, &tool->edit_node);
+
+ if( tool->tracking_node.shape_id != -1 )
+ {
+ gv_shape_layer_move_node(tool->layer, &tool->tracking_node);
+ gv_shape_layer_get_node(tool->layer, &tool->tracking_node);
+ }
+
+ gv_shape_layer_get_node(tool->layer, &tool->edit_node);
+
+ gv_undo_end_group( undo_group );
+ tool->changing = FALSE;
+ }
+ }
+}
+
+static void
+gv_node_tool_motion_notify(GvTool *rtool, GdkEventMotion *event)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ if (tool->dragging)
+ {
+ /* Drag selected node */
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &tool->v_tail.x, &tool->v_tail.y );
+
+ /* Move the node by dereferencing the vertex pointer (!).
+ We promise to put it back when the mouse button is released. */
+ tool->edit_node.vertex->x = tool->v_orig.x + (tool->v_tail.x -
+ tool->v_head.x);
+ tool->edit_node.vertex->y = tool->v_orig.y + (tool->v_tail.y -
+ tool->v_head.y);
+
+ if( tool->tracking_node.shape_id != -1 )
+ *(tool->tracking_node.vertex) = *(tool->edit_node.vertex);
+
+ /* Inform layer of node motion */
+ gv_shape_layer_node_motion(tool->layer, tool->edit_node.shape_id);
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_node_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ if (!gv_node_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ {
+ gint undo_group;
+
+ if( !tool->node_selected )
+ return;
+
+ /* Delete the currently selected node (forces redraw) */
+ /* This also clears the node selection (via. *_layer_changed) */
+
+ undo_group = gv_undo_start_group();
+ if( tool->tracking_node.shape_id != -1 )
+ {
+ GvNodeInfo second_node;
+ GvVertex new_first_vert;
+
+ second_node.shape_id = tool->edit_node.shape_id;
+ second_node.ring_id = tool->edit_node.ring_id;
+ second_node.node_id = 1;
+
+ gv_shape_layer_get_node( tool->layer, &second_node );
+ new_first_vert = *(second_node.vertex);
+
+ tool->tracking_node.vertex = &new_first_vert;
+
+ gv_shape_layer_move_node(tool->layer, &tool->tracking_node);
+ }
+
+ gv_shape_layer_delete_node(tool->layer, &tool->edit_node);
+ gv_undo_end_group( undo_group );
+
+ tool->tracking_node.shape_id = -1;
+ tool->node_selected = FALSE;
+ }
+ break;
+ }
+}
+
+static void
+gv_node_tool_draw(GvTool *rtool)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ if (tool->node_selected)
+ {
+ glPointSize(4.0);
+ glBegin(GL_POINTS);
+ glVertex2v((GLgeocoord*)tool->edit_node.vertex);
+ glEnd();
+ }
+}
+
+static void
+gv_node_tool_deactivate(GvTool *rtool, GvViewArea *view)
+{
+ GvNodeTool *tool = GV_NODE_TOOL(rtool);
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+
+ if (tool->layer)
+ {
+ gv_shape_layer_clear_selection(tool->layer);
+ gv_view_area_queue_draw(view);
+ }
+ tool->node_selected = FALSE;
+ tool->dragging = FALSE;
+}
+
+static void
+gv_node_tool_layer_change(GvNodeTool *tool, gpointer info)
+{
+ if (!tool->changing)
+ {
+ /* Unexpected change in layer (or node delete) occured:
+ clear node selection. */
+ tool->node_selected = FALSE;
+ tool->dragging = FALSE;
+ }
+}
+
+static gint
+gv_node_tool_configure(GvNodeTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ /* Attempt to find a line layer to edit */
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPE_LAYER,
+ FALSE);
+ if (!layer)
+ {
+ g_warning("gv_node_tool_configure(): no shape layer in view");
+ return FALSE;
+ }
+
+ gv_node_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+
+ return tool->layer != NULL;
+}
+
+#include "pics/node_cursor.xbm"
+#include "pics/node_cursor_mask.xbm"
+
+static GdkCursor *
+gv_node_tool_make_cursor(void)
+{
+ GdkCursor *cursor;
+ GdkPixmap *source, *mask;
+ GdkColor fg, bg;
+
+ gdk_color_parse("black", &fg);
+ gdk_color_parse("white", &bg);
+ source = gdk_bitmap_create_from_data(NULL, node_cursor_bits,
+ node_cursor_width,
+ node_cursor_height);
+ mask = gdk_bitmap_create_from_data(NULL, node_cursor_mask_bits,
+ node_cursor_mask_width,
+ node_cursor_mask_height);
+ cursor = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg,
+ node_cursor_x_hot,
+ node_cursor_y_hot);
+ gdk_pixmap_unref(source);
+ gdk_pixmap_unref(mask);
+
+ return cursor;
+}
Added: packages/openev/branches/upstream/current/gvnodetool.h
===================================================================
--- packages/openev/branches/upstream/current/gvnodetool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvnodetool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * $Id: gvnodetool.h,v 1.4 2002/09/30 20:09:27 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Node editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvnodetool.h,v $
+ * Revision 1.4 2002/09/30 20:09:27 warmerda
+ * Ensure that first/last vertex of closed rings are kept in sync. Added
+ * "track_node" concept. Only works for GvShapesLayer areas, not the old
+ * GvAreaLayer.
+ *
+ * Revision 1.3 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_NODE_TOOL_H__
+#define __GV_NODE_TOOL_H__
+
+#include "gvtool.h"
+#include "gvshapelayer.h"
+
+#define GV_TYPE_NODE_TOOL (gv_node_tool_get_type ())
+#define GV_NODE_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_NODE_TOOL, GvNodeTool))
+#define GV_NODE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_NODE_TOOL, GvNodeToolClass))
+#define GV_IS_NODE_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_NODE_TOOL))
+#define GV_IS_NODE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_NODE_TOOL))
+
+typedef struct _GvNodeTool GvNodeTool;
+typedef struct _GvNodeToolClass GvNodeToolClass;
+
+struct _GvNodeTool
+{
+ GvTool tool;
+
+ GvShapeLayer *layer;
+ gint node_selected : 1;
+ gint dragging : 1;
+ gint changing : 1;
+ GvVertex v_orig;
+ GvNodeInfo edit_node;
+ GvVertex v_head;
+ GvVertex v_tail;
+
+ GvNodeInfo tracking_node;
+ GvVertex v_orig_tracking;
+};
+
+struct _GvNodeToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_node_tool_get_type(void);
+GvTool* gv_node_tool_new(void);
+void gv_node_tool_set_layer(GvNodeTool *tool, GvShapeLayer *layer);
+
+#endif /* __GV_NODE_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvogr.c
===================================================================
--- packages/openev/branches/upstream/current/gvogr.c (rev 0)
+++ packages/openev/branches/upstream/current/gvogr.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,360 @@
+/******************************************************************************
+ * $Id: gvogr.c,v 1.5 2004/01/20 16:05:02 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Read/write link to OGR.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvogr.c,v $
+ * Revision 1.5 2004/01/20 16:05:02 warmerda
+ * added setting of _ogr_driver_name for S52 viewer
+ *
+ * Revision 1.4 2003/01/06 21:19:45 warmerda
+ * added one-layer access
+ *
+ * Revision 1.3 2003/01/06 18:21:51 warmerda
+ * Added debug on unexpected NULL
+ *
+ * Revision 1.2 2002/11/04 16:33:45 sduclos
+ * Add gard against NULL GeometryRef handle
+ *
+ * Revision 1.1 2002/09/26 19:24:09 warmerda
+ * New
+ *
+ * Revision 1.8 2002/09/09 17:41:36 warmerda
+ * cleanup dataset if iLayer out of range
+ *
+ * Revision 1.7 2002/07/15 18:42:10 pgs
+ * added _filename to gv_shapes that come from shape files or ogr
+ *
+ * Revision 1.6 2002/05/07 02:51:15 warmerda
+ * preliminary support for GVSHAPE_COLLECTION
+ *
+ * Revision 1.5 2001/11/09 15:20:24 warmerda
+ * get ogr style string as _gv_ogrfs
+ *
+ * Revision 1.4 2000/11/13 20:04:13 warmerda
+ * fixed memory leak with geometryless features
+ *
+ * Revision 1.3 2000/10/24 04:26:18 warmerda
+ * easy of use, and bug fixes for ogr link
+ *
+ * Revision 1.2 2000/07/24 01:30:21 warmerda
+ * added read support for multipolygons
+ *
+ * Revision 1.1 2000/07/03 12:48:22 warmerda
+ * New
+ *
+ */
+
+#include "ogr_api.h"
+#include "gvshapes.h"
+#include "cpl_error.h"
+
+// helper
+int _getGeoPtCount(OGRGeometryH hGeom, int iGeo, OGRGeometryH *hGeomRef )
+{
+ int vert_count = 0;
+
+ *hGeomRef = OGR_G_GetGeometryRef( hGeom, iGeo );
+ if( NULL != *hGeomRef )
+ {
+ vert_count = OGR_G_GetPointCount( *hGeomRef );
+ }
+ else
+ {
+ /* FIXME: something is wrong in OGR if we get here
+ * ie the geometry handle doesn't refer to a geometry!
+ */
+ CPLDebug( "OpenEV", "gvogr.c:_getGeoPtCount() .. got null geometry!" );
+ }
+
+ return vert_count;
+}
+
+/************************************************************************/
+/* ogr_geometry_to_gv_shape() */
+/************************************************************************/
+
+static GvShape *ogr_geometry_to_gv_shape( OGRGeometryH hGeom )
+
+{
+ GvShape *gv_shape = NULL;
+ OGRwkbGeometryType eType;
+
+ if( hGeom == NULL )
+ {
+ // Use collection - which can be empty - to represent a geometryless
+ // feature.
+
+ return gv_shape_new( GVSHAPE_COLLECTION );
+ }
+
+ eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
+
+ if( eType == wkbPoint )
+ {
+ gv_shape = gv_shape_new( GVSHAPE_POINT );
+ gv_shape_set_xyz( gv_shape, 0, 0,
+ OGR_G_GetX( hGeom, 0 ),
+ OGR_G_GetY( hGeom, 0 ),
+ OGR_G_GetZ( hGeom, 0 ) );
+ }
+
+ else if( eType == wkbLineString )
+ {
+ int node, count = OGR_G_GetPointCount(hGeom);
+
+ gv_shape = gv_shape_new( GVSHAPE_LINE );
+ for( node = count-1; node >= 0; node-- )
+ gv_shape_set_xyz( gv_shape, 0, node,
+ OGR_G_GetX( hGeom, node ),
+ OGR_G_GetY( hGeom, node ),
+ OGR_G_GetZ( hGeom, node ) );
+ }
+
+ else if( eType == wkbPolygon )
+ {
+ OGRGeometryH hRing;
+ int iRing = 0, nRingCount = OGR_G_GetGeometryCount( hGeom );
+
+ gv_shape = gv_shape_new( GVSHAPE_AREA );
+
+ for( iRing = 0; iRing < nRingCount; iRing++ )
+ {
+ int node;
+ int vert_count = _getGeoPtCount( hGeom, iRing, &hRing );
+
+ //hRing = OGR_G_GetGeometryRef( hGeom, iRing );
+ //vert_count = OGR_G_GetPointCount(hRing);
+
+ for( node = vert_count - 1; node >= 0; node-- )
+ gv_shape_set_xyz( gv_shape, iRing, node,
+ OGR_G_GetX( hRing, node ),
+ OGR_G_GetY( hRing, node ),
+ OGR_G_GetZ( hRing, node ) );
+ }
+ }
+
+ else if( eType == wkbMultiPolygon )
+ {
+ int iPoly, nShapeRing = 0;
+
+ gv_shape = gv_shape_new( GVSHAPE_AREA );
+
+ for( iPoly = 0; iPoly < OGR_G_GetGeometryCount( hGeom ); iPoly++ )
+ {
+ //OGRGeometryH hPoly, hRing;
+ OGRGeometryH hPoly;
+ int iRing, nRingCount;
+
+ hPoly = OGR_G_GetGeometryRef( hGeom, iPoly );
+ nRingCount = OGR_G_GetGeometryCount( hPoly );
+
+ for( iRing = 0; iRing < nRingCount; iRing++ )
+ {
+ OGRGeometryH hRing;
+ int vert_count = _getGeoPtCount( hPoly, iRing, &hRing );
+ int node;
+
+ //hRing = OGR_G_GetGeometryRef( hPoly, iRing );
+ //vert_count = OGR_G_GetPointCount(hRing);
+
+ for( node = vert_count - 1; node >= 0; node-- )
+ gv_shape_set_xyz( gv_shape, nShapeRing, node,
+ OGR_G_GetX( hRing, node ),
+ OGR_G_GetY( hRing, node ),
+ OGR_G_GetZ( hRing, node ) );
+ nShapeRing++;
+ }
+ }
+ }
+
+ else if( eType == wkbGeometryCollection
+ || eType == wkbMultiLineString
+ || eType == wkbMultiPoint )
+ {
+ int iGeom, nGeomCount;
+
+ nGeomCount = OGR_G_GetGeometryCount( hGeom );
+
+ gv_shape = gv_shape_new( GVSHAPE_COLLECTION );
+
+ for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+ {
+ OGRGeometryH hSubGeom = OGR_G_GetGeometryRef( hGeom, iGeom );
+ GvShape *sub_shape;
+
+ sub_shape = ogr_geometry_to_gv_shape( hSubGeom );
+ gv_shape_collection_add_shape( gv_shape, sub_shape );
+ }
+ }
+
+ return gv_shape;
+}
+
+/************************************************************************/
+/* gv_shapes_from_ogr_layer() */
+/************************************************************************/
+
+GvData *gv_shapes_from_ogr_layer(OGRLayerH hLayer)
+
+{
+ int field_count = 0, field_index;
+ GvShapes *shapes_data;
+ GvProperties *properties;
+ OGRFeatureDefnH hDefn;
+ OGRFeatureH hFeature;
+
+ hDefn = OGR_L_GetLayerDefn( hLayer );
+ field_count = OGR_FD_GetFieldCount( hDefn );
+
+/* -------------------------------------------------------------------- */
+/* Create shapes layer, and assign some metadata about the */
+/* field definitions. */
+/* -------------------------------------------------------------------- */
+ shapes_data = GV_SHAPES(gv_shapes_new());
+ gv_data_set_name( GV_DATA(shapes_data), OGR_FD_GetName(hDefn) );
+
+ properties = gv_data_get_properties( GV_DATA(shapes_data) );
+
+ for(field_index = 0; field_index < field_count; field_index++ )
+ {
+ OGRFieldDefnH hField = OGR_FD_GetFieldDefn( hDefn, field_index );
+ OGRFieldType eFldType;
+ char prop_value[64], prop_name[64];
+
+ sprintf( prop_name, "_field_name_%d", field_index+1 );
+ gv_properties_set( properties, prop_name,
+ OGR_Fld_GetNameRef( hField ) );
+
+ sprintf( prop_name, "_field_width_%d", field_index+1 );
+ sprintf( prop_value, "%d", OGR_Fld_GetWidth( hField ) );
+ gv_properties_set( properties, prop_name, prop_value );
+
+ eFldType = OGR_Fld_GetType( hField );
+ if( eFldType == OFTReal )
+ {
+ sprintf( prop_name, "_field_precision_%d", field_index+1 );
+ sprintf( prop_value, "%d", OGR_Fld_GetPrecision(hField) );
+ gv_properties_set( properties, prop_name, prop_value );
+ }
+
+ sprintf( prop_name, "_field_type_%d", field_index+1 );
+ if( eFldType == OFTInteger )
+ gv_properties_set( properties, prop_name, "integer" );
+ else if( eFldType == OFTReal )
+ gv_properties_set( properties, prop_name, "float" );
+ else
+ gv_properties_set( properties, prop_name, "string" );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Copy all the shapes, and their attributes. */
+/* -------------------------------------------------------------------- */
+ OGR_L_ResetReading( hLayer );
+ while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL )
+ {
+ GvShape *gv_shape = NULL;
+
+ gv_shape = ogr_geometry_to_gv_shape( OGR_F_GetGeometryRef(hFeature) );
+
+ if( gv_shape != NULL )
+ {
+ properties = gv_shape_get_properties( gv_shape );
+
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ if( OGR_F_IsFieldSet( hFeature, field_index ) )
+ {
+ gv_properties_set( properties,
+ OGR_Fld_GetNameRef(
+ OGR_F_GetFieldDefnRef(hFeature,field_index) ),
+ OGR_F_GetFieldAsString( hFeature, field_index ) );
+ }
+ }
+
+ if( OGR_F_GetStyleString(hFeature) != NULL )
+ gv_properties_set( properties, "_gv_ogrfs",
+ OGR_F_GetStyleString( hFeature ) );
+ }
+
+ if( gv_shape != NULL )
+ gv_shapes_add_shape( shapes_data, gv_shape );
+
+ OGR_F_Destroy( hFeature );
+ }
+
+ return GV_DATA(shapes_data);
+}
+
+/************************************************************************/
+/* gv_shapes_from_ogr() */
+/************************************************************************/
+
+GvData *gv_shapes_from_ogr(const char *filename, int iLayer)
+
+{
+ OGRLayerH hLayer;
+ OGRDataSourceH hDS;
+ GvData *psData;
+ OGRSFDriverH hDriver;
+
+/* -------------------------------------------------------------------- */
+/* Open the OGR dataset. */
+/* -------------------------------------------------------------------- */
+ OGRRegisterAll();
+
+ hDS = OGROpen( filename, FALSE, &hDriver );
+ if( hDS == NULL )
+ return NULL;
+
+
+
+ if( iLayer < 0 || iLayer >= OGR_DS_GetLayerCount(hDS) )
+ {
+ OGR_DS_Destroy( hDS );
+ return NULL;
+ }
+
+ hLayer = OGR_DS_GetLayer( hDS, iLayer );
+
+/* -------------------------------------------------------------------- */
+/* Actually read the shapes. */
+/* -------------------------------------------------------------------- */
+ psData = gv_shapes_from_ogr_layer( hLayer );
+
+ if( psData != NULL )
+ {
+ gv_data_set_property( psData, "_filename", filename );
+ gv_data_set_property( psData, "_ogr_driver_name",
+ OGR_Dr_GetName(hDriver) );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ OGR_DS_Destroy( hDS );
+
+ return psData;
+}
+
Added: packages/openev/branches/upstream/current/gvpointlayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvpointlayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpointlayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,305 @@
+/******************************************************************************
+ * $Id: gvpointlayer.c,v 1.6 2002/11/05 18:56:24 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for GvPoints.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpointlayer.c,v $
+ * Revision 1.6 2002/11/05 18:56:24 sduclos
+ * fix gcc warning
+ *
+ * Revision 1.5 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.4 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvpointlayer.h"
+#include <GL/gl.h>
+
+#define DEFAULT_POINT_SIZE 6
+
+static void gv_point_layer_class_init(GvPointLayerClass *klass);
+static void gv_point_layer_init(GvPointLayer *layer);
+static void gv_point_layer_draw(GvPointLayer *layer, GvViewArea *view);
+static void gv_point_layer_extents(GvPointLayer *layer, GvRect *rect);
+static void gv_point_layer_data_change(GvPointLayer *layer, gpointer change_info);
+static void gv_point_layer_draw_selected(GvPointLayer *layer, GvViewArea *view);
+static void gv_point_layer_delete_selected(GvPointLayer *layer);
+static void gv_point_layer_translate_selected(GvPointLayer *layer, GvVertex *delta);
+static void gv_point_layer_pick_shape(GvPointLayer *layer);
+
+GtkType
+gv_point_layer_get_type(void)
+{
+ static GtkType point_layer_type = 0;
+
+ if (!point_layer_type)
+ {
+ static const GtkTypeInfo point_layer_info =
+ {
+ "GvPointLayer",
+ sizeof(GvPointLayer),
+ sizeof(GvPointLayerClass),
+ (GtkClassInitFunc) gv_point_layer_class_init,
+ (GtkObjectInitFunc) gv_point_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ point_layer_type = gtk_type_unique(gv_shape_layer_get_type(),
+ &point_layer_info);
+ }
+ return point_layer_type;
+}
+
+static void
+gv_point_layer_class_init(GvPointLayerClass *klass)
+{
+ typedef void (*f)();
+ GvDataClass *data_class;
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ data_class = (GvDataClass*) klass;
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ data_class->changed = (f) gv_point_layer_data_change;
+
+ layer_class->draw = (f) gv_point_layer_draw;
+ layer_class->extents_request = (f) gv_point_layer_extents;
+
+ shape_layer_class->draw_selected = (f) gv_point_layer_draw_selected;
+ shape_layer_class->delete_selected = (f) gv_point_layer_delete_selected;
+ shape_layer_class->translate_selected = (f) gv_point_layer_translate_selected;
+ shape_layer_class->pick_shape = (f) gv_point_layer_pick_shape;
+}
+
+static void
+gv_point_layer_init(GvPointLayer *layer)
+{
+ GvColor default_point_color = {0.0, 1.0, 1.0, 1.0}; /* cyan */
+
+ layer->data = NULL;
+ layer->point_size = DEFAULT_POINT_SIZE;
+ gv_color_copy(GV_SHAPE_LAYER(layer)->color, default_point_color);
+}
+
+GtkObject *
+gv_point_layer_new(GvPoints *data)
+{
+ GvPointLayer *layer = GV_POINT_LAYER(gtk_type_new(
+ gv_point_layer_get_type()));
+
+ if (data)
+ {
+ layer->data = data;
+ }
+ else
+ {
+ layer->data = GV_POINTS(gv_points_new());
+ }
+
+ /* Set the selected array to reflect the data length if points already exist */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_points_num_points(layer->data));
+
+ gv_data_set_parent(GV_DATA(layer), GV_DATA(layer->data));
+
+ return GTK_OBJECT(layer);
+}
+
+gint
+gv_point_layer_select_new_point(GvPointLayer *layer, GvVertex *vertex)
+{
+ gint point_id;
+
+ point_id = gv_points_new_point(layer->data, vertex);
+
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_points_num_points(layer->data));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(layer), point_id);
+
+ return point_id;
+}
+
+/*******************************************************/
+
+static void
+gv_point_layer_draw(GvPointLayer *layer, GvViewArea *view)
+{
+ gint i, points;
+ GvPoint *point;
+ gint *selected, presentation;
+ gvgeocoord dx, dy, x, y;
+ gint hit_selected = FALSE;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ points = gv_points_num_points(layer->data);
+
+ /* Crosshairs are "sprites": always drawn upright, the same size */
+ dx = layer->point_size;
+ dy = 0.0;
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+ glBegin(GL_LINES);
+ for (i=0; i < points; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ point = gv_points_get_point(layer->data, i);
+ x = point->v.x;
+ y = point->v.y;
+
+ glVertex2(x-dx, y-dy);
+ glVertex2(x+dx, y+dy);
+ glVertex2(x+dy, y-dx);
+ glVertex2(x-dy, y+dx);
+ }
+ glEnd();
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ gv_point_layer_draw_selected(layer, view);
+ }
+}
+
+static void
+gv_point_layer_draw_selected(GvPointLayer *layer, GvViewArea *view)
+{
+ gint i, points;
+ GvPoint *point;
+ gint *selected;
+ gvgeocoord dx, dy, bx, by, x, y;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ points = gv_points_num_points(layer->data);
+
+ /* Crosshairs are "sprites": always drawn upright, the same size */
+ dx = layer->point_size;
+ dy = 0.0;
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+ bx = by = layer->point_size + 2;
+ gv_view_area_correct_for_transform(view, bx, by, &bx, &by);
+
+ glColor4fv(GV_SHAPE_LAYER(layer)->color);
+ for (i=0; i < points; ++i)
+ {
+ if (selected[i])
+ {
+ point = gv_points_get_point(layer->data, i);
+ x = point->v.x;
+ y = point->v.y;
+
+ /* Draw crosshairs */
+ glBegin(GL_LINES);
+ glVertex2(x-dx, y-dy);
+ glVertex2(x+dx, y+dy);
+ glVertex2(x+dy, y-dx);
+ glVertex2(x-dy, y+dx);
+ glEnd();
+
+ /* Draw box around crosshairs */
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x-bx, y-by);
+ glVertex2(x+by, y-bx);
+ glVertex2(x+bx, y+by);
+ glVertex2(x-by, y+bx);
+ glEnd();
+ }
+ }
+}
+
+static void
+gv_point_layer_pick_shape(GvPointLayer *layer)
+{
+ gint i, points;
+ GvPoint *point;
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+ points = gv_points_num_points(layer->data);
+
+ glPointSize(layer->point_size * 2.0);
+ for (i=0; i < points; ++i)
+ {
+ point = gv_points_get_point(layer->data, i);
+
+ glLoadName(i);
+ glBegin(GL_POINTS);
+ glVertex2v((GLgeocoord*)&point->v);
+ glEnd();
+ }
+}
+
+static void
+gv_point_layer_delete_selected(GvPointLayer *layer)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_points_delete_points(layer->data, sel->len, (gint*)sel->data);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_point_layer_translate_selected(GvPointLayer *layer, GvVertex *delta)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_points_translate_points(layer->data, sel->len, (gint*)sel->data,
+ delta->x, delta->y);
+ }
+ g_array_free(sel, TRUE);
+}
+
+static void
+gv_point_layer_extents(GvPointLayer *layer, GvRect *rect)
+{
+ gv_points_get_extents(layer->data, rect);
+}
+
+static void
+gv_point_layer_data_change(GvPointLayer *layer, gpointer change_info)
+{
+ /* Reset the selected array to reflect the data length */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_points_num_points(layer->data));
+}
Added: packages/openev/branches/upstream/current/gvpointlayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvpointlayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpointlayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,66 @@
+/******************************************************************************
+ * $Id: gvpointlayer.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for GvPoints.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpointlayer.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_POINT_LAYER_H__
+#define __GV_POINT_LAYER_H__
+
+#include "gvshapelayer.h"
+#include "gvpoints.h"
+
+#define GV_TYPE_POINT_LAYER (gv_point_layer_get_type ())
+#define GV_POINT_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_POINT_LAYER, GvPointLayer))
+#define GV_POINT_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_POINT_LAYER, GvPointLayerClass))
+#define GV_IS_POINT_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_POINT_LAYER))
+#define GV_IS_POINT_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_POINT_LAYER))
+
+typedef struct _GvPointLayer GvPointLayer;
+typedef struct _GvPointLayerClass GvPointLayerClass;
+
+struct _GvPointLayer
+{
+ GvShapeLayer shape_layer;
+
+ GvPoints *data;
+ gvfloat point_size;
+};
+
+struct _GvPointLayerClass
+{
+ GvShapeLayerClass parent_class;
+};
+
+GtkType gv_point_layer_get_type(void);
+GtkObject* gv_point_layer_new(GvPoints *data);
+
+gint gv_point_layer_select_new_point(GvPointLayer *layer, GvVertex *vertex);
+
+#endif /* __GV_POINT_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvpoints.c
===================================================================
--- packages/openev/branches/upstream/current/gvpoints.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpoints.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,405 @@
+/******************************************************************************
+ * $Id: gvpoints.c,v 1.7 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Points data container (superceed by GvShapes)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpoints.c,v $
+ * Revision 1.7 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gextra.h"
+#include "gvpoints.h"
+
+typedef struct _GvPointsMemento GvPointsMemento;
+
+struct _GvPointsMemento
+{
+ GvDataMemento base;
+ GArray *point_ids;
+ GArray *points;
+};
+
+static void gv_points_class_init(GvPointsClass *klass);
+static void gv_points_init(GvPoints *points);
+static void gv_points_get_memento(GvData *points, gpointer info, GvDataMemento **memento);
+static void gv_points_set_memento(GvData *points, GvDataMemento *memento);
+static void gv_points_del_memento(GvData *points, GvDataMemento *memento);
+static void gv_points_changed(GvData *points, gpointer data);
+static void gv_points_finalize(GtkObject *object);
+
+GtkType
+gv_points_get_type(void)
+{
+ static GtkType points_type = 0;
+
+ if (!points_type)
+ {
+ static const GtkTypeInfo points_info =
+ {
+ "GvPoints",
+ sizeof(GvPoints),
+ sizeof(GvPointsClass),
+ (GtkClassInitFunc) gv_points_class_init,
+ (GtkObjectInitFunc) gv_points_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ points_type = gtk_type_unique(gv_data_get_type(), &points_info);
+ }
+ return points_type;
+}
+
+static void
+gv_points_init(GvPoints *points)
+{
+ points->points = g_array_new(FALSE, FALSE, sizeof(GvPoint));
+ points->extents_valid = FALSE;
+}
+
+static void
+gv_points_class_init(GvPointsClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+ data_class = (GvDataClass*) klass;
+
+ object_class->finalize = gv_points_finalize;
+
+ data_class->changed = gv_points_changed;
+ data_class->get_memento = gv_points_get_memento;
+ data_class->set_memento = gv_points_set_memento;
+ data_class->del_memento = gv_points_del_memento;
+}
+
+GvData *
+gv_points_new(void)
+{
+ return GV_DATA(gtk_type_new(gv_points_get_type()));
+}
+
+gint
+gv_points_new_point(GvPoints *points, GvVertex *vertex)
+{
+ int point_id;
+ GvPoint point;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ change_info.shape_id = &point_id;
+
+ if (vertex)
+ {
+ point.v = *vertex;
+ }
+ else
+ {
+ point.v.x = point.v.y = 0.0;
+ }
+ point.meta = NULL;
+ point_id = points->points->len;
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ g_array_append_val(points->points, point);
+
+ gv_data_changed(GV_DATA(points), &change_info);
+
+ return point_id;
+}
+
+void
+gv_points_delete_points(GvPoints *points, gint num_points, gint *point_id)
+{
+ GvShapeChangeInfo change_info = {GV_CHANGE_DELETE, 0, NULL};
+
+ change_info.num_shapes = num_points;
+ change_info.shape_id = point_id;
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ /* FIXME: can't use g_array_remove_index_fast() here since there is no
+ g_array_insert_index_fast() function. */
+
+ if (num_points == 1)
+ {
+ g_array_remove_index(points->points, *point_id);
+ }
+ else
+ {
+ /* Strategy: sort the line_id buffer and delete lines in desending
+ order, so that indicies remain valid */
+ gint *id, i;
+
+ id = g_memdup_type(point_id, int, num_points);
+ g_sort_type(id, gint, num_points);
+
+ for (i=num_points-1; i >= 0; --i)
+ {
+ g_array_remove_index(points->points, id[i]);
+ }
+ g_free(id);
+ }
+ gv_data_changed(GV_DATA(points), &change_info);
+}
+
+void
+gv_points_translate_points(GvPoints *points, gint num_points, gint *point_id,
+ gvgeocoord dx, gvgeocoord dy)
+{
+ GvPoint *point;
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_points;
+ change_info.shape_id = point_id;
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ for (i=0; i < num_points; ++i)
+ {
+ g_return_if_fail(point_id[i] >= 0 &&
+ point_id[i] < points->points->len);
+ point = gv_points_get_point(points, point_id[i]);
+
+ point->v.x += dx;
+ point->v.y += dy;
+ }
+ gv_data_changed(GV_DATA(points), &change_info);
+}
+
+void
+gv_points_set_point(GvPoints *points, gint point_id, GvVertex *vertex)
+{
+ GvPoint *point;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &point_id;
+
+ g_return_if_fail(vertex);
+ g_return_if_fail(point_id >= 0 && point_id < points->points->len);
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ point = gv_points_get_point(points, point_id);
+ point->v.x = vertex->x;
+ point->v.y = vertex->y;
+
+ gv_data_changed(GV_DATA(points), &change_info);
+}
+
+void
+gv_points_get_extents(GvPoints *points, GvRect *rect)
+{
+ if (!points->extents_valid)
+ {
+ gint i, num_points;
+ GvVertex vmax, vmin, v;
+
+ vmin.x = vmin.y = GV_MAXFLOAT;
+ vmax.x = vmax.y = -GV_MAXFLOAT;
+ num_points = gv_points_num_points(points);
+ for (i=0; i < num_points; ++i)
+ {
+ v = gv_points_get_point(points, i)->v;
+ if (v.x < vmin.x) vmin.x = v.x;
+ if (v.x > vmax.x) vmax.x = v.x;
+ if (v.y < vmin.y) vmin.y = v.y;
+ if (v.y > vmax.y) vmax.y = v.y;
+ }
+
+ if (num_points == 0)
+ {
+ points->extents.x = 0;
+ points->extents.y = 0;
+ points->extents.width = 0;
+ points->extents.height = 0;
+ }
+ else
+ {
+ points->extents.x = vmin.x;
+ points->extents.y = vmin.y;
+ points->extents.width = vmax.x - vmin.x;
+ points->extents.height = vmax.y - vmin.y;
+ }
+ points->extents_valid = TRUE;
+ }
+
+ *rect = points->extents;
+}
+
+/*********************************************/
+
+static void
+gv_points_replace_points(GvPoints *points, gint num_points, gint *point_id,
+ GvPoint *pts)
+{
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_points;
+ change_info.shape_id = point_id;
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ for (i=0; i < num_points; ++i)
+ {
+ g_array_index(points->points, GvPoint, point_id[i]) = pts[i];
+ }
+
+ gv_data_changed(GV_DATA(points), &change_info);
+}
+
+static void
+gv_points_insert_points(GvPoints *points, gint num_points, gint *point_id,
+ GvPoint *pts)
+{
+ /* The point_id array must be in ascending order! */
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 0, NULL};
+
+ change_info.num_shapes = num_points;
+ change_info.shape_id = point_id;
+
+ gv_data_changing(GV_DATA(points), &change_info);
+
+ for (i=0; i < num_points; ++i)
+ {
+ /* FIXME: need to write a g_array_insert_index_fast() function,
+ but that requires access to the elt_size private member of
+ GArray */
+ g_array_insert_val(points->points, point_id[i], pts[i]);
+ }
+
+ gv_data_changed(GV_DATA(points), &change_info);
+}
+
+static void
+gv_points_get_memento(GvData *gv_data, gpointer data,
+ GvDataMemento **memento)
+{
+ GvPoints *points = GV_POINTS(gv_data);
+ GvPointsMemento *mem;
+ GvShapeChangeInfo *info = (GvShapeChangeInfo *) data;
+ int i;
+
+ mem = g_new(GvPointsMemento, 1);
+ mem->base.data = GV_DATA(points);
+ mem->base.type = info->change_type;
+
+ mem->point_ids = g_array_new(FALSE, FALSE, sizeof(gint));
+ g_array_append_vals(mem->point_ids, info->shape_id, info->num_shapes);
+
+ /* Grab points in ascending order */
+ if (info->num_shapes > 1)
+ {
+ g_sort_type(mem->point_ids->data, gint, mem->point_ids->len);
+ }
+
+ if (info->change_type == GV_CHANGE_ADD)
+ {
+ mem->points = NULL;
+ }
+ else
+ {
+ mem->points = g_array_new(FALSE, FALSE, sizeof(GvPoint));
+ for (i=0; i < info->num_shapes; ++i)
+ {
+ GvPoint *point = gv_points_get_point(points, info->shape_id[i]);
+ g_array_append_val(mem->points, *point);
+ }
+ }
+
+ *memento = (GvDataMemento*)mem;
+}
+
+static void
+gv_points_set_memento(GvData *gv_data, GvDataMemento *data_memento)
+{
+ GvPoints *points = GV_POINTS(gv_data);
+ GvPointsMemento *memento = (GvPointsMemento *) data_memento;
+
+ switch (memento->base.type)
+ {
+ case GV_CHANGE_ADD:
+ gv_points_delete_points(points, memento->point_ids->len,
+ (gint*)memento->point_ids->data);
+ break;
+
+ case GV_CHANGE_REPLACE:
+ gv_points_replace_points(points, memento->point_ids->len,
+ (gint*)memento->point_ids->data,
+ (GvPoint*)memento->points->data);
+ break;
+
+ case GV_CHANGE_DELETE:
+ gv_points_insert_points(points, memento->point_ids->len,
+ (gint*)memento->point_ids->data,
+ (GvPoint*)memento->points->data);
+ break;
+ }
+
+ gv_points_del_memento((GvData *) points, (GvDataMemento *) memento);
+}
+
+static void
+gv_points_del_memento(GvData *gv_data, GvDataMemento *data_memento)
+{
+ GvPointsMemento *memento = (GvPointsMemento *) data_memento;
+
+ if (memento->points)
+ {
+ g_array_free(memento->points, TRUE);
+ }
+ g_array_free(memento->point_ids, TRUE);
+ g_free(memento);
+}
+
+static void
+gv_points_changed(GvData *gv_data, gpointer data)
+{
+ GvPoints *points = GV_POINTS(gv_data);
+
+ points->extents_valid = FALSE;
+}
+
+static void
+gv_points_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvPoints *points = GV_POINTS(object);
+
+ g_array_free(points->points, TRUE);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
Added: packages/openev/branches/upstream/current/gvpoints.h
===================================================================
--- packages/openev/branches/upstream/current/gvpoints.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpoints.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * $Id: gvpoints.h,v 1.4 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Points data container (superceed by GvShapes)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpoints.h,v $
+ * Revision 1.4 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.3 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_POINTS_H__
+#define __GV_POINTS_H__
+
+#include "gvdata.h"
+
+#define GV_TYPE_POINTS (gv_points_get_type ())
+#define GV_POINTS(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_POINTS, GvPoints))
+#define GV_POINTS_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_POINTS, GvPointsClass))
+#define GV_IS_POINTS(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_POINTS))
+#define GV_IS_POINTS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_POINTS))
+
+typedef struct _GvPoint GvPoint;
+typedef struct _GvPoints GvPoints;
+typedef struct _GvPointsClass GvPointsClass;
+
+struct _GvPoint
+{
+ GvVertex v;
+ gpointer meta;
+};
+
+struct _GvPoints
+{
+ GvData data;
+
+ GArray *points;
+ GvRect extents;
+ guint extents_valid : 1;
+};
+
+struct _GvPointsClass
+{
+ GvDataClass parent_class;
+};
+
+GtkType gv_points_get_type (void);
+
+GvData* gv_points_new(void);
+gint gv_points_new_point(GvPoints *points, GvVertex *vertex);
+void gv_points_delete_points(GvPoints *points, gint num_points, gint *point_id);
+void gv_points_translate_points(GvPoints *points, gint num_points, gint *point_id, gvgeocoord dx, gvgeocoord dy);
+void gv_points_set_point(GvPoints *points, gint point_id, GvVertex *vertex);
+void gv_points_get_extents(GvPoints *points, GvRect *rect);
+
+#define gv_points_num_points(pts) \
+ (pts->points->len)
+#define gv_points_get_point(pts,id) \
+ (&g_array_index(pts->points, GvPoint, id))
+#define gv_points_get_meta(pts,id) \
+ (gv_points_get_point(pts,id)->meta)
+#define gv_points_set_meta(pts,id,data) \
+ gv_points_get_point(pts,id)->meta = data
+
+#endif /*__GV_POINTS_H__ */
Added: packages/openev/branches/upstream/current/gvpointtool.c
===================================================================
--- packages/openev/branches/upstream/current/gvpointtool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpointtool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,286 @@
+/******************************************************************************
+ * $Id: gvpointtool.c,v 1.11 2001/04/09 18:15:20 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Point editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpointtool.c,v $
+ * Revision 1.11 2001/04/09 18:15:20 warmerda
+ * improved warning
+ *
+ * Revision 1.10 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.9 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.8 2000/07/24 14:00:24 warmerda
+ * set_layer with NULL should be allowed
+ *
+ * Revision 1.7 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.6 2000/07/17 17:11:54 warmerda
+ * added delete key support
+ *
+ * Revision 1.5 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvpointtool.h"
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtksignal.h>
+
+static void gv_point_tool_class_init(GvPointToolClass *klass);
+static void gv_point_tool_init(GvPointTool *tool);
+static void gv_point_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_point_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_point_tool_deactivate(GvTool *tool, GvViewArea *view);
+static gint gv_point_tool_configure(GvTool *tool);
+
+GtkType
+gv_point_tool_get_type(void)
+{
+ static GtkType point_tool_type = 0;
+
+ if (!point_tool_type)
+ {
+ static const GtkTypeInfo point_tool_info =
+ {
+ "GvPointTool",
+ sizeof(GvPointTool),
+ sizeof(GvPointToolClass),
+ (GtkClassInitFunc) gv_point_tool_class_init,
+ (GtkObjectInitFunc) gv_point_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ point_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &point_tool_info);
+ }
+ return point_tool_type;
+}
+
+static void
+gv_point_tool_class_init(GvPointToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_point_tool_deactivate;
+ tool_class->button_press = gv_point_tool_button_press;
+ tool_class->key_press = gv_point_tool_key_press;
+}
+
+static void
+gv_point_tool_init(GvPointTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->layer = NULL;
+ tool->named_layer = NULL;
+}
+
+GvTool *
+gv_point_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_POINT_TOOL));
+}
+
+static gint gv_point_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvPointTool *tool = (GvPointTool *) data;
+
+ if( tool->layer == GV_SHAPE_LAYER(layer) )
+ gv_point_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_point_tool_set_layer(GvPointTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_point_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL
+ && !GV_IS_POINT_LAYER(layer) && !GV_IS_SHAPES_LAYER(layer) )
+ {
+ g_warning( "gv_point_tool_set_layer(): not a point capable layer" );
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_point_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ /* Disconnect from the previous layer */
+ if (tool->layer)
+ {
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ gtk_signal_disconnect_by_data( GTK_OBJECT(tool->layer),
+ GTK_OBJECT(tool) );
+ }
+
+ tool->layer = layer;
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_point_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+void
+gv_point_tool_set_named_layer(GvPointTool *tool, gchar *name)
+{
+ if (tool->named_layer)
+ {
+ g_free(tool->named_layer);
+ tool->named_layer = NULL;
+ }
+ if (name)
+ {
+ tool->named_layer = g_strdup(name);
+ }
+ /* Tool layer will be updated next time it is configured */
+}
+
+static void
+gv_point_tool_button_press(GvTool *tool, GdkEventButton *event)
+{
+ if (event->button == 1)
+ {
+ GvVertex vertex;
+
+ if (!gv_point_tool_configure(tool)) return;
+
+ /* Get pointer location */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &vertex.x, &vertex.y);
+
+ if( !gv_tool_check_bounds( GV_TOOL(tool), vertex.x, vertex.y ) )
+ return;
+
+ /* Add a new point */
+ if( GV_IS_POINT_LAYER(GV_POINT_TOOL(tool)->layer) )
+ {
+ gv_point_layer_select_new_point(
+ GV_POINT_LAYER(GV_POINT_TOOL(tool)->layer),
+ &vertex);
+ }
+ else
+ {
+ GvShape *new_point;
+
+ new_point = gv_shape_new( GVSHAPE_POINT );
+ gv_shape_set_xyz( new_point, 0, 0, vertex.x, vertex.y, 0.0 );
+ gv_shapes_layer_select_new_shape(
+ GV_SHAPES_LAYER(GV_POINT_TOOL(tool)->layer),
+ new_point );
+ }
+ }
+}
+
+static void
+gv_point_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvPointTool *tool = GV_POINT_TOOL(rtool);
+
+ if (!gv_point_tool_configure(GV_TOOL(tool))) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ /* Delete the currently selected lines (forces redraw) */
+ gv_shape_layer_delete_selected(tool->layer);
+ break;
+ }
+}
+
+static void
+gv_point_tool_deactivate(GvTool *r_tool, GvViewArea *view)
+{
+ GvPointTool *tool = GV_POINT_TOOL(r_tool);
+
+ /* Disconnect from layer */
+ if (tool->layer)
+ {
+ gv_point_tool_set_layer(tool, NULL);
+ }
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static gint
+gv_point_tool_configure(GvTool *r_tool)
+{
+ GvPointTool *tool = GV_POINT_TOOL(r_tool);
+
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ if (tool->named_layer)
+ {
+ /* Look for named layer if given */
+ layer = gv_view_area_get_named_layer(GV_TOOL(tool)->view,
+ tool->named_layer);
+ }
+ else
+ {
+ /* Attempt to find a point layer to edit */
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_POINT_LAYER,
+ FALSE);
+ if( layer == NULL )
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPES_LAYER,
+ FALSE);
+ }
+ if (!layer)
+ {
+ g_warning("gv_point_tool_configure(): no editable point layer in view");
+ return FALSE;
+ }
+
+ gv_point_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+ return tool->layer != NULL;
+}
Added: packages/openev/branches/upstream/current/gvpointtool.h
===================================================================
--- packages/openev/branches/upstream/current/gvpointtool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpointtool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: gvpointtool.h,v 1.4 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Point editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpointtool.h,v $
+ * Revision 1.4 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_POINT_TOOL_H__
+#define __GV_POINT_TOOL_H__
+
+#include "gvtool.h"
+#include "gvpointlayer.h"
+#include "gvshapeslayer.h"
+
+#define GV_TYPE_POINT_TOOL (gv_point_tool_get_type ())
+#define GV_POINT_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_POINT_TOOL, GvPointTool))
+#define GV_POINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_POINT_TOOL, GvPointToolClass))
+#define GV_IS_POINT_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_POINT_TOOL))
+#define GV_IS_POINT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_POINT_TOOL))
+
+typedef struct _GvPointTool GvPointTool;
+typedef struct _GvPointToolClass GvPointToolClass;
+
+struct _GvPointTool
+{
+ GvTool tool;
+
+ GvShapeLayer *layer;
+ gchar *named_layer;
+};
+
+struct _GvPointToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_point_tool_get_type(void);
+GvTool* gv_point_tool_new(void);
+void gv_point_tool_set_layer(GvPointTool *tool, GvShapeLayer *layer);
+void gv_point_tool_set_named_layer(GvPointTool *tool, gchar *name);
+
+#endif /* __GV_POINT_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvpoitool.c
===================================================================
--- packages/openev/branches/upstream/current/gvpoitool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpoitool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,254 @@
+/******************************************************************************
+ * $Id: gvpoitool.c,v 1.3 2003/01/14 16:16:24 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Point of interest editing mode.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ *
+ */
+
+#include "gvpoitool.h"
+#include <gtk/gtksignal.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdio.h>
+
+#define DEFAULT_POI_SIZE 6.0
+
+/* Signals */
+enum
+{
+ POI_CHANGED,
+ LAST_SIGNAL
+};
+
+static void gv_poi_tool_class_init(GvPoiToolClass *klass);
+static void gv_poi_tool_init(GvPoiTool *tool);
+static void gv_poi_tool_draw(GvTool *tool);
+static void gv_poi_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_poi_tool_deactivate(GvTool *tool, GvViewArea *view);
+
+static guint poitool_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_poi_tool_get_type(void)
+{
+ static GtkType poi_tool_type = 0;
+
+ if (!poi_tool_type)
+ {
+ static const GtkTypeInfo poi_tool_info =
+ {
+ "GvPoiTool",
+ sizeof(GvPoiTool),
+ sizeof(GvPoiToolClass),
+ (GtkClassInitFunc) gv_poi_tool_class_init,
+ (GtkObjectInitFunc) gv_poi_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ poi_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &poi_tool_info);
+ }
+ return poi_tool_type;
+}
+
+static void
+gv_poi_tool_class_init(GvPoiToolClass *klass)
+{
+ GvToolClass *tool_class;
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+ tool_class = (GvToolClass*)klass;
+
+ poitool_signals[POI_CHANGED] =
+ gtk_signal_new ("poi_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvPoiToolClass,poi_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ gtk_object_class_add_signals(object_class, poitool_signals, LAST_SIGNAL);
+
+ klass->poi_changed = NULL;
+
+ tool_class->deactivate = gv_poi_tool_deactivate;
+ tool_class->draw = gv_poi_tool_draw;
+ tool_class->button_release = gv_poi_tool_button_release;
+
+}
+static void
+gv_poi_tool_init(GvPoiTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->poi_marked = FALSE;
+ tool->poi_size = DEFAULT_POI_SIZE;
+}
+
+GvTool *
+gv_poi_tool_new(void)
+{
+ GvTool *tool;
+
+ tool = GV_TOOL(gtk_type_new(GV_TYPE_POI_TOOL));
+
+
+
+ return tool;
+
+}
+
+gint
+gv_poi_tool_get_point(GvPoiTool *tool, GvVertex *point)
+{
+ if (!tool->poi_marked)
+ {
+ return FALSE;
+ }
+
+ point->x = tool->v_center.x;
+ point->y = tool->v_center.y;
+
+ return TRUE;
+}
+
+gint
+gv_poi_tool_new_point(GvPoiTool *tool, GvVertex *point)
+{
+ /* Create new POI */
+ tool->poi_marked = TRUE;
+
+ tool->v_center.x = point->x;
+ tool->v_center.y = point->y;
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_center.x), &(tool->v_center.y) );
+
+ gtk_signal_emit(GTK_OBJECT(tool),
+ poitool_signals[POI_CHANGED]);
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+
+ return TRUE;
+}
+
+/**************************************************************/
+
+static void
+gv_poi_tool_button_release(GvTool *ptool, GdkEventButton *event)
+{
+ GvPoiTool *tool = GV_POI_TOOL(ptool);
+
+ if ((event->button == 1) && !(event->state & GDK_CONTROL_MASK)
+ && !(event->state & GDK_SHIFT_MASK) )
+ {
+
+ /* Set head and tail vertex to pointer position */
+ /* Map pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_center.x, &tool->v_center.y);
+
+ if( gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_center.x, tool->v_center.y ) )
+ {
+ tool->poi_marked = TRUE;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ gtk_signal_emit(GTK_OBJECT(tool),
+ poitool_signals[POI_CHANGED]);
+ }
+ }
+ if ((event->button == 2) && !(event->state & GDK_CONTROL_MASK)
+ && !(event->state & GDK_SHIFT_MASK) )
+ {
+ /* If user presses 2nd button within the view window, */
+ /* clear the point and redraw view without it */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_center.x, &tool->v_center.y);
+
+ if( gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_center.x, tool->v_center.y ) )
+ {
+ tool->poi_marked = FALSE;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+
+ gtk_signal_emit(GTK_OBJECT(tool),
+ poitool_signals[POI_CHANGED]);
+ }
+ }
+
+}
+
+static void
+gv_poi_tool_draw(GvTool *ptool)
+{
+ GvPoiTool *tool = GV_POI_TOOL(ptool);
+ gvgeocoord dx, dy, bx, by, x, y;
+
+ if (tool->poi_marked)
+ {
+ dx = tool->poi_size;
+ dy = 0.0;
+ gv_view_area_correct_for_transform(GV_TOOL(tool)->view, dx, dy, &dx, &dy);
+ bx = by = tool->poi_size + 2;
+ gv_view_area_correct_for_transform(GV_TOOL(tool)->view, bx, by, &bx, &by);
+
+ x = tool->v_center.x;
+ y = tool->v_center.y;
+
+ glRenderMode(GL_RENDER);
+ glColor3f(1.0,0.5,0.0);
+
+ /* Draw crosshairs */
+ glBegin(GL_LINES);
+ glVertex2(x-dx, y-dy);
+ glVertex2(x+dx, y+dy);
+ glVertex2(x+dy, y-dx);
+ glVertex2(x-dy, y+dx);
+ glEnd();
+
+ /* Draw box around crosshairs */
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x-bx, y-by);
+ glVertex2(x+by, y-bx);
+ glVertex2(x+bx, y+by);
+ glVertex2(x-by, y+bx);
+ glEnd();
+ }
+}
+
+static void
+gv_poi_tool_deactivate(GvTool *ptool, GvViewArea *view)
+{
+ GvPoiTool *tool = GV_POI_TOOL(ptool);
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+
+ tool->poi_marked = FALSE;
+
+ gv_view_area_queue_draw(view);
+}
Added: packages/openev/branches/upstream/current/gvpoitool.h
===================================================================
--- packages/openev/branches/upstream/current/gvpoitool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpoitool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: gvpoitool.h,v 1.1 2002/02/28 18:52:22 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Pegion of interest editing mode.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ */
+
+#ifndef __GV_POI_TOOL_H__
+#define __GV_POI_TOOL_H__
+
+#include "gvtypes.h"
+#include "gvtool.h"
+
+#define GV_TYPE_POI_TOOL (gv_poi_tool_get_type ())
+#define GV_POI_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_POI_TOOL, GvPoiTool))
+#define GV_POI_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_POI_TOOL, GvPoiToolClass))
+#define GV_IS_POI_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_POI_TOOL))
+#define GV_IS_POI_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_POI_TOOL))
+
+typedef struct _GvPoiTool GvPoiTool;
+typedef struct _GvPoiToolClass GvPoiToolClass;
+
+struct _GvPoiTool
+{
+ GvTool tool;
+
+ gint poi_marked : 1;
+ gvfloat poi_size; /* Default size of lines to draw to mark point */
+
+ GvVertex v_center;
+};
+
+struct _GvPoiToolClass
+{
+ GvToolClass parent_class;
+
+ void (* poi_changed)(GvPoiTool *tool);
+};
+
+GtkType gv_poi_tool_get_type(void);
+GvTool* gv_poi_tool_new(void);
+
+gint gv_poi_tool_get_point(GvPoiTool *tool, GvVertex *point);
+gint gv_poi_tool_new_point(GvPoiTool *tool, GvVertex *point);
+
+#endif /* __GV_POI_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvpolylines.c
===================================================================
--- packages/openev/branches/upstream/current/gvpolylines.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpolylines.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,565 @@
+/******************************************************************************
+ * $Id: gvpolylines.c,v 1.10 2002/11/05 18:56:21 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Polylines data container (superceeded by GvShapes)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpolylines.c,v $
+ * Revision 1.10 2002/11/05 18:56:21 sduclos
+ * fix gcc warning
+ *
+ * Revision 1.9 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.8 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gextra.h"
+#include "gvpolylines.h"
+
+typedef struct _GvLinesMemento GvLinesMemento;
+
+struct _GvLinesMemento
+{
+ GvDataMemento base;
+ GArray *line_ids;
+ GPtrArray *lines;
+};
+
+static void gv_polylines_class_init(GvPolylinesClass *klass);
+static void gv_polylines_init(GvPolylines *pline);
+static void gv_polylines_replace_lines(GvPolylines *pline, gint num_lines, gint *line_ids, GArray **line);
+static void gv_polylines_insert_lines(GvPolylines *pline, gint num_lines, gint *line_ids, GArray **line);
+static void gv_polylines_get_memento(GvPolylines *pline, GvShapeChangeInfo *info, GvDataMemento **memento);
+static void gv_polylines_set_memento(GvPolylines *pline, GvLinesMemento *memento);
+static void gv_polylines_del_memento(GvPolylines *pline, GvLinesMemento *memento);
+static void gv_polylines_changed(GvPolylines *pline, gpointer data);
+static void gv_polylines_finalize(GtkObject *object);
+
+GtkType
+gv_polylines_get_type(void)
+{
+ static GtkType polylines_type = 0;
+
+ if (!polylines_type)
+ {
+ static const GtkTypeInfo polylines_info =
+ {
+ "GvPolylines",
+ sizeof(GvPolylines),
+ sizeof(GvPolylinesClass),
+ (GtkClassInitFunc) gv_polylines_class_init,
+ (GtkObjectInitFunc) gv_polylines_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ polylines_type = gtk_type_unique(gv_data_get_type(), &polylines_info);
+ }
+ return polylines_type;
+}
+
+static void
+gv_polylines_init(GvPolylines *pline)
+{
+ pline->lines = g_ptr_array_new();
+ pline->extents_valid = FALSE;
+}
+
+static void
+gv_polylines_class_init(GvPolylinesClass *klass)
+{
+ typedef void (*f)();
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+ data_class = (GvDataClass*) klass;
+
+ object_class->finalize = gv_polylines_finalize;
+
+ data_class->changed = (f) gv_polylines_changed;
+ data_class->get_memento = (f) gv_polylines_get_memento;
+ data_class->set_memento = (f) gv_polylines_set_memento;
+ data_class->del_memento = (f) gv_polylines_del_memento;
+}
+
+GvData *
+gv_polylines_new(void)
+{
+ return GV_DATA(gtk_type_new(gv_polylines_get_type()));
+}
+
+gint
+gv_polylines_new_line(GvPolylines *pline)
+{
+ GArray *line;
+ int line_id;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ line_id = pline->lines->len;
+ line = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_return_val_if_fail(line, 0);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_ptr_array_add(pline->lines, (gpointer)line);
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+
+ return line_id;
+}
+
+gint
+gv_polylines_new_line_with_data(GvPolylines *pline, gint num_nodes,
+ GvVertex *vertex)
+{
+ GArray *line;
+ gint line_id;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ line_id = pline->lines->len;
+ line = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_return_val_if_fail(line, 0);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_ptr_array_add(pline->lines, (gpointer)line);
+ g_array_append_vals(line, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+
+ return line_id;
+}
+
+gint
+gv_polylines_num_nodes(GvPolylines *pline, gint line_id)
+{
+ GArray *line;
+
+ g_return_val_if_fail(line_id >= 0 && line_id < pline->lines->len, 0);
+ line = gv_polylines_get_line(pline, line_id);
+ return line->len;
+}
+
+void
+gv_polylines_translate_lines(GvPolylines *pline, gint num_lines, gint *line_id,
+ gvgeocoord dx, gvgeocoord dy)
+{
+ GArray *line;
+ int i, j;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.shape_id = line_id;
+ change_info.num_shapes = num_lines;
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ for (j=0; j < num_lines; ++j)
+ {
+ g_return_if_fail(line_id[j] >= 0 && line_id[j] < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id[j]);
+
+ for (i=0; i < line->len; ++i)
+ {
+ g_array_index(line, GvVertex, i).x += dx;
+ g_array_index(line, GvVertex, i).y += dy;
+ }
+ }
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_delete_lines(GvPolylines *pline, gint num_lines, gint *line_id)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_DELETE, 0, NULL};
+
+ change_info.num_shapes = num_lines;
+ change_info.shape_id = line_id;
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ if (num_lines == 1)
+ {
+ line = (GArray*)g_ptr_array_remove_index_fast(pline->lines, *line_id);
+ if (line) g_array_free(line, TRUE);
+ }
+ else
+ {
+ /* Strategy: sort the line_id buffer and delete lines in desending
+ order, so that indicies remain valid */
+ gint *id, i;
+
+ id = g_memdup_type(line_id, gint, num_lines);
+ g_sort_type(id, gint, num_lines);
+
+ for (i=num_lines-1; i >= 0; --i)
+ {
+ line = (GArray*)g_ptr_array_remove_index_fast(pline->lines, id[i]);
+ if (line) g_array_free(line, TRUE);
+ }
+ g_free(id);
+ }
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_set_nodes(GvPolylines *pline, gint line_id, gint num_nodes,
+ GvVertex *vertex)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ g_return_if_fail(line_id >= 0 && line_id < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_array_set_size(line, 0);
+ g_array_append_vals(line, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_append_nodes(GvPolylines *pline, gint line_id, gint num_nodes,
+ GvVertex *vertex)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ g_return_if_fail(line_id >= 0 && line_id < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_array_append_vals(line, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_insert_nodes(GvPolylines *pline, gint line_id, gint node_id,
+ gint num_nodes, GvVertex *vertex)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ g_return_if_fail(line_id >= 0 && line_id < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_array_insert_vals(line, node_id, vertex, num_nodes);
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_delete_nodes(GvPolylines *pline, gint line_id, gint num_nodes,
+ gint *node_id)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ g_return_if_fail(line_id >= 0 && line_id < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ if (num_nodes == 1)
+ {
+ /* Need to preserve node order, so we can't use *_remove_fast */
+ g_array_remove_index(line, *node_id);
+ }
+ else
+ {
+ /* Strategy: sort the node_id buffer and delete nodes in desending
+ order, so that indicies remain valid */
+ gint *id, i;
+
+ id = g_memdup_type(node_id, gint, num_nodes);
+ g_sort_type(id, gint, num_nodes);
+
+ for (i=num_nodes-1; i >= 0; --i)
+ {
+ g_array_remove_index(line, id[i]);
+ }
+ g_free(id);
+ }
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+void
+gv_polylines_move_node(GvPolylines *pline, gint line_id, gint node_id,
+ GvVertex *vertex)
+{
+ GArray *line;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 1, NULL};
+
+ change_info.shape_id = &line_id;
+
+ g_return_if_fail(line_id >= 0 && line_id < pline->lines->len);
+ line = gv_polylines_get_line(pline, line_id);
+ g_return_if_fail(node_id >= 0 && node_id < line->len);
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ g_array_index(line, GvVertex, node_id).x = vertex->x;
+ g_array_index(line, GvVertex, node_id).y = vertex->y;
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+GvVertex *
+gv_polylines_get_node(GvPolylines *pline, gint line_id, gint node_id)
+{
+ GArray *line;
+
+ g_return_val_if_fail(line_id >= 0 && line_id < pline->lines->len, NULL);
+ line = gv_polylines_get_line(pline, line_id);
+ g_return_val_if_fail(node_id >= 0 && node_id < line->len, NULL);
+
+ return &g_array_index(line, GvVertex, node_id);
+}
+
+void
+gv_polylines_get_extents(GvPolylines *pline, GvRect *rect)
+{
+ if (!pline->extents_valid)
+ {
+ gint i, j, lines;
+ GArray *line;
+ GvVertex vmax, vmin, *v;
+
+ vmin.x = vmin.y = GV_MAXFLOAT;
+ vmax.x = vmax.y = -GV_MAXFLOAT;
+ lines = gv_polylines_num_lines(pline);
+ for (i=0; i < lines; ++i)
+ {
+ line = gv_polylines_get_line(pline, i);
+ for (j=0; j < line->len; ++j)
+ {
+ v = &g_array_index(line, GvVertex, j);
+ if (v->x < vmin.x) vmin.x = v->x;
+ if (v->x > vmax.x) vmax.x = v->x;
+ if (v->y < vmin.y) vmin.y = v->y;
+ if (v->y > vmax.y) vmax.y = v->y;
+ }
+ }
+
+ if (lines == 0 || (lines == 1 && line->len == 0))
+ {
+ pline->extents.x = 0;
+ pline->extents.y = 0;
+ pline->extents.width = 0;
+ pline->extents.height = 0;
+ }
+ else
+ {
+ pline->extents.x = vmin.x;
+ pline->extents.y = vmin.y;
+ pline->extents.width = vmax.x - vmin.x;
+ pline->extents.height = vmax.y - vmin.y;
+ }
+ pline->extents_valid = TRUE;
+ }
+ rect->x = pline->extents.x;
+ rect->y = pline->extents.y;
+ rect->width = pline->extents.width;
+ rect->height = pline->extents.height;
+}
+
+/*********************************************/
+
+static void
+gv_polylines_replace_lines(GvPolylines *pline, gint num_lines, gint *line_id,
+ GArray **line)
+{
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_lines;
+ change_info.shape_id = line_id;
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ for (i=0; i < num_lines; ++i)
+ {
+ g_array_free(gv_polylines_get_line(pline, line_id[i]), TRUE);
+
+ g_ptr_array_index(pline->lines, line_id[i]) = line[i];
+ }
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+static void
+gv_polylines_insert_lines(GvPolylines *pline, gint num_lines, gint *line_ids,
+ GArray **line)
+{
+ /* The line_id array must be in ascending order! */
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 0, NULL};
+
+ change_info.num_shapes = num_lines;
+ change_info.shape_id = line_ids;
+
+ gv_data_changing(GV_DATA(pline), &change_info);
+
+ for (i=0; i < num_lines; ++i)
+ {
+ g_ptr_array_insert_fast(pline->lines, line_ids[i], line[i]);
+ }
+
+ gv_data_changed(GV_DATA(pline), &change_info);
+}
+
+static void
+gv_polylines_get_memento(GvPolylines *pline, GvShapeChangeInfo *info,
+ GvDataMemento **memento)
+{
+ GvLinesMemento *mem;
+ int i;
+
+ mem = g_new(GvLinesMemento, 1);
+ mem->base.data = GV_DATA(pline);
+ mem->base.type = info->change_type;
+
+ mem->line_ids = g_array_new(FALSE, FALSE, sizeof(gint));
+ g_array_append_vals(mem->line_ids, info->shape_id, info->num_shapes);
+
+ /* Grab areas in ascending order */
+ if (info->num_shapes > 1)
+ {
+ g_sort_type(mem->line_ids->data, gint, mem->line_ids->len);
+ }
+
+ if (info->change_type == GV_CHANGE_ADD)
+ {
+ mem->lines = NULL;
+ }
+ else
+ {
+ mem->lines = g_ptr_array_new();
+ for (i=0; i < info->num_shapes; ++i)
+ {
+ GArray *line = gv_polylines_get_line(pline, info->shape_id[i]);
+ GArray *copy = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_array_append_vals(copy, line->data, line->len);
+ g_ptr_array_add(mem->lines, copy);
+ }
+ }
+
+ *memento = (GvDataMemento*)mem;
+}
+
+static void
+gv_polylines_set_memento(GvPolylines *pline, GvLinesMemento *memento)
+{
+ switch (memento->base.type)
+ {
+ case GV_CHANGE_ADD:
+ gv_polylines_delete_lines(pline, memento->line_ids->len,
+ (gint*)memento->line_ids->data);
+ break;
+
+ case GV_CHANGE_REPLACE:
+ gv_polylines_replace_lines(pline, memento->line_ids->len,
+ (gint*)memento->line_ids->data,
+ (GArray**)memento->lines->pdata);
+ break;
+
+ case GV_CHANGE_DELETE:
+ gv_polylines_insert_lines(pline, memento->line_ids->len,
+ (gint*)memento->line_ids->data,
+ (GArray**)memento->lines->pdata);
+ break;
+ }
+
+ if (memento->lines)
+ {
+ g_ptr_array_free(memento->lines, TRUE);
+ memento->lines = NULL;
+ }
+ gv_polylines_del_memento(pline, memento);
+}
+
+static void
+gv_polylines_del_memento(GvPolylines *pline, GvLinesMemento *memento)
+{
+ int i;
+
+ if (memento->lines)
+ {
+ for (i=0; i < memento->lines->len; ++i)
+ {
+ g_array_free(g_ptr_array_index(memento->lines, i), TRUE);
+ }
+ g_ptr_array_free(memento->lines, TRUE);
+ }
+ g_array_free(memento->line_ids, TRUE);
+ g_free(memento);
+}
+
+static void
+gv_polylines_changed(GvPolylines *pline, gpointer data)
+{
+ pline->extents_valid = FALSE;
+}
+
+static void
+gv_polylines_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvPolylines *pline;
+ int i;
+
+ pline = GV_POLYLINES(object);
+
+ for (i=0; i < gv_polylines_num_lines(pline); i++)
+ {
+ g_array_free(gv_polylines_get_line(pline, i), TRUE);
+ }
+ g_ptr_array_free(pline->lines, TRUE);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
Added: packages/openev/branches/upstream/current/gvpolylines.h
===================================================================
--- packages/openev/branches/upstream/current/gvpolylines.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpolylines.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * $Id: gvpolylines.h,v 1.7 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Polylines data container (superceeded by GvShapes)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpolylines.h,v $
+ * Revision 1.7 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.6 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_POLYLINES_H__
+#define __GV_POLYLINES_H__
+
+#include "gvdata.h"
+
+#define GV_TYPE_POLYLINES (gv_polylines_get_type ())
+#define GV_POLYLINES(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_POLYLINES, GvPolylines))
+#define GV_POLYLINES_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_POLYLINES, GvPolylinesClass))
+#define GV_IS_POLYLINES(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_POLYLINES))
+#define GV_IS_POLYLINES_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_POLYLINES))
+
+typedef struct _GvPolylines GvPolylines;
+typedef struct _GvPolylinesClass GvPolylinesClass;
+
+struct _GvPolylines
+{
+ GvData data;
+
+ GPtrArray *lines;
+ GvRect extents;
+ guint extents_valid : 1;
+};
+
+struct _GvPolylinesClass
+{
+ GvDataClass parent_class;
+};
+
+GtkType gv_polylines_get_type (void);
+
+GvData* gv_polylines_new(void);
+gint gv_polylines_new_line(GvPolylines *pline);
+gint gv_polylines_new_line_with_data(GvPolylines *pline, gint num_nodes, GvVertex *vertex);
+gint gv_polylines_num_nodes(GvPolylines *pline, gint line_id);
+
+void gv_polylines_delete_lines(GvPolylines *pline, gint num_lines, gint *line_id);
+void gv_polylines_translate_lines(GvPolylines *pline, gint num_lines, gint *line_id, gvgeocoord dx, gvgeocoord dy);
+void gv_polylines_set_nodes(GvPolylines *pline, gint line_id, gint num_nodes, GvVertex *vertex);
+void gv_polylines_append_nodes(GvPolylines *pline, gint line_id, gint num_nodex, GvVertex *vertex);
+void gv_polylines_insert_nodes(GvPolylines *pline, gint line_id, gint node_id, gint num_nodes, GvVertex *vertex);
+void gv_polylines_delete_nodes(GvPolylines *pline, gint line_id, gint num_nodes, gint *node_id);
+void gv_polylines_move_node(GvPolylines *pline, gint line_id, gint node_id, GvVertex *vertex);
+GvVertex* gv_polylines_get_node(GvPolylines *pline, gint line_id, gint node_id);
+void gv_polylines_get_extents(GvPolylines *pline, GvRect *rect);
+
+#define gv_polylines_num_lines(pline) \
+ (pline->lines->len)
+#define gv_polylines_get_line(pline,id) \
+ ((GArray*)g_ptr_array_index(pline->lines, id))
+
+#endif /*__GV_POLYLINES_H__ */
+
Added: packages/openev/branches/upstream/current/gvpquerylayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvpquerylayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvpquerylayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,232 @@
+/******************************************************************************
+ * $Id: gvpquerylayer.c,v 1.11 2004/08/20 13:53:47 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Point query layer.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpquerylayer.c,v $
+ * Revision 1.11 2004/08/20 13:53:47 warmerda
+ * allow GvShapes to be passed into constructor
+ *
+ * Revision 1.10 2003/08/27 19:58:43 warmerda
+ * added force_simple flag for gv_view_area_bmfont_draw
+ *
+ * Revision 1.9 2003/02/27 03:59:21 warmerda
+ * added view to gv_shapes_layer_get_draw_info
+ *
+ * Revision 1.8 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.7 2000/08/04 14:14:12 warmerda
+ * GvShapes shape ids now persistent
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvpquerylayer.h"
+#include "gvutils.h"
+#include <GL/gl.h>
+
+static void gv_pquery_layer_class_init(GvPqueryLayerClass *klass);
+static void gv_pquery_layer_init(GvPqueryLayer *layer);
+static void gv_pquery_layer_setup(GvLayer *layer, GvViewArea *view);
+static void gv_pquery_layer_draw(GvLayer *layer, GvViewArea *view);
+static void gv_pquery_layer_draw_selected(GvShapeLayer *layer,
+ GvViewArea *view);
+
+GtkType
+gv_pquery_layer_get_type(void)
+{
+ static GtkType pquery_layer_type = 0;
+
+ if (!pquery_layer_type)
+ {
+ static const GtkTypeInfo pquery_layer_info =
+ {
+ "GvPqueryLayer",
+ sizeof(GvPqueryLayer),
+ sizeof(GvPqueryLayerClass),
+ (GtkClassInitFunc) gv_pquery_layer_class_init,
+ (GtkObjectInitFunc) gv_pquery_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ pquery_layer_type = gtk_type_unique(gv_shapes_layer_get_type(),
+ &pquery_layer_info);
+ }
+ return pquery_layer_type;
+}
+
+static void
+gv_pquery_layer_class_init(GvPqueryLayerClass *klass)
+{
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ layer_class->setup = gv_pquery_layer_setup;
+ layer_class->draw = gv_pquery_layer_draw;
+ shape_layer_class->draw_selected = gv_pquery_layer_draw_selected;
+}
+
+static void
+gv_pquery_layer_init(GvPqueryLayer *layer)
+{
+ layer->font = 0;
+}
+
+GtkObject *
+gv_pquery_layer_new( GvShapes *data )
+{
+ GvPqueryLayer *layer = GV_PQUERY_LAYER(gtk_type_new(
+ gv_pquery_layer_get_type()));
+
+ if( data == NULL )
+ {
+ data = GV_SHAPES(gv_shapes_new());
+ gv_data_set_name( GV_DATA(data), "Query Points" );
+ }
+
+ gv_shapes_layer_set_data( GV_SHAPES_LAYER(layer), data );
+
+ return GTK_OBJECT(layer);
+}
+
+/*******************************************************/
+
+static void
+gv_pquery_layer_setup(GvLayer *rlayer, GvViewArea *view)
+{
+ GvPqueryLayer *layer = GV_PQUERY_LAYER(rlayer);
+
+ layer->font = gv_view_area_bmfont_load(view, "fixed");
+}
+
+static void gv_pquery_layer_draw_text(GvViewArea * view,
+ GvPqueryLayer *layer, GvShape *shape,
+ gvgeocoord dx, gvgeocoord dy )
+
+{
+ const char *text;
+ gvgeocoord x, y;
+
+ x = gv_shape_get_x( shape, 0, 0 );
+ y = gv_shape_get_y( shape, 0, 0 );
+
+ /* FIXME: the label should be cached in the point structure */
+ text = gv_format_point_query( view, gv_data_get_properties(GV_DATA(layer)),
+ x, y );
+
+ gv_view_area_bmfont_draw(view, layer->font, x+dx, y+dy,
+ (char *) text, 0);
+}
+
+static void
+gv_pquery_layer_draw(GvLayer *rlayer, GvViewArea *view)
+{
+ GvPqueryLayer *layer = GV_PQUERY_LAYER(rlayer);
+ gint i, points;
+ gint *selected, presentation;
+ gvgeocoord dx, dy;
+ gint hit_selected = FALSE;
+ GvShapeDrawInfo drawinfo;
+ GvShape *shape;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ gv_shapes_layer_get_draw_info( view, GV_SHAPES_LAYER(rlayer), &drawinfo );
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ /* Call the parent class draw func to make crosshairs */
+ (*((GvLayerClass*)gtk_type_class(GV_TYPE_SHAPES_LAYER))->draw)
+ (GV_LAYER(layer), view);
+
+ /* Get offset for text */
+ dx = dy = drawinfo.point_size;
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ glColor4fv(drawinfo.point_color);
+ for (i=0; i < points; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL )
+ gv_pquery_layer_draw_text( view, layer, shape, dx, dy );
+ }
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ gv_pquery_layer_draw_selected(GV_SHAPE_LAYER(layer), view);
+ }
+}
+
+static void
+gv_pquery_layer_draw_selected(GvShapeLayer *rlayer, GvViewArea *view)
+{
+ gint i, points;
+ gint *selected;
+ gvgeocoord dx, dy;
+ GvPqueryLayer *layer = GV_PQUERY_LAYER(rlayer);
+ GvShapeDrawInfo drawinfo;
+ GvShape *shape;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ gv_shapes_layer_get_draw_info( view, GV_SHAPES_LAYER(rlayer), &drawinfo );
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ /* Call the parent class draw func to make crosshairs */
+ (*((GvShapeLayerClass*)gtk_type_class(GV_TYPE_SHAPES_LAYER))->
+ draw_selected)(GV_SHAPE_LAYER(layer), view);
+
+ /* Get offset for text */
+ dx = dy = drawinfo.point_size;
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ glColor4fv(drawinfo.point_color);
+ for (i=0; i < points; ++i)
+ {
+ if (!selected[i])
+ {
+ continue;
+ }
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL )
+ gv_pquery_layer_draw_text( view, layer, shape, dx, dy );
+ }
+}
+
+
Added: packages/openev/branches/upstream/current/gvpquerylayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvpquerylayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvpquerylayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * $Id: gvpquerylayer.h,v 1.5 2004/08/20 13:53:48 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Point query layer.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvpquerylayer.h,v $
+ * Revision 1.5 2004/08/20 13:53:48 warmerda
+ * allow GvShapes to be passed into constructor
+ *
+ * Revision 1.4 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_PQUERY_LAYER_H__
+#define __GV_PQUERY_LAYER_H__
+
+#include "gvshapeslayer.h"
+
+#define GV_TYPE_PQUERY_LAYER (gv_pquery_layer_get_type ())
+#define GV_PQUERY_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_PQUERY_LAYER, GvPqueryLayer))
+#define GV_PQUERY_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_PQUERY_LAYER, GvPqueryLayerClass))
+#define GV_IS_PQUERY_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_PQUERY_LAYER))
+#define GV_IS_PQUERY_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_PQUERY_LAYER))
+
+typedef struct _GvPqueryLayer GvPqueryLayer;
+typedef struct _GvPqueryLayerClass GvPqueryLayerClass;
+
+struct _GvPqueryLayer
+{
+ GvShapesLayer layer;
+
+ gint font;
+};
+
+struct _GvPqueryLayerClass
+{
+ GvShapesLayerClass parent_class;
+};
+
+GtkType gv_pquery_layer_get_type(void);
+GtkObject* gv_pquery_layer_new( GvShapes * );
+
+#endif /* __GV_PQUERY_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvprint.c
===================================================================
--- packages/openev/branches/upstream/current/gvprint.c (rev 0)
+++ packages/openev/branches/upstream/current/gvprint.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,409 @@
+/******************************************************************************
+ * $Id: gvprint.c,v 1.8 2001/02/15 16:36:51 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvViewArea printing support.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvprint.c,v $
+ * Revision 1.8 2001/02/15 16:36:51 warmerda
+ * fixed serious bug with print_handler - now deinitialized when done
+ *
+ * Revision 1.7 2000/08/07 18:42:48 warmerda
+ * added windows printing stubs
+ *
+ * Revision 1.6 2000/08/03 18:20:41 warmerda
+ * implemented print scaling and paper sizes properly
+ *
+ * Revision 1.5 2000/07/20 03:21:26 warmerda
+ * added is_rgb for print_to_file()
+ *
+ * Revision 1.4 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvviewarea.h"
+#include "gdal.h"
+#include "cpl_conv.h"
+
+typedef struct
+{
+ gint width;
+ gint (*cb_func)(void *, const char *);
+ void *cb_data;
+ gint is_rgb; /* otherwise reduce to greyscale */
+ char *text_buf;
+} gvPostScriptOptions;
+
+static gint print_handler( void * cb_data, void * scanline_in )
+
+{
+ unsigned char *scanline = (unsigned char *) scanline_in;
+ static GDALDatasetH working_ds = NULL;
+ static int next_scanline = 0;
+ static GDALRasterBandH red_band, green_band, blue_band;
+ gint width;
+
+ if( cb_data == NULL && scanline_in == NULL )
+ {
+ next_scanline = 0;
+ working_ds = NULL;
+ return -1;
+ }
+
+ if( working_ds != cb_data )
+ {
+ working_ds = (GDALDatasetH) cb_data;
+ next_scanline = 0;
+
+ red_band = GDALGetRasterBand( working_ds, 1 );
+ if( GDALGetRasterCount( working_ds ) >= 3 )
+ {
+ green_band = GDALGetRasterBand( working_ds, 2 );
+ blue_band = GDALGetRasterBand( working_ds, 3 );
+ }
+ else
+ {
+ green_band = blue_band = NULL;
+ }
+
+ if( red_band == NULL )
+ return -1;
+ }
+
+ width = GDALGetRasterXSize( working_ds );
+
+ if( green_band == NULL )
+ {
+ GByte *grey;
+ int i, value;
+
+ grey = g_new( GByte, width );
+
+ for( i = 0; i < width; i++ )
+ {
+ value = *(scanline++);
+ value += *(scanline++);
+ value += *(scanline++);
+ value = (value+1) / 3;
+ grey[i] = value;
+ }
+
+ GDALRasterIO( red_band, GF_Write, 0, next_scanline, width, 1,
+ grey, width, 1, GDT_Byte, 1, 0 );
+ g_free( grey );
+ }
+ else
+ {
+ GDALRasterIO( red_band, GF_Write, 0, next_scanline, width, 1,
+ scanline+0, width, 1, GDT_Byte, 3, 0 );
+ GDALRasterIO( green_band, GF_Write, 0, next_scanline, width, 1,
+ scanline+1, width, 1, GDT_Byte, 3, 0 );
+ GDALRasterIO( blue_band, GF_Write, 0, next_scanline, width, 1,
+ scanline+2, width, 1, GDT_Byte, 3, 0 );
+ }
+
+ next_scanline++;
+
+ return 0;
+}
+
+gint
+gv_view_area_print_to_file(GvViewArea *view, int width, int height,
+ const char * filename, const char * format,
+ int is_rgb )
+
+{
+ GDALDriverH driver;
+ GDALDatasetH dataset;
+ gint errcode;
+
+ driver = GDALGetDriverByName( format );
+ if( driver == NULL )
+ return -1;
+
+ if( is_rgb )
+ dataset = GDALCreate( driver, filename, width, height, 3, GDT_Byte,
+ NULL );
+ else
+ dataset = GDALCreate( driver, filename, width, height, 1, GDT_Byte,
+ NULL );
+
+ if( dataset == NULL )
+ return -1;
+
+ errcode = gv_view_area_render_to_func( view, width, height,
+ print_handler, dataset );
+ GDALClose( dataset );
+
+ print_handler( NULL, NULL );
+
+ return errcode;
+}
+
+static gint postscript_handler( void * cb_data, void * scanline_in )
+
+{
+ unsigned char *scanline = (unsigned char *) scanline_in;
+ gvPostScriptOptions *options = (gvPostScriptOptions *) cb_data;
+ int i;
+
+ if( options->is_rgb )
+ {
+ for( i = 0; i < options->width; i++ )
+ sprintf( options->text_buf + i*2, "%02x",
+ scanline[i*3] );
+
+ for( i = 0; i < options->width; i++ )
+ sprintf( options->text_buf + i*2 + options->width*2, "%02x",
+ scanline[i*3+1] );
+
+ for( i = 0; i < options->width; i++ )
+ sprintf( options->text_buf + i*2 + options->width*4, "%02x",
+ scanline[i*3+2] );
+
+ options->text_buf[options->width*6] = '\0';
+ }
+ else
+ {
+ for( i = 0; i < options->width; i++ )
+ {
+ int value;
+
+ value = *(scanline++);
+ value += *(scanline++);
+ value += *(scanline++);
+ value = (value+1) / 3;
+
+ sprintf( options->text_buf + i*2, "%02x", value );
+ }
+ options->text_buf[options->width*2] = '\0';
+ }
+
+ strcat( options->text_buf, "\n" );
+
+
+
+ return options->cb_func( options->cb_data, options->text_buf );
+}
+
+gint
+gv_view_area_render_postscript(GvViewArea *view, int width, int height,
+ float ulx, float uly, float lrx, float lry,
+ int is_rgb,
+ gint (*cb_func)(void *, const char *),
+ void * cb_data )
+
+{
+ gvPostScriptOptions options;
+ int errcode;
+ char line[128];
+
+ /* write prolog */
+
+ cb_func( cb_data, "%!PS-Adobe-3.0 EPSF-3.0\n" );
+ cb_func( cb_data, "%%Creator: gview\n" );
+ cb_func( cb_data, "%%Title: gview_print\n" );
+ cb_func( cb_data, "%%CreationDate: Thu Apr 6 20:11:10 2000\n" );
+ cb_func( cb_data, "%%DocumentData: Clean7Bit\n" );
+ cb_func( cb_data, "%%Origin: 0 0\n" );
+#ifdef notdef
+ sprintf( line, "%%%%BoundingBox: 0 0 %d %d\n", width, height );
+ cb_func( cb_data, line );
+#endif
+ cb_func( cb_data, "%%LanguageLevel: 1\n" );
+ cb_func( cb_data, "%%Pages: 1\n" );
+ cb_func( cb_data, "%%EndComments\n" );
+ cb_func( cb_data, "%%BeginSetup\n" );
+ cb_func( cb_data, "%%EndSetup\n" );
+ cb_func( cb_data, "%%Page: 1 1\n" );
+ cb_func( cb_data, "gsave\n" );
+ cb_func( cb_data, "100 dict begin\n" );
+
+ sprintf( line, "%f %f translate\n", ulx*72.0, uly*72.0 );
+ cb_func( cb_data, line );
+
+ sprintf( line, "%f %f scale\n", (lrx - ulx)*72.0, (lry - uly)*72.0 );
+ cb_func( cb_data, line );
+
+ if( is_rgb )
+ {
+ sprintf( line,
+ "%%ImageData: %d %d 8 3 0 %d 2 \"true 3 colorimage\"\n",
+ width, height, width );
+ cb_func( cb_data, line );
+
+ sprintf( line, "/line0 %d string def\n", width );
+ cb_func( cb_data, line );
+
+ sprintf( line, "/line1 %d string def\n", width );
+ cb_func( cb_data, line );
+
+ sprintf( line, "/line2 %d string def\n", width );
+ cb_func( cb_data, line );
+ }
+ else
+ {
+ sprintf( line,
+ "%%ImageData: %d %d 8 1 0 %d 2 \"image\"\n",
+ width, height, width );
+ cb_func( cb_data, line );
+
+ sprintf( line, "/scanLine %d string def\n", width );
+ cb_func( cb_data, line );
+ }
+
+
+ sprintf( line, "%d %d 8\n", width, height );
+ cb_func( cb_data, line );
+
+ sprintf( line, "[%d 0 0 %d 0 %d]\n", width, -height, height );
+ cb_func( cb_data, line );
+
+ if( is_rgb )
+ {
+ cb_func( cb_data, "{currentfile line0 readhexstring pop}bind\n" );
+ cb_func( cb_data, "{currentfile line1 readhexstring pop}bind\n" );
+ cb_func( cb_data, "{currentfile line2 readhexstring pop}bind\n" );
+ cb_func( cb_data, "true 3 colorimage\n" );
+ }
+ else
+ {
+ cb_func( cb_data, "{currentfile scanLine readhexstring pop}bind\n" );
+ cb_func( cb_data, "image\n" );
+ }
+
+ /* now prepare and write image data */
+ options.cb_func = cb_func;
+ options.cb_data = cb_data;
+ options.width = width;
+ options.is_rgb = is_rgb;
+ options.text_buf = g_malloc(width * 6 + 3);
+ if( options.text_buf == NULL )
+ return -1;
+
+ errcode = gv_view_area_render_to_func( view, width, height,
+ postscript_handler, &options );
+
+ g_free( options.text_buf );
+
+ /* write postlog */
+
+ if( errcode == 0 )
+ {
+ cb_func( cb_data, "end\n" );
+ cb_func( cb_data, "grestore\n" );
+ cb_func( cb_data, "showpage\n" );
+ cb_func( cb_data, "%%Trailer\n" );
+ cb_func( cb_data, "%%Pages: 1\n" );
+ cb_func( cb_data, "%%EOF\n" );
+ }
+
+ return errcode;
+}
+
+static gint
+postscript_to_file_handler( void *cb_data, const char * text )
+
+{
+ FILE *fp = (FILE *) cb_data;
+
+ if( fputs(text, fp) < 0 )
+ return -1;
+ else
+ return 0;
+}
+
+#ifndef _WIN32
+static gint
+gv_view_area_print_postscript_to_pipe(GvViewArea *view,
+ int width, int height,
+ float ulx, float uly,
+ float lrx, float lry,
+ int is_rgb, const char * filename )
+
+{
+ FILE *fp;
+ int errcode;
+
+ fp = popen( filename, "w" );
+ if( fp == NULL )
+ return -1;
+
+ errcode =
+ gv_view_area_render_postscript(view, width, height, ulx, uly, lrx, lry,
+ is_rgb,postscript_to_file_handler, fp );
+
+ pclose(fp);
+
+ return errcode;
+}
+#endif
+
+gint
+gv_view_area_print_postscript_to_file(GvViewArea *view,
+ int width, int height,
+ float ulx, float uly,
+ float lrx, float lry,
+ int is_rgb,
+ const char * filename )
+
+{
+ FILE *fp;
+ int errcode;
+
+#ifndef _WIN32
+ if(filename[0] == '|')
+ return gv_view_area_print_postscript_to_pipe(view, width, height,
+ ulx, uly, lrx, lry,
+ is_rgb, filename+1 );
+#endif
+
+ fp = fopen( filename, "wt" );
+ if( fp == NULL )
+ return -1;
+
+ errcode =
+ gv_view_area_render_postscript(view, width, height, ulx, uly, lrx, lry,
+ is_rgb,postscript_to_file_handler, fp );
+
+ fclose(fp);
+
+ return errcode;
+}
+
+#ifndef WIN32
+void gv_view_area_page_setup()
+{
+}
+
+gint
+gv_view_area_print_to_windriver(GvViewArea *view, int width, int height,
+ float ulx, float uly, float lrx, float lry,
+ int is_rgb )
+
+{
+ return 1;
+}
+#endif
+
Added: packages/openev/branches/upstream/current/gvproperties.c
===================================================================
--- packages/openev/branches/upstream/current/gvproperties.c (rev 0)
+++ packages/openev/branches/upstream/current/gvproperties.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,490 @@
+/******************************************************************************
+ * $Id: gvproperties.c,v 1.5 2002/09/09 16:22:45 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Generic string properties list.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvproperties.c,v $
+ * Revision 1.5 2002/09/09 16:22:45 warmerda
+ * use int instead of gint to avoid glib.h dependency
+ *
+ * Revision 1.4 2002/07/24 18:06:26 warmerda
+ * reimplement properties using quarks
+ *
+ * Revision 1.3 2000/09/21 02:55:11 warmerda
+ * added gv_properties_clear
+ *
+ * Revision 1.2 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvtypes.h"
+#include "cpl_port.h"
+#include "gvproperties.h"
+
+/************************************************************************/
+/* ==================================================================== */
+/* GvProperties */
+/* */
+/* Hash table based implementation. */
+/* */
+/* Each GvProperties is a guint32 pointer. If it is NULL there */
+/* are no properties otherwise it points to an array of */
+/* integers: */
+/* */
+/* [0] = Max allocated name/values possible. */
+/* [1] = Number of name/value property settings. */
+/* [2] = key id of first property name. */
+/* [3] = quark id of first property values. */
+/* ... */
+/* */
+/* The property names are kept in a custom case insensitive */
+/* symbol table and hash table. The property values (which */
+/* must be case sensitive) are implemented using normal GLib */
+/* quarks. */
+/* ==================================================================== */
+/************************************************************************/
+
+#ifdef USE_HASH_BASED_GVPROPERTIES
+
+#include <glib.h>
+
+#define G_QUARK_BLOCK_SIZE (512)
+
+static GHashTable *gvpk_keyid_ht = NULL;
+static gchar **gvpk_keyids = NULL;
+static GQuark gvpk_keyid_seq_id = 0;
+
+#define PROP_KEYID(properties,i) ((*properties)[i*2+2])
+#define PROP_VALUEID(properties,i) ((*properties)[i*2+3])
+#define PROP_COUNT(properties) ((*properties)[1])
+#define PROP_MAXCOUNT(properties) ((*properties)[0])
+
+/************************************************************************/
+/* gvpk_str_equal() */
+/* */
+/* Case insensitive string compare. Used for the property */
+/* names hash table. */
+/************************************************************************/
+
+static gint gvpk_str_equal (gconstpointer v1, gconstpointer v2)
+
+{
+ const gchar *string1 = v1;
+ const gchar *string2 = v2;
+
+ return EQUAL(string1, string2);
+}
+
+/************************************************************************/
+/* gvpk_str_hash() */
+/* */
+/* 31bit hash (like g_str_hash()) except that it is case */
+/* insensitive. All upper case letters are implicitly treated */
+/* as lower case. */
+/************************************************************************/
+
+static guint gvpk_str_hash (gconstpointer key)
+{
+ const char *p = key;
+ guint h = 0, v;
+
+ for (; *p != '\0'; p++)
+ {
+ v = tolower(*p);
+ h = (h << 5) - h + v;
+ }
+
+ return h;
+}
+
+/************************************************************************/
+/* gvpk_keyid_from_string() */
+/************************************************************************/
+
+guint32 gvpk_keyid_from_string( const char *string )
+
+{
+ guint32 keyid;
+
+ if (gvpk_keyid_ht)
+ keyid = (guint32) g_hash_table_lookup (gvpk_keyid_ht, string);
+ else
+ {
+ gvpk_keyid_ht = g_hash_table_new (gvpk_str_hash, gvpk_str_equal);
+ keyid = 0;
+ }
+
+ /* Does key does exist yet? */
+ if (!keyid)
+ {
+ /* grow key id table if full */
+ if (gvpk_keyid_seq_id % G_QUARK_BLOCK_SIZE == 0)
+ gvpk_keyids = g_renew (gchar*, gvpk_keyids,
+ gvpk_keyid_seq_id + G_QUARK_BLOCK_SIZE);
+
+ /* add keyid to key id table */
+ gvpk_keyids[gvpk_keyid_seq_id] = g_strdup(string);
+ gvpk_keyid_seq_id++;
+
+ /* Add key to hash table */
+ keyid = gvpk_keyid_seq_id;
+ g_hash_table_insert (gvpk_keyid_ht, gvpk_keyids[keyid-1],
+ GUINT_TO_POINTER (keyid));
+ }
+
+ return keyid;
+}
+
+
+/************************************************************************/
+/* gv_properties_set() */
+/* */
+/* Set a single name/value property set in the list. */
+/************************************************************************/
+
+void gv_properties_set( GvProperties *properties,
+ const char * name, const char * value )
+
+{
+ guint keyid = gvpk_keyid_from_string( name );
+ GQuark valueq = g_quark_from_string( value );
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Initial allocation of properties. */
+/* -------------------------------------------------------------------- */
+ if( *properties == NULL )
+ {
+ *properties = g_new( guint32, 8 );
+ PROP_MAXCOUNT(properties) = 3;
+ PROP_COUNT(properties) = 0;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Does the key already exist in the properties list? If so, */
+/* just reset the value. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < PROP_COUNT(properties); i++ )
+ {
+ if( PROP_KEYID(properties,i) == keyid )
+ {
+ PROP_VALUEID(properties,i) = (guint32) valueq;
+ return;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* We need to add the name/value pair to the list. Does the */
+/* allocation of the list need to be grown? */
+/* -------------------------------------------------------------------- */
+ if( PROP_MAXCOUNT(properties) == PROP_COUNT(properties) )
+ {
+ int new_max = PROP_MAXCOUNT(properties) * 2;
+
+ *properties = g_renew( guint32, *properties, new_max * 2 + 2 );
+ PROP_MAXCOUNT(properties) = new_max;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add the new name/value pair. */
+/* -------------------------------------------------------------------- */
+ i = PROP_COUNT(properties);
+
+ PROP_COUNT(properties)++;
+
+ PROP_KEYID(properties,i) = keyid;
+ PROP_VALUEID(properties,i) = (guint32) valueq;
+}
+
+/************************************************************************/
+/* gv_properties_get() */
+/* */
+/* Fetch a single property or return NULL on failure. */
+/************************************************************************/
+
+const char * gv_properties_get( GvProperties *properties, const char * name )
+
+{
+ guint32 keyid = gvpk_keyid_from_string( name );
+ int i;
+
+ if( *properties == NULL )
+ return NULL;
+
+ for( i = 0; i < PROP_COUNT(properties); i++ )
+ {
+ if( PROP_KEYID(properties,i) == keyid )
+ return g_quark_to_string( (GQuark) PROP_VALUEID(properties,i) );
+ }
+
+ return NULL;
+}
+
+/************************************************************************/
+/* gv_properties_count() */
+/* */
+/* Return the number of name/value properties in this list. */
+/************************************************************************/
+
+int gv_properties_count( GvProperties *properties )
+
+{
+ if( *properties == NULL )
+ return 0;
+ else
+ return PROP_COUNT(properties);
+}
+
+/************************************************************************/
+/* gv_properties_get_name_by_index() */
+/* */
+/* Fetch the propert name of the 'nth' entry in the property list. */
+/************************************************************************/
+
+const char * gv_properties_get_name_by_index( GvProperties * properties,
+ int prop_index )
+
+{
+ guint32 keyid;
+
+ if( *properties == NULL )
+ return NULL;
+
+ if( prop_index < 0 || prop_index >= PROP_COUNT(properties) )
+ return NULL;
+
+ keyid = PROP_KEYID(properties,prop_index);
+
+ g_assert( keyid >= 1 && keyid <= gvpk_keyid_seq_id );
+
+ return gvpk_keyids[keyid-1];
+}
+
+/************************************************************************/
+/* gv_properties_get_value_by_index() */
+/* */
+/* Fetch the value of the 'nth' entry in the property list. */
+/************************************************************************/
+
+const char * gv_properties_get_value_by_index( GvProperties * properties,
+ int prop_index )
+
+{
+ GQuark value_id;
+
+ if( *properties == NULL )
+ return NULL;
+
+ if( prop_index < 0 || prop_index >= PROP_COUNT(properties) )
+ return NULL;
+
+ value_id = (GQuark) PROP_VALUEID(properties,prop_index);
+
+ return g_quark_to_string( value_id );
+}
+
+/************************************************************************/
+/* g_properties_remove() */
+/* */
+/* Remove the indicated property, if is it present. */
+/************************************************************************/
+
+void gv_properties_remove( GvProperties *properties, const char * key )
+
+{
+ guint32 keyid = gvpk_keyid_from_string( key );
+ int i;
+
+ if( *properties == NULL )
+ return;
+
+ for( i = 0; i < PROP_COUNT(properties); i++ )
+ {
+ if( PROP_KEYID(properties,i) == keyid )
+ {
+ int last_prop = PROP_COUNT(properties)-1;
+
+ PROP_KEYID(properties,i) = PROP_KEYID(properties,last_prop);
+ PROP_VALUEID(properties,i) = PROP_VALUEID(properties,last_prop);
+ PROP_COUNT(properties)--;
+ return;
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_properties_init() */
+/* */
+/* Initialize a GvProperties value. */
+/************************************************************************/
+
+void gv_properties_init( GvProperties *properties )
+
+{
+ *properties = NULL;
+}
+
+/************************************************************************/
+/* gv_properties_destroy() */
+/* */
+/* Wipe whole properties list, recovering all allocation. */
+/************************************************************************/
+void gv_properties_destroy( GvProperties *properties )
+
+{
+ if( *properties != NULL )
+ {
+ g_free( *properties );
+ *properties = NULL;
+ }
+}
+
+/************************************************************************/
+/* gv_properties_clear() */
+/* */
+/* Wipe all properties. */
+/************************************************************************/
+
+void gv_properties_clear( GvProperties *properties )
+
+{
+ gv_properties_destroy( properties );
+}
+
+/************************************************************************/
+/* gv_properties_copy() */
+/* */
+/* Make an efficient copy of a properties list. It is assumed */
+/* that the target GvProperties has not even been initialized. */
+/************************************************************************/
+
+void gv_properties_copy( GvProperties *source, GvProperties *target )
+
+{
+ if( *source == NULL )
+ {
+ *target = NULL;
+ return;
+ }
+
+ *target = g_new( guint32, PROP_COUNT(source) * 2 + 2 );
+ memcpy( *target, *source, sizeof(guint32) * (PROP_COUNT(source)*2 + 2));
+ PROP_MAXCOUNT(target) = PROP_COUNT(target);
+}
+
+#endif /* notdef USE_QUARK_BASED_GVPROPERTIES */
+
+/************************************************************************/
+/* ==================================================================== */
+/* GvProperties */
+/* */
+/* CPL StringList based implementation. */
+/* ==================================================================== */
+/************************************************************************/
+
+#ifndef USE_HASH_BASED_GVPROPERTIES
+#include "cpl_string.h"
+
+void gv_properties_set( GvProperties *properties,
+ const char * name, const char * value )
+
+{
+ *properties = CSLSetNameValue( *properties, name, value );
+}
+
+const char * gv_properties_get( GvProperties *properties, const char * name )
+
+{
+ return CSLFetchNameValue( *properties, name );
+}
+
+int gv_properties_count( GvProperties *properties )
+
+{
+ return CSLCount( *properties );
+}
+
+const char * gv_properties_get_name_by_index( GvProperties * properties,
+ int prop_index )
+
+{
+ static char *last_property = NULL;
+
+ if( last_property != NULL )
+ CPLFree( last_property );
+
+ last_property = NULL;
+ CPLParseNameValue( (*properties)[prop_index], &last_property );
+
+ return last_property;
+}
+
+const char * gv_properties_get_value_by_index( GvProperties * properties,
+ int prop_index )
+
+{
+ return CPLParseNameValue( (*properties)[prop_index], NULL );
+}
+
+void gv_properties_remove( GvProperties *properties, const char * key )
+
+{
+ int prop_index = CSLFindString( *properties, key );
+ char **targets;
+
+ if( prop_index >= 0 )
+ {
+ *properties = CSLRemoveStrings( *properties, prop_index, 1,
+ &targets );
+ CSLDestroy( targets );
+ }
+}
+
+void gv_properties_init( GvProperties *properties )
+
+{
+ *properties = NULL;
+}
+
+void gv_properties_destroy( GvProperties *properties )
+
+{
+ CSLDestroy( *properties );
+ *properties = NULL;
+}
+
+void gv_properties_clear( GvProperties *properties )
+
+{
+ gv_properties_destroy( properties );
+}
+
+void gv_properties_copy( GvProperties *source, GvProperties *target )
+
+{
+ *target = CSLDuplicate( *source );
+}
+#endif /* notdef USE_HASH_BASED_GVPROPERTIES */
+
Added: packages/openev/branches/upstream/current/gvproperties.h
===================================================================
--- packages/openev/branches/upstream/current/gvproperties.h (rev 0)
+++ packages/openev/branches/upstream/current/gvproperties.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,68 @@
+/******************************************************************************
+ * $Id: gvproperties.h,v 1.6 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Generic string properties list.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvproperties.h,v $
+ * Revision 1.6 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.5 2002/09/09 16:22:45 warmerda
+ * use int instead of gint to avoid glib.h dependency
+ *
+ * Revision 1.4 2002/07/24 18:06:26 warmerda
+ * reimplement properties using quarks
+ *
+ * Revision 1.3 2000/09/21 02:55:11 warmerda
+ * added gv_properties_clear
+ *
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_PROPERTIES_H__
+#define __GV_PROPERTIES_H__
+
+#define USE_HASH_BASED_GVPROPERTIES
+
+#ifdef USE_HASH_BASED_GVPROPERTIES
+#include <glib.h>
+ typedef guint32 *GvProperties;
+#else
+ typedef char **GvProperties;
+#endif
+
+void gv_properties_set( GvProperties *, const char *name, const char *value);
+const char * gv_properties_get( GvProperties *, const char *name );
+int gv_properties_count( GvProperties * );
+const char *gv_properties_get_name_by_index( GvProperties *, int );
+const char *gv_properties_get_value_by_index( GvProperties *, int );
+void gv_properties_remove( GvProperties *, const char * );
+void gv_properties_init( GvProperties * );
+void gv_properties_copy( GvProperties *source, GvProperties *target );
+void gv_properties_destroy( GvProperties * );
+void gv_properties_clear( GvProperties * );
+
+#endif /*__GV_PROPERTIES_H__ */
Added: packages/openev/branches/upstream/current/gvraster.c
===================================================================
--- packages/openev/branches/upstream/current/gvraster.c (rev 0)
+++ packages/openev/branches/upstream/current/gvraster.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2605 @@
+/******************************************************************************
+ * $Id: gvraster.c,v 1.75 2004/09/20 13:15:35 pgs Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster data container.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvraster.c,v $
+ * Revision 1.75 2004/09/20 13:15:35 pgs
+ * added patch for isnan on win32
+ *
+ * Revision 1.74 2004/09/07 15:21:34 gmwalter
+ * Check for nan's as well as nodata
+ * when calculating scaling min/max
+ * values.
+ *
+ * Revision 1.73 2004/07/03 07:39:11 andrey_kiselev
+ * Grab double floats from the GDAL in gv_raster_get_sample().
+ *
+ * Revision 1.72 2004/01/22 19:57:10 andrey_kiselev
+ * Use gv_raster_get_nodata() function to fetch the NODATA value from the image
+ * using GDALGetRasterNoDataValue().
+ *
+ * Revision 1.71 2003/11/06 14:26:24 gmwalter
+ * Avoid mismatch between tiles being downsampled from higher-resolution
+ * tiles and tiles being loaded for the first time at lower resolution
+ * when overview downsampling method does not match openev's.
+ *
+ * Revision 1.70 2003/09/11 20:00:29 gmwalter
+ * Add ability to specify a preferred polynomial order for warping a raster,
+ * and add "safe mode" (only used if ATLANTIS_BUILD is defined).
+ *
+ * Revision 1.69 2003/06/25 14:45:07 gmwalter
+ * Fixed a bug in gv_georef_to_pixel in geotransform case (was ignoring
+ * rotational terms).
+ *
+ * Revision 1.68 2003/03/02 04:43:58 warmerda
+ * CInt32 and CFloat64 are complex too!
+ *
+ * Revision 1.67 2003/02/20 19:27:15 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.66 2003/02/07 20:06:50 andrey_kiselev
+ * Memory leaks fixed.
+ *
+ * Revision 1.65 2002/10/29 22:28:26 warmerda
+ * fill out tile in reads that are not full resolution
+ *
+ * Revision 1.64 2002/10/29 05:44:05 warmerda
+ * always flood image values to right edge and bottom of tile on load
+ *
+ * Revision 1.63 2002/10/08 22:56:18 warmerda
+ * Modified gv_raster_build_poly_transform() to back off using the highest
+ * possible order polynomial if the CRS_compute_georef_equations() call fails.
+ * This ensures that underdetermined sets of GCPs (ie. those with linear
+ * dependencies) can still produce useful polynomials, even if they are only
+ * 1st order.
+ *
+ * Revision 1.62 2002/02/15 22:10:09 warmerda
+ * ensure that setting zero gcps clear the poly transform
+ *
+ * Revision 1.61 2001/11/29 15:53:42 warmerda
+ * added autoscale_samples preference
+ *
+ * Revision 1.60 2001/11/28 19:18:29 warmerda
+ * Added set_gcps(), and get_gcps() methods on GvRaster, and the
+ * geotransform-changed signal generated when the gcps change.
+ *
+ * Revision 1.59 2001/10/17 16:22:38 warmerda
+ * added unhandled raster type check
+ *
+ * Revision 1.58 2001/10/16 18:50:06 warmerda
+ * now possible to pass sample set into autoscale
+ *
+ * Revision 1.57 2001/08/22 02:34:52 warmerda
+ * fixed failure to sort samples in some cases for autoscale
+ *
+ * Revision 1.56 2001/08/15 13:05:57 warmerda
+ * modified default autoscale std_dev to 2.5
+ *
+ * Revision 1.55 2001/08/14 17:03:24 warmerda
+ * added standard deviation autoscaling support
+ *
+ * Revision 1.54 2001/07/24 02:21:54 warmerda
+ * added 8bit phase averaging
+ *
+ * Revision 1.53 2001/07/13 22:15:36 warmerda
+ * added nodata aware averaging
+ *
+ * Revision 1.52 2001/04/02 18:10:46 warmerda
+ * expose gv_raster_autoscale() to python
+ *
+ * Revision 1.51 2001/01/08 17:47:23 warmerda
+ * fixed additional window edge conditions in gv_raster_tile_get_gdal
+ *
+ * Revision 1.50 2000/11/28 02:49:51 warmerda
+ * fixed edge handling bugs with rasters smaller than one tile
+ *
+ * Revision 1.49 2000/11/01 03:47:45 warmerda
+ * Fixed serious bug with memory corruption that is mostly likely to occur
+ * with large images. See Bug 120968 on SourceForge.
+ *
+ * Revision 1.48 2000/09/27 19:18:50 warmerda
+ * Honour GvSMSample for real and complex images.
+ * Add GvRaster.sm field. If set to GvSMSample always let GDAL do the
+ * decimation for faster loads.
+ *
+ * Revision 1.47 2000/08/25 20:06:34 warmerda
+ * Added support for GDAL bands with arbitrary overviews (ie. OGDI)
+ * Avoid having scaling min and max the same.
+ *
+ * Revision 1.46 2000/08/24 03:37:52 warmerda
+ * added PIXEL as a coordinate system
+ *
+ * Revision 1.45 2000/08/16 14:08:23 warmerda
+ * report data name, not file name
+ *
+ * Revision 1.44 2000/08/09 17:37:13 warmerda
+ * debug on finalize
+ *
+ * Revision 1.43 2000/08/02 19:17:30 warmerda
+ * added debug statement
+ *
+ * Revision 1.42 2000/07/27 20:33:12 warmerda
+ * set max lod to 7 instead of 4 for 4x4 textures
+ *
+ * Revision 1.41 2000/07/18 14:53:54 warmerda
+ * go directly to gdal in sample call, if full res raster not available
+ *
+ * Revision 1.40 2000/07/12 19:26:32 warmerda
+ * try to avoid using gcps if geotransform is set
+ *
+ * Revision 1.39 2000/07/10 14:27:53 warmerda
+ * use GRASS derived CRS code instead of Numerical Recipes gvgcpfit code
+ *
+ * Revision 1.38 2000/06/27 15:46:47 warmerda
+ * added gv_closest_gdal_lod to make optimal use of overviews
+ *
+ * Revision 1.37 2000/06/26 15:12:33 warmerda
+ * set name automatically
+ *
+ * Revision 1.36 2000/06/20 15:26:21 warmerda
+ * fixed more free/g_free problems
+ *
+ * Revision 1.35 2000/06/20 14:37:26 warmerda
+ * fixed free/g_free() problem
+ *
+ * Revision 1.34 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+
+
+#include <stdlib.h>
+#include <assert.h>
+#include "gvraster.h"
+#include "gvrastertypes.h"
+#include "gvrasteraverage.h"
+#include "gvmanager.h"
+#include "cpl_conv.h"
+
+#ifdef WIN32
+#include <float.h> /* for isnan */
+#define isnan _isnan
+#endif
+
+#define USE_CRS
+#ifdef USE_CRS
+# include "crs.h"
+#else
+# include "gvgcpfit.h"
+#endif
+
+enum
+{
+ GEOTRANSFORM_CHANGED,
+ LAST_SIGNAL
+};
+
+typedef struct _GvRasterMemento
+{
+ GvDataMemento base;
+
+ int x_off;
+ int y_off;
+ int width;
+ int height;
+
+ void *data;
+} GvRasterMemento;
+
+static void gv_raster_class_init(GvRasterClass *klass);
+static void gv_raster_init(GvRaster *raster);
+static void gv_raster_finalize(GtkObject *object);
+static gint gv_raster_build_poly_transform( GvRaster *raster );
+static gint gv_raster_build_poly_transformCL( GvRaster *raster, int poly_order );
+static void gv_raster_get_memento(GvData *raster, gpointer info,
+ GvDataMemento **memento);
+static void gv_raster_set_memento(GvData *raster, GvDataMemento *memento);
+static void gv_raster_del_memento(GvData *raster, GvDataMemento *memento);
+
+static int gv_raster_check_poly_order( GvRaster *raster, int poly_order );
+
+static guint raster_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_raster_get_type(void)
+{
+ static GtkType raster_type = 0;
+
+ if (!raster_type)
+ {
+ static const GtkTypeInfo raster_info =
+ {
+ "GvRaster",
+ sizeof(GvRaster),
+ sizeof(GvRasterClass),
+ (GtkClassInitFunc) gv_raster_class_init,
+ (GtkObjectInitFunc) gv_raster_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ raster_type = gtk_type_unique(gv_data_get_type(), &raster_info);
+ }
+ return raster_type;
+}
+
+static void
+gv_raster_init(GvRaster *raster)
+{
+ raster->poly_order = -1;
+ raster->poly_pixel_coeff = NULL;
+ raster->poly_line_coeff = NULL;
+ raster->poly_x_coeff = NULL;
+ raster->poly_y_coeff = NULL;
+ raster->poly_z_coeff = NULL;
+
+ raster->gcp_count = 0;
+ raster->gcp_list = NULL;
+
+ raster->geotransform[0] = 0.0;
+ raster->geotransform[1] = 1.0;
+ raster->geotransform[2] = 0.0;
+ raster->geotransform[3] = 0.0;
+ raster->geotransform[4] = 0.0;
+ raster->geotransform[5] = 1.0;
+
+ /* Linking/cursor specific transform (special case- default off) */
+ raster->poly_orderCL = -1;
+ raster->poly_pixel_coeffCL = NULL;
+ raster->poly_line_coeffCL = NULL;
+ raster->poly_x_coeffCL = NULL;
+ raster->poly_y_coeffCL = NULL;
+ raster->poly_z_coeffCL = NULL;
+ raster->gcp_countCL = 0;
+ raster->gcp_listCL = NULL;
+
+}
+
+static void
+gv_raster_class_init(GvRasterClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ raster_signals[GEOTRANSFORM_CHANGED] =
+ gtk_signal_new ("geotransform-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET(GvRasterClass,
+ geotransform_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals(object_class, raster_signals,
+ LAST_SIGNAL);
+
+ object_class->finalize = gv_raster_finalize;
+
+ data_class = (GvDataClass *) klass;
+ data_class->get_memento = gv_raster_get_memento;
+ data_class->set_memento = gv_raster_set_memento;
+ data_class->del_memento = gv_raster_del_memento;
+
+}
+
+static void
+gv_raster_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvRaster *raster = GV_RASTER(object);
+
+ CPLDebug( "OpenEV", "gv_raster_finalize(%s)\n",
+ gv_data_get_name(GV_DATA(object)) );
+
+ if( raster->cache != NULL )
+ gv_raster_cache_free( raster->cache );
+
+ if( GDALDereferenceDataset( raster->dataset ) < 1 )
+ GDALClose( raster->dataset );
+
+ if( raster->poly_order > -1 )
+ {
+ g_free( raster->poly_pixel_coeff );
+ g_free( raster->poly_line_coeff );
+ g_free( raster->poly_x_coeff );
+ g_free( raster->poly_y_coeff );
+ g_free( raster->poly_z_coeff );
+ }
+
+ if( raster->poly_orderCL > -1 )
+ {
+ g_free( raster->poly_pixel_coeffCL );
+ g_free( raster->poly_line_coeffCL );
+ g_free( raster->poly_x_coeffCL );
+ g_free( raster->poly_y_coeffCL );
+ g_free( raster->poly_z_coeffCL );
+ }
+
+ if( raster->gcp_count > 0 )
+ {
+ GDALDeinitGCPs( raster->gcp_count, raster->gcp_list );
+ CPLFree( raster->gcp_list );
+ }
+
+ if( raster->gcp_countCL > 0 )
+ {
+ GDALDeinitGCPs( raster->gcp_countCL, raster->gcp_listCL );
+ CPLFree( raster->gcp_listCL );
+ }
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+
+static void gv_raster_changed( GvRaster *raster,
+ void * raw_change_info )
+
+{
+ GvRasterChangeInfo *change_info = (GvRasterChangeInfo *) raw_change_info;
+
+ if( change_info != NULL )
+ gv_raster_flush_cache( raster,
+ change_info->x_off, change_info->y_off,
+ change_info->width, change_info->height );
+ else
+ gv_raster_flush_cache( raster, 0, 0, -1, -1 );
+}
+
+GvData *
+gv_raster_new( GDALDatasetH dataset, int real_band,
+ GvSampleMethod sm )
+{
+ char *name;
+ GvRaster *raster = GV_RASTER(gtk_type_new(gv_raster_get_type()));
+
+ gtk_signal_connect( GTK_OBJECT(raster), "changed",
+ gv_raster_changed, NULL );
+
+ raster->dataset = dataset;
+ GDALReferenceDataset( dataset );
+
+ raster->gdal_band = GDALGetRasterBand(dataset,real_band);
+
+ raster->sm = sm;
+
+ /* set the name */
+ name = (char *) g_malloc(strlen(GDALGetDescription(dataset))+8);
+ sprintf( name, "%s:%d", GDALGetDescription(dataset), real_band );
+ gv_data_set_name( GV_DATA(raster), name );
+ g_free( name );
+
+ switch( GDALGetRasterDataType(raster->gdal_band) )
+ {
+ case GDT_Byte:
+ if( sm == GvSMAverage )
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_byte_real_average;
+ else if( sm == GvSMAverage8bitPhase )
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_byte_realphase_average;
+ else
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_byte_real_sample;
+ raster->type = GV_RASTER_BYTE_REAL;
+ raster->gdal_type = GDT_Byte;
+ break;
+
+ case GDT_CInt16:
+ case GDT_CInt32:
+ case GDT_CFloat32:
+ case GDT_CFloat64:
+ if( sm == GvSMAverage )
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_float_complex_average;
+ else
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_float_complex_sample;
+ raster->type = GV_RASTER_FLOAT_COMPLEX;
+ raster->gdal_type = GDT_CFloat32;
+ break;
+
+ default:
+ if( sm == GvSMAverage && gv_raster_get_nodata( raster, NULL ) )
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_float_real_average_nodata;
+ else if( sm == GvSMAverage )
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_float_real_average;
+ else
+ raster->average = (void *(*)(GvRaster*,void*,int,int))
+ gv_raster_float_real_sample;
+ raster->type = GV_RASTER_FLOAT_REAL;
+ raster->gdal_type = GDT_Float32;
+ break;
+ }
+
+ if( raster->type == GV_RASTER_BYTE_REAL
+ || !gv_raster_autoscale(raster,GvASAAutomatic,-1.0,0,NULL,NULL,NULL) )
+ {
+ raster->min = 0;
+ raster->max = 255;
+ }
+
+ raster->tile_x = 256;
+ raster->tile_y = 256;
+ raster->width = GDALGetRasterXSize(dataset);
+ raster->height = GDALGetRasterYSize(dataset);
+ raster->tiles_across = (raster->width + raster->tile_x-GV_TILE_OVERLAP-1)
+ / (raster->tile_x-GV_TILE_OVERLAP);
+ raster->tiles_down = (raster->height + raster->tile_y-GV_TILE_OVERLAP-1)
+ / (raster->tile_y-GV_TILE_OVERLAP);
+ raster->max_lod = 7;
+ raster->item_size = GDALGetDataTypeSize(raster->gdal_type) / 8;
+
+ if( GDALGetGeoTransform(dataset, raster->geotransform) != CE_None )
+ {
+ raster->geotransform[0] = 0.0;
+ raster->geotransform[1] = 1.0;
+ raster->geotransform[2] = 0.0;
+ raster->geotransform[3] = 0.0;
+ raster->geotransform[4] = 0.0;
+ raster->geotransform[5] = 1.0;
+ }
+
+ if( GDALGetGCPCount(dataset) > 0
+ && raster->geotransform[0] == 0.0
+ && raster->geotransform[1] == 1.0
+ && raster->geotransform[2] == 0.0
+ && raster->geotransform[3] == 0.0
+ && raster->geotransform[4] == 0.0
+ && raster->geotransform[5] == 1.0 )
+ {
+ gv_data_set_projection( GV_DATA(raster),
+ GDALGetGCPProjection( dataset ) );
+
+ gv_raster_set_gcps( raster,
+ GDALGetGCPCount(dataset),
+ GDALGetGCPs(dataset) );
+ }
+ else
+ {
+ if( EQUAL(GDALGetProjectionRef( dataset ),"")
+ && raster->geotransform[0] == 0.0
+ && raster->geotransform[1] == 1.0
+ && raster->geotransform[2] == 0.0
+ && raster->geotransform[3] == 0.0
+ && raster->geotransform[4] == 0.0
+ && raster->geotransform[5] == 1.0 )
+ {
+ gv_data_set_projection( GV_DATA(raster), "PIXEL" );
+ }
+ else
+ {
+ gv_data_set_projection( GV_DATA(raster),
+ GDALGetProjectionRef( dataset ) );
+ }
+ }
+
+ raster->max_tiles = raster->tiles_across * raster->tiles_down;
+ if( ( raster->cache = gv_raster_cache_new( raster->max_tiles,
+ raster->max_lod ) ) == NULL )
+ {
+ g_free( raster );
+ return NULL;
+ }
+
+ return GV_DATA(raster);
+}
+
+gint *
+gv_raster_tile_xy_get( GvRaster *raster, gint tile, gint lod, gint *coords )
+{
+ gint tile_in_x, tile_in_y;
+
+ if( coords == NULL )
+ {
+ if( ( coords = g_new( int, 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+ }
+
+ tile_in_x = tile % raster->tiles_across;
+
+ tile_in_y = tile / raster->tiles_across;
+
+ coords[0] = tile_in_x * (raster->tile_x - GV_TILE_OVERLAP)
+ - GV_TILE_OVERLAP/2;
+ coords[1] = tile_in_y * (raster->tile_y - GV_TILE_OVERLAP)
+ - GV_TILE_OVERLAP/2;
+ coords[2] = coords[0] + raster->tile_x;
+ coords[3] = coords[1] + raster->tile_y;
+
+ return coords;
+}
+
+static int
+gv_raster_tile_get_gdal( GvRaster *raster, GDALRasterBandH band, gint *coords,
+ void *buffer, int buf_width, int buf_height,
+ int pixel_offset, int line_offset )
+
+{
+ int width, height;
+ int size, factor, i;
+ int win_xoff, win_yoff, win_xsize, win_ysize;
+ int rd_buf_width, rd_buf_height, rd_xoff = 0, rd_yoff = 0;
+ unsigned char *buf_u;
+
+ width = coords[2] - coords[0];
+ height = coords[3] - coords[1];
+ size = buf_width * buf_height * raster->item_size;
+ factor = width / buf_width;
+
+ if( coords[0] + width > raster->width
+ || coords[1] + height > raster->height )
+ {
+ width = MIN(width,raster->width - coords[0] );
+ rd_buf_width = width / factor;
+ height = MIN(height,raster->height - coords[1] );
+ rd_buf_height = height / factor;
+ }
+ else
+ {
+ rd_buf_width = width / factor;
+ rd_buf_height = height / factor;
+ }
+
+ win_xoff = coords[0];
+ win_yoff = coords[1];
+ win_xsize = rd_buf_width * factor;
+ win_ysize = rd_buf_height * factor;
+
+ if( win_xsize == 0 || win_ysize == 0 )
+ {
+ /* We can't provide for the sliver requested, so return doing
+ nothing. */
+ return TRUE;
+ }
+
+ buf_u = (unsigned char *) buffer;
+
+ if( coords[0] < 0 )
+ {
+ assert( coords[0] == -1 );
+ win_xoff += 1;
+ win_xsize -= 1;
+ rd_buf_width -= 1;
+ buf_u += pixel_offset;
+ rd_xoff = 1;
+ }
+
+ if( coords[1] < 0 )
+ {
+ assert( coords[1] == -1 );
+ win_yoff += 1;
+ win_ysize -= 1;
+ rd_buf_height -= 1;
+ buf_u += line_offset;
+ rd_yoff = 1;
+ }
+
+#ifdef notdef
+ CPLDebug( "OpenEV-RasterIO",
+ "%s:%d (%d,%d %dx%d) to (%dx%d) of (%dx%d)",
+ GDALGetDescription( raster->dataset ),
+ -1, win_xoff, win_yoff, win_xsize, win_ysize,
+ rd_buf_width, rd_buf_height, buf_width, buf_height );
+#endif
+
+ GDALRasterIO( band, GF_Read, win_xoff, win_yoff, win_xsize, win_ysize,
+ buf_u, rd_buf_width, rd_buf_height,
+ raster->gdal_type, pixel_offset, line_offset );
+ buf_u = (unsigned char *) buffer;
+
+ /* do we need to set the left most pixel from one in? */
+ if( win_xoff == 0 && coords[0] == -1 )
+ {
+ for( i = 0; i < buf_height; i++ )
+ {
+ memcpy( buf_u + i*line_offset,
+ buf_u + i*line_offset + pixel_offset,
+ pixel_offset );
+ }
+ }
+
+ /* do we need to set the top scanline from the second? */
+ if( win_yoff == 0 && coords[1] == -1 )
+ {
+ memcpy( buf_u, buf_u + line_offset, line_offset );
+ }
+
+ /* do we need to set the right most real pixel + 1? */
+ if( rd_xoff + rd_buf_width < buf_width )
+ {
+ int pixel_to_set;
+ unsigned char *u_buf_base = (unsigned char *) buffer;
+
+ assert( rd_buf_width < buf_width );
+ pixel_to_set = rd_buf_width + rd_xoff;
+ assert( pixel_to_set >= 1 && pixel_to_set < buf_width );
+
+ while( pixel_to_set < buf_width )
+ {
+ for( i = 0; i < buf_height; i++ )
+ {
+ assert( i >= 0 && i < raster->tile_y );
+ memcpy( u_buf_base + i*line_offset + pixel_to_set*pixel_offset,
+ u_buf_base + i*line_offset + (pixel_to_set-1)*pixel_offset,
+ pixel_offset );
+ }
+ pixel_to_set++;
+ }
+ }
+
+ /* do we need to set the bottom most real pixel + 1? */
+ if( rd_yoff + rd_buf_height < buf_height )
+ {
+ int line_to_set;
+ unsigned char *u_buf_base = (unsigned char *) buffer;
+
+ assert( buf_height != rd_buf_height );
+ line_to_set = rd_buf_height + rd_yoff;
+ assert( line_to_set >= 1 && line_to_set < buf_height );
+ assert( line_offset*factor == raster->item_size * raster->tile_x );
+
+ /* we will actually keep copying the line till we get to the bottom
+ of the buffer */
+ while( line_to_set < buf_height )
+ {
+ memcpy( u_buf_base + line_to_set*line_offset,
+ u_buf_base + (line_to_set-1)*line_offset,
+ line_offset );
+ line_to_set++;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * Based on the available overviews, identify the closest appropriate
+ * lod available from the GDAL band.
+ */
+
+static int gv_closest_gdal_lod( GDALRasterBandH band, int desired_lod )
+
+{
+ int ov_index;
+ int best_lod;
+ double best_factor = 1.0;
+ double desired_factor = (1 << desired_lod);
+
+#ifdef ATLANTIS_BUILD
+ if ((gv_manager_get_preference(gv_get_manager(),"safe_mode") != NULL) &&
+ (strcmp(gv_manager_get_preference(gv_get_manager(),"safe_mode"),"on") == 0))
+ return 0;
+#endif
+
+ if( GDALHasArbitraryOverviews( band ) )
+ return desired_lod;
+
+ for( ov_index = 0; ov_index < GDALGetOverviewCount( band ); ov_index++ )
+ {
+ GDALRasterBandH oband = GDALGetOverview( band, ov_index );
+ double ofactor;
+
+ ofactor = GDALGetRasterBandXSize( band ) /
+ (double) GDALGetRasterBandXSize( oband );
+
+ /* We already found something better */
+ if( ofactor < best_factor )
+ continue;
+
+ /* We don't want to upsample by much! */
+ if( ofactor > desired_factor * 1.2 )
+ continue;
+
+ best_factor = ofactor;
+ }
+
+ best_lod = 0;
+ while( best_factor*0.8 > (1 << best_lod) )
+ best_lod++;
+
+ return best_lod;
+}
+
+void *
+gv_raster_tile_get( GvRaster *raster, gint tile, gint lod )
+{
+ gint *coords = NULL;
+ gint cur_lod;
+ gint i;
+ int need_to_free_buffer = 0;
+ void *buffer = NULL;
+ void *temp_buffer;
+
+
+ if( raster->cache != NULL )
+ {
+ cur_lod = gv_raster_cache_get_best_lod( raster->cache, tile, lod );
+
+ if( cur_lod == lod )
+ {
+ return gv_raster_cache_get( raster->cache, tile, lod );
+ }
+ else if( cur_lod > lod || cur_lod == -1 )
+ {
+ int width, height, pixel_offset, line_offset;
+ int buf_width, buf_height;
+ int size, factor;
+
+ coords = gv_raster_tile_xy_get( raster, tile, lod, coords );
+
+ width = coords[2] - coords[0];
+ height = coords[3] - coords[1];
+
+ /* If sample mode is average, retrieve the closest resolution
+ overview tile from gdal and then average down as much as
+ necessary; otherwise (sample mode is decimate), let gdal do
+ the downsampling (retrieve the tile from gdal using coordinates
+ for cur_lod=lod).
+ */
+
+ if( raster->sm == GvSMAverage )
+ cur_lod = gv_closest_gdal_lod( raster->gdal_band, lod );
+ else
+ cur_lod = lod;
+
+#ifdef ATLANTIS_BUILD
+ /* safe mode ignores overviews */
+ if ((gv_manager_get_preference(gv_get_manager(),"safe_mode") != NULL) &&
+ (strcmp(gv_manager_get_preference(gv_get_manager(),"safe_mode"),"on") == 0))
+ {
+ cur_lod = 0;
+ }
+#endif
+
+ factor = 1 << cur_lod;
+ buf_width = width / factor;
+ buf_height = height / factor;
+
+ size = buf_width * buf_height * raster->item_size;
+ buffer = g_malloc(size);
+
+ pixel_offset = raster->item_size;
+ line_offset = buf_width * raster->item_size;
+
+ if( coords[0] + width > raster->width
+ || coords[1] + height > raster->height
+ || coords[0] < 0 || coords[1] < 0 )
+ memset( buffer, 0, size );
+
+ if( buffer != NULL )
+ {
+ if( !gv_raster_tile_get_gdal( raster, raster->gdal_band,
+ coords,
+ buffer, buf_width, buf_height,
+ pixel_offset, line_offset ) )
+ {
+ g_free( buffer );
+ return NULL;
+ }
+ }
+
+ if ( coords )
+ {
+ g_free( coords );
+ coords = NULL;
+ }
+ need_to_free_buffer = 1;
+
+ } else {
+ int width, height, pixel_offset, line_offset;
+ int buf_width, buf_height;
+ int size, factor, gdal_lod;
+
+ /* When a tile is loaded, gdal returns overview values
+ if present; otherwise it downsamples. To avoid a
+ mismatch between tiles downsampled from higher
+ resolution tiles and tiles being loaded at lower
+ resolution from scratch, check for a gdal overview
+ close to this lod before downsampling the higher
+ resolution tile. This code used to point buffer to
+ the higher-resolution tile which then got downsampled
+ in the for-loop below, but this caused display issues in
+ some cases (eg. if overviews were generated
+ using averaging, but openev's overview sampling is
+ set to decimate, then zooming out on an image with averaged
+ overviews will result in the area just zoomed out from
+ looking specklier than the surrounding areas
+ because the surroundings are loaded from the low-res averaged
+ overviews, but the area just zoomed out is decimated
+ from a high res averaged overview). Now, this is changed so the
+ code first checks for a gdal overview that is better for
+ downsampling than the current closest resolution cached
+ tile, but uses the cached tile if no better overview
+ is found. This should hopefully avoid display
+ inconsistencies, but still make use of the cached tile
+ if no overviews are present rather than downsampling
+ from scratch (otherwise this else could go entirely,
+ and the else if above could handle all cases where
+ cur_lod != lod).
+ */
+ gdal_lod = gv_closest_gdal_lod( raster->gdal_band, lod );
+ if ((gdal_lod <= cur_lod) || (gdal_lod > lod))
+ {
+ /* No better overviews available to downsample */
+ buffer = gv_raster_cache_get( raster->cache, tile, cur_lod );
+ }
+ else
+ {
+ cur_lod=gdal_lod;
+ coords = gv_raster_tile_xy_get( raster, tile, lod, coords );
+
+ width = coords[2] - coords[0];
+ height = coords[3] - coords[1];
+
+ if ((gv_manager_get_preference(gv_get_manager(),"safe_mode") != NULL) &&
+ (strcmp(gv_manager_get_preference(gv_get_manager(),"safe_mode"),"on") == 0))
+ {
+ cur_lod = 0;
+ }
+
+ factor = 1 << cur_lod;
+ buf_width = width / factor;
+ buf_height = height / factor;
+
+ size = buf_width * buf_height * raster->item_size;
+ buffer = g_malloc(size);
+
+ pixel_offset = raster->item_size;
+ line_offset = buf_width * raster->item_size;
+
+ if( coords[0] + width > raster->width
+ || coords[1] + height > raster->height
+ || coords[0] < 0 || coords[1] < 0 )
+ memset( buffer, 0, size );
+
+ if( buffer != NULL )
+ {
+ if( !gv_raster_tile_get_gdal( raster, raster->gdal_band,
+ coords,
+ buffer, buf_width, buf_height,
+ pixel_offset, line_offset ) )
+ {
+ g_free( buffer );
+ return NULL;
+ }
+ }
+
+ if ( coords )
+ {
+ g_free( coords );
+ coords = NULL;
+ }
+ need_to_free_buffer = 1;
+ }
+ }
+
+ for( i = cur_lod; i < lod; i++ )
+ {
+ temp_buffer = raster->average( raster,
+ buffer, raster->tile_x >> i,
+ raster->tile_y >> i );
+
+ if( need_to_free_buffer )
+ {
+ g_free( buffer );
+ } else {
+ need_to_free_buffer = 1;
+ }
+
+ buffer = temp_buffer;
+ }
+
+ if( buffer != NULL )
+ gv_raster_cache_put( raster->cache, tile, lod, buffer,
+ (raster->item_size * ( raster->tile_x >> lod )
+ * ( raster->tile_y >> lod ) ) );
+
+ return buffer;
+ }
+
+ return NULL;
+}
+
+void
+gv_raster_flush_cache( GvRaster *raster,
+ int x_off, int y_off, int width, int height )
+{
+ if( raster->gdal_band != NULL )
+ GDALFlushRasterCache( raster->gdal_band );
+
+ if( width < 1 || height < 1 )
+ gv_raster_cache_flush_all( raster->cache );
+ else
+ {
+ gint tile, lod;
+
+ for( tile = 0; tile < raster->cache->max_tiles; tile++ )
+ {
+ gint coords[4];
+
+ gv_raster_tile_xy_get( raster, tile, 0, coords );
+
+ if( x_off < coords[2] && y_off < coords[3]
+ && x_off+width > coords[0] && y_off+height > coords[1] )
+ {
+ for( lod = 0; lod < raster->cache->max_lod; lod++ )
+ gv_raster_cache_del( raster->cache, tile, lod );
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_raster_get_nodata() */
+/************************************************************************/
+
+/**
+ * Queries NODATA value for the specified raster.
+ *
+ * @param raster Pointer to GvRaster object.
+ *
+ * @param nodata Pointer to the variable which should be filled with the
+ * NODATA value.
+ *
+ * @return TRUE if specified raster object has NODATA set and FALSE otherwise.
+ */
+
+gint
+gv_raster_get_nodata(GvRaster *raster, double *nodata )
+
+{
+ int nodata_set = FALSE;
+
+ g_return_val_if_fail( GV_IS_RASTER( raster ), FALSE );
+ g_return_val_if_fail( raster != NULL, FALSE);
+
+ if ( nodata )
+ *nodata = GDALGetRasterNoDataValue( raster->gdal_band, &nodata_set );
+ else
+ GDALGetRasterNoDataValue( raster->gdal_band, &nodata_set );
+
+ if( !nodata_set )
+ return FALSE;
+
+ return TRUE;
+}
+
+gint
+gv_raster_get_sample(GvRaster *raster, double x, double y,
+ double *real, double *imaginary )
+
+{
+ gint pixel, line, tile_x_off, tile_y_off;
+ gint tile, x_within_tile, y_within_tile;
+ void *data;
+
+ pixel = (int) floor(x);
+ line = (int) floor(y);
+
+ if( pixel < 0 || line < 0
+ || pixel >= raster->width || line >= raster->height )
+ return FALSE;
+
+ tile_x_off = pixel / (raster->tile_x-GV_TILE_OVERLAP);
+ tile_y_off = line / (raster->tile_y-GV_TILE_OVERLAP);
+ x_within_tile = pixel
+ - (tile_x_off * (raster->tile_x-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2);
+ y_within_tile = line
+ - (tile_y_off * (raster->tile_y-GV_TILE_OVERLAP) - GV_TILE_OVERLAP/2);
+
+ tile = tile_x_off + tile_y_off * raster->tiles_across;
+ if( gv_raster_cache_get_best_lod( raster->cache, tile, 0 ) == 0 )
+ {
+ data = gv_raster_tile_get( raster, tile, 0 );
+
+ data = ((unsigned char *) data)
+ + (x_within_tile + y_within_tile * raster->tile_x) * raster->item_size;
+
+ switch( raster->type )
+ {
+ case GV_RASTER_BYTE_REAL:
+ *real = ((unsigned char *) data)[0];
+ *imaginary = 0.0;
+ break;
+
+ case GV_RASTER_BYTE_COMPLEX:
+ *real = ((unsigned char *) data)[0];
+ *imaginary = ((unsigned char *) data)[1];
+ break;
+
+ case GV_RASTER_FLOAT_REAL:
+ *real = ((float *) data)[0];
+ *imaginary = 0.0;
+ break;
+
+ case GV_RASTER_FLOAT_COMPLEX:
+ *real = ((float *) data)[0];
+ *imaginary = ((float *) data)[1];
+ break;
+
+ default:
+ printf( "Unsupported raster type in gv_raster_get_sample().\n" );
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* use GDAL directly to get value, on assumption it can do a single
+ pixel more efficiently than a whole GvRaster tile */
+
+ double value[2];
+
+ GDALRasterIO( raster->gdal_band, GF_Read, pixel, line, 1, 1,
+ value, 1, 1, GDT_CFloat64, 0, 0 );
+
+ *real = value[0];
+ *imaginary = value[1];
+ }
+
+ return TRUE;
+}
+
+static int
+gv_float_compare( const void *float1, const void *float2 )
+{
+ const float *f1 = (float *) float1;
+ const float *f2 = (float *) float2;
+
+ if( *f1 < *f2 )
+ return -1;
+ else if( *f1 > *f2 )
+ return 1;
+ else
+ return 0;
+}
+
+gint
+gv_raster_autoscale( GvRaster *raster, GvAutoScaleAlg alg, double alg_param,
+ int sample_count, float *sample_set,
+ double *min_out, double *max_out )
+
+
+{
+ int local_samples = FALSE;
+ int tail_size, i, sorted = FALSE;
+ double no_data, raster_min=0.0, raster_max=255.0;
+
+/* -------------------------------------------------------------------- */
+/* Collect a set of sample points. */
+/* -------------------------------------------------------------------- */
+ if( sample_set == NULL )
+ {
+ local_samples = TRUE;
+ if( gv_manager_get_preference(gv_get_manager(),"autoscale_samples") )
+ {
+ sample_count = atoi(
+ gv_manager_get_preference(gv_get_manager(),"autoscale_samples"));
+ sample_count = MAX(10,sample_count);
+ }
+ else
+ sample_count = 10000;
+
+ sample_set = g_new(float,sample_count);
+ sample_count = GDALGetRandomRasterSample(raster->gdal_band,
+ sample_count, sample_set );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Strip out any nodata values found. */
+/* -------------------------------------------------------------------- */
+ if( gv_raster_get_nodata( raster, &no_data ) )
+ {
+ int j = 0;
+
+ for( i = 0; i < sample_count; i++ )
+ {
+ if( ( sample_set[i] != (float)no_data ) &&
+ !(isnan(sample_set[i])) )
+ sample_set[j++] = sample_set[i];
+ }
+
+ sample_count = j;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we didn't find a nodata value, try stripping away the */
+/* most extreme value after sorting. This should let us get */
+/* rid of stuff that is likely a nodata value, but in a */
+/* classified image will unfortunately get rid of the lowest */
+/* and highest classes. */
+/* -------------------------------------------------------------------- */
+ else if( sample_count > 2 )
+ {
+ int j = 0;
+
+ for( i = 0; i < sample_count; i++ )
+ {
+ if ( !(isnan(sample_set[i])) )
+ sample_set[j++] = sample_set[i];
+ }
+
+ sample_count = j;
+
+ qsort( sample_set, sample_count, sizeof(float), gv_float_compare );
+ sorted = TRUE;
+
+ if( sample_set[0] != sample_set[sample_count-1] )
+ {
+ for( i = 1;
+ i < sample_count && sample_set[i] == sample_set[0];
+ i++ ) {}
+
+ if( i > 1 )
+ {
+ memmove( sample_set, sample_set + i,
+ sizeof(float) * (sample_count - i) );
+ sample_count -= i;
+ }
+ }
+
+ if( sample_set[0] != sample_set[sample_count-1] )
+ {
+ for( i = 1;
+ i < sample_count
+ && sample_set[sample_count-i-1] == sample_set[sample_count-1];
+ i++ ) {}
+
+ if( i > 1 )
+ sample_count -= i;
+ }
+ }
+
+ if( sample_count < 2 )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Determine the algorithm to use. */
+/* -------------------------------------------------------------------- */
+ if( alg == GvASAAutomatic )
+ {
+ const char *alg_str;
+
+ alg_str= gv_manager_get_preference(gv_get_manager(),"scale_algorithm");
+
+ if( alg_str != NULL && EQUAL(alg_str,"percent_tail_trim") )
+ {
+ alg = GvASAPercentTailTrim;
+ alg_param = -1.0;
+ }
+ else if( alg_str != NULL && EQUAL(alg_str,"std_deviation") )
+ {
+ alg = GvASAStdDeviation;
+ alg_param = -1.0;
+ }
+ else
+ {
+#ifdef ATLANTIS_BUILD
+ alg = GvASAStdDeviation;
+#else
+ alg = GvASAPercentTailTrim;
+#endif
+ alg_param = -1.0;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Determine the parameter value to use. A -1 means use what's */
+/* in the preferences. */
+/* -------------------------------------------------------------------- */
+ if( alg_param < -0.9 && alg == GvASAStdDeviation )
+ {
+ const char *alg_param_str;
+
+ alg_param = 2.5;
+ alg_param_str =
+ gv_manager_get_preference(gv_get_manager(),
+ "scale_std_deviations");
+ if( alg_param_str != NULL )
+ alg_param = atof(alg_param_str);
+ }
+ else if( alg_param < -0.9 && alg == GvASAPercentTailTrim )
+ {
+ const char *alg_param_str;
+
+ alg = GvASAPercentTailTrim;
+ alg_param = 0.02;
+ alg_param_str =
+ gv_manager_get_preference(gv_get_manager(),"scale_percent_tail");
+ if( alg_param_str != NULL )
+ alg_param = atof(alg_param_str);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Implementation for percent tail trim method. */
+/* -------------------------------------------------------------------- */
+ if( alg == GvASAPercentTailTrim )
+ {
+ if( !sorted )
+ {
+ qsort( sample_set, sample_count, sizeof(float), gv_float_compare );
+ sorted = TRUE;
+ }
+
+ if( alg_param > 0.5 )
+ alg_param = alg_param / 100.0;
+
+ tail_size = (int) (alg_param * sample_count);
+
+ raster_min = sample_set[tail_size];
+ raster_max = sample_set[sample_count - tail_size - 1];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Implement standard deviation method. */
+/* -------------------------------------------------------------------- */
+ else if( alg == GvASAStdDeviation )
+ {
+ double sum = 0.0, sum_squares = 0.0, mean, std_dev;
+
+ /* compute the std deviation & mean */
+
+ for( i = 0; i < sample_count; i++ )
+ sum += sample_set[i];
+
+ mean = sum / sample_count;
+
+ for( i = 0; i < sample_count; i++ )
+ sum_squares += (mean - sample_set[i]) * (mean - sample_set[i]);
+
+ std_dev = sqrt(sum_squares / (sample_count - 1));
+
+ raster_min = mean - std_dev * alg_param;
+ raster_max = mean + std_dev * alg_param;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Ensure we don't end up with a degenerate range. */
+/* -------------------------------------------------------------------- */
+ if( raster_min == raster_max )
+ {
+ raster_min = raster_min - 0.5;
+ raster_max = raster_max + 0.5;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Return results or assign directly to raster. */
+/* -------------------------------------------------------------------- */
+ if( min_out != NULL && max_out != NULL )
+ {
+ *min_out = raster_min;
+ *max_out = raster_max;
+ }
+ else
+ {
+ raster->min = raster_min;
+ raster->max = raster_max;
+ }
+
+ if( local_samples )
+ g_free( sample_set );
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_raster_collect_random_sample() */
+/* */
+/* Collect random samples from available loaded tiles. */
+/************************************************************************/
+
+int gv_raster_collect_random_sample( GvRaster *raster,
+ int sample_count, float *sample_set,
+ int xoff, int yoff, int xsize, int ysize,
+ GArray *tile_list )
+
+{
+ int result, tile, as_count, itile, cs_count;
+ float sampling_rate;
+
+ if( xoff >= raster->width || yoff >= raster->height
+ || xoff + xsize < 0 || yoff + ysize < 0 )
+ return 0;
+
+/* -------------------------------------------------------------------- */
+/* If we don't have a tile list, create one locally from the */
+/* bounding rectangle. */
+/* -------------------------------------------------------------------- */
+ if( tile_list == NULL )
+ {
+ tile_list = g_array_new( FALSE, FALSE, sizeof(int) );
+
+ for( tile = 0; tile < raster->max_tiles; tile++ )
+ {
+ gint coords[4];
+
+ gv_raster_tile_xy_get( raster, tile, 0, coords );
+ if( coords[0] > xoff + xsize || coords[2] < xoff
+ || coords[1] > yoff + ysize || coords[3] < yoff )
+ continue;
+
+ g_array_append_val( tile_list, tile );
+ }
+
+ result = gv_raster_collect_random_sample(
+ raster, sample_count, sample_set,
+ xoff, yoff, xsize, ysize,
+ tile_list );
+
+ g_array_free( tile_list, TRUE );
+
+ return result;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Count available values so we can work out a sampling rate. */
+/* -------------------------------------------------------------------- */
+ as_count = 0;
+ for( itile = 0; itile < tile_list->len; itile++ )
+ {
+ int lod, lod_factor;
+ gint coords[4];
+
+ /* do we have this tile? Pick largested avail tile */
+
+ tile = ((int *) tile_list->data)[itile];
+ if( tile == -1 )
+ continue;
+
+ for( lod = 0; lod < raster->max_lod; lod++ )
+ {
+ if( raster->cache->tiles[lod][tile] != NULL )
+ break;
+ }
+
+ if( lod == raster->max_lod )
+ continue;
+
+ /* compute the applicable region in full res */
+ gv_raster_tile_xy_get( raster, tile, lod, coords );
+
+ if( xoff > coords[2] || yoff > coords[3]
+ || xoff + xsize < coords[0] || yoff + ysize < coords[1] )
+ continue;
+
+ if( xoff > coords[0] )
+ coords[0] = xoff;
+ if( yoff > coords[1] )
+ coords[1] = yoff;
+ if( xoff+xsize < coords[2] )
+ coords[2] = xoff+xsize;
+ if( yoff+ysize < coords[3] )
+ coords[3] = yoff+ysize;
+
+ if( lod > 0 )
+ lod_factor = 2 << (lod-1);
+ else
+ lod_factor = 1;
+
+ as_count += (((coords[2] - coords[0]) / lod_factor)
+ * ((coords[3] - coords[1]) / lod_factor));
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute sampling rate. */
+/* -------------------------------------------------------------------- */
+ if( as_count <= sample_count )
+ sampling_rate = 1;
+ else
+ sampling_rate = as_count / (double) sample_count;
+
+/* -------------------------------------------------------------------- */
+/* collect samples from tiles. */
+/* -------------------------------------------------------------------- */
+ cs_count = 0;
+
+ for( itile = 0; itile < tile_list->len; itile++ )
+ {
+ int lod, lod_factor, i, x, y, lod_xsize, lod_ysize;
+ gint coords[4];
+ float fi;
+ void *data = NULL;
+
+ /* do we have this tile? Pick largested avail tile */
+
+ tile = ((int *) tile_list->data)[itile];
+ if( tile == -1 )
+ continue;
+
+ for( lod = 0; lod < raster->max_lod; lod++ )
+ {
+ if( raster->cache->tiles[lod][tile] != NULL )
+ {
+ data = raster->cache->tiles[lod][tile]->data;
+ break;
+ }
+ }
+
+ if( data == NULL )
+ continue;
+
+ if( lod > 0 )
+ lod_factor = 2 << (lod-1);
+ else
+ lod_factor = 1;
+
+ /* compute the applicable region in full res */
+ gv_raster_tile_xy_get( raster, tile, lod, coords );
+
+ if( xoff > coords[2] || yoff > coords[3]
+ || xoff + xsize < coords[0] || yoff + ysize < coords[1] )
+ continue;
+
+ as_count = (((coords[2] - coords[0]) / lod_factor)
+ * ((coords[3] - coords[1]) / lod_factor));
+
+ lod_xsize = (coords[2] - coords[0]) / lod_factor;
+ lod_ysize = (coords[2] - coords[0]) / lod_factor;
+
+ for( fi = 0.5; fi < as_count; fi += sampling_rate )
+ {
+ i = (int) fi;
+
+ x = coords[0] + (i % lod_xsize) * lod_factor;
+ y = coords[1] + (i / lod_xsize) * lod_factor;
+
+ if( x < xoff || x >= xoff+xsize || y < yoff || y >= yoff+ysize )
+ continue;
+
+ if( cs_count == sample_count )
+ continue;
+
+ if( raster->type == GV_RASTER_BYTE_REAL )
+ sample_set[cs_count++] = ((unsigned char *) data)[i];
+ else if( raster->type == GV_RASTER_FLOAT_COMPLEX )
+ {
+ float real, imag;
+
+ real = ((float *) data)[i*2];
+ imag = ((float *) data)[i*2+1];
+ sample_set[cs_count++] = sqrt(real*real + imag*imag);
+ }
+ else if( raster->type == GV_RASTER_FLOAT_REAL )
+ sample_set[cs_count++] = ((float *) data)[i];
+ }
+ }
+
+ return cs_count;
+}
+
+/************************************************************************/
+/* gv_raster_collect_histogram() */
+/* */
+/* Collect histogram information from available loaded tiles. */
+/************************************************************************/
+
+int gv_raster_collect_histogram( GvRaster *raster,
+ double scale_min, double scale_max,
+ int bucket_count, int *histogram,
+ int include_out_of_range,
+ int xoff, int yoff, int xsize, int ysize,
+ GArray *tile_list )
+
+{
+ int tile, itile, cs_count, tile_values, i;
+ float scale_coef;
+
+ if( xoff >= raster->width || yoff >= raster->height
+ || xoff + xsize < 0 || yoff + ysize < 0 )
+ return 0;
+
+ if( (scale_max - scale_min) == 0.0 )
+ return 0;
+
+ scale_coef = bucket_count / (scale_max - scale_min);
+
+/* -------------------------------------------------------------------- */
+/* If we don't have a tile list, create one locally from the */
+/* bounding rectangle. */
+/* -------------------------------------------------------------------- */
+ if( tile_list == NULL )
+ {
+ int result;
+
+ tile_list = g_array_new( FALSE, FALSE, sizeof(int) );
+
+ for( tile = 0; tile < raster->max_tiles; tile++ )
+ {
+ gint coords[4];
+
+ gv_raster_tile_xy_get( raster, tile, 0, coords );
+ if( coords[0] > xoff + xsize || coords[2] < xoff
+ || coords[1] > yoff + ysize || coords[3] < yoff )
+ continue;
+
+ g_array_append_val( tile_list, tile );
+ }
+
+ result = gv_raster_collect_histogram(
+ raster, scale_min, scale_max, bucket_count, histogram,
+ include_out_of_range,
+ xoff, yoff, xsize, ysize,
+ tile_list );
+
+ g_array_free( tile_list, TRUE );
+
+ return result;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Zero histogram. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < bucket_count; i++ )
+ histogram[i] = 0;
+
+/* -------------------------------------------------------------------- */
+/* collect samples from tiles. */
+/* -------------------------------------------------------------------- */
+ cs_count = 0;
+
+ for( itile = 0; itile < tile_list->len; itile++ )
+ {
+ int lod, lod_factor, x, y, lod_xsize, lod_ysize;
+ gint coords[4];
+ void *data = NULL;
+
+ /* do we have this tile? Pick largested avail tile */
+
+ tile = ((int *) tile_list->data)[itile];
+ if( tile == -1 )
+ continue;
+
+ for( lod = 0; lod < raster->max_lod; lod++ )
+ {
+ if( raster->cache->tiles[lod][tile] != NULL )
+ {
+ data = raster->cache->tiles[lod][tile]->data;
+ break;
+ }
+ }
+
+ if( data == NULL )
+ continue;
+
+ if( lod > 0 )
+ lod_factor = 2 << (lod-1);
+ else
+ lod_factor = 1;
+
+ /* compute the applicable region in full res */
+ gv_raster_tile_xy_get( raster, tile, lod, coords );
+
+ if( xoff > coords[2] || yoff > coords[3]
+ || xoff + xsize < coords[0] || yoff + ysize < coords[1] )
+ continue;
+
+ lod_xsize = (coords[2] - coords[0]) / lod_factor;
+ lod_ysize = (coords[2] - coords[0]) / lod_factor;
+ tile_values = lod_xsize * lod_ysize;
+
+ for( i = 0; i < tile_values; i++ )
+ {
+ float value;
+
+ x = coords[0] + (i % lod_xsize) * lod_factor;
+ y = coords[1] + (i / lod_xsize) * lod_factor;
+
+ if( x < xoff || x >= xoff+xsize || y < yoff || y >= yoff+ysize )
+ continue;
+
+ if( raster->type == GV_RASTER_BYTE_REAL )
+ value = ((unsigned char *) data)[i];
+ else if( raster->type == GV_RASTER_FLOAT_COMPLEX )
+ {
+ float real, imag;
+
+ real = ((float *) data)[i*2];
+ imag = ((float *) data)[i*2+1];
+ value = sqrt(real*real + imag*imag);
+ }
+ else if( raster->type == GV_RASTER_FLOAT_REAL )
+ value = ((float *) data)[i];
+ else
+ {
+ assert( FALSE );
+ value = 0.0;
+ }
+
+ if( value < scale_min )
+ {
+ if( include_out_of_range )
+ {
+ histogram[0]++;
+ cs_count++;
+ }
+ }
+ else if( value > scale_max )
+ {
+ if( include_out_of_range )
+ {
+ histogram[bucket_count-1]++;
+ cs_count++;
+ }
+ }
+ else
+ {
+ int bucket;
+
+ bucket = (int) ((value - scale_min) * scale_coef);
+ bucket = MIN(bucket,bucket_count-1);
+ histogram[bucket]++;
+ cs_count++;
+ }
+ }
+ }
+
+ return cs_count;
+}
+
+/* Approximate width or height of central pixel in georef coordinates */
+
+double gv_raster_pixel_size( GvRaster *raster )
+
+{
+ double x1, y1, x2, y2;
+
+ x1 = raster->width / 2;
+ y1 = raster->height / 2;
+
+ x2 = x1 + 1.0;
+ y2 = y1 + 1.0;
+
+ gv_raster_pixel_to_georef( raster, &x1, &y1, NULL );
+ gv_raster_pixel_to_georef( raster, &x2, &y2, NULL );
+
+ return (ABS(x2-x1) + ABS(y2-y1)) * 0.5;
+}
+
+static void
+gv_raster_get_memento(GvData *data, gpointer change_info,
+ GvDataMemento **memento)
+{
+ GvRaster *raster = GV_RASTER(data);
+ GvRasterMemento *mem;
+ GvRasterChangeInfo *info = (GvRasterChangeInfo *) change_info;
+
+ *memento = NULL;
+ if( change_info == NULL )
+ return;
+
+ mem = g_new(GvRasterMemento, 1);
+ mem->base.data = data;
+ mem->base.type = info->change_type;
+
+ mem->x_off = info->x_off;
+ mem->y_off = info->y_off;
+ mem->width = info->width;
+ mem->height = info->height;
+
+ mem->data = g_malloc(info->width * info->height * raster->item_size);
+ if( mem->data == NULL )
+ return;
+
+ GDALRasterIO( raster->gdal_band, GF_Read,
+ mem->x_off, mem->y_off, mem->width, mem->height,
+ mem->data, mem->width, mem->height, raster->gdal_type,
+ 0, 0 );
+
+ *memento = (GvDataMemento*)mem;
+}
+
+static void
+gv_raster_set_memento(GvData *data, GvDataMemento *data_memento)
+{
+ GvRaster *raster = GV_RASTER(data);
+ GvRasterMemento *mem = (GvRasterMemento *) data_memento;
+ GvRasterChangeInfo change_info;
+
+ GDALRasterIO( raster->gdal_band, GF_Write,
+ mem->x_off, mem->y_off, mem->width, mem->height,
+ mem->data, mem->width, mem->height, raster->gdal_type,
+ 0, 0 );
+
+ change_info.change_type = GV_CHANGE_REPLACE;
+ change_info.x_off = mem->x_off;
+ change_info.y_off = mem->y_off;
+ change_info.width = mem->width;
+ change_info.height = mem->height;
+ gv_data_changed( GV_DATA(raster), &change_info );
+
+ gv_raster_del_memento( data, data_memento );
+}
+
+static void
+gv_raster_del_memento(GvData *data, GvDataMemento *data_memento)
+{
+ GvRasterMemento *memento = (GvRasterMemento *) data_memento;
+
+ if (memento->data)
+ g_free( memento->data );
+
+ g_free(memento);
+}
+
+/************************************************************************/
+/* gv_raster_set_gcps() */
+/************************************************************************/
+
+int gv_raster_set_gcps( GvRaster *raster, int gcp_count,
+ const GDAL_GCP *gcps )
+
+{
+ int success;
+
+ if( raster->gcp_count > 0 )
+ {
+ GDALDeinitGCPs( raster->gcp_count, raster->gcp_list );
+ CPLFree( raster->gcp_list );
+ raster->gcp_list = NULL;
+ }
+
+ raster->gcp_count = gcp_count;
+ if( gcp_count == 0 )
+ {
+ raster->poly_order = -1;
+ gtk_signal_emit(GTK_OBJECT(raster),
+ raster_signals[GEOTRANSFORM_CHANGED]);
+ return TRUE;
+ }
+
+ raster->gcp_list = GDALDuplicateGCPs( gcp_count, gcps );
+
+ success = gv_raster_build_poly_transform( raster );
+
+ if( !success )
+ gtk_signal_emit(GTK_OBJECT(raster),
+ raster_signals[GEOTRANSFORM_CHANGED]);
+
+ return success;
+}
+
+int gv_raster_set_gcpsCL( GvRaster *raster, int gcp_count,
+ const GDAL_GCP *gcps,int poly_order )
+
+{
+ int success;
+
+ if( raster->gcp_countCL > 0 )
+ {
+ GDALDeinitGCPs( raster->gcp_countCL, raster->gcp_listCL );
+ CPLFree( raster->gcp_listCL );
+ raster->gcp_listCL = NULL;
+ }
+
+ raster->gcp_countCL = gcp_count;
+ if( gcp_count == 0 )
+ {
+ raster->poly_orderCL = -1;
+ return TRUE;
+ }
+
+ raster->gcp_listCL = GDALDuplicateGCPs( gcp_count, gcps );
+
+ success = gv_raster_build_poly_transformCL( raster,poly_order );
+
+ return success;
+}
+
+/************************************************************************/
+/* gv_raster_get_gcp_count() */
+/************************************************************************/
+
+int gv_raster_get_gcp_count( GvRaster *raster )
+
+{
+ return raster->gcp_count;
+}
+
+int gv_raster_get_gcp_countCL( GvRaster *raster )
+
+{
+ return raster->gcp_countCL;
+}
+
+/************************************************************************/
+/* gv_raster_get_gcps() */
+/************************************************************************/
+
+const GDAL_GCP *gv_raster_get_gcps( GvRaster *raster )
+
+{
+ return raster->gcp_list;
+}
+
+const GDAL_GCP *gv_raster_get_gcpsCL( GvRaster *raster )
+
+{
+ return raster->gcp_listCL;
+}
+
+/* ==================================================================== */
+/* USE_CRS: GCP fitting using GRASS derived crs.c/h code. */
+/* ==================================================================== */
+
+#if defined(USE_CRS)
+
+/* build polynomial coefficients based on gcps */
+
+static gint gv_raster_build_poly_transform( GvRaster *raster )
+
+{
+ double *pixel, *line, *x, *y;
+#ifdef ATLANTIS_BUILD
+ double diff_x=0.0, diff_y=0.0;
+#endif
+ int i, *status, success;
+ struct Control_Points cps;
+
+ int poly_order_pref=1; /* polynomial order preference- only used if preference is set */
+
+ /* defaults */
+#ifdef ATLANTIS_BUILD
+ if( raster->gcp_count == 0 )
+ return FALSE;
+#else
+ if( raster->gcp_count < 3 )
+ return FALSE;
+#endif
+
+ if( raster->gcp_count >= 10 )
+ raster->poly_order = 2; /* 3rd order not too stable with CRS code */
+ else if( raster->gcp_count >= 6 )
+ raster->poly_order = 2;
+ else
+ raster->poly_order = 1;
+
+
+ /* User has specified a preference for polynomial order. Do a sanity */
+ /* check, then use it if it's reasonable */
+ if (gv_data_get_property( GV_DATA(raster), "poly_order_preference" ) != NULL )
+ {
+ poly_order_pref = atoi(gv_data_get_property( GV_DATA(raster), "poly_order_preference" ));
+ raster->poly_order = gv_raster_check_poly_order(raster,poly_order_pref);
+ if (poly_order_pref != raster->poly_order)
+ {
+ g_warning("gv_raster_build_poly_transform(): Inappropriate polynomial order setting.");
+ }
+
+ }
+
+ pixel = g_new(double,raster->gcp_count);
+ line = g_new(double,raster->gcp_count);
+ x = g_new(double,raster->gcp_count);
+ y = g_new(double,raster->gcp_count);
+ status = g_new(int,raster->gcp_count);
+
+ for( i = 0; i < raster->gcp_count; i++ )
+ {
+ x[i] = raster->gcp_list[i].dfGCPX;
+ y[i] = raster->gcp_list[i].dfGCPY;
+ pixel[i] = raster->gcp_list[i].dfGCPPixel;
+ line[i] = raster->gcp_list[i].dfGCPLine;
+ status[i] = 1; /* use this point */
+ }
+
+ raster->poly_x_coeff = g_new(double,20);
+ raster->poly_y_coeff = g_new(double,20);
+ raster->poly_z_coeff = NULL;
+ raster->poly_pixel_coeff = g_new(double,20);
+ raster->poly_line_coeff = g_new(double,20);
+
+ cps.count = raster->gcp_count;
+ cps.e1 = pixel;
+ cps.n1 = line;
+ cps.e2 = x;
+ cps.n2 = y;
+ cps.status = status;
+
+#ifdef ATLANTIS_BUILD
+ if( raster->gcp_count <3 )
+ {
+ for( i = 0; i < raster->gcp_count; i++ )
+ {
+ diff_x += (x[i]-pixel[i]);
+ diff_y += (y[i]-line[i]);
+ }
+ raster->poly_pixel_coeff[0] = -diff_x/(double)raster->gcp_count;
+ raster->poly_line_coeff[0] = -diff_y/(double)raster->gcp_count;
+ raster->poly_x_coeff[0] = -raster->poly_pixel_coeff[0];
+ raster->poly_y_coeff[0] = -raster->poly_line_coeff[0];
+ raster->poly_x_coeff[1] = raster->poly_pixel_coeff[1]=1.0;
+ raster->poly_y_coeff[2] = raster->poly_line_coeff[2]=1.0;
+
+ return TRUE;
+ }
+
+ success = CRS_compute_georef_equations( &cps,
+ raster->poly_x_coeff,
+ raster->poly_y_coeff,
+ raster->poly_pixel_coeff,
+ raster->poly_line_coeff,
+ raster->poly_order );
+
+#else
+ while( (success =
+ CRS_compute_georef_equations( &cps,
+ raster->poly_x_coeff,
+ raster->poly_y_coeff,
+ raster->poly_pixel_coeff,
+ raster->poly_line_coeff,
+ raster->poly_order )) != 1
+ && raster->poly_order > 1 )
+ {
+ raster->poly_order--;
+ }
+#endif
+
+ if( success != 1 )
+ {
+ g_warning( "CRS_compute_georef_equations failed." );
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ g_free( x );
+ g_free( y );
+ g_free( pixel );
+ g_free( line );
+ g_free( status );
+
+ gtk_signal_emit(GTK_OBJECT(raster),
+ raster_signals[GEOTRANSFORM_CHANGED]);
+
+ return TRUE;
+}
+
+static gint gv_raster_build_poly_transformCL( GvRaster *raster, int poly_order )
+
+{
+ double *pixel, *line, *x, *y;
+ double diff_x=0.0, diff_y=0.0;
+ int i, *status;
+ struct Control_Points cps;
+
+ if( raster->gcp_countCL == 0 )
+ return FALSE;
+
+ if (poly_order < 0)
+ {
+ /* default to 1 (poly_order < 0 used to indicate defaults should be used)*/
+ raster->poly_orderCL = 1;
+ }
+ else
+ {
+ raster->poly_orderCL = poly_order;
+ if ((raster->gcp_countCL < 6) && (poly_order > 1))
+ {
+ g_warning("Not enough gcp's for polynomial order > 1: resetting to 1.");
+ raster->poly_orderCL = 1;
+ }
+ else if ((raster->gcp_countCL < 10) && (poly_order > 2))
+ {
+ g_warning("Not enough gcp's for polynomial order > 2: resetting to 2.");
+ raster->poly_orderCL = 2;
+ }
+ }
+
+ pixel = g_new(double,raster->gcp_countCL);
+ line = g_new(double,raster->gcp_countCL);
+ x = g_new(double,raster->gcp_countCL);
+ y = g_new(double,raster->gcp_countCL);
+ status = g_new(int,raster->gcp_countCL);
+
+ for( i = 0; i < raster->gcp_countCL; i++ )
+ {
+ x[i] = raster->gcp_listCL[i].dfGCPX;
+ y[i] = raster->gcp_listCL[i].dfGCPY;
+ pixel[i] = raster->gcp_listCL[i].dfGCPPixel;
+ line[i] = raster->gcp_listCL[i].dfGCPLine;
+ status[i] = 1; /* use this point */
+ }
+
+ raster->poly_x_coeffCL = g_new(double,20);
+ raster->poly_y_coeffCL = g_new(double,20);
+ raster->poly_z_coeffCL = NULL;
+ raster->poly_pixel_coeffCL = g_new(double,20);
+ raster->poly_line_coeffCL = g_new(double,20);
+
+ cps.count = raster->gcp_countCL;
+ cps.e1 = pixel;
+ cps.n1 = line;
+ cps.e2 = x;
+ cps.n2 = y;
+ cps.status = status;
+
+ if( raster->gcp_countCL <3 )
+ {
+ for( i = 0; i < raster->gcp_countCL; i++ )
+ {
+ diff_x += (x[i]-pixel[i]);
+ diff_y += (y[i]-line[i]);
+ }
+ raster->poly_pixel_coeffCL[0] = -diff_x/(double)raster->gcp_countCL;
+ raster->poly_line_coeffCL[0] = -diff_y/(double)raster->gcp_countCL;
+ raster->poly_x_coeffCL[0] = -raster->poly_pixel_coeffCL[0];
+ raster->poly_y_coeffCL[0] = -raster->poly_line_coeffCL[0];
+ raster->poly_x_coeffCL[1] = raster->poly_pixel_coeffCL[1]=1.0;
+ raster->poly_y_coeffCL[2] = raster->poly_line_coeffCL[2]=1.0;
+
+ return TRUE;
+ }
+
+ if( CRS_compute_georef_equations( &cps,
+ raster->poly_x_coeffCL,
+ raster->poly_y_coeffCL,
+ raster->poly_pixel_coeffCL,
+ raster->poly_line_coeffCL,
+ raster->poly_orderCL ) != 1 )
+ {
+ g_warning( "CRS_compute_georef_equations failed." );
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ g_free( x );
+ g_free( y );
+ g_free( pixel );
+ g_free( line );
+ g_free( status );
+
+ return TRUE;
+}
+
+/* Transform pixel/line coordinates to georeferenced coordinates */
+
+gint gv_raster_pixel_to_georef( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_order > -1 )
+ {
+ CRS_georef( *x, *y, x, y,
+ raster->poly_x_coeff, raster->poly_y_coeff,
+ raster->poly_order );
+
+ /* z is left unchanged */
+ }
+ else
+ {
+ double x_out, y_out;
+
+ x_out = raster->geotransform[0]
+ + *x * raster->geotransform[1] + *y * raster->geotransform[2];
+ y_out = raster->geotransform[3]
+ + *x * raster->geotransform[4] + *y * raster->geotransform[5];
+
+ *x = x_out;
+ *y = y_out;
+ }
+
+ return TRUE;
+}
+
+gint gv_raster_pixel_to_georefCL( GvRaster *raster,
+ double *x, double *y, double *z )
+{
+ if (raster->poly_orderCL > -1 )
+ {
+ CRS_georef( *x, *y, x, y,
+ raster->poly_x_coeffCL, raster->poly_y_coeffCL,
+ raster->poly_orderCL );
+
+ /* z is left unchanged */
+ }
+ else
+ {
+ /* Default to standard transformation if cursor-link */
+ /* specific transforms aren't defined. */
+ gv_raster_pixel_to_georef(raster,x,y,z);
+ }
+
+ return TRUE;
+}
+
+/* Transform georeferenced coordinates to pixel/line coordinates */
+
+gint gv_raster_georef_to_pixel( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_order > -1 )
+ {
+ CRS_georef( *x, *y, x, y,
+ raster->poly_pixel_coeff, raster->poly_line_coeff,
+ raster->poly_order );
+
+ /* z is left unchanged */
+ }
+ else
+ {
+ double x_out, y_out, det;
+
+ det = ((raster->geotransform[1]*raster->geotransform[5])-
+ (raster->geotransform[2]*raster->geotransform[4]));
+
+ if (fabs(det) < 0.000000000000001)
+ return FALSE;
+
+ /* Original code commented out below: it left out the rotational terms! */
+ /* *x = (*x - raster->geotransform[0]) / raster->geotransform[1]; */
+ /* *y = (*y - raster->geotransform[3]) / raster->geotransform[5]; */
+
+ x_out = ((raster->geotransform[5]*(*x - raster->geotransform[0])) -
+ (raster->geotransform[2]*(*y - raster->geotransform[3])))/ det;
+
+ y_out = ((raster->geotransform[1]*(*y - raster->geotransform[3])) -
+ (raster->geotransform[4]*(*x - raster->geotransform[0])))/ det;
+
+ *x = x_out;
+ *y = y_out;
+
+ }
+
+ return TRUE;
+}
+
+gint gv_raster_georef_to_pixelCL( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+
+ if( raster->poly_orderCL > -1 )
+ {
+ CRS_georef( *x, *y, x, y,
+ raster->poly_pixel_coeffCL, raster->poly_line_coeffCL,
+ raster->poly_orderCL );
+ /* z is left unchanged */
+ }
+ else
+ {
+ /* Default to standard transformation if cursor-link */
+ /* specific transforms aren't defined. */
+ gv_raster_georef_to_pixel(raster,x,y,z);
+ }
+
+ return TRUE;
+}
+
+#endif /* defined(USE_CRS) */
+
+/* ==================================================================== */
+/* not defined USE_CRS: GCP fitting using EarthView derived */
+/* code in gvgcpfit.c */
+/* ==================================================================== */
+
+#if !defined(USE_CRS)
+
+/* build polynomial coefficients based on gcps */
+
+static gint gv_raster_build_poly_transform( GvRaster *raster )
+
+{
+ double *pixel, *line, *x, *y, *z, rms;
+ int i;
+
+ int poly_order_pref=1; /* polynomial order preference- only used if preference is set */
+
+ if( raster->gcp_count < 3 )
+ return FALSE;
+
+ if( raster->gcp_count >= 10 )
+ raster->poly_order = 3;
+ else if( raster->gcp_count >= 6 )
+ raster->poly_order = 2;
+ else
+ raster->poly_order = 1;
+
+ /* User has specified a preference for polynomial order. Do a sanity */
+ /* check, then use it if it's reasonable */
+ if (gv_data_get_property( GV_DATA(raster), "poly_order_preference" ) != NULL )
+ {
+ poly_order_pref = atoi(gv_data_get_property( GV_DATA(raster), "poly_order_preference" ));
+ raster->poly_order = gv_raster_check_poly_order(raster,poly_order_pref);
+ if (poly_order_pref != raster->poly_order)
+ {
+ g_warning("gv_raster_build_poly_transform(): Inappropriate polynomial order setting.");
+ }
+
+ }
+
+ pixel = g_new(double,raster->gcp_count);
+ line = g_new(double,raster->gcp_count);
+ x = g_new(double,raster->gcp_count);
+ y = g_new(double,raster->gcp_count);
+ z = g_new(double,raster->gcp_count);
+
+ for( i = 0; i < raster->gcp_count; i++ )
+ {
+ x[i] = raster->gcp_list[i].dfGCPX;
+ y[i] = raster->gcp_list[i].dfGCPY;
+ z[i] = raster->gcp_list[i].dfGCPZ;
+ pixel[i] = raster->gcp_list[i].dfGCPPixel;
+ line[i] = raster->gcp_list[i].dfGCPLine;
+ }
+
+ raster->poly_x_coeff = g_new(double,20);
+ raster->poly_y_coeff = g_new(double,20);
+ raster->poly_z_coeff = g_new(double,20);
+ raster->poly_pixel_coeff = g_new(double,20);
+ raster->poly_line_coeff = g_new(double,20);
+
+ if( TwoDPolyFit( &rms, raster->poly_x_coeff, raster->poly_order,
+ raster->gcp_count, x, pixel, line ) != SUCCESS )
+ {
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_y_coeff, raster->poly_order,
+ raster->gcp_count, y, pixel, line ) != SUCCESS )
+ {
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_z_coeff, raster->poly_order,
+ raster->gcp_count, z, pixel, line ) != SUCCESS )
+ {
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_pixel_coeff, raster->poly_order,
+ raster->gcp_count, pixel, x, y ) != SUCCESS )
+ {
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_line_coeff, raster->poly_order,
+ raster->gcp_count, line, x, y ) != SUCCESS )
+ {
+ raster->poly_order = -1;
+ return FALSE;
+ }
+
+ g_free( x );
+ g_free( y );
+ g_free( z );
+ g_free( pixel );
+ g_free( line );
+
+ gtk_signal_emit(GTK_OBJECT(raster),
+ raster_signals[GEOTRANSFORM_CHANGED]);
+
+ return TRUE;
+}
+static gint gv_raster_build_poly_transformCL( GvRaster *raster, int poly_order )
+
+{
+ double *pixel, *line, *x, *y, *z, rms;
+ int i;
+
+ if( raster->gcp_countCL < 3 )
+ return FALSE;
+
+ if (poly_order < 0)
+ {
+ /* poly_order < 0 used to indicate defaults should be used */
+ if( raster->gcp_countCL >= 10 )
+ raster->poly_orderCL = 3;
+ else if( raster->gcp_countCL >= 6 )
+ raster->poly_orderCL = 2;
+ else
+ raster->poly_orderCL = 1;
+
+ }
+ else
+ {
+ raster->poly_orderCL = poly_order;
+ if ((raster->gcp_countCL < 6) && (poly_order > 1))
+ {
+ g_warning("Not enough gcp's for polynomial order > 1: resetting to 1.");
+ raster->poly_orderCL = 1;
+ }
+ else if ((raster->gcp_countCL < 10) && (poly_order > 2))
+ {
+ g_warning("Not enough gcp's for polynomial order > 2: resetting to 2.");
+ raster->poly_orderCL = 2;
+ }
+ }
+
+
+ pixel = g_new(double,raster->gcp_countCL);
+ line = g_new(double,raster->gcp_countCL);
+ x = g_new(double,raster->gcp_countCL);
+ y = g_new(double,raster->gcp_countCL);
+ z = g_new(double,raster->gcp_countCL);
+
+ for( i = 0; i < raster->gcp_countCL; i++ )
+ {
+ x[i] = raster->gcp_listCL[i].dfGCPX;
+ y[i] = raster->gcp_listCL[i].dfGCPY;
+ z[i] = raster->gcp_listCL[i].dfGCPZ;
+ pixel[i] = raster->gcp_listCL[i].dfGCPPixel;
+ line[i] = raster->gcp_listCL[i].dfGCPLine;
+ }
+
+ raster->poly_x_coeffCL = g_new(double,20);
+ raster->poly_y_coeffCL = g_new(double,20);
+ raster->poly_z_coeffCL = g_new(double,20);
+ raster->poly_pixel_coeffCL = g_new(double,20);
+ raster->poly_line_coeffCL = g_new(double,20);
+
+ if( TwoDPolyFit( &rms, raster->poly_x_coeffCL, raster->poly_orderCL,
+ raster->gcp_countCL, x, pixel, line ) != SUCCESS )
+ {
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_y_coeffCL, raster->poly_orderCL,
+ raster->gcp_countCL, y, pixel, line ) != SUCCESS )
+ {
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_z_coeffCL, raster->poly_orderCL,
+ raster->gcp_countCL, z, pixel, line ) != SUCCESS )
+ {
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_pixel_coeffCL, raster->poly_orderCL,
+ raster->gcp_countCL, pixel, x, y ) != SUCCESS )
+ {
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ if( TwoDPolyFit( &rms, raster->poly_line_coeffCL, raster->poly_orderCL,
+ raster->gcp_countCL, line, x, y ) != SUCCESS )
+ {
+ raster->poly_orderCL = -1;
+ return FALSE;
+ }
+
+ g_free( x );
+ g_free( y );
+ g_free( z );
+ g_free( pixel );
+ g_free( line );
+
+ return TRUE;
+}
+
+/* Transform pixel/line coordinates to georeferenced coordinates */
+
+gint gv_raster_pixel_to_georef( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_order > -1 )
+ {
+ double x_out, y_out, z_out;
+
+ x_out = TwoDPolyEval( raster->poly_x_coeff, raster->poly_order,
+ *x, *y );
+
+ y_out = TwoDPolyEval( raster->poly_y_coeff, raster->poly_order,
+ *x, *y );
+
+ z_out = TwoDPolyEval( raster->poly_z_coeff, raster->poly_order,
+ *x, *y );
+
+ *x = x_out;
+ *y = y_out;
+
+ if( z != NULL )
+ *z = z_out;
+ }
+ else
+ {
+ double x_out, y_out;
+
+ x_out = raster->geotransform[0]
+ + *x * raster->geotransform[1] + *y * raster->geotransform[2];
+ y_out = raster->geotransform[3]
+ + *x * raster->geotransform[4] + *y * raster->geotransform[5];
+
+ *x = x_out;
+ *y = y_out;
+ }
+
+ return TRUE;
+}
+
+gint gv_raster_pixel_to_georefCL( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_orderCL > -1 )
+ {
+ double x_out, y_out, z_out;
+
+ x_out = TwoDPolyEval( raster->poly_x_coeffCL, raster->poly_orderCL,
+ *x, *y );
+
+ y_out = TwoDPolyEval( raster->poly_y_coeffCL, raster->poly_orderCL,
+ *x, *y );
+
+ z_out = TwoDPolyEval( raster->poly_z_coeffCL, raster->poly_orderCL,
+ *x, *y );
+
+ *x = x_out;
+ *y = y_out;
+
+ if( z != NULL )
+ *z = z_out;
+ }
+ else
+ {
+ /* Default to standard transformation if cursor-link */
+ /* specific transforms aren't defined. */
+ gv_raster_pixel_to_georef(raster,x,y,z);
+ }
+
+ return TRUE;
+}
+
+/* Transform georeferenced coordinates to pixel/line coordinates */
+
+gint gv_raster_georef_to_pixel( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_order > -1 )
+ {
+ double x_out, y_out;
+
+ x_out = TwoDPolyEval( raster->poly_pixel_coeff, raster->poly_order,
+ *x, *y );
+
+ y_out = TwoDPolyEval( raster->poly_line_coeff, raster->poly_order,
+ *x, *y );
+
+ *x = x_out;
+ *y = y_out;
+ }
+ else
+ {
+ *x = (*x - raster->geotransform[0]) / raster->geotransform[1];
+ *y = (*y - raster->geotransform[3]) / raster->geotransform[5];
+ }
+
+ return TRUE;
+}
+gint gv_raster_georef_to_pixelCL( GvRaster *raster,
+ double *x, double *y, double *z )
+
+{
+ if( raster->poly_orderCL > -1 )
+ {
+ double x_out, y_out;
+
+ x_out = TwoDPolyEval( raster->poly_pixel_coeffCL, raster->poly_orderCL,
+ *x, *y );
+
+ y_out = TwoDPolyEval( raster->poly_line_coeffCL, raster->poly_orderCL,
+ *x, *y );
+
+ *x = x_out;
+ *y = y_out;
+ }
+ else
+ {
+ /* Default to standard transformation if cursor-link */
+ /* specific transforms aren't defined. */
+ gv_raster_georef_to_pixel(raster,x,y,z);
+ }
+
+ return TRUE;
+}
+
+#endif /* !defined(USE_CRS) */
+
+/* ========================================================================= */
+/* gv_raster_check_poly_order: Sanity check the desired polynomial order */
+/* input: raster, desired polynomial order. */
+/* output: closest matching polynomial order. */
+/* ========================================================================= */
+static int gv_raster_check_poly_order( GvRaster *raster,
+ int desired_poly_order )
+{
+ int poly_order;
+
+ poly_order = desired_poly_order;
+
+ if (poly_order > 3)
+ {
+
+ if( raster->gcp_count >= 10 )
+ poly_order = 3;
+ else if( raster->gcp_count >= 6 )
+ poly_order = 2;
+ else
+ poly_order = 1;
+
+ }
+ else if (poly_order == 3)
+ {
+ if( raster->gcp_count < 6 )
+ poly_order = 1;
+ else if (raster->gcp_count < 10)
+ poly_order = 2;
+
+ }
+ else if (poly_order == 2)
+ {
+ if( raster->gcp_count < 6 )
+ poly_order = 1;
+
+ }
+ else if (poly_order < 1)
+ poly_order = 1;
+
+ return poly_order;
+
+}
+
+void gv_raster_set_poly_order_preference( GvRaster *raster, int poly_order )
+{
+ char txt[16];
+ int success;
+
+ sprintf(txt,"%d",poly_order);
+ gv_data_set_property(GV_DATA(raster),"poly_order_preference",txt );
+
+ if (raster->gcp_count > 0)
+ {
+ /* If gcps have already been set, rebuild poly transform */
+ success = gv_raster_build_poly_transform( raster );
+
+ if( !success )
+ gtk_signal_emit(GTK_OBJECT(raster),
+ raster_signals[GEOTRANSFORM_CHANGED]);
+ }
+
+}
Added: packages/openev/branches/upstream/current/gvraster.h
===================================================================
--- packages/openev/branches/upstream/current/gvraster.h (rev 0)
+++ packages/openev/branches/upstream/current/gvraster.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,223 @@
+/******************************************************************************
+ * $Id: gvraster.h,v 1.28 2004/01/22 19:57:11 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster data container.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvraster.h,v $
+ * Revision 1.28 2004/01/22 19:57:11 andrey_kiselev
+ * Use gv_raster_get_nodata() function to fetch the NODATA value from the image
+ * using GDALGetRasterNoDataValue().
+ *
+ * Revision 1.27 2003/09/11 20:00:30 gmwalter
+ * Add ability to specify a preferred polynomial order for warping a raster,
+ * and add "safe mode" (only used if ATLANTIS_BUILD is defined).
+ *
+ * Revision 1.26 2003/02/20 19:27:16 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.25 2001/11/28 19:18:29 warmerda
+ * Added set_gcps(), and get_gcps() methods on GvRaster, and the
+ * geotransform-changed signal generated when the gcps change.
+ *
+ * Revision 1.24 2001/10/16 18:50:06 warmerda
+ * now possible to pass sample set into autoscale
+ *
+ * Revision 1.23 2001/08/14 17:03:24 warmerda
+ * added standard deviation autoscaling support
+ *
+ * Revision 1.22 2001/07/24 02:21:54 warmerda
+ * added 8bit phase averaging
+ *
+ * Revision 1.21 2001/07/13 22:15:36 warmerda
+ * added nodata aware averaging
+ *
+ * Revision 1.20 2001/04/02 18:10:46 warmerda
+ * expose gv_raster_autoscale() to python
+ *
+ * Revision 1.19 2000/09/27 19:18:50 warmerda
+ * Honour GvSMSample for real and complex images.
+ * Add GvRaster.sm field. If set to GvSMSample always let GDAL do the
+ * decimation for faster loads.
+ *
+ * Revision 1.18 2000/06/26 15:12:47 warmerda
+ * added get_min, get_max macros
+ *
+ * Revision 1.17 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_RASTER_H__
+#define __GV_RASTER_H__
+
+#include "gvdata.h"
+#include "gvrastercache.h"
+#include "gvmesh.h"
+
+#include "gdal.h"
+
+#define GV_TYPE_RASTER (gv_raster_get_type ())
+#define GV_RASTER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_RASTER, GvRaster))
+#define GV_RASTER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_RASTER, GvRasterClass))
+#define GV_IS_RASTER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_RASTER))
+#define GV_IS_RASTER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_RASTER))
+
+typedef enum {
+ GvSMAverage = 0,
+ GvSMSample = 1,
+ GvSMAverage8bitPhase = 2
+} GvSampleMethod;
+
+typedef enum {
+ GvASAAutomatic = 0,
+ GvASAPercentTailTrim = 1,
+ GvASAStdDeviation = 2
+} GvAutoScaleAlg;
+
+typedef struct _GvRaster GvRaster;
+typedef struct _GvRasterClass GvRasterClass;
+
+#define GV_TILE_OVERLAP 2
+
+struct _GvRaster
+{
+ GvData data;
+
+ gint max_tiles, /* total tiles */
+ width, /* width of raster */
+ height, /* height of raster */
+ tile_x, /* tile width */
+ tile_y, /* tile height */
+ tiles_across, /* tiles per row */
+ tiles_down, /* tiles per column */
+ max_lod; /* maximum level of detail(+1) */
+
+ float min, max; /* suggested scaling min/max */
+
+ GvSampleMethod sm; /* Sample method */
+ void *(*average)(GvRaster *raster, void *buffer, int tsize_x, int tsize_y);
+
+ int type; /* GV_RASTER_* */
+ int item_size; /* size of pixel group */
+
+ gv_raster_cache *cache; /* read cache */
+
+ double geotransform[6]; /* pl to georef transform */
+
+ int gcp_count; /* 0 if not relativant */
+ GDAL_GCP *gcp_list;
+ int poly_order; /* -1 if not intialized */
+ double *poly_pixel_coeff;
+ double *poly_line_coeff;
+ double *poly_x_coeff;
+ double *poly_y_coeff;
+ double *poly_z_coeff;
+
+ /* Separate transformations to be used by ghost cursor and linking */
+ /* DEFAULTS TO REGULAR TRANSFORMATION IF THESE AREN'T SET */
+ int gcp_countCL; /* 0 if not relativant */
+ GDAL_GCP *gcp_listCL;
+ int poly_orderCL; /* -1 if not intialized */
+ double *poly_pixel_coeffCL;
+ double *poly_line_coeffCL;
+ double *poly_x_coeffCL;
+ double *poly_y_coeffCL;
+ double *poly_z_coeffCL;
+
+ /* End of cursor/link-specific transform stuff */
+
+ GDALDatasetH dataset; /* source dataset */
+ GDALRasterBandH gdal_band; /* real band */
+
+ GDALDataType gdal_type; /* GDT_Byte, etc */
+};
+
+struct _GvRasterClass
+{
+ GvDataClass parent_class;
+ void (* geotransform_changed)(GvRaster *raster);
+};
+
+GtkType gv_raster_get_type(void);
+
+GvData* gv_raster_new( GDALDatasetH dataset, int real_band, GvSampleMethod sm);
+
+void *gv_raster_tile_get(GvRaster *raster, int tile, int lod );
+gint *gv_raster_tile_xy_get(GvRaster *raster, int tile, int lod, gint *coords);
+gint gv_raster_datatype_get(GvRaster *raster );
+gint gv_raster_dataformat_get(GvRaster *raster );
+void gv_raster_flush_cache(GvRaster *raster,
+ int x_off, int y_off, int width, int height );
+gint gv_raster_get_nodata(GvRaster *raster, double *nodata );
+gint gv_raster_get_sample(GvRaster *raster, double x, double y,
+ double *real, double *imaginary );
+double gv_raster_pixel_size( GvRaster *raster );
+gint gv_raster_pixel_to_georef(GvRaster *raster,
+ double *x, double *y, double *z );
+gint gv_raster_georef_to_pixel(GvRaster *raster,
+ double *x, double *y, double *z );
+gint gv_raster_autoscale( GvRaster *raster, GvAutoScaleAlg alg,
+ double alg_param,
+ int sample_count, float *sample_set,
+ double *out_min, double *out_max );
+int gv_raster_collect_random_sample( GvRaster *raster,
+ int sample_count, float *sample_set,
+ int xoff, int yoff, int xsize, int ysize,
+ GArray *tile_list );
+
+int
+gv_raster_collect_histogram(GvRaster *raster,
+ double scale_min, double scale_max,
+ int bucket_count, int *histogram,
+ int include_out_of_range,
+ int xoff, int yoff, int xsize, int ysize,
+ GArray *tile_list );
+
+#define gv_raster_get_min(raster) ((GV_RASTER(raster))->min)
+#define gv_raster_get_max(raster) ((GV_RASTER(raster))->max)
+
+int gv_raster_set_gcps(GvRaster *raster, int gcp_count, const GDAL_GCP *gcps);
+int gv_raster_get_gcp_count(GvRaster *raster);
+const GDAL_GCP *gv_raster_get_gcps(GvRaster *raster);
+
+
+/* Cursor/Link specific transforms (only used if set)*/
+int gv_raster_set_gcpsCL(GvRaster *raster, int gcp_count, const GDAL_GCP *gcps, int poly_order);
+int gv_raster_get_gcp_countCL(GvRaster *raster);
+const GDAL_GCP *gv_raster_get_gcpsCL(GvRaster *raster);
+gint gv_raster_pixel_to_georefCL(GvRaster *raster,
+ double *x, double *y, double *z );
+gint gv_raster_georef_to_pixelCL(GvRaster *raster,
+ double *x, double *y, double *z );
+
+/* Set preferred polynomial order for this raster (optional) */
+void gv_raster_set_poly_order_preference( GvRaster *raster, int poly_order );
+
+#endif /* __GV_RASTER_H__ */
+
Added: packages/openev/branches/upstream/current/gvrasteraverage.c
===================================================================
--- packages/openev/branches/upstream/current/gvrasteraverage.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrasteraverage.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,384 @@
+/******************************************************************************
+ * $Id: gvrasteraverage.c,v 1.18 2004/02/18 16:07:27 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster downsampling kernels (averaged and otherwise)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasteraverage.c,v $
+ * Revision 1.18 2004/02/18 16:07:27 andrey_kiselev
+ * Use gv_raster_get_nodata() instead of GDALGetRasterNoDataValue().
+ *
+ * Revision 1.17 2002/11/27 04:35:59 warmerda
+ * try to mitigate the downward bias of averaging due to truncation in 8bit
+ *
+ * Revision 1.16 2001/07/24 02:23:53 warmerda
+ * removed debugging printf
+ *
+ * Revision 1.15 2001/07/24 02:21:54 warmerda
+ * added 8bit phase averaging
+ *
+ * Revision 1.14 2001/07/16 15:07:45 warmerda
+ * rewrote complex averaging to precisely average magnitudes
+ *
+ * Revision 1.13 2001/07/13 22:15:36 warmerda
+ * added nodata aware averaging
+ *
+ * Revision 1.12 2001/01/30 19:27:51 warmerda
+ * added logic to try and preserve stddev in complex average code
+ *
+ * Revision 1.11 2000/09/27 19:17:28 warmerda
+ * added new _sample functions
+ *
+ * Revision 1.10 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <math.h>
+#include "gvraster.h"
+#include "gvrasteraverage.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+/* This function does the equivelent of the GDAL "MAGPHASE" averaging.
+ * It produces a magnitude weighted average of phase (by operating in
+ * real/imaginary space) and then scales the resulting magnitude by
+ * the averaged magnitude to preserve the average magnitude.
+ */
+
+float *gv_raster_float_complex_average( GvRaster *raster,
+ float *iq, int tsize_x, int tsize_y )
+{
+ int i, base, averaged_size, next_base;
+ float *iq_average, target_mag, ratio, prefix_mag;
+
+ averaged_size = (tsize_x * tsize_y) / 4;
+
+ if( ( iq_average = g_new( float, averaged_size*2 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < averaged_size; i++ )
+ {
+ base = ( ( ( i * 2 ) / tsize_x ) * tsize_x * 2 ) + ( 4 * i );
+ next_base = base + tsize_x*2;
+
+ iq_average[2*i] = ( iq[base] + iq[base+2] + iq[next_base] + iq[next_base+2] ) / 4;
+ iq_average[2*i+1] = ( iq[base+1] + iq[base+3] + iq[next_base+1] + iq[next_base+3] ) / 4;
+
+ /*
+ * Compute average of input magnitudes and use this to scale the output
+ * magnitude.
+ */
+ target_mag = (
+ sqrt(iq[base]*iq[base] + iq[base+1]*iq[base+1])
+ + sqrt(iq[base+2]*iq[base+2] + iq[base+3]*iq[base+3])
+ + sqrt(iq[next_base]*iq[next_base] + iq[next_base+1]*iq[next_base+1])
+ + sqrt(iq[next_base+2]*iq[next_base+2] + iq[next_base+3]*iq[next_base+3])
+ ) / 4.0;
+
+ prefix_mag = sqrt(iq_average[2*i]*iq_average[2*i]
+ + iq_average[2*i+1]*iq_average[2*i+1]);
+
+ if( prefix_mag != 0.0 && target_mag != 0.0 )
+ {
+ ratio = target_mag / prefix_mag;
+ iq_average[2*i] *= ratio;
+ iq_average[2*i+1] *= ratio;
+ }
+ }
+ return iq_average;
+}
+
+float *gv_raster_float_complex_sample( GvRaster *raster,
+ float *iq, int tsize_x, int tsize_y )
+{
+ float *avg, *buf_out;
+ int i, e;
+
+ if( ( avg = g_new( float, tsize_x * tsize_y / 2 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ buf_out = avg;
+ for( i = 0; i < tsize_y; i += 2 )
+ {
+ float *buf_in;
+
+ buf_in = iq + i * tsize_x * 2;
+
+ for( e = tsize_x/2; e > 0; e-- )
+ {
+ *(buf_out++) = *(buf_in++);
+ *(buf_out++) = *(buf_in++);
+ buf_in += 2;
+ }
+ }
+
+ return avg;
+}
+
+float *gv_raster_float_real_average( GvRaster *raster,
+ float *buffer, int tsize_x, int tsize_y )
+{
+ float *avg, total;
+ int i, e, base;
+
+ if( ( avg = g_new( float, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < tsize_y >> 1; i++ )
+ {
+ for( e = 0; e < tsize_x >> 1; e++ )
+ {
+ base = 2*((i*tsize_x)+e);
+ total = buffer[base];
+ total += buffer[base+1];
+ total += buffer[base+tsize_x];
+ total += buffer[base+tsize_x+1];
+
+ avg[i*(tsize_y>>1)+e] = total / 4;
+ }
+ }
+
+ return avg;
+
+}
+
+float *gv_raster_float_real_average_nodata( GvRaster *raster, float *buffer,
+ int tsize_x, int tsize_y )
+{
+ int i, e, base;
+ float *avg, total;
+ double nodata;
+
+ gv_raster_get_nodata( raster, &nodata );
+
+ if( ( avg = g_new( float, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < tsize_y >> 1; i++ )
+ {
+ for( e = 0; e < tsize_x >> 1; e++ )
+ {
+ int count = 0;
+
+ total = 0;
+ base = 2*((i*tsize_x)+e);
+
+ if( buffer[base] != (float)nodata )
+ {
+ total += buffer[base];
+ count++;
+ }
+ if( buffer[base+1] != (float)nodata )
+ {
+ total += buffer[base+1];
+ count++;
+ }
+ if( buffer[base+tsize_x] != (float)nodata )
+ {
+ total += buffer[base+tsize_x];
+ count++;
+ }
+ if( buffer[base+tsize_x+1] != (float)nodata )
+ {
+ total += buffer[base+tsize_x+1];
+ count++;
+ }
+
+ if( count > 0 )
+ avg[i*(tsize_y>>1)+e] = total / count;
+ else
+ avg[i*(tsize_y>>1)+e] = (float)nodata;
+ }
+ }
+
+ return avg;
+
+}
+
+float *gv_raster_float_real_sample( GvRaster *raster,
+ float *buffer, int tsize_x, int tsize_y )
+{
+ float *avg, *buf_out;
+ int i, e;
+
+ if( ( avg = g_new( float, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ buf_out = avg;
+ for( i = 0; i < tsize_y; i += 2 )
+ {
+ float *buf_in;
+
+ buf_in = buffer + i * tsize_x;
+
+ for( e = tsize_x/2; e > 0; e-- )
+ {
+ *(buf_out++) = *buf_in;
+ buf_in += 2;
+ }
+ }
+
+ return avg;
+}
+
+/* Convert 8bit phase into complex value with magnitude 1. */
+
+static void gvrf_8bit_phase_to_complex( int in_phase, float *r, float *i )
+{
+ float phase = (in_phase / 256.0) * 2 * M_PI;
+
+ if( phase > M_PI )
+ phase -= 2*M_PI;
+
+ *r = cos(phase);
+ *i = sin(phase);
+}
+
+/*
+** This is a specialized algorithm to average 8bit phase information.
+** The phase is rescaled into 0->2PI (from 0-255), translated into unit
+** length complex vectors and then averaged. The resulting complex value
+** is converted back into phase and rescaled into 0-255.
+*/
+
+unsigned char *gv_raster_byte_realphase_average( GvRaster *raster,
+ unsigned char *buffer, int tsize_x, int tsize_y )
+{
+ unsigned char *avg;
+ int i, e, base;
+
+ if( ( avg = g_new( unsigned char, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < tsize_y >> 1; i++ )
+ {
+ for( e = 0; e < tsize_x >> 1; e++ )
+ {
+ float total_r = 0.0, total_i = 0.0;
+ float real, imag, phase;
+
+ base = 2*((i*tsize_x)+e);
+
+ gvrf_8bit_phase_to_complex( buffer[base], &real, &imag );
+ total_r += real;
+ total_i += imag;
+
+ gvrf_8bit_phase_to_complex( buffer[base+1], &real, &imag );
+ total_r += real;
+ total_i += imag;
+
+ gvrf_8bit_phase_to_complex( buffer[base+tsize_x], &real, &imag );
+ total_r += real;
+ total_i += imag;
+
+ gvrf_8bit_phase_to_complex( buffer[base+tsize_x+1], &real, &imag );
+ total_r += real;
+ total_i += imag;
+
+ real = total_r * 0.25;
+ imag = total_i * 0.25;
+
+ phase = atan2(imag, real);
+ while( phase < 0.0 )
+ phase += 2 * M_PI;
+ while( phase >= 2*M_PI )
+ phase -= 2 * M_PI;
+
+ avg[i*(tsize_y>>1)+e] = floor((phase * 256) / (2*M_PI));
+ }
+ }
+
+ return avg;
+}
+
+unsigned char *gv_raster_byte_real_average( GvRaster *raster,
+ unsigned char *buffer,
+ int tsize_x, int tsize_y )
+{
+ unsigned char *avg;
+ int i, e, total, base;
+
+ if( ( avg = g_new( unsigned char, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < tsize_y >> 1; i++ )
+ {
+ for( e = 0; e < tsize_x >> 1; e++ )
+ {
+ base = 2*((i*tsize_x)+e);
+ total = buffer[base];
+ total += buffer[base+1];
+ total += buffer[base+tsize_x];
+ total += buffer[base+tsize_x+1];
+
+ avg[i*(tsize_y>>1)+e] = (total+2) / 4;
+ }
+ }
+
+ return avg;
+}
+
+unsigned char *gv_raster_byte_real_sample( GvRaster *raster,
+ unsigned char *buffer,
+ int tsize_x, int tsize_y )
+{
+ unsigned char *avg;
+ int i, e, base;
+
+ if( ( avg = g_new( unsigned char, tsize_x * tsize_y / 4 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ for( i = 0; i < tsize_y >> 1; i++ )
+ {
+ for( e = 0; e < tsize_x >> 1; e++ )
+ {
+ base = 2*((i*tsize_x)+e);
+ avg[i*(tsize_y>>1)+e] = buffer[base];
+ }
+ }
+
+ return avg;
+}
+
Added: packages/openev/branches/upstream/current/gvrasteraverage.h
===================================================================
--- packages/openev/branches/upstream/current/gvrasteraverage.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrasteraverage.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: gvrasteraverage.h,v 1.8 2001/07/24 02:21:54 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster downsampling kernels (averaged and otherwise)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasteraverage.h,v $
+ * Revision 1.8 2001/07/24 02:21:54 warmerda
+ * added 8bit phase averaging
+ *
+ * Revision 1.7 2001/07/13 22:15:36 warmerda
+ * added nodata aware averaging
+ *
+ * Revision 1.6 2000/09/27 19:17:28 warmerda
+ * added new _sample functions
+ *
+ * Revision 1.5 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef _GV_RASTER_AVERAGE_H_
+#define _GV_RASTER_AVERAGE_H_
+
+unsigned char *gv_raster_byte_real_average( GvRaster *raster,
+ unsigned char *buffer,
+ int tsize_x, int tsize_y );
+unsigned char *gv_raster_byte_real_sample( GvRaster *raster,
+ unsigned char *buffer,
+ int tsize_x, int tsize_y );
+
+unsigned char *gv_raster_byte_realphase_average( GvRaster *raster,
+ unsigned char *buffer, int tsize_x, int tsize_y );
+
+float *gv_raster_float_real_average_nodata( GvRaster *raster, float *buffer,
+ int tsize_x, int tsize_y );
+float *gv_raster_float_real_average( GvRaster *raster,
+ float *buffer, int tsize_x, int tsize_y );
+float *gv_raster_float_real_sample( GvRaster *raster,
+ float *buffer, int tsize_x, int tsize_y );
+
+float *gv_raster_float_complex_average(GvRaster *raster,
+ float *buffer,int tsize_x,int tsize_y);
+float *gv_raster_float_complex_sample(GvRaster *raster,
+ float *buffer,int tsize_x,int tsize_y);
+
+#endif
Added: packages/openev/branches/upstream/current/gvrastercache.c
===================================================================
--- packages/openev/branches/upstream/current/gvrastercache.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrastercache.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,304 @@
+/******************************************************************************
+ * $Id: gvrastercache.c,v 1.12 2000/06/20 13:26:55 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvRaster tile caching.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrastercache.c,v $
+ * Revision 1.12 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "gvrastercache.h"
+
+static gint gv_cache_max = 20 * 1024 * 1024;
+static gint gv_cache_used = 0;
+
+static gv_raster_cache_tile *lru_head = NULL;
+static gv_raster_cache_tile *lru_tail = NULL;
+
+
+static void gv_raster_cache_tile_touch( gv_raster_cache_tile * );
+static int gv_raster_cache_purge_lru();
+
+gv_raster_cache *
+gv_raster_cache_new( gint tiles, gint lod )
+{
+ gv_raster_cache *cache;
+ int i;
+
+ if( ( cache = g_new( gv_raster_cache, 1 ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ cache->max_lod = lod;
+ cache->max_tiles = tiles;
+
+ /* Allocate tile pointer arrays, but not the tiles themselves */
+ if( (cache->tiles = g_new(gv_raster_cache_tile**,cache->max_lod)) == NULL )
+ {
+ g_free( cache );
+ return NULL;
+ }
+
+ for( i = 0; i < cache->max_lod; i++ )
+ {
+ cache->tiles[i] = g_new0(gv_raster_cache_tile*,cache->max_tiles);
+ if( cache->tiles[i] == NULL )
+ return NULL;
+ }
+
+ return cache;
+}
+
+void *gv_raster_cache_get( gv_raster_cache *cache, gint tile, gint lod )
+{
+ if( tile < cache->max_tiles && lod < cache->max_lod
+ && cache->tiles[lod][tile] )
+ {
+ gv_raster_cache_tile_touch( cache->tiles[lod][tile] );
+ return cache->tiles[lod][tile]->data;
+ } else {
+ return NULL;
+ }
+}
+
+int gv_raster_cache_get_max()
+
+{
+ return gv_cache_max;
+}
+
+void gv_raster_cache_set_max( int new_max )
+
+{
+ gv_cache_max = new_max;
+
+ /* free space to ensure we stay below our limit */
+ while( gv_cache_used > gv_cache_max )
+ {
+ if( !gv_raster_cache_purge_lru() )
+ break;
+ }
+}
+
+int gv_raster_cache_get_used()
+
+{
+ return gv_cache_used;
+}
+
+void
+gv_raster_cache_put( gv_raster_cache *cache, gint tile, gint lod, void *data, gint size )
+{
+ gv_raster_cache_tile *tile_obj;
+
+ if( tile >= cache->max_tiles || lod >= cache->max_lod )
+ {
+ g_warning( "Illegal tile or lod in gv_raster_cache_put" );
+ return;
+ }
+
+ /* If there is an existing tile, just blow it away */
+ tile_obj = cache->tiles[lod][tile];
+ if( tile_obj != NULL )
+ gv_raster_cache_del( cache, tile, lod );
+
+ /* free space to ensure we stay below our limit */
+ while( gv_cache_used + size > gv_cache_max )
+ {
+ if( !gv_raster_cache_purge_lru() )
+ break;
+ }
+
+ /* create a new tile */
+ tile_obj = cache->tiles[lod][tile] = g_new0(gv_raster_cache_tile,1);
+ tile_obj->tile = tile;
+ tile_obj->lod = lod;
+ tile_obj->cache = cache;
+ tile_obj->data = data;
+ tile_obj->size = size;
+
+ /* increment total used space */
+ gv_cache_used += size;
+
+ /* put into LRU list */
+ gv_raster_cache_tile_touch( tile_obj );
+}
+
+void
+gv_raster_cache_del( gv_raster_cache *cache, gint tile, gint lod )
+{
+ gv_raster_cache_tile *tile_obj;
+
+ if( tile >= cache->max_tiles || lod >= cache->max_lod )
+ return;
+
+ if( cache->tiles[lod][tile] == NULL )
+ return;
+
+ tile_obj = cache->tiles[lod][tile];
+ cache->tiles[lod][tile] = NULL;
+
+ /* removed from LRU list */
+ if( lru_head == tile_obj )
+ lru_head = tile_obj->next;
+
+ if( lru_tail == tile_obj )
+ lru_tail = tile_obj->prev;
+
+ if( tile_obj->prev != NULL )
+ tile_obj->prev->next = tile_obj->next;
+
+ if( tile_obj->next != NULL )
+ tile_obj->next->prev = tile_obj->prev;
+
+ /* Free tile data, and tile object itself */
+ gv_cache_used -= tile_obj->size;
+ g_free( tile_obj->data );
+ g_free( tile_obj );
+}
+
+/*
+ * Touch a cache tile, moving it to the end of the LRU list.
+ */
+static void gv_raster_cache_tile_touch( gv_raster_cache_tile * tile_obj )
+{
+ /* don't put the most reduced LOD tiles on LRU list
+ ... they are `locked in' */
+ if( tile_obj->lod == tile_obj->cache->max_lod-1 )
+ return;
+
+ /* Remove from LRU list (if it's there) */
+ if( lru_head == tile_obj )
+ lru_head = tile_obj->next;
+
+ if( lru_tail == tile_obj )
+ lru_tail = tile_obj->prev;
+
+ if( tile_obj->prev != NULL )
+ tile_obj->prev->next = tile_obj->next;
+
+ if( tile_obj->next != NULL )
+ tile_obj->next->prev = tile_obj->prev;
+
+ /* Push on the tail of the LRU list */
+ if( lru_tail == NULL )
+ {
+ lru_head = lru_tail = tile_obj;
+ tile_obj->next = NULL;
+ tile_obj->prev = NULL;
+ }
+ else
+ {
+ lru_tail->next = tile_obj;
+ tile_obj->prev = lru_tail;
+ tile_obj->next = NULL;
+ lru_tail = tile_obj;
+ }
+}
+
+/*
+ * Purge the least recently used tile for a given level of detail.
+ */
+static int
+gv_raster_cache_purge_lru()
+{
+ if( lru_head == NULL )
+ return FALSE;
+
+ gv_raster_cache_del( lru_head->cache, lru_head->tile, lru_head->lod );
+
+ return TRUE;
+}
+
+/*
+ * Flush all tiles in the cache without destroying the cache.
+ */
+void
+gv_raster_cache_flush_all( gv_raster_cache *cache )
+{
+ gint i, lod;
+
+ for( lod = 0; lod < cache->max_lod; lod++ )
+ {
+ for( i = 0; i < cache->max_tiles; i++ )
+ {
+ gv_raster_cache_del( cache, i, lod );
+ }
+ }
+}
+
+int
+gv_raster_cache_get_best_lod( gv_raster_cache *cache, gint tile, gint lod )
+{
+ int retval, i;
+
+ if( cache->tiles[lod][tile] )
+ {
+ return lod;
+ } else {
+
+ retval = -1;
+
+ for( i = cache->max_lod-1; i >= 0; i-- )
+ {
+ if( i == lod )
+ continue;
+
+ if( cache->tiles[i][tile] )
+ {
+ if( i > lod )
+ {
+ retval = i;
+ } else {
+ return i;
+ }
+ }
+ }
+
+ return retval;
+ }
+}
+
+void
+gv_raster_cache_free( gv_raster_cache * cache )
+{
+ int lod;
+
+ if( cache == NULL )
+ return;
+
+ gv_raster_cache_flush_all( cache );
+
+ for( lod = 0; lod < cache->max_lod; lod++ )
+ g_free( cache->tiles[lod] );
+
+ g_free( cache->tiles );
+
+ g_free( cache );
+}
Added: packages/openev/branches/upstream/current/gvrastercache.h
===================================================================
--- packages/openev/branches/upstream/current/gvrastercache.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrastercache.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * $Id: gvrastercache.h,v 1.10 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvRaster tile caching.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrastercache.h,v $
+ * Revision 1.10 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_RASTER_CACHE_H__
+#define __GV_RASTER_CACHE_H__
+
+#include <gtk/gtk.h>
+
+
+typedef struct _gv_raster_cache gv_raster_cache;
+typedef struct _gv_raster_cache_tile gv_raster_cache_tile;
+
+struct _gv_raster_cache_tile {
+ gv_raster_cache_tile *prev;
+ gv_raster_cache_tile *next;
+ gv_raster_cache *cache;
+
+ int tile;
+ int lod;
+ int lru;
+ int size;
+ void *data;
+};
+
+struct _gv_raster_cache {
+ int max_lod;
+ int max_tiles;
+
+ gv_raster_cache_tile ***tiles; /* double dimensioned as [lod][tile] */
+};
+
+gv_raster_cache *gv_raster_cache_new( gint max_tiles, gint max_lod );
+
+void gv_raster_cache_free( gv_raster_cache * );
+
+void *gv_raster_cache_get( gv_raster_cache *cache, gint tile, gint lod );
+
+void gv_raster_cache_put( gv_raster_cache *cache, gint tile, gint lod, void *data, gint size );
+
+int gv_raster_cache_get_best_lod( gv_raster_cache *cache, gint tile, gint lod );
+
+void gv_raster_cache_flush_all( gv_raster_cache * );
+void gv_raster_cache_del( gv_raster_cache *cache, gint tile, gint lod );
+int gv_raster_cache_get_max();
+void gv_raster_cache_set_max(int);
+int gv_raster_cache_get_used();
+
+#endif
Added: packages/openev/branches/upstream/current/gvrasterconvert.c
===================================================================
--- packages/openev/branches/upstream/current/gvrasterconvert.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterconvert.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,511 @@
+/******************************************************************************
+ * $Id: gvrasterconvert.c,v 1.20 2004/06/23 14:35:03 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster conversion functions (float->byte, apply lut, etc)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterconvert.c,v $
+ * Revision 1.20 2004/06/23 14:35:03 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.19 2004/04/02 17:01:02 gmwalter
+ * Updated nodata support for complex and
+ * rgb data.
+ *
+ * Revision 1.18 2003/05/18 11:02:56 andrey_kiselev
+ * Memory leak fixed.
+ *
+ * Revision 1.17 2001/10/17 20:12:53 warmerda
+ * fixed type casting warning
+ *
+ * Revision 1.16 2001/10/17 16:23:51 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.15 2001/08/21 23:44:47 warmerda
+ * fixed nodata_mask freeing logic
+ *
+ * Revision 1.14 2001/08/17 00:54:41 warmerda
+ * fixed nodata_mask leak
+ *
+ * Revision 1.13 2000/09/29 04:27:02 warmerda
+ * fixed nodata handling in grayscale case
+ *
+ * Revision 1.12 2000/08/25 20:11:07 warmerda
+ * added preliminary nodata support
+ *
+ * Revision 1.11 2000/06/26 15:13:11 warmerda
+ * include alpha in RGB if alpha blending set on
+ *
+ * Revision 1.10 2000/06/23 12:54:59 warmerda
+ * largely rewrote
+ *
+ * Revision 1.9 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include "gvrasterlayer.h"
+
+static unsigned char *
+gv_raster_layer_gltile_complex( GvRasterLayer *layer, int tile, int lod,
+ int *format, int *type, int *needs_free )
+
+{
+ unsigned char *raw_data;
+ int i, pixel_count;
+ int * rgba_data, *LUT = (int *) layer->pc_lut;
+ unsigned char *nodata_mask = NULL;
+ unsigned char *rgba_ptr=NULL;
+
+ if( layer->pc_lut == NULL )
+ {
+ g_warning("gv_raster_layer_gltile_complex without pc_lut!" );
+ return NULL;
+ }
+
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+
+ if( layer->source_list[0].nodata_active )
+ {
+ nodata_mask = g_new( unsigned char, pixel_count );
+ memset( nodata_mask, 1, pixel_count );
+ }
+
+ if( layer->pc_lut_composed != NULL )
+ LUT = (int *) layer->pc_lut_composed;
+
+ raw_data = gv_raster_layer_srctile_xy_get( layer, 0, tile, lod,
+ needs_free, nodata_mask );
+
+ rgba_data = g_new(int,pixel_count);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ rgba_data[i] = LUT[raw_data[i*2+1]+raw_data[i*2]*256];
+ }
+
+ if( nodata_mask != NULL )
+ {
+ rgba_ptr = (unsigned char *) rgba_data;
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if( nodata_mask[i] == 0 )
+ rgba_ptr[i*4+3] = 0;
+ }
+ rgba_ptr = NULL;
+ }
+
+ if( *needs_free )
+ g_free( raw_data );
+
+ if( nodata_mask != NULL )
+ g_free( nodata_mask );
+
+ *format = GL_RGBA;
+ *type = GL_UNSIGNED_BYTE;
+ *needs_free = TRUE;
+
+ return (unsigned char *) rgba_data;
+}
+
+static unsigned char *
+gv_raster_layer_gltile_single( GvRasterLayer *layer, int tile, int lod,
+ int *format, int *type, int *needs_free )
+
+{
+ int pixel_count;
+ unsigned char *raw_data;
+ unsigned char *nodata_mask = NULL;
+
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+
+ if( layer->source_list[0].nodata_active )
+ {
+ nodata_mask = g_new( unsigned char, pixel_count );
+ memset( nodata_mask, 1, pixel_count );
+ }
+
+ raw_data = gv_raster_layer_srctile_xy_get( layer, 0, tile, lod,
+ needs_free, nodata_mask );
+
+ *format = GL_LUMINANCE;
+ *type = GL_UNSIGNED_BYTE;
+
+ if( layer->pc_lut != NULL )
+ {
+ int i;
+ int * rgba_data, *LUT = (int *) layer->pc_lut;
+
+ rgba_data = g_new(int,pixel_count);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ rgba_data[i] = LUT[raw_data[i]];
+ }
+
+ if( *needs_free )
+ g_free( raw_data );
+
+ *needs_free = TRUE;
+ raw_data = (unsigned char *) rgba_data;
+ *format = GL_RGBA;
+
+ if( nodata_mask != NULL )
+ {
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if( nodata_mask[i] == 0 )
+ rgba_data[i] = 0;
+ }
+ }
+ }
+ else if( nodata_mask != NULL )
+ {
+ int i;
+ unsigned char * la_data;
+
+ la_data = g_new(unsigned char,pixel_count*2);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if( nodata_mask[i] == 0 )
+ {
+ la_data[i*2+0] = 0;
+ la_data[i*2+1] = 0;
+ }
+ else
+ {
+ la_data[i*2+0] = raw_data[i];
+ la_data[i*2+1] = 255;
+ }
+ }
+
+ if( *needs_free )
+ g_free( raw_data );
+
+ *needs_free = TRUE;
+ raw_data = (unsigned char *) la_data;
+ *format = GL_LUMINANCE_ALPHA;
+ }
+
+ if( nodata_mask != NULL )
+ g_free( nodata_mask );
+
+ return raw_data;
+}
+
+static unsigned char *
+gv_raster_layer_gltile_rgba( GvRasterLayer *layer, int tile, int lod,
+ int *format, int *type, int *needs_free )
+
+{
+ unsigned char *red, *green, *blue, *alpha=NULL, *ret_data=NULL;
+ int free_red, free_green, free_blue, free_alpha=FALSE;
+ int pixel_count;
+ unsigned char *nodata_r=NULL, *nodata_g=NULL;
+ unsigned char *nodata_b=NULL, *nodata_a=NULL;
+
+ /* variables that are only used for complex bands*/
+ char *LUT=NULL;
+ int i;
+ unsigned char *cred=NULL, *cgreen=NULL, *cblue=NULL, *calpha=NULL;
+
+
+ /* Is alpha blending enabled? */
+ if( layer->gl_info.blend_enable )
+ {
+ *format = GL_RGBA;
+ *type = GL_UNSIGNED_BYTE;
+ }
+ else
+ {
+ *format = GL_RGB;
+ *type = GL_UNSIGNED_BYTE;
+ }
+
+ /* Get nodata information */
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+
+ if( layer->source_list[0].nodata_active )
+ {
+ nodata_r = g_new( unsigned char, pixel_count );
+ memset( nodata_r, 1, pixel_count );
+ }
+
+ if( layer->source_list[1].nodata_active )
+ {
+ nodata_g = g_new( unsigned char, pixel_count );
+ memset( nodata_g, 1, pixel_count );
+ }
+
+ if( layer->source_list[2].nodata_active )
+ {
+ nodata_b = g_new( unsigned char, pixel_count );
+ memset( nodata_b, 1, pixel_count );
+ }
+
+ /* Get source data */
+
+ red = gv_raster_layer_srctile_xy_get( layer, 0, tile, lod, &free_red,
+ nodata_r );
+ green = gv_raster_layer_srctile_xy_get( layer, 1, tile, lod, &free_green,
+ nodata_g );
+ blue = gv_raster_layer_srctile_xy_get( layer, 2, tile, lod, &free_blue,
+ nodata_b );
+
+ if( red == NULL || green == NULL || blue == NULL )
+ {
+ g_warning( "failed to fetch component in gv_raster_layer_gltile_rgba");
+ if ( nodata_r != NULL )
+ g_free( nodata_r );
+ if ( nodata_g != NULL )
+ g_free( nodata_g );
+ if ( nodata_b != NULL )
+ g_free( nodata_b );
+
+ return NULL;
+ }
+
+ cred = g_new( unsigned char, pixel_count );
+ if ( (layer->source_list[0].data != NULL) &&
+ (layer->source_list[0].data->gdal_type == GDT_CFloat32) )
+ {
+ if (layer->source_list[0].lut_rgba_composed != NULL)
+ LUT = (char *) layer->source_list[0].lut_rgba_composed;
+ else
+ LUT = (char *) layer->pc_lut_rgba_complex;
+ for ( i = 0; i < pixel_count; i++ )
+ {
+ cred[i] = LUT[red[i*2+1]*4+red[i*2]*4*256+0];
+ }
+ }
+ else
+ {
+ memcpy(cred, red, pixel_count);
+ }
+
+ cgreen = g_new( unsigned char, pixel_count );
+ if ((layer->source_list[1].data != NULL) &&
+ ( layer->source_list[1].data->gdal_type == GDT_CFloat32 ))
+ {
+ if (layer->source_list[1].lut_rgba_composed != NULL)
+ LUT = (char *) layer->source_list[1].lut_rgba_composed;
+ else
+ LUT = (char *) layer->pc_lut_rgba_complex;
+ for ( i = 0; i < pixel_count; i++ )
+ {
+ cgreen[i] = LUT[green[i*2+1]*4+green[i*2]*4*256+1];
+ }
+ }
+ else
+ {
+ memcpy(cgreen, green, pixel_count);
+ }
+
+
+ cblue = g_new( unsigned char, pixel_count );
+ if ( (layer->source_list[2].data != NULL) &&
+ (layer->source_list[2].data->gdal_type == GDT_CFloat32) )
+ {
+ if (layer->source_list[2].lut_rgba_composed != NULL)
+ LUT = (char *) layer->source_list[2].lut_rgba_composed;
+ else
+ LUT = (char *) layer->pc_lut_rgba_complex;
+ for ( i = 0; i < pixel_count; i++ )
+ {
+ cblue[i] = LUT[blue[i*2+1]*4+blue[i*2]*4*256+2];
+ }
+ }
+ else
+ {
+ memcpy(cblue, blue, pixel_count);
+ }
+
+
+ if( *format == GL_RGBA )
+ {
+ if( layer->source_list[3].nodata_active )
+ {
+ nodata_a = g_new( unsigned char, pixel_count );
+ memset( nodata_a, 1, pixel_count );
+ }
+ alpha = gv_raster_layer_srctile_xy_get( layer, 3, tile, lod,
+ &free_alpha, nodata_a );
+
+ calpha = g_new( unsigned char, pixel_count );
+ if ( (layer->source_list[3].data != NULL) &&
+ (layer->source_list[3].data->gdal_type == GDT_CFloat32) )
+ {
+ if (layer->source_list[3].lut_rgba_composed != NULL)
+ LUT = (char *) layer->source_list[3].lut_rgba_composed;
+ else
+ LUT = (char *) layer->pc_lut_rgba_complex;
+ for ( i = 0; i < pixel_count; i++ )
+ {
+ calpha[i] = LUT[alpha[i*2+1]*4+alpha[i*2]*4*256+0];
+ }
+ }
+ else
+ {
+ memcpy(calpha, alpha, pixel_count);
+ }
+
+ }
+
+ /* Interleave */
+
+ if( *format == GL_RGBA )
+ {
+ int i, pixel_count;
+
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+ ret_data = (unsigned char *) g_malloc(pixel_count*4);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ ret_data[i*4 ] = cred[i];
+ ret_data[i*4+1] = cgreen[i];
+ ret_data[i*4+2] = cblue[i];
+ ret_data[i*4+3] = calpha[i];
+ }
+ /* If this really slows things down, then could combine
+ all of these into a single for loop by creating a
+ case-type statement:
+ if ((nodata_r != NULL) && (nodata_g != NULL)
+ && (nodata_b != NULL) && (nodata_a != NULL))
+ {
+ (single for loop that assigns r,g,b,a and checks nodata_r,
+ nodata_g, nodata_b, nodata_a)
+ }
+ else if ((nodata_r != NULL) && (nodata_g != NULL)
+ && (nodata_b != NULL))
+ {
+ (single for loop that assigns r,g,b,a and checks nodata_r,
+ nodata_g, nodata_b)
+ }
+ etc.
+ */
+ if (nodata_r != NULL)
+ {
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if ( nodata_r[i] == 0 )
+ ret_data[i*4+3] = 0;
+ }
+ }
+ if (nodata_g != NULL)
+ {
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if ( nodata_g[i] == 0 )
+ ret_data[i*4+3] = 0;
+ }
+ }
+ if (nodata_b != NULL)
+ {
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if ( nodata_b[i] == 0 )
+ ret_data[i*4+3] = 0;
+ }
+ }
+ if (nodata_a != NULL)
+ {
+ for( i = 0; i < pixel_count; i++ )
+ {
+ if ( nodata_a[i] == 0 )
+ ret_data[i*4+3] = 0;
+ }
+ }
+ }
+ else
+ {
+ int i, pixel_count;
+
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+ ret_data = (unsigned char *) g_malloc(pixel_count*3);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ ret_data[i*3 ] = cred[i];
+ ret_data[i*3+1] = cgreen[i];
+ ret_data[i*3+2] = cblue[i];
+ }
+ }
+ *needs_free = TRUE;
+
+ if( free_red )
+ g_free( red );
+
+ if( free_green )
+ g_free( green );
+
+ if( free_blue )
+ g_free( blue );
+
+ if( free_alpha )
+ g_free( alpha );
+
+ if ( nodata_r != NULL )
+ g_free( nodata_r );
+ if ( nodata_g != NULL )
+ g_free( nodata_g );
+ if ( nodata_b != NULL )
+ g_free( nodata_b );
+ if ( nodata_a != NULL )
+ g_free( nodata_a );
+ if ( cred != NULL );
+ g_free( cred );
+ if ( cgreen != NULL );
+ g_free( cgreen );
+ if ( cblue != NULL );
+ g_free( cblue );
+ if ( calpha != NULL );
+ g_free( calpha );
+
+ return ret_data;
+}
+
+unsigned char *
+gv_raster_layer_gltile_get( GvRasterLayer *layer, int tile, int lod,
+ int *format, int *type, int *needs_free )
+
+{
+ if( layer->mode == GV_RLM_SINGLE )
+ return gv_raster_layer_gltile_single( layer, tile, lod, format, type,
+ needs_free );
+ else if( layer->mode == GV_RLM_RGBA )
+ return gv_raster_layer_gltile_rgba( layer, tile, lod, format, type,
+ needs_free );
+ else if( layer->mode == GV_RLM_COMPLEX )
+ return gv_raster_layer_gltile_complex( layer, tile, lod, format, type,
+ needs_free );
+ else
+ {
+ g_warning( "unexpected layer mode in gv_raster_layer_gltile_get()" );
+ return NULL;
+ }
+
+}
Added: packages/openev/branches/upstream/current/gvrasterize.c
===================================================================
--- packages/openev/branches/upstream/current/gvrasterize.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterize.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,353 @@
+/******************************************************************************
+ * $Id: gvrasterize.c,v 1.5 2004/11/19 23:59:37 gmwalter Exp $
+ *
+ * Project: CIETMAP / OpenEV
+ * Purpose: Vector rasterization code high level API (initially GvAreaShapes
+ * to GDAL raster).
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterize.c,v $
+ * Revision 1.5 2004/11/19 23:59:37 gmwalter
+ * Check in Aude's rasterization updates.
+ *
+ * Revision 1.4 2001/03/29 14:59:56 warmerda
+ * added fill_short flag to control handling of slivers
+ *
+ * Revision 1.3 2000/12/04 01:21:48 warmerda
+ * fixed allocation of panParts
+ *
+ * Revision 1.2 2000/09/15 02:21:10 warmerda
+ * Fixed off by one error in gvrasterize.c
+ *
+ * Revision 1.1 2000/09/15 01:29:04 warmerda
+ * New
+ *
+ */
+
+#include "gvrasterize.h"
+#include "cpl_conv.h"
+
+typedef struct {
+ unsigned char * pabyChunkBuf;
+ int nXSize;
+ int nYSize;
+ GDALDataType eType;
+ double dfBurnValue;
+} GvRasterizeInfo;
+
+/************************************************************************/
+/* gvBurnScanline() */
+/************************************************************************/
+
+void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd )
+
+{
+ GvRasterizeInfo *psInfo = (GvRasterizeInfo *) pCBData;
+
+ CPLAssert( nY >= 0 && nY < psInfo->nYSize );
+ CPLAssert( nXStart <= nXEnd );
+ CPLAssert( nXStart < psInfo->nXSize );
+
+ /* CPLAssert( nXEnd > 0 ); */
+ CPLAssert( nXEnd >= 0 );
+
+ if( nXStart < 0 )
+ nXStart = 0;
+ if( nXEnd >= psInfo->nXSize )
+ nXEnd = psInfo->nXSize - 1;
+
+ if( psInfo->eType == GDT_Byte )
+ {
+ unsigned char *pabyInsert;
+ unsigned char nBurnValue = (unsigned char) psInfo->dfBurnValue;
+
+ pabyInsert = psInfo->pabyChunkBuf + nY * psInfo->nXSize + nXStart;
+ memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
+ }
+ else
+ {
+ int nPixels = nXEnd - nXStart + 1;
+ float *pafInsert;
+
+ pafInsert = ((float *) psInfo->pabyChunkBuf)
+ + nY * psInfo->nXSize + nXStart;
+
+ while( nPixels-- > 0 )
+ *(pafInsert++) = psInfo->dfBurnValue;
+ }
+}
+
+
+/************************************************************************/
+/* gv_rasterize_one_shape() */
+/************************************************************************/
+static void
+gv_rasterize_one_shape( unsigned char * pabyChunkBuf, int nYOff, int nYSize,
+ GDALDataType eType, GvRaster * raster,
+ GvShape * shape, double dfBurnValue, int bFillShort )
+
+{
+ int nParts, *panPartSize, nPoints, i;
+ llPoint *pasPoints;
+ GvRasterizeInfo sInfo;
+
+ sInfo.nXSize = raster->width;
+ sInfo.nYSize = nYSize;
+ sInfo.pabyChunkBuf = pabyChunkBuf;
+ sInfo.eType = eType;
+ sInfo.dfBurnValue = dfBurnValue;
+
+/* -------------------------------------------------------------------- */
+/* Prepare parts, and points arrays */
+/* -------------------------------------------------------------------- */
+ nParts = gv_shape_get_rings( shape );
+ panPartSize = (int *) CPLMalloc(nParts * sizeof(int));
+
+ nPoints = 0;
+ for( i = 0; i < nParts; i++ )
+ {
+ panPartSize[i] = gv_shape_get_nodes( shape, i );
+ nPoints += panPartSize[i];
+ }
+
+ pasPoints = (llPoint *) CPLMalloc(sizeof(llPoint) * nPoints);
+
+/* -------------------------------------------------------------------- */
+/* Transform points, taking into account our chunk buffer offset. */
+/* -------------------------------------------------------------------- */
+ nPoints = 0;
+ for( i = 0; i < nParts; i++ )
+ {
+ int node, part_points = 0;
+
+ for( node = 0; node < panPartSize[i]; node++ )
+ {
+ double dfX, dfY, dfZ;
+ int nX, nY;
+
+ dfX = gv_shape_get_x( shape, i, node );
+ dfY = gv_shape_get_y( shape, i, node );
+ dfZ = 0.0;
+ gv_raster_georef_to_pixel( raster, &dfX, &dfY, &dfZ );
+
+ nX = (int) dfX;
+ nY = ((int) dfY) - nYOff;
+
+ if( node == 0
+ || pasPoints[nPoints-1].x != nX
+ || pasPoints[nPoints-1].y != nY )
+ {
+ pasPoints[nPoints].x = nX;
+ pasPoints[nPoints].y = nY;
+ nPoints++;
+ part_points++;
+ }
+ }
+ panPartSize[i] = part_points;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Perform the rasterization. */
+/* -------------------------------------------------------------------- */
+ llImageFilledPolygon( raster->width, nYSize,
+ nParts, panPartSize, pasPoints, bFillShort,
+ gvBurnScanline, &sInfo );
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ CPLFree( pasPoints );
+ CPLFree( panPartSize );
+}
+
+
+/************************************************************************/
+/* gv_rasterize_one_shape() */
+/************************************************************************/
+static void
+gv_rasterize_new_one_shape( unsigned char * pabyChunkBuf, int nYOff, int nYSize,
+ GDALDataType eType, GvRaster * raster,
+ GvShape * shape, double dfBurnValue, int method )
+
+{
+ int nParts, *panPartSize, nPoints, i;
+ dllPoint *pasPoints;
+ GvRasterizeInfo sInfo;
+
+ sInfo.nXSize = raster->width;
+ sInfo.nYSize = nYSize;
+ sInfo.pabyChunkBuf = pabyChunkBuf;
+ sInfo.eType = eType;
+ sInfo.dfBurnValue = dfBurnValue;
+
+/* -------------------------------------------------------------------- */
+/* Prepare parts, and points arrays */
+/* -------------------------------------------------------------------- */
+ nParts = gv_shape_get_rings( shape );
+ panPartSize = (int *) CPLMalloc(nParts * sizeof(int));
+
+ nPoints = 0;
+ for( i = 0; i < nParts; i++ )
+ {
+ panPartSize[i] = gv_shape_get_nodes( shape, i );
+ nPoints += panPartSize[i];
+ }
+
+ pasPoints = (dllPoint *) CPLMalloc(sizeof(dllPoint) * nPoints);
+
+/* -------------------------------------------------------------------- */
+/* Transform points, taking into account our chunk buffer offset. */
+/* -------------------------------------------------------------------- */
+ nPoints = 0;
+ for( i = 0; i < nParts; i++ )
+ {
+ int node, part_points = 0;
+
+ for( node = 0; node < panPartSize[i]; node++ )
+ {
+ double dfX, dfY, dfZ;
+
+
+ dfX = gv_shape_get_x( shape, i, node );
+ dfY = gv_shape_get_y( shape, i, node );
+ dfZ = 0.0;
+ gv_raster_georef_to_pixel( raster, &dfX, &dfY, &dfZ );
+
+
+ if( node == 0
+ || pasPoints[nPoints-1].x != dfX
+ || pasPoints[nPoints-1].y != dfY )
+ {
+ pasPoints[nPoints].x = dfX;
+ pasPoints[nPoints].y = dfY - nYOff;
+ nPoints++;
+ part_points++;
+ }
+ }
+ panPartSize[i] = part_points;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Perform the rasterization. */
+/* -------------------------------------------------------------------- */
+ dllImageFilledPolygon( raster->width, nYSize,
+ nParts, panPartSize, pasPoints,
+ gvBurnScanline, &sInfo, method );
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ CPLFree( pasPoints );
+ CPLFree( panPartSize );
+}
+
+
+/************************************************************************/
+/* gv_raster_rasterize_shapes() */
+/************************************************************************/
+
+int gv_raster_rasterize_shapes( GvRaster *raster,
+ int shape_count, GvShape **shapes,
+ double dfBurnValue, int bFillShort )
+
+{
+ GDALDataType eType;
+ int nYChunkSize, nScanlineBytes;
+ unsigned char *pabyChunkBuf;
+ int iY;
+ GvRasterChangeInfo change_info;
+
+/* -------------------------------------------------------------------- */
+/* Establish a chunksize to operate on. The larger the chunk */
+/* size the less times we need to make a pass through all the */
+/* shapes. */
+/* -------------------------------------------------------------------- */
+ if( raster->gdal_type == GDT_Byte )
+ eType = GDT_Byte;
+ else
+ eType = GDT_Float32;
+
+ nScanlineBytes = raster->width * (GDALGetDataTypeSize(eType)/8);
+ nYChunkSize = 10000000 / nScanlineBytes;
+ if( nYChunkSize > raster->height )
+ nYChunkSize = raster->height;
+
+ pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
+ if( pabyChunkBuf == NULL )
+ {
+ CPLError( CE_Failure, CPLE_OutOfMemory,
+ "Unable to allocate rasterization buffer." );
+ return FALSE;
+ }
+
+/* ==================================================================== */
+/* Loop over image in designated chunks. */
+/* ==================================================================== */
+ for( iY = 0; iY < raster->height; iY += nYChunkSize )
+ {
+ int nThisYChunkSize;
+ int iShape;
+
+ nThisYChunkSize = nYChunkSize;
+ if( nThisYChunkSize + iY > raster->height )
+ nThisYChunkSize = raster->height - iY;
+
+ GDALRasterIO( raster->gdal_band, GF_Read,
+ 0, iY, raster->width, nThisYChunkSize,
+ pabyChunkBuf, raster->width, nThisYChunkSize, eType,
+ 0, 0 );
+
+ for( iShape = 0; iShape < shape_count; iShape++ )
+ {
+
+ if (bFillShort < 2 )
+ gv_rasterize_one_shape( pabyChunkBuf, iY, nThisYChunkSize,
+ eType, raster,
+ shapes[iShape], dfBurnValue, bFillShort );
+ else
+ gv_rasterize_new_one_shape( pabyChunkBuf, iY, nThisYChunkSize,
+ eType, raster,
+ shapes[iShape], dfBurnValue, bFillShort - 2 );
+ }
+
+ GDALRasterIO( raster->gdal_band, GF_Write,
+ 0, iY, raster->width, nThisYChunkSize,
+ pabyChunkBuf, raster->width, nThisYChunkSize, eType,
+ 0, 0 );
+ }
+
+ VSIFree( pabyChunkBuf );
+
+/* -------------------------------------------------------------------- */
+/* Invalidate the raster to force a reload. */
+/* -------------------------------------------------------------------- */
+ change_info.change_type = GV_CHANGE_REPLACE;
+ change_info.x_off = 0;
+ change_info.y_off = 0;
+ change_info.width = raster->width;
+ change_info.height = raster->height;
+
+ gv_data_changed( GV_DATA(raster), &change_info );
+
+ return TRUE;
+}
+
Added: packages/openev/branches/upstream/current/gvrasterize.h
===================================================================
--- packages/openev/branches/upstream/current/gvrasterize.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterize.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,81 @@
+/******************************************************************************
+ * $Id: gvrasterize.h,v 1.3 2004/11/19 23:59:37 gmwalter Exp $
+ *
+ * Project: CIETMAP / OpenEV
+ * Purpose: Vector rasterization code (initially GvAreaShapes to GDAL raster).
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterize.h,v $
+ * Revision 1.3 2004/11/19 23:59:37 gmwalter
+ * Check in Aude's rasterization updates.
+ *
+ * Revision 1.2 2001/03/29 14:59:56 warmerda
+ * added fill_short flag to control handling of slivers
+ *
+ * Revision 1.1 2000/09/15 01:29:04 warmerda
+ * New
+ *
+ */
+
+#ifndef __GVRASTERIZE_H__
+#define __GVRASTERIZE_H__
+
+#include "gdal.h"
+#include "gvraster.h"
+#include "gvshapes.h"
+
+CPL_C_START
+
+/* -------------------------------------------------------------------- */
+/* Low level rasterizer API. */
+/* -------------------------------------------------------------------- */
+typedef struct {
+ int x, y;
+} llPoint;
+
+typedef struct {
+ double x, y;
+} dllPoint;
+
+
+typedef void (*llScanlineFunc)( void *pCBData, int nY, int nXStart, int nXEnd);
+
+
+void llImageFilledPolygon( int nRasterXSize, int nRasterYSize,
+ int nPartCount, int * panPartSize, llPoint * pasPoints,
+ int bFillShort,
+ llScanlineFunc pfnScanlineFunc, void * pCBData );
+
+void dllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData,
+ int method);
+
+
+/* -------------------------------------------------------------------- */
+/* High level API - GvShapes burned into GDAL raster. */
+/* -------------------------------------------------------------------- */
+int gv_raster_rasterize_shapes( GvRaster *raster,
+ int shape_count, GvShape **shapes,
+ double dfBurnValue, int bFillShort );
+
+#endif /* ndef __GVRASTERIZE_H__ */
Added: packages/openev/branches/upstream/current/gvrasterlayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvrasterlayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterlayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2259 @@
+/******************************************************************************
+ * $Id: gvrasterlayer.c,v 1.87 2005/08/30 12:44:11 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster display layer (managed textures, redraw, etc)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterlayer.c,v $
+ * Revision 1.87 2005/08/30 12:44:11 andrey_kiselev
+ * Fixed compilation of macro in gv_raster_layer_view_extents() (gcc 4 related).
+ *
+ * Revision 1.86 2004/06/23 14:35:04 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.85 2004/02/20 10:40:36 andrey_kiselev
+ * Use gv_raster_get_nodata() instead of GDALGetNoDataValue().
+ *
+ * Revision 1.84 2004/02/18 16:57:41 andrey_kiselev
+ * Fixed setting min/max levels in gv_raster_layer_init().
+ *
+ * Revision 1.83 2003/09/11 20:00:31 gmwalter
+ * Add ability to specify a preferred polynomial order for warping a raster,
+ * and add "safe mode" (only used if ATLANTIS_BUILD is defined).
+ *
+ * Revision 1.82 2003/02/20 19:27:16 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.81 2003/02/07 20:06:49 andrey_kiselev
+ * Memory leaks fixed.
+ *
+ * Revision 1.80 2003/02/06 08:19:24 warmerda
+ * Added support for force_load property on GvRasterLayer
+ *
+ * Revision 1.79 2003/01/24 16:54:52 warmerda
+ * turn some g_warning()s into CPLDebug calls for CIETmap/Paul
+ *
+ * Revision 1.78 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.77 2002/10/29 05:43:20 warmerda
+ * added some debugging logic in texture load code
+ *
+ * Revision 1.76 2002/04/12 14:40:36 gmwalter
+ * Removed the gvmesh rescale function (not needed because of view area
+ * rescaling).
+ *
+ * Revision 1.74 2002/03/20 19:19:00 warmerda
+ * add support for exact_render flag on GvViewArea
+ *
+ * Revision 1.73 2002/03/07 02:31:56 warmerda
+ * added default_height to add_height functions
+ *
+ * Revision 1.72 2001/12/10 18:48:19 warmerda
+ * ifdef out disconnect from prototype data in teardown
+ *
+ * Revision 1.71 2001/11/29 15:53:42 warmerda
+ * added autoscale_samples preference
+ *
+ * Revision 1.70 2001/11/28 19:23:04 warmerda
+ * Added logic to keep track if the mesh is dirty (out of date), and to
+ * refresh it before a redraw. It is marked dirty when the prototype data
+ * emits a geotransform-changed signal.
+ *
+ * Revision 1.69 2001/10/25 20:30:46 warmerda
+ * added interp_mode preference to control default subpixel interp
+ *
+ * Revision 1.68 2001/10/17 16:23:51 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.67 2001/10/16 18:50:29 warmerda
+ * added autoscale and histogram functions
+ *
+ * Revision 1.66 2001/10/12 17:44:18 warmerda
+ * avoid extra redraws when many raster layers displayed
+ *
+ * Revision 1.65 2001/09/25 20:04:16 warmerda
+ * cleanup idle tasks on finalize
+ *
+ * Revision 1.64 2001/08/22 16:20:38 warmerda
+ * use gv_mesh_reset_to_identity for setting to raw
+ *
+ * Revision 1.63 2001/08/08 02:57:55 warmerda
+ * removed unused support for normals
+ *
+ * Revision 1.62 2001/07/24 21:21:45 warmerda
+ * added EV style phase colormap
+ *
+ * Revision 1.61 2001/07/16 15:20:12 warmerda
+ * default to magnitude for complex images, instead of phase/magnitude
+ *
+ * Revision 1.60 2001/07/03 14:26:05 warmerda
+ * added set/get raw ability
+ *
+ * Revision 1.59 2001/01/30 19:34:29 warmerda
+ * make gv_raster_layer_purge_all_textures() public
+ *
+ * Revision 1.58 2001/01/30 14:32:32 warmerda
+ * No longer purges textures on a display-change. Added
+ * gv_raster_layer_purge_all_textures(), to clear textures on in cases where
+ * this is necessary. Now can change alpha with texture_mode_set() without
+ * throwing away textures.
+ *
+ * Revision 1.57 2000/10/06 15:35:33 warmerda
+ * set nodata value by default if present on GDALRasterBand
+ *
+ * Revision 1.56 2000/08/31 20:20:19 warmerda
+ * always destroy old textures before resizing them in ...texture_load
+ *
+ * Revision 1.55 2000/08/25 20:12:47 warmerda
+ * added preliminary nodata support
+ *
+ * Revision 1.54 2000/08/24 17:00:45 srawlin
+ * fixed 3D LOD calculation to account for image flip
+ *
+ * Revision 1.53 2000/08/24 15:48:39 srawlin
+ * Added flip in 3D mode tile list calculation
+ *
+ * Revision 1.52 2000/08/18 21:32:29 warmerda
+ * Fixed bug where tiles would pile up on the missing_tex list over multiple
+ * calls to the gv_raster_layer_draw() if there were no intermediate calls
+ * to the idle handler.
+ *
+ * Introduced a hack into gv_raster_layer_texture_load() to call glGetError()
+ * every now and then to try and work around a flaw in Xi Graphics GL drivers.
+ *
+ * Revision 1.51 2000/08/09 17:37:58 warmerda
+ * disconnect view callback on teardown, clear sources on destroy
+ *
+ * Revision 1.50 2000/07/25 17:51:07 warmerda
+ * change debug to use CPLDebug
+ *
+ * Revision 1.49 2000/07/25 14:19:49 warmerda
+ * dequeue old draw tasks before setting new ones in draw
+ *
+ * Revision 1.48 2000/07/24 21:25:37 warmerda
+ * always set fragment color, even if modulate off
+ *
+ * Revision 1.47 2000/07/18 15:32:53 warmerda
+ * set upper bound on redraw time to 2.0 seconds
+ *
+ * Revision 1.46 2000/07/18 15:04:50 warmerda
+ * tuning of idle handler texture logic
+ *
+ * Revision 1.45 2000/07/17 19:47:56 warmerda
+ * try to wait 3*redraw time
+ *
+ * Revision 1.44 2000/07/17 19:31:50 warmerda
+ * added tentative support for scaling redraw wait to actual redraw time
+ *
+ * Revision 1.43 2000/07/07 17:54:42 warmerda
+ * Modified 3D tile-in-view selection to use corners of tiles, and to compute
+ * the view cone based on a windows corners.
+ *
+ * Revision 1.42 2000/07/03 20:58:31 warmerda
+ * eye_pos in georef coordinates now
+ *
+ * Revision 1.40 2000/06/29 14:38:37 warmerda
+ * use GvManager for idle tasks
+ *
+ * Revision 1.39 2000/06/28 12:09:40 warmerda
+ * initial fragment color to all white
+ *
+ * Revision 1.38 2000/06/27 21:25:41 warmerda
+ * rewrote texture caching completely
+ *
+ * Revision 1.37 2000/06/23 12:56:18 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.36 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
+#include "gvrasterlayer.h"
+#include "gvrastertypes.h"
+#include "gvrasteraverage.h"
+#include "gvrasterlut.h"
+#include "gvmanager.h"
+#include "ogr_srs_api.h"
+
+
+#if !defined(GL_CLAMP_TO_EDGE) && defined(GL_CLAMP)
+# define GL_CLAMP_TO_EDGE GL_CLAMP
+#endif
+
+
+static void gv_raster_layer_class_init(GvRasterLayerClass *klass);
+static void gv_raster_layer_init(GvRasterLayer *layer);
+static void gv_raster_layer_draw(GvLayer *layer, GvViewArea *area);
+static void gv_raster_layer_extents(GvLayer *layer, GvRect *rect);
+static gint gv_raster_layer_texture_load( GvRasterLayer *layer, gint tile_num, gint lod );
+static gint gv_raster_layer_idle_handler( gpointer data );
+static void gv_raster_layer_setup( GvLayer *layer, GvViewArea *view );
+static void gv_raster_layer_teardown( GvLayer *layer, GvViewArea *view );
+static void gv_raster_layer_state_changed( GvViewArea *view, GvRasterLayer *layer );
+static void gv_raster_layer_finalize( GtkObject *object );
+static void gv_raster_layer_destroy( GtkObject *object );
+static gint gv_raster_layer_texture_size( gint format, gint type );
+static void gv_raster_layer_gl_disp_set( GvRasterLayer *layer );
+static void gv_raster_layer_gl_disp_unset( void );
+static gint gv_raster_layer_reproject( GvLayer *layer,
+ const char *new_projection );
+static int gvrl_to_georef_cb( int pt_count, double *x, double *y, double *z,
+ void *cb_data );
+static int gvrl_to_raw_cb( int pt_count, double *x, double *y, double *z,
+ void *cb_data );
+static int
+gv_mesh_transform_with_func(GvMesh *mesh,
+ int (*trfunc)(int,double*,double*,double*,void *),
+ void *cb_data );
+
+struct _GvRasterLayerIdleInfo {
+ GvRasterLayer *layer;
+ GvViewArea *area;
+ int lod;
+};
+
+enum {
+ GV_RASTER_LAYER_BLEND_OFF = 0,
+ GV_RASTER_LAYER_BLEND_FILTER,
+ GV_RASTER_LAYER_BLEND_ADD,
+ GV_RASTER_LAYER_BLEND_MULTIPLY,
+ GV_RASTER_LAYER_BLEND_CUSTOM
+};
+
+GtkType
+gv_raster_layer_get_type(void)
+{
+ static GtkType raster_layer_type = 0;
+
+ if (!raster_layer_type)
+ {
+ static const GtkTypeInfo area_layer_info =
+ {
+ "GvRasterLayer",
+ sizeof(GvRasterLayer),
+ sizeof(GvRasterLayerClass),
+ (GtkClassInitFunc) gv_raster_layer_class_init,
+ (GtkObjectInitFunc) gv_raster_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ raster_layer_type = gtk_type_unique(gv_layer_get_type(),
+ &area_layer_info);
+ }
+ return raster_layer_type;
+}
+
+static void
+gv_raster_layer_init(GvRasterLayer *layer)
+{
+ int i;
+
+ layer->prototype_data = NULL;
+ layer->source_count = 0;
+ layer->mode = 0;
+ layer->mesh = NULL;
+ layer->pc_lut = NULL;
+
+ for( i = 0; i < MAX_RASTER_SOURCE; i++ )
+ {
+ layer->source_list[i].lut = NULL;
+ layer->source_list[i].lut_rgba_composed = NULL;
+ layer->source_list[i].data = NULL;
+ layer->source_list[i].const_value = 0;
+ layer->source_list[i].min = 0.0;
+ layer->source_list[i].max = 255.0;
+ layer->source_list[i].nodata_active = FALSE;
+ layer->source_list[i].nodata_real = -1e8;
+ layer->source_list[i].nodata_imaginary = 0.0;
+ }
+}
+
+static void
+gv_raster_layer_class_init(GvRasterLayerClass *klass)
+{
+ GvLayerClass *layer_class;
+
+ layer_class = (GvLayerClass*) klass;
+ layer_class->draw = gv_raster_layer_draw;
+ layer_class->extents_request = gv_raster_layer_extents;
+ layer_class->setup = gv_raster_layer_setup;
+ layer_class->teardown = gv_raster_layer_teardown;
+ layer_class->reproject = gv_raster_layer_reproject;
+
+ ((GtkObjectClass *) klass)->destroy = gv_raster_layer_destroy;
+ ((GtkObjectClass *) klass)->finalize = gv_raster_layer_finalize;
+}
+
+GtkObject *
+gv_raster_layer_new(int mode, GvRaster *prototype_data,
+ GvProperties creation_properties)
+{
+ GvRasterLayer *layer;
+ double nodata_real=-1e8, nodata_imaginary=0.0;
+ int nodata_active = FALSE;
+ const char *interp_pref;
+
+ if( prototype_data == NULL )
+ return NULL;
+
+ layer = GV_RASTER_LAYER(gtk_type_new(gv_raster_layer_get_type()));
+
+ layer->tile_x = prototype_data->tile_x;
+ layer->tile_y = prototype_data->tile_y;
+ layer->prototype_data = prototype_data;
+ layer->pc_lut = NULL;
+ layer->pc_lut_composed = NULL;
+ layer->pc_lut_rgba_complex = NULL;
+
+ if( mode == GV_RLM_AUTO )
+ {
+ GDALColorInterp interp;
+
+ interp = GDALGetRasterColorInterpretation( prototype_data->gdal_band );
+ if( GDALDataTypeIsComplex( prototype_data->gdal_type ) )
+ mode = GV_RLM_COMPLEX;
+ else if( interp == GCI_RedBand
+ || interp == GCI_GreenBand
+ || interp == GCI_BlueBand )
+ mode = GV_RLM_RGBA;
+ else
+ mode = GV_RLM_SINGLE;
+ }
+ layer->mode = mode;
+
+ if( gv_properties_get(&creation_properties,"mesh_lod") != NULL)
+ {
+ layer->mesh = gv_mesh_new_identity( prototype_data,
+ atoi(gv_properties_get(&creation_properties,"mesh_lod")));
+ } else {
+ layer->mesh = gv_mesh_new_identity( prototype_data, 0 );
+ }
+
+ layer->mesh_is_raw = TRUE;
+ layer->mesh_is_dirty = FALSE;
+ gv_mesh_transform_with_func( layer->mesh, gvrl_to_raw_cb,
+ prototype_data );
+
+ if( gv_properties_get(&creation_properties,"raw") == NULL )
+ {
+ gv_mesh_transform_with_func( layer->mesh, gvrl_to_georef_cb,
+ prototype_data );
+
+ gv_data_set_projection( GV_DATA(layer),
+ gv_data_get_projection(GV_DATA(prototype_data)) );
+
+ layer->mesh_is_raw = FALSE;
+ }
+
+ memset( layer->source_list + 0, 0,
+ sizeof(GvRasterSource) * MAX_RASTER_SOURCE);
+
+ /* Default GL parameters */
+ layer->gl_info.blend_enable = 0;
+ layer->gl_info.alpha_test = 0;
+
+ layer->gl_info.tex_env_mode = GL_REPLACE;
+ layer->gl_info.fragment_color[0] = 1.0;
+ layer->gl_info.fragment_color[1] = 1.0;
+ layer->gl_info.fragment_color[2] = 1.0;
+ layer->gl_info.fragment_color[3] = 1.0;
+
+ layer->gl_info.s_wrap = GL_CLAMP;
+ layer->gl_info.t_wrap = GL_CLAMP;
+
+ interp_pref = gv_properties_get(&creation_properties,"interp_mode");
+ if( interp_pref == NULL )
+ interp_pref = gv_manager_get_preference(gv_get_manager(),
+ "interp_mode");
+
+#ifdef ATLANTIS_BUILD
+ /* Default to nearest for atlantis builds */
+ if( interp_pref == NULL || strcmp(interp_pref,"linear") != 0 )
+ {
+ layer->gl_info.mag_filter = GL_NEAREST;
+ layer->gl_info.min_filter = GL_NEAREST;
+ }
+ else
+ {
+ layer->gl_info.mag_filter = GL_LINEAR;
+ layer->gl_info.min_filter = GL_LINEAR;
+ }
+#else
+ if( interp_pref == NULL || strcmp(interp_pref,"nearest") != 0 )
+ {
+ layer->gl_info.mag_filter = GL_LINEAR;
+ layer->gl_info.min_filter = GL_LINEAR;
+ }
+ else
+ {
+ layer->gl_info.mag_filter = GL_NEAREST;
+ layer->gl_info.min_filter = GL_NEAREST;
+ }
+#endif
+ /* Setup texture related information */
+ layer->tile_list = g_array_new( FALSE, FALSE, sizeof( int ) ) ;
+ layer->missing_tex = g_array_new( FALSE, FALSE, sizeof( int ) );
+
+ /* Allocate texture structures */
+
+ if( ( layer->textures = g_new0( GvRasterLayerTexObj *,
+ prototype_data->max_tiles ) ) == NULL )
+ {
+ return NULL;
+ }
+
+ /* FIXME ... should we always do this? */
+ gv_data_set_parent(GV_DATA(layer), GV_DATA(prototype_data));
+
+ /* check for nodata value */
+ nodata_active = gv_raster_get_nodata( prototype_data, &nodata_real );
+
+ /* Setup mode dependent information */
+ switch( mode )
+ {
+ case GV_RLM_SINGLE:
+ layer->source_count = 1;
+ if( GDALGetRasterColorTable( prototype_data->gdal_band ) != NULL )
+ {
+ gv_raster_layer_set_source( layer, 0, prototype_data, 0, 255.0,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ gv_raster_layer_apply_gdal_color_table( layer,
+ GDALGetRasterColorTable( prototype_data->gdal_band ) );
+ }
+ else
+ gv_raster_layer_set_source( layer, 0, prototype_data,
+ prototype_data->min, prototype_data->max,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ break;
+
+ case GV_RLM_COMPLEX:
+ layer->source_count = 1;
+ layer->pc_lut = NULL;
+ gv_raster_layer_lut_color_wheel_new_ev(layer, FALSE, TRUE );
+ gv_raster_layer_set_source( layer, 0, prototype_data,
+ prototype_data->min,
+ prototype_data->max,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ break;
+
+ case GV_RLM_RGBA:
+ layer->source_count = 4;
+
+ layer->pc_lut_rgba_complex = NULL;
+ gv_raster_layer_lut_color_wheel_new_ev(layer, FALSE, TRUE );
+
+ gv_raster_layer_set_source( layer, 0, prototype_data,
+ prototype_data->min, prototype_data->max,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ gv_raster_layer_set_source( layer, 1, prototype_data,
+ prototype_data->min, prototype_data->max,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ gv_raster_layer_set_source( layer, 2, prototype_data,
+ prototype_data->min, prototype_data->max,
+ 0, NULL, nodata_active, nodata_real,
+ nodata_imaginary );
+ gv_raster_layer_set_source( layer, 3, NULL, 0, 255,
+ 255, NULL, FALSE, 0.0, 0.0 );
+ break;
+
+ default:
+ g_warning( "unexpected raster layer mode" );
+ return NULL;
+ }
+
+ return GTK_OBJECT(layer);
+}
+
+static void gv_raster_layer_destroy( GtkObject *gtk_object )
+
+{
+ GvLayerClass *parent_class;
+ GvRasterLayer *rlayer = GV_RASTER_LAYER(gtk_object);
+ int isource;
+
+ CPLDebug( "OpenEV", "gv_raster_layer_destroy(%s)\n",
+ gv_data_get_name(GV_DATA(rlayer)) );
+
+ /* clear any "source" references */
+ for( isource = 0; isource < rlayer->source_count; isource++ )
+ gv_raster_layer_set_source( rlayer, isource, NULL, 0, 0, 0, NULL,
+ FALSE, 0.0, 0.0 );
+
+ gtk_object_unref( GTK_OBJECT(rlayer->mesh) );
+ rlayer->mesh = NULL;
+
+ if ( rlayer->textures )
+ g_free( rlayer->textures );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_layer_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(gtk_object);
+}
+
+/*
+** Clean up any outstanding idle tasks against this raster layer.
+*/
+
+static void gv_raster_layer_cleanup_idle( GvRasterLayer *layer )
+
+{
+ GvIdleTask *task_list;
+
+ /* Ensure that any existing idle task for this layer is blown away */
+ for( task_list = gv_get_manager()->idle_tasks;
+ task_list != NULL; task_list = task_list->next )
+ {
+ if( strcmp(task_list->name,"raster-layer-update") == 0 )
+ {
+ struct _GvRasterLayerIdleInfo *info;
+
+ info = (struct _GvRasterLayerIdleInfo *) task_list->task_info;
+ if( info->layer == layer )
+ {
+ g_assert( GV_LAYER(layer)->pending_idle );
+ GV_LAYER(layer)->pending_idle = FALSE;
+
+ gv_manager_dequeue_task( gv_get_manager(), task_list );
+ g_free( info );
+ break;
+ }
+ }
+ }
+
+ g_assert( !GV_LAYER(layer)->pending_idle );
+ GV_LAYER(layer)->pending_idle = FALSE;
+}
+
+static void gv_raster_layer_finalize( GtkObject * gtk_object )
+
+{
+ GvLayerClass *parent_class;
+ GvRasterLayer *rlayer = GV_RASTER_LAYER(gtk_object);
+
+ CPLDebug( "OpenEV", "gv_raster_layer_finalize(%s)\n",
+ gv_data_get_name(GV_DATA(rlayer)) );
+
+ if( rlayer->pc_lut != NULL )
+ {
+ g_free(rlayer->pc_lut);
+ rlayer->pc_lut = NULL;
+ }
+ if( rlayer->pc_lut_composed != NULL )
+ {
+ g_free(rlayer->pc_lut_composed);
+ rlayer->pc_lut_composed = NULL;
+ }
+
+ gv_raster_layer_cleanup_idle( rlayer );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_layer_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(gtk_object);
+}
+
+void gv_raster_layer_purge_all_textures( GvRasterLayer *layer )
+
+{
+ gint texture;
+
+ for( texture = 0;
+ texture < layer->prototype_data->max_tiles;
+ texture++ )
+ {
+ if( layer->textures[texture] )
+ gv_raster_layer_purge_texture( layer, texture );
+ }
+}
+
+static void gv_raster_layer_raster_changed( GvRaster *raster,
+ void * raw_change_info,
+ GvRasterLayer *layer )
+{
+ GvRasterChangeInfo *change_info = (GvRasterChangeInfo *) raw_change_info;
+ gint texture;
+
+ if( change_info != NULL
+ && (change_info->width > 0 && change_info->height > 0) )
+ {
+ for( texture = 0;
+ texture < layer->prototype_data->max_tiles;
+ texture++ )
+ {
+ gint coords[4];
+
+ gv_raster_tile_xy_get( raster, texture, 0, coords );
+
+ if( change_info->x_off < coords[2]
+ && change_info->y_off < coords[3]
+ && change_info->x_off+change_info->width > coords[0]
+ && change_info->y_off+change_info->height > coords[1] )
+ {
+ if( layer->textures[texture] )
+ gv_raster_layer_purge_texture( layer, texture );
+ }
+ }
+ }
+ else
+ {
+ gv_raster_layer_purge_all_textures( layer );
+ }
+}
+
+static void
+gv_raster_layer_raster_geotransform_changed( GvRaster *raster,
+ int junk,
+ GvRasterLayer *layer )
+{
+ if( layer->mesh_is_raw )
+ return;
+
+ if( layer->mesh_is_dirty )
+ return;
+
+ layer->mesh_is_dirty = TRUE;
+ gv_raster_layer_purge_all_textures( layer );
+ gv_view_area_queue_draw( GV_LAYER(layer)->view );
+}
+
+static void gv_raster_layer_setup( GvLayer *layer, GvViewArea *view )
+{
+ gtk_signal_connect( GTK_OBJECT(view), "view-state-changed",
+ gv_raster_layer_state_changed, layer );
+ /* FIXME: we need this on all sources. */
+ gtk_signal_connect( GTK_OBJECT(GV_RASTER_LAYER(layer)->prototype_data),
+ "changed",
+ gv_raster_layer_raster_changed, layer );
+ gtk_signal_connect( GTK_OBJECT(GV_RASTER_LAYER(layer)->prototype_data),
+ "geotransform-changed",
+ gv_raster_layer_raster_geotransform_changed, layer );
+}
+
+static void gv_raster_layer_teardown( GvLayer *layer, GvViewArea *view )
+{
+ gv_raster_layer_cleanup_idle( GV_RASTER_LAYER(layer) );
+
+ gtk_signal_disconnect_by_data( GTK_OBJECT(view), GTK_OBJECT(layer) );
+#ifdef notdef
+ gtk_signal_disconnect_by_data(
+ GTK_OBJECT(GV_RASTER_LAYER(layer)->prototype_data),
+ GTK_OBJECT(layer) );
+#endif
+}
+
+static void gv_raster_layer_state_changed( GvViewArea *view, GvRasterLayer *layer )
+{
+ if( layer->tile_list )
+ g_array_set_size( layer->tile_list, 0 );
+}
+
+
+static void
+gv_raster_layer_draw( GvLayer *layer, GvViewArea *area )
+{
+ GvRasterLayer *raster_layer = GV_RASTER_LAYER(layer);
+ gint *list = NULL,
+ lod=0, i = 0, e;
+ struct _GvRasterLayerIdleInfo *idle_info = NULL;
+ double pixel_size, pixel_zoom;
+ int tiles_to_force_load = 0;
+
+ GvMeshTile *mesh = NULL;
+
+ if(!gv_layer_is_visible(layer)) return;
+
+ /* Ensure that any existing idle task for this layer is blown away */
+ gv_raster_layer_cleanup_idle( raster_layer );
+
+ g_array_set_size( raster_layer->missing_tex, 0 );
+
+ /* Ensure the mesh is up to date */
+ gv_raster_layer_refresh_mesh( raster_layer );
+
+ /* Get the list of tiles to draw for current view */
+
+ if( !raster_layer->tile_list->len )
+ {
+ raster_layer->tile_list =
+ gv_mesh_tilelist_get( raster_layer->mesh, area, raster_layer,
+ raster_layer->tile_list );
+ }
+
+ list = (gint *) raster_layer->tile_list->data;
+
+ /* 2D - Mode Decide level of detail (LOD). Note: each tile gets same LOD */
+ /* see below for 3D mode LOD calculation */
+ pixel_size = gv_raster_layer_pixel_size(raster_layer);
+ pixel_zoom = log(pixel_size) / log(2);
+
+ if ( !area->flag_3d )
+ {
+ /* 2D Mode */
+ lod = (int) (-area->state.zoom - pixel_zoom);
+
+ if( lod < 0 )
+ lod = 0;
+
+ if( lod >= raster_layer->prototype_data->max_lod )
+ lod = raster_layer->prototype_data->max_lod-1;
+
+ } else {
+ /* 3D Case */
+
+ /* Simple distance to Z axis - works pretty well, but not efficent for large images, need reduced LOD in distance */
+ /* lod = (int) ((area->state.eye_pos[2]+250)/128.0 - pixel_zoom); */
+ }
+
+ /*
+ ** Find if we are willing to force load any tiles during rendering in
+ ** an attempt to reduce flicker.
+ */
+ if( gv_data_get_property( GV_DATA(raster_layer), "force_load" ) != NULL )
+ tiles_to_force_load =
+ atoi(gv_data_get_property( GV_DATA(raster_layer), "force_load" ));
+#ifdef ATLANTIS_BUILD
+ else if( (gv_manager_get_preference(gv_get_manager(),"safe_mode") != NULL) &&
+ (strcmp(gv_manager_get_preference(gv_get_manager(),"safe_mode"),"on") == 0))
+ tiles_to_force_load = 100;
+#endif
+ gv_raster_layer_gl_disp_set( raster_layer );
+
+ for( i = 0; list[i] != -1; i++ )
+ {
+ int process_when_idle;
+ int skip_render;
+ double tile_dist = 0.0;
+ GvRasterLayerTexObj *tex;
+
+ tex = raster_layer->textures[list[i]];
+
+ /* 3D Mode - Calculate individula LODs for each tile based on
+ distance from centre of tile to view position */
+ if ( area->flag_3d )
+ {
+ gint *tile_coords;
+ double x_center, y_center, z_center;
+ double temp_x, temp_y, temp_z, pixel_ratio;
+ int debug3d = 0;
+
+ if( gv_manager_get_preference(gv_get_manager(),"DEBUG3D") != NULL )
+ debug3d =
+ atoi(gv_manager_get_preference(gv_get_manager(),"DEBUG3D"));
+
+
+ /* Get Corners to get LOD*/
+ tile_coords = gv_mesh_get_tile_corner_coords( raster_layer->mesh,
+ list[i]);
+ x_center = (tile_coords[0]+tile_coords[2])/2.0;
+ y_center = (tile_coords[1]+tile_coords[5])/2.0;
+ z_center = 0.0;
+ gv_raster_layer_pixel_to_view(raster_layer,
+ &x_center,&y_center,&z_center);
+
+ /* Calculate the optimal LOD for this tile */
+
+ /* ??? Are these distances correct??? They seem to work. */
+ if( debug3d > 1 )
+ {
+ printf( "--- lod calc ---: tile_center=(%f,%f,%f)\n",
+ x_center, y_center, z_center );
+ }
+
+ /* Must account for image flip - eye_pos is okay, just the tile */
+ temp_x = area->state.eye_pos[0] - (x_center * area->state.flip_x);
+ temp_y = area->state.eye_pos[1] - (y_center * area->state.flip_y);
+ temp_z = area->state.eye_pos[2] - z_center;
+ tile_dist = sqrt(temp_x*temp_x + temp_y*temp_y + temp_z*temp_z);
+
+ /* How many texture pixels are required to cover one screen pixel
+ * We are assuming that fov is 90 degrees so that the distance
+ * from center of view to top edge of view (shape_y*0.5) is the
+ * same as the distance from eye_pos to center of view.
+ */
+
+ pixel_ratio = (ABS(tile_dist) / pixel_size)
+ / (area->state.shape_y*0.5);
+
+ lod = (int) (log(pixel_ratio)/log(2));
+
+ if( debug3d )
+ printf( "tile_dist=%f, pixel_size=%f, ratio=%f, lod=%d\n",
+ tile_dist, pixel_size, pixel_ratio, lod );
+
+ free(tile_coords);
+
+ if( lod < 0 )
+ lod = 0;
+
+ if( lod >= raster_layer->prototype_data->max_lod )
+ lod = raster_layer->prototype_data->max_lod-1;
+ }
+
+ if( (tex == NULL || tex->lod != lod) && area->exact_render )
+ {
+ gv_raster_layer_texture_load( raster_layer, list[i], lod );
+ tex = raster_layer->textures[list[i]];
+ CPLAssert( tex->lod == lod );
+ }
+
+ if( tex == NULL && tiles_to_force_load > 0 )
+ {
+ CPLDebug( "OpenEV", "force loading tile for layer %s.",
+ gv_data_get_name( GV_DATA(raster_layer) ) );
+
+ gv_raster_layer_texture_load( raster_layer, list[i], lod );
+ tex = raster_layer->textures[list[i]];
+ tiles_to_force_load--;
+
+ // Re-enable textures that are disabled by loader.
+ gv_raster_layer_gl_disp_set( raster_layer );
+ }
+
+ /* Get mesh for tile */
+ if( tex != NULL )
+ mesh = gv_mesh_get( raster_layer->mesh, list[i], tex->lod,
+ lod, mesh );
+ else
+ mesh = NULL;
+
+ if( tex == NULL || tex->tex_obj == 0 )
+ {
+ /* we have no texture at all. Skip rendering, and queue
+ idle request to fetch data */
+ process_when_idle = TRUE;
+ skip_render = TRUE;
+ }
+ else if( mesh == NULL )
+ {
+ /* this should never happen, right? */
+ skip_render = TRUE;
+ process_when_idle = FALSE;
+ }
+
+ else if( tex->lod != lod )
+ {
+ /* we have a texture, but it's not the optimal lod, render
+ it, and queue fetching of the correct lod */
+
+ process_when_idle = TRUE;
+ skip_render = FALSE;
+ }
+ else
+ {
+ /* general case of having the desired texture available */
+
+ process_when_idle = FALSE;
+ skip_render = FALSE;
+ }
+
+ if( process_when_idle )
+ {
+ /* add this to missing texture list */
+
+ g_array_append_val( raster_layer->missing_tex, list[i] );
+
+ if( !idle_info )
+ {
+ if( (idle_info = g_new(struct _GvRasterLayerIdleInfo,1))
+ != NULL )
+ {
+ idle_info->layer = raster_layer;
+ idle_info->area = area;
+ idle_info->lod = lod;
+ gv_manager_queue_task( gv_get_manager(),
+ "raster-layer-update", 10,
+ gv_raster_layer_idle_handler,
+ idle_info );
+ GV_LAYER(layer)->pending_idle = TRUE;
+ }
+ }
+ }
+
+ if( skip_render )
+ continue;
+
+ /* mark last used time, but only if it is the optimal resolution */
+ if( !process_when_idle )
+ gv_raster_layer_touch_texture( raster_layer, list[i] );
+
+ /* bind texture to be displayed */
+ glBindTexture( GL_TEXTURE_2D, tex->tex_obj );
+
+ /* Draw mesh */
+ if( mesh->tex_coords )
+ {
+ glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+ glTexCoordPointer( 2, GL_FLOAT, 0, mesh->tex_coords );
+ }
+
+ glEnableClientState( GL_VERTEX_ARRAY );
+ glVertexPointer( 3, GL_FLOAT, 0, mesh->vertices );
+
+ for( e = 0; e <= mesh->restarts; e++ )
+ {
+ glDrawElements( mesh->list_type, mesh->range, GL_UNSIGNED_INT,
+ &(mesh->indices[e*mesh->range]) );
+ }
+
+ glDisableClientState( GL_VERTEX_ARRAY );
+ glDisableClientState( GL_NORMAL_ARRAY );
+ glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+
+ if ( mesh )
+ {
+ g_free( mesh );
+ mesh = NULL;
+ }
+ }
+
+ gv_raster_layer_gl_disp_unset();
+}
+
+/* Idle handler */
+
+static gint
+gv_raster_layer_idle_handler( gpointer data )
+{
+ struct _GvRasterLayerIdleInfo *idle_info = (struct _GvRasterLayerIdleInfo *) data;
+ GvRasterLayer *layer = idle_info->layer;
+ gint i, tile, temp_lod, lod;
+ gboolean tile_loaded = FALSE;
+ GvViewArea *view = GV_LAYER(layer)->view;
+
+ g_assert( GV_LAYER(layer)->pending_idle );
+ GV_LAYER(layer)->pending_idle = FALSE;
+
+ if( !GTK_WIDGET_REALIZED( GTK_WIDGET(view) )
+ || !gtk_gl_area_make_current(GTK_GL_AREA(view))
+ || layer->missing_tex->len == 0 )
+ {
+ g_free( idle_info );
+ return FALSE;
+ }
+
+ tile_loaded = FALSE;
+ lod = idle_info->lod;
+
+ /* first scan for any completely missing textures */
+ for( i = 0; i < layer->missing_tex->len; i++ )
+ {
+ tile = g_array_index( layer->missing_tex, int, i );
+
+ /* try to fill in textures where we have no lod at all */
+ if( layer->textures[tile] == NULL )
+ {
+ /* FIXME: Need to check all sources? */
+ if( ( temp_lod = gv_raster_cache_get_best_lod(
+ layer->prototype_data->cache,
+ tile, lod ) ) == -1 )
+ temp_lod = lod;
+
+ /* force downsamping if higher resolution available, to avoid
+ tieing up too much texture memory */
+ if( temp_lod < lod )
+ temp_lod = lod;
+
+ gv_raster_layer_texture_load( layer, tile, temp_lod );
+
+ g_array_index( layer->missing_tex, int, i ) = -1;
+
+ /* if too long has elapsed, break out to give the user a chance
+ to provide input */
+ if( gv_view_area_redraw_timeout(view) )
+ break;
+ }
+ }
+
+ /* make another pass processing anything that needs updating. */
+ for( i = 0;
+ i < layer->missing_tex->len && !gv_view_area_redraw_timeout(view);
+ i++ )
+ {
+ tile = g_array_index( layer->missing_tex, int, i );
+ if( tile < 0 )
+ continue;
+
+ gv_raster_layer_texture_load( layer, tile, lod );
+ }
+
+ g_array_set_size( layer->missing_tex, 0 );
+
+ /*
+ * We only requeue a draw if we ran out of time, or if we know there
+ * are no other layers with pending work they would like to do before
+ * a redraw.
+ */
+ if( gv_view_area_redraw_timeout(view)
+ || !gv_view_area_pending_idle_work(view) )
+ gv_view_area_queue_draw( view);
+
+ g_free( idle_info );
+ return FALSE;
+}
+
+
+/* Load the named texture (tile_num / lod) into a bound texture
+ (via glBindTextures/glTexImage2D) */
+
+static gint
+gv_raster_layer_texture_load( GvRasterLayer *layer, gint tile_num, gint lod )
+{
+ gint size;
+ void *buffer;
+ int format, type, needs_free;
+ static int counter = 0;
+
+ /* give up with an error if we fail to get the cache tile */
+ buffer = gv_raster_layer_gltile_get(layer,tile_num,lod, &format, &type,
+ &needs_free );
+ if( buffer == NULL )
+ return 1;
+
+ size = gv_raster_layer_texture_size( format, type );
+ size *= ( layer->tile_x >> lod ) * ( layer->tile_y >> lod );
+
+ glEnable( GL_TEXTURE_2D );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ layer->gl_info.mag_filter );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ layer->gl_info.min_filter );
+
+#ifdef notdef
+ if( layer->textures[tile_num] == NULL )
+ {
+ GLuint tex_obj;
+
+ /* Never been allocated -- here we go */
+ glGenTextures( 1, &tex_obj );
+
+ gv_raster_layer_create_texture( layer, tile_num, tex_obj, lod, size );
+ }
+ else
+ {
+ gv_raster_layer_reset_texture( layer, tile_num, lod, size );
+ }
+#else
+ {
+ GLuint tex_obj;
+
+ if( layer->textures[tile_num] != NULL )
+ gv_raster_layer_purge_texture( layer, tile_num );
+
+ /* Never been allocated -- here we go */
+ glGenTextures( 1, &tex_obj );
+
+ gv_raster_layer_create_texture( layer, tile_num, tex_obj, lod, size );
+ }
+#endif
+
+ if( layer->textures[tile_num] == NULL )
+ {
+ CPLDebug( "OpenEV",
+ "gv_raster_layer_texture_load(): "
+ "unexpectedly missing texture" );
+ return 1;
+ }
+
+ glBindTexture( GL_TEXTURE_2D, layer->textures[tile_num]->tex_obj );
+
+ /*
+ * We seem to see frequent crashes with Xi Graphics GL drivers if
+ * we do too many glTexImage calls without resyncronizing with the
+ * server. The following hack is intended to introduce a round trip
+ * with the server "every now and then" while adding minimal wait
+ * overhead.
+ */
+ if( counter++ % 100 == 0 && glGetError() != 0 )
+ {
+ CPLDebug( "OpenEV",
+ "Got GL Error in gv_raster_layer_texture_load()" );
+ }
+
+ glTexImage2D( GL_TEXTURE_2D, 0, format,
+ layer->tile_x >> lod,
+ layer->tile_y >> lod,
+ 0, format, type, buffer );
+
+#ifdef notdef
+ if( layer->tile_x >> lod <= 16 )
+ {
+ int iX, iY, max = layer->tile_x >> lod;
+
+ printf(" format = %d, type = %d\n", format, type );
+ for( iY = 0; iY < max; iY++ )
+ {
+ for( iX = 0; iX < max; iX++ )
+ printf( "%02X%02X ",
+ ((unsigned char *) buffer)[(iX + iY*max)*2],
+ ((unsigned char *) buffer)[(iX + iY*max)*2+1] );
+ printf( "\n" );
+ }
+ }
+#endif
+
+ glDisable( GL_TEXTURE_2D );
+
+ if( needs_free )
+ g_free( buffer );
+
+ return 0;
+}
+
+static gint gv_raster_layer_texture_size( gint format, gint type )
+{
+ gint elem_size;
+ gint n_elems;
+
+ switch( type )
+ {
+ case GL_UNSIGNED_BYTE:
+ elem_size = sizeof( unsigned char );
+ break;
+ default:
+ elem_size = 1;
+ fprintf( stderr, "Unknown type in gv_raster_layer_texture_size\n" );
+ break;
+ }
+
+ switch( format )
+ {
+ case GL_RGBA:
+ n_elems = 4;
+ break;
+ case GL_RGB:
+ n_elems = 3;
+ break;
+ case GL_LUMINANCE:
+ n_elems = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ n_elems = 2;
+ break;
+ default:
+ n_elems = 1;
+ fprintf( stderr, "Unknown format in gv_raster_layer_texture_size\n" );
+ break;
+ }
+
+ return n_elems * elem_size;
+}
+
+static void gv_raster_layer_gl_disp_set( GvRasterLayer *layer )
+{
+ glEnable( GL_TEXTURE_2D );
+
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, layer->gl_info.tex_env_mode );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, layer->gl_info.s_wrap );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, layer->gl_info.t_wrap );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, layer->gl_info.mag_filter );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, layer->gl_info.min_filter );
+
+ if( layer->gl_info.tex_env_mode == GL_MODULATE )
+ glColor4fv( layer->gl_info.fragment_color );
+ else
+ glColor4f( 1.0, 1.0, 1.0, 1.0 );
+
+ if( layer->gl_info.blend_enable )
+ {
+ glEnable( GL_BLEND );
+
+ glBlendFunc( layer->gl_info.blend_src, layer->gl_info.blend_dst );
+ }
+
+ if( layer->gl_info.alpha_test )
+ {
+ glEnable( GL_ALPHA_TEST );
+
+ glAlphaFunc( layer->gl_info.alpha_test_mode,
+ layer->gl_info.alpha_test_val );
+ }
+
+}
+
+static void gv_raster_layer_gl_disp_unset( void )
+{
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_BLEND );
+ glDisable( GL_ALPHA_TEST );
+}
+
+static void
+gv_raster_layer_extents(GvLayer *layer, GvRect *rect)
+{
+ gv_mesh_extents( GV_RASTER_LAYER(layer)->mesh, rect );
+}
+
+
+long
+gv_raster_layer_texture_clamp_set( GvRasterLayer *layer, int s_clamp, int t_clamp )
+{
+ int modes[] = { GL_CLAMP, GL_REPEAT };
+ int max_modes = 2;
+
+ g_return_val_if_fail( layer != NULL, 1 );
+
+ if( s_clamp >= max_modes || t_clamp >= max_modes )
+ return 1;
+
+ layer->gl_info.s_wrap = modes[s_clamp];
+ layer->gl_info.t_wrap = modes[t_clamp];
+
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+
+ return 0;
+}
+
+long
+gv_raster_layer_zoom_set( GvRasterLayer *layer, int mag_mode, int min_mode )
+{
+ int modes[] = { GL_LINEAR, GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR };
+ int max_mag_modes = 2;
+ int max_min_modes = 3;
+
+ if( mag_mode >= max_mag_modes || min_mode >= max_min_modes )
+ return 1;
+
+ layer->gl_info.mag_filter = modes[mag_mode];
+ layer->gl_info.min_filter = modes[min_mode];
+
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+
+ return 0;
+}
+
+long
+gv_raster_layer_zoom_get( GvRasterLayer *layer, int *mag_mode, int *min_mode )
+{
+ int modes[] = { GL_LINEAR, GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR };
+ int max_mag_modes = 2;
+ int max_min_modes = 3;
+ int i;
+
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+
+ *mag_mode = -1;
+ *min_mode = -1;
+
+ for( i = 0; i < max_mag_modes; i++ )
+ if( layer->gl_info.mag_filter == modes[i] )
+ *mag_mode = i;
+
+ for( i = 0; i < max_min_modes; i++ )
+ if( layer->gl_info.min_filter == modes[i] )
+ *min_mode = i;
+
+ if( *mag_mode == -1 || *min_mode == -1 )
+ return 1;
+
+ return 0;
+}
+
+long
+gv_raster_layer_texture_mode_set( GvRasterLayer *layer, int texture_mode, GvColor color )
+{
+ int modes[] = { GL_REPLACE, GL_MODULATE };
+ int max_modes = 2;
+
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( texture_mode < max_modes, 1 );
+
+ if( modes[texture_mode] != layer->gl_info.tex_env_mode
+ || color[0] != layer->gl_info.fragment_color[0]
+ || color[1] != layer->gl_info.fragment_color[1]
+ || color[2] != layer->gl_info.fragment_color[2]
+ || color[3] != layer->gl_info.fragment_color[3] )
+ {
+ layer->gl_info.tex_env_mode = modes[texture_mode];
+ memcpy( layer->gl_info.fragment_color, color, sizeof( GvColor ) );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+ }
+
+ return 0;
+}
+
+long
+gv_raster_layer_texture_mode_get( GvRasterLayer *layer, int *texture_mode, GvColor *color )
+{
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( texture_mode != NULL, 1 );
+ g_return_val_if_fail( color != NULL, 1 );
+
+ switch( layer->gl_info.tex_env_mode )
+ {
+ case GL_REPLACE:
+ *texture_mode = 0;
+ break;
+ case GL_MODULATE:
+ *texture_mode = 1;
+ break;
+ default:
+ return 1;
+ }
+
+ memcpy( color, layer->gl_info.fragment_color, sizeof( GvColor ) );
+
+ return 0;
+}
+
+long
+gv_raster_layer_alpha_set( GvRasterLayer *layer, int alpha_mode, float alpha_check_val )
+{
+ int modes[] = { 0, GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL };
+ int max_modes = 8;
+
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( alpha_mode < max_modes, 1 );
+
+ if( alpha_mode )
+ {
+ layer->gl_info.alpha_test = 1;
+
+ layer->gl_info.alpha_test_mode = modes[alpha_mode];
+
+ layer->gl_info.alpha_test_val = alpha_check_val;
+ } else {
+ layer->gl_info.alpha_test = 0;
+ }
+
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+
+ return 0;
+}
+
+long
+gv_raster_layer_alpha_get( GvRasterLayer *layer, int *alpha_mode, float *alpha_check_val )
+{
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( alpha_mode != NULL, 1 );
+ g_return_val_if_fail( alpha_check_val != NULL, 1 );
+
+ if( layer->gl_info.alpha_test )
+ {
+ switch( layer->gl_info.alpha_test_mode )
+ {
+ case GL_NEVER:
+ *alpha_mode = 1;
+ break;
+ case GL_ALWAYS:
+ *alpha_mode = 2;
+ break;
+ case GL_LESS:
+ *alpha_mode = 3;
+ break;
+ case GL_LEQUAL:
+ *alpha_mode = 4;
+ break;
+ case GL_EQUAL:
+ *alpha_mode = 5;
+ break;
+ case GL_GEQUAL:
+ *alpha_mode = 6;
+ break;
+ case GL_GREATER:
+ *alpha_mode = 7;
+ break;
+ case GL_NOTEQUAL:
+ *alpha_mode = 8;
+ break;
+ default:
+ return 1;
+ }
+ } else {
+ *alpha_mode = 0;
+ }
+
+ *alpha_check_val = layer->gl_info.alpha_test_val;
+
+ return 0;
+}
+
+long
+gv_raster_layer_blend_mode_set( GvRasterLayer *layer, int blend_mode, int sfactor, int dfactor )
+{
+ int factors[] = { GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
+ int max_factors = 7; /* This must match the entries in the factors[] list */
+ int max_modes = 5;
+ int new_blend_src, new_blend_dst, new_blend_enable;
+
+ g_return_val_if_fail( blend_mode < max_modes, 1 );
+
+ g_return_val_if_fail( ( blend_mode != GV_RASTER_LAYER_BLEND_MODE_CUSTOM )
+ || ( sfactor < max_factors && dfactor < max_factors ), 1 );
+
+ switch( blend_mode )
+ {
+ case GV_RASTER_LAYER_BLEND_MODE_FILTER:
+ new_blend_src = GL_SRC_ALPHA;
+ new_blend_dst = GL_ONE_MINUS_SRC_ALPHA;
+ new_blend_enable = 1;
+ break;
+ case GV_RASTER_LAYER_BLEND_MODE_MULTIPLY:
+ new_blend_src = GL_DST_COLOR;
+ new_blend_dst = GL_ZERO;
+ new_blend_enable = 1;
+ break;
+ case GV_RASTER_LAYER_BLEND_MODE_ADD:
+ new_blend_src = GL_ONE;
+ new_blend_dst = GL_ONE;
+ new_blend_enable = 1;
+ break;
+ case GV_RASTER_LAYER_BLEND_MODE_CUSTOM:
+ new_blend_src = factors[sfactor];
+ new_blend_dst = factors[dfactor];
+ new_blend_enable = 1;
+ break;
+ default:
+ new_blend_enable = 0;
+ new_blend_src = layer->gl_info.blend_src;
+ new_blend_dst = layer->gl_info.blend_dst;
+ break;
+ }
+
+ if( layer->gl_info.blend_enable != new_blend_enable
+ || layer->gl_info.blend_src != new_blend_src
+ || layer->gl_info.blend_dst != new_blend_dst )
+ {
+ layer->gl_info.blend_src = new_blend_src;
+ layer->gl_info.blend_dst = new_blend_dst;
+ layer->gl_info.blend_enable = new_blend_enable;
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+ }
+
+ return 0;
+}
+
+long
+gv_raster_layer_blend_mode_get( GvRasterLayer *layer, int *blend_mode, int *sfactor, int *dfactor )
+{
+ int factors[] = { GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA };
+ int max_factors = 7;
+ int i;
+
+ if( layer->gl_info.blend_enable )
+ {
+ *blend_mode = 4;
+
+ for( i = 0; i < max_factors; i++ )
+ {
+ if( factors[i] == layer->gl_info.blend_src )
+ {
+ *sfactor = i;
+ break;
+ }
+
+ if( factors[i] == layer->gl_info.blend_dst )
+ {
+ *dfactor = i;
+ }
+ }
+ } else {
+ *blend_mode = 0;
+ *sfactor = 0;
+ *dfactor = 0;
+ }
+ return 0;
+}
+
+int gv_raster_layer_mode_get( GvRasterLayer *layer )
+
+{
+ return layer->mode;
+}
+
+
+/* the following function should move to gvmesh.h/c when Paul is done with
+ them. */
+
+static int
+gv_mesh_transform_with_func(GvMesh *mesh,
+ int (*trfunc)(int,double*,double*,double*,void *),
+ void *cb_data )
+{
+ int tile;
+
+ for( tile = 0; tile < mesh->max_tiles; tile++ )
+ {
+ GArray *verts;
+ float *xyz_verts;
+ int xyz_offset;
+
+ verts = g_array_index( mesh->vertices, GArray *, tile );
+
+ xyz_verts = (float *) verts->data;
+ for( xyz_offset = 0; xyz_offset < verts->len; xyz_offset += 3 )
+ {
+ double x_out, y_out, z_out;
+
+ x_out = xyz_verts[0];
+ y_out = xyz_verts[1];
+ z_out = xyz_verts[2];
+
+ if( !trfunc( 1, &x_out, &y_out, &z_out, cb_data ) )
+ return FALSE;
+
+ xyz_verts[0] = x_out;
+ xyz_verts[1] = y_out;
+ xyz_verts[2] = z_out;
+
+ xyz_verts += 3;
+ }
+ }
+
+ return TRUE;
+}
+
+static int gvrl_reproject_cb( int pt_count, double *x, double *y, double *z,
+ void *cb_data )
+
+{
+ OGRCoordinateTransformationH *ct = (OGRCoordinateTransformationH) cb_data;
+
+ return OCTTransform( ct, pt_count, x, y, z );
+}
+
+static gint
+gv_raster_layer_reproject( GvLayer *layer,
+ const char * new_projection )
+
+{
+ int success = TRUE;
+ OGRSpatialReferenceH hSRSNew = NULL, hSRSOld = NULL;
+ OGRCoordinateTransformationH hTransform = NULL;
+
+ /*
+ * Try and establish if we can, or need to do reprojection.
+ */
+ if( gv_data_get_projection(GV_DATA(layer)) == NULL )
+ return FALSE;
+
+ if( EQUAL(gv_data_get_projection(GV_DATA(layer)),"PIXEL") )
+ return FALSE;
+
+ hSRSNew = OSRNewSpatialReference( new_projection );
+ if( hSRSNew == NULL )
+ return FALSE;
+
+ hSRSOld = OSRNewSpatialReference(gv_data_get_projection(GV_DATA(layer)));
+ if( hSRSOld == NULL )
+ {
+ OSRDestroySpatialReference( hSRSNew );
+ return FALSE;
+ }
+
+ if( OSRIsSame( hSRSOld, hSRSNew ) )
+ {
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ return TRUE;
+ }
+
+ /*
+ * Establish transformation.
+ */
+
+ hTransform = OCTNewCoordinateTransformation( hSRSOld, hSRSNew );
+ if( hTransform == NULL )
+ {
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ return FALSE;
+ }
+
+ /*
+ * Transform all the mesh points.
+ */
+
+ success = gv_mesh_transform_with_func( GV_RASTER_LAYER(layer)->mesh,
+ gvrl_reproject_cb,
+ (void *) hTransform );
+
+ OCTDestroyCoordinateTransformation( hTransform );
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ if( success )
+ gv_data_set_projection( GV_DATA(layer), new_projection );
+
+ return success;
+}
+
+static int
+gvrl_to_georef_cb( int pt_count, double *x, double *y, double *z,
+ void *cb_data )
+
+{
+ GvRaster *raster = GV_RASTER(cb_data);
+ int i, success = TRUE;
+
+ for( i = 0; i < pt_count; i++ )
+ {
+ success |= gv_raster_pixel_to_georef( raster, x+i, y+i, z+i );
+ }
+
+ return success;
+}
+
+static int
+gvrl_to_raw_cb( int pt_count, double *x, double *y, double *z,
+ void *cb_data )
+
+{
+ GvRaster *raster = GV_RASTER(cb_data);
+ int i, success = TRUE;
+
+ for( i = 0; i < pt_count; i++ )
+ {
+ y[i] = raster->height - y[i];
+ }
+
+ return success;
+}
+
+void gv_raster_layer_refresh_mesh( GvRasterLayer *layer )
+
+{
+ GvRaster *prototype_data = layer->prototype_data;
+
+ if( !layer->mesh_is_dirty )
+ return;
+
+ /* Should we actually reset the mesh to raw? */
+ if( layer->mesh_is_raw )
+ return;
+
+ gv_mesh_reset_to_identity( layer->mesh );
+
+ gv_mesh_transform_with_func( layer->mesh, gvrl_to_georef_cb,
+ prototype_data );
+ layer->mesh_is_dirty = FALSE;
+}
+
+int gv_raster_layer_set_raw( GvRasterLayer *layer, int raw_enable )
+
+{
+ GvRaster *prototype_data = layer->prototype_data;
+
+ if( !raw_enable == !layer->mesh_is_raw )
+ return TRUE;
+
+ if( !raw_enable )
+ {
+ gv_mesh_transform_with_func( layer->mesh, gvrl_to_georef_cb,
+ prototype_data );
+
+ gv_data_set_projection( GV_DATA(layer),
+ gv_data_get_projection(GV_DATA(prototype_data)) );
+
+ layer->mesh_is_raw = FALSE;
+ }
+ else
+ {
+ /* we can't rawify ungeoreferenced layers */
+ if( gv_data_get_projection( GV_DATA(layer) ) != NULL
+ && EQUAL(gv_data_get_projection( GV_DATA(layer) ),"PIXEL") )
+ return FALSE;
+
+ gv_mesh_reset_to_identity( layer->mesh );
+
+ gv_data_set_projection( GV_DATA(layer), NULL );
+
+ layer->mesh_is_raw = TRUE;
+ }
+
+ return TRUE;
+}
+
+gint gv_raster_layer_pixel_to_view(GvRasterLayer *layer,
+ double *x, double *y, double *z )
+
+{
+ int success = TRUE;
+
+ if( !layer->mesh_is_raw )
+ {
+ success = gv_raster_pixel_to_georef( layer->prototype_data, x, y, z );
+ }
+
+ if( success
+ && gv_data_get_projection(GV_DATA(layer->prototype_data)) != NULL
+ && gv_data_get_projection(GV_DATA(layer)) != NULL
+ && !EQUAL(gv_data_get_projection(GV_DATA(layer->prototype_data)),
+ gv_data_get_projection(GV_DATA(layer))) )
+ {
+ g_warning( "gv_raster_pixel_to_view doesn't reproject yet." );
+ }
+
+ return success;
+}
+
+gint gv_raster_layer_view_to_pixel(GvRasterLayer *layer,
+ double *x, double *y, double *z )
+
+{
+ int success = TRUE;
+
+ if( success
+ && gv_data_get_projection(GV_DATA(layer->prototype_data)) != NULL
+ && gv_data_get_projection(GV_DATA(layer)) != NULL
+ && !EQUAL(gv_data_get_projection(GV_DATA(layer->prototype_data)),
+ gv_data_get_projection(GV_DATA(layer))) )
+ {
+ g_warning( "gv_raster_pixel_to_view doesn't reproject yet." );
+ }
+
+ if( success && !layer->mesh_is_raw )
+ {
+ success = gv_raster_georef_to_pixel( layer->prototype_data, x, y, z );
+ }
+
+ return success;
+}
+
+double gv_raster_layer_pixel_size( GvRasterLayer *raster )
+
+{
+ double x1, y1, x2, y2;
+
+ x1 = raster->prototype_data->width / 2;
+ y1 = raster->prototype_data->height / 2;
+
+ x2 = x1 + 1.0;
+ y2 = y1 + 1.0;
+
+ gv_raster_layer_pixel_to_view( raster, &x1, &y1, NULL );
+ gv_raster_layer_pixel_to_view( raster, &x2, &y2, NULL );
+
+ return (ABS(x2-x1) + ABS(y2-y1)) * 0.5;
+}
+
+int gv_raster_layer_get_mode( GvRasterLayer *layer )
+
+{
+ return layer->mode;
+}
+
+void gv_raster_layer_add_height( GvRasterLayer *layer, GvRaster *height_raster,
+ double default_height )
+{
+ gv_mesh_add_height(layer->mesh, height_raster, default_height );
+}
+
+void gv_raster_layer_clamp_height( GvRasterLayer *layer, int bclamp_min, int bclamp_max,
+ double min_height, double max_height )
+{
+ gv_mesh_clamp_height(layer->mesh, bclamp_min, bclamp_max, min_height, max_height );
+}
+
+#define GV_MESH_RIGHT_X_BIT 1
+#define GV_MESH_LEFT_X_BIT 2
+#define GV_MESH_TOP_Y_BIT 4
+#define GV_MESH_BOT_Y_BIT 8
+
+#define DEG2RAD 0.01745329252
+#define RAD2DEG 57.2986885
+
+static GArray *
+gv_mesh_tilelist_get_2d( GvMesh *mesh, GvViewArea *view,
+ GvRasterLayer *rlayer, GArray *tilelist )
+{
+ float cos_ang, sin_ang;
+ float term1, term2, term3, term4, term5, term6;
+ gint i, e, j, dimensions, mask;
+ float x, y; /* Just to make it compile */
+ GArray *verts;
+
+ cos_ang = cos( view->state.rot * DEG2RAD );
+ sin_ang = sin( view->state.rot * DEG2RAD );
+
+ term1 = (2/view->state.shape_x) *
+ view->state.linear_zoom *
+ view->state.flip_x *
+ cos_ang;
+
+ term2 = (2/view->state.shape_x) *
+ -view->state.linear_zoom *
+ view->state.flip_y *
+ sin_ang;
+
+ term3 = (2/view->state.shape_x) *
+ view->state.linear_zoom *
+ ( ( view->state.flip_x *
+ view->state.tx *
+ cos_ang ) -
+ ( view->state.flip_y *
+ view->state.ty *
+ sin_ang ) );
+
+ term4 = (2/view->state.shape_y) *
+ view->state.linear_zoom *
+ view->state.flip_x *
+ sin_ang;
+
+ term5 = (2/view->state.shape_y) *
+ view->state.linear_zoom *
+ view->state.flip_y *
+ cos_ang;
+
+ term6 = (2/view->state.shape_y) *
+ view->state.linear_zoom *
+ ( ( view->state.flip_x *
+ view->state.tx *
+ sin_ang ) +
+ ( view->state.flip_y *
+ view->state.ty *
+ cos_ang ) );
+
+ dimensions = ( 1 << mesh->detail );
+
+ for( i = 0; i < mesh->max_tiles; i++ )
+ {
+ if( ( verts = g_array_index( mesh->vertices, GArray *, i ) ) != NULL )
+ {
+ mask = 0xFF;
+
+ for( e = 0; e <= (dimensions+1); e += (dimensions+1) )
+ {
+ for( j = 0; j <= dimensions; j += dimensions )
+ {
+ gint mask_point = 0;
+ gfloat old_x, old_y;
+
+ old_x = g_array_index( verts, float, 3*(e*dimensions+j) );
+ old_y = g_array_index( verts, float, 3*(e*dimensions+j)+1 );
+
+ x = ( term1*old_x ) + ( term2*old_y ) + term3;
+ y = ( term4*old_x ) + ( term5*old_y ) + term6;
+
+ if( x > 1.0 )
+ mask_point |= GV_MESH_RIGHT_X_BIT;
+
+ if( x < -1.0 )
+ mask_point |= GV_MESH_LEFT_X_BIT;
+
+ if( y > 1.0 )
+ mask_point |= GV_MESH_TOP_Y_BIT;
+
+ if( y < -1.0 )
+ mask_point |= GV_MESH_BOT_Y_BIT;
+
+ mask &= mask_point;
+
+ }
+ }
+
+ if( !mask )
+ {
+ g_array_append_val( tilelist, i );
+ }
+
+ }
+ }
+
+ return tilelist;
+}
+
+static GArray *
+gv_mesh_tilelist_get_3d( GvMesh *mesh, GvViewArea *view,
+ GvRasterLayer *rlayer, GArray *tilelist )
+{
+ float tile_vect[3]; /* xyz */
+ float tile_magnitude, eye_dir_magnitude, cos_angle;
+ float eye_pos[3], eye_dir[3];
+ float diag, cos_diag;
+ int debug3d = 0;
+ int tiles_across = rlayer->prototype_data->tiles_across;
+ int tiles_down = rlayer->prototype_data->tiles_down;
+ int *cornerInside, tile_i, tile_j;
+
+ if( gv_manager_get_preference(gv_get_manager(),"DEBUG3D") != NULL )
+ debug3d = atoi(gv_manager_get_preference(gv_get_manager(),"DEBUG3D"));
+
+ eye_pos[0] = view->state.eye_pos[0];
+ eye_pos[1] = view->state.eye_pos[1];
+ eye_pos[2] = view->state.eye_pos[2];
+
+ eye_dir[0] = view->state.eye_dir[0];
+ eye_dir[1] = view->state.eye_dir[1];
+ eye_dir[2] = view->state.eye_dir[2];
+
+ eye_dir_magnitude = sqrt( (eye_dir[0]) * (eye_dir[0]) +
+ (eye_dir[1]) * (eye_dir[1]) +
+ (eye_dir[2]) * (eye_dir[2]));
+ /*
+ * Compute the diagonal of the window to the y axis, and from this
+ * the cos() of the angle between the eye direction and the vector to
+ * the corner of the window.
+ */
+ diag = sqrt(1.0 + (view->state.shape_x*view->state.shape_x)
+ /(view->state.shape_y*view->state.shape_y));
+
+ cos_diag = 1.0 / sqrt(1+diag*diag);
+
+ if( debug3d )
+ {
+ printf( "diagonal angle = %.1f\n",
+ acos(cos_diag) * RAD2DEG );
+ }
+
+ /* Allocate array of flags for each tile corner. */
+ cornerInside = (int *) g_new(int,(tiles_across+1)*(tiles_down+1));
+
+ /*
+ * Loop over each tile corner, and work out if it is inside the cone
+ * or not.
+ */
+
+ for( tile_j = 0; tile_j < tiles_down+1; tile_j++ )
+ {
+ int tile_y;
+
+ tile_y = tile_j * rlayer->prototype_data->tile_y;
+ if( tile_y > rlayer->prototype_data->height )
+ tile_y = rlayer->prototype_data->height;
+
+ for( tile_i = 0; tile_i < tiles_across+1; tile_i++ )
+ {
+ int tile_x;
+ double geo_x, geo_y, geo_z;
+
+ tile_x = tile_i * rlayer->prototype_data->tile_x;
+ if( tile_x > rlayer->prototype_data->width )
+ tile_x = rlayer->prototype_data->width;
+
+ geo_x = tile_x * view->state.flip_x;
+ geo_y = tile_y * view->state.flip_y;
+ geo_z = 0.0;
+
+ gv_raster_layer_pixel_to_view(rlayer, &geo_x, &geo_y, &geo_z );
+
+ tile_vect[0] = geo_x - eye_pos[0];
+ tile_vect[1] = geo_y - eye_pos[1];
+ tile_vect[2] = geo_z - eye_pos[2];
+
+ tile_magnitude = sqrt(tile_vect[0]*tile_vect[0] +
+ tile_vect[1]*tile_vect[1] +
+ tile_vect[2]*tile_vect[2]);
+
+ /* Dot product of tile vector with eye_direction to find
+ cos of angle*/
+ cos_angle = (tile_vect[0] * (eye_dir[0]) +
+ tile_vect[1] * (eye_dir[1]) +
+ tile_vect[2] * (eye_dir[2]) )
+ / (tile_magnitude * eye_dir_magnitude);
+
+ cornerInside[tile_j * (tiles_across+1) + tile_i] =
+ (cos_angle >= cos_diag);
+
+ if( debug3d > 1 )
+ {
+ printf("tile (%d,%d) z %f angle=%f ",
+ tile_i, tile_j,
+ eye_pos[2], RAD2DEG * acos(cos_angle));
+
+ if( cornerInside[tile_j*(tiles_across+1)+tile_i] )
+ {
+ printf("\n");
+ } else {
+ printf("not\n");
+ }
+ }
+ if( debug3d > 2)
+ {
+ printf("tile(%f,%f,%f) tile_mag %f eye_mag %f\n",
+ tile_vect[0], tile_vect[1], tile_vect[2],
+ tile_magnitude, eye_dir_magnitude);
+ }
+ }
+ }
+
+ /*
+ * Scan through all the files, and for each one establish whether
+ * any of the corners are in the view cone. If so, add the tile
+ * to the list of files to be drawn.
+ */
+ for( tile_j = 0; tile_j < tiles_down; tile_j++ )
+ {
+ for( tile_i = 0; tile_i < tiles_across; tile_i++ )
+ {
+ int tile = tile_i + tile_j * tiles_across;
+ int corner = tile_i + tile_j * (tiles_across+1);
+
+ if( cornerInside[corner]
+ || cornerInside[corner+1]
+ || cornerInside[corner+tiles_across+1]
+ || cornerInside[corner+tiles_across+2] )
+ {
+ g_array_append_val( tilelist, tile );
+ }
+ }
+ }
+
+ g_free( cornerInside );
+
+ return tilelist;
+}
+
+GArray *
+gv_mesh_tilelist_get( GvMesh *mesh, GvViewArea *view,
+ GvRasterLayer *rlayer, GArray *tilelist )
+{
+ gint i;
+
+ if( !view->flag_3d)
+ gv_mesh_tilelist_get_2d( mesh, view, rlayer, tilelist );
+ else
+ gv_mesh_tilelist_get_3d( mesh, view, rlayer, tilelist );
+
+ i = -1;
+ g_array_append_val( tilelist, i );
+
+ return tilelist;
+}
+
+#define GROW_RANGE(x,xoff,xsize) { \
+ if( (int)(x) < 0 ) (x) = 0.0; \
+ if( (int)(x) < (xoff) ) { (xsize) += (xoff) - (int)(x); (xoff) = (int)(x); } \
+ else if( (int)(x) > (xoff)+(xsize) ) { (xsize) = (int)(x) - (xoff); } }
+
+static void
+gv_raster_layer_view_extents( GvRasterLayer *rlayer,
+ int *xoff, int *yoff, int *xsize, int *ysize )
+
+{
+ GvRaster *raster;
+ GvViewArea *view;
+
+ raster = rlayer->prototype_data;
+ view = GV_LAYER(rlayer)->view;
+
+ /*
+ ** Compute a bounding rectangle. In 3D we will just use all tiles
+ ** identified in the tile list, but for 2D we try to restrict things
+ ** more closely.
+ */
+ if( view->flag_3d )
+ {
+ *xoff = *yoff = 0;
+ *xsize = raster->width;
+ *ysize = raster->height;
+ }
+ else
+ {
+ gvgeocoord x, y;
+ double dx, dy;
+
+ *xsize = 1;
+ *ysize = 1;
+
+ /* upper left */
+ gv_view_area_map_pointer( view, 0.0, 0.0, &x, &y );
+ dx = x; dy = y;
+ if( gv_raster_layer_view_to_pixel( rlayer, &dx, &dy, NULL ) )
+ {
+ *xoff = MAX(0,MIN(raster->width-1,(int) dx));
+ *yoff = MAX(0,MIN(raster->height-1,(int) dy));
+ }
+ else
+ {
+ *xoff = 0;
+ *yoff = 0;
+ }
+
+ /* upper right */
+ gv_view_area_map_pointer( view, view->state.shape_x, 0.0,
+ &x, &y );
+ dx = x; dy = y;
+ if( gv_raster_layer_view_to_pixel( rlayer, &dx, &dy, NULL ) )
+ {
+ GROW_RANGE(dx, *xoff, *xsize );
+ GROW_RANGE(dy, *yoff, *ysize );
+ }
+
+ /* lower right */
+ gv_view_area_map_pointer( view,
+ view->state.shape_x,
+ view->state.shape_y,
+ &x, &y );
+ dx = x; dy = y;
+ if( gv_raster_layer_view_to_pixel( rlayer, &dx, &dy, NULL ) )
+ {
+ GROW_RANGE(dx, *xoff, *xsize );
+ GROW_RANGE(dy, *yoff, *ysize );
+ }
+
+ /* lower left */
+ gv_view_area_map_pointer( view, 0.0, view->state.shape_y,
+ &x, &y );
+ dx = x; dy = y;
+ if( gv_raster_layer_view_to_pixel( rlayer, &dx, &dy, NULL ) )
+ {
+ GROW_RANGE(dx, *xoff, *xsize );
+ GROW_RANGE(dy, *yoff, *ysize );
+ }
+
+ if( *xoff + *xsize > raster->width )
+ *xsize = raster->width - *xoff;
+ if( *yoff + *ysize > raster->height )
+ *ysize = raster->height - *yoff;
+ }
+}
+
+#undef GROW_RANGE
+
+gint
+gv_raster_layer_autoscale_view( GvRasterLayer *rlayer, int isrc,
+ GvAutoScaleAlg alg, double alg_param,
+ double *out_min, double *out_max )
+
+{
+ int sample_count, ret_val;
+ float *samples;
+ GvRaster *raster;
+ GvViewArea *view;
+ GArray *tile_list;
+ int xoff, yoff, xsize, ysize;
+
+ if( isrc < 0 || isrc >= rlayer->source_count )
+ return FALSE;
+
+ raster = rlayer->source_list[isrc].data;
+ if( raster == NULL )
+ return FALSE;
+
+ view = GV_LAYER(rlayer)->view;
+
+ /*
+ ** Build the tile list for the view. Even works in 3D!
+ */
+ tile_list = g_array_new( FALSE, FALSE, sizeof(int) );
+
+ tile_list = gv_mesh_tilelist_get( rlayer->mesh, view, rlayer, tile_list );
+
+ /*
+ ** Compute a bounding rectangle. In 3D we will just use all tiles
+ ** identified in the tile list, but for 2D we try to restrict things
+ ** more closely.
+ */
+ gv_raster_layer_view_extents( rlayer, &xoff, &yoff, &xsize, &ysize );
+
+ /*
+ ** Collect random samples to computing scaling min/max.
+ */
+ if( gv_manager_get_preference(gv_get_manager(),"autoscale_samples") )
+ {
+ sample_count = atoi(
+ gv_manager_get_preference(gv_get_manager(),"autoscale_samples"));
+ sample_count = MAX(10,sample_count);
+ }
+ else
+ sample_count = 10000;
+
+ samples = (float *) g_new(float,sample_count);
+
+ sample_count =
+ gv_raster_collect_random_sample(
+ raster, 10000, samples,
+ xoff, yoff, xsize, ysize, tile_list );
+
+ /*
+ ** Perform the autoscaling.
+ */
+ ret_val =
+ gv_raster_autoscale( raster, alg, alg_param, sample_count, samples,
+ out_min, out_max );
+
+ g_free( samples );
+
+ g_array_free( tile_list, TRUE );
+
+ return ret_val;
+}
+
+gint gv_raster_layer_histogram_view( GvRasterLayer *rlayer, int isrc,
+ double scale_min, double scale_max,
+ int include_out_of_range,
+ int bucket_count, int *histogram )
+
+{
+ GvRaster *raster;
+ GvViewArea *view;
+ GArray *tile_list;
+ int xoff, yoff, xsize, ysize;
+
+ if( isrc < 0 || isrc >= rlayer->source_count )
+ return 0;
+
+ raster = rlayer->source_list[isrc].data;
+ if( raster == NULL )
+ return 0;
+
+ view = GV_LAYER(rlayer)->view;
+
+ /*
+ ** Build the tile list for the view. Even works in 3D!
+ */
+ tile_list = g_array_new( FALSE, FALSE, sizeof(int) );
+
+ tile_list = gv_mesh_tilelist_get( rlayer->mesh, view, rlayer, tile_list );
+
+ /*
+ ** Compute a bounding rectangle. In 3D we will just use all tiles
+ ** identified in the tile list, but for 2D we try to restrict things
+ ** more closely.
+ */
+ gv_raster_layer_view_extents( rlayer, &xoff, &yoff, &xsize, &ysize );
+
+ /*
+ ** Perform the histogram.
+ */
+
+ return gv_raster_collect_histogram( raster, scale_min, scale_max,
+ bucket_count, histogram,
+ include_out_of_range,
+ xoff, yoff, xsize, ysize, tile_list );
+}
Added: packages/openev/branches/upstream/current/gvrasterlayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvrasterlayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterlayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,320 @@
+/******************************************************************************
+ * $Id: gvrasterlayer.h,v 1.32 2004/06/23 14:35:05 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster display layer (managed textures, redraw, etc)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterlayer.h,v $
+ * Revision 1.32 2004/06/23 14:35:05 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.31 2004/01/22 20:45:27 andrey_kiselev
+ * Added methods gv_raster_layer_nodata_set() and gv_raster_layer_nodata_get() to
+ * work with nodata_* layer properties and method gv_raster_layer_type_get() to
+ * query raster data type.
+ *
+ * Revision 1.30 2002/04/12 14:40:37 gmwalter
+ * Removed the gvmesh rescale function (not needed because of view area
+ * rescaling).
+ *
+ * Revision 1.28 2002/03/07 02:31:56 warmerda
+ * added default_height to add_height functions
+ *
+ * Revision 1.27 2001/12/13 03:29:17 warmerda
+ * avoid purging textures used in this render
+ *
+ * Revision 1.26 2001/11/28 19:23:04 warmerda
+ * Added logic to keep track if the mesh is dirty (out of date), and to
+ * refresh it before a redraw. It is marked dirty when the prototype data
+ * emits a geotransform-changed signal.
+ *
+ * Revision 1.25 2001/10/17 16:23:52 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.24 2001/10/16 18:50:29 warmerda
+ * added autoscale and histogram functions
+ *
+ * Revision 1.23 2001/07/13 22:16:03 warmerda
+ * disard unused pc_lut_{x,y} fields
+ *
+ * Revision 1.22 2001/07/03 14:26:05 warmerda
+ * added set/get raw ability
+ *
+ * Revision 1.21 2001/01/30 19:34:29 warmerda
+ * make gv_raster_layer_purge_all_textures() public
+ *
+ * Revision 1.20 2000/08/25 20:11:52 warmerda
+ * added preliminary nodata support
+ *
+ * Revision 1.19 2000/07/18 15:04:25 warmerda
+ * added texture dump prototype
+ *
+ * Revision 1.18 2000/07/03 20:58:31 warmerda
+ * eye_pos in georef coordinates now
+ *
+ * Revision 1.17 2000/06/27 21:25:41 warmerda
+ * rewrote texture caching completely
+ *
+ * Revision 1.16 2000/06/23 12:56:18 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.15 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_RASTER_LAYER_H__
+#define __GV_RASTER_LAYER_H__
+
+#include <gtkgl/gdkgl.h>
+#include <GL/gl.h>
+#include "gvlayer.h"
+#include "gvraster.h"
+
+
+#define GV_TYPE_RASTER_LAYER (gv_raster_layer_get_type ())
+#define GV_RASTER_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_RASTER_LAYER, GvRasterLayer))
+#define GV_RASTER_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_RASTER_LAYER, GvRasterLayerClass))
+#define GV_IS_RASTER_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_RASTER_LAYER))
+#define GV_IS_RASTER_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_CLASS_LAYER))
+
+typedef struct _GvRasterLayer GvRasterLayer;
+typedef struct _GvRasterLayerClass GvRasterLayerClass;
+
+/* Need to include here since we need GvRasterLayer definition */
+
+enum {
+ GV_RASTER_LAYER_BLEND_MODE_OFF = 0,
+ GV_RASTER_LAYER_BLEND_MODE_FILTER,
+ GV_RASTER_LAYER_BLEND_MODE_MULTIPLY,
+ GV_RASTER_LAYER_BLEND_MODE_ADD,
+ GV_RASTER_LAYER_BLEND_MODE_CUSTOM
+};
+
+typedef enum {
+ GV_RLM_AUTO = 0,
+ GV_RLM_SINGLE = 1,
+ GV_RLM_RGBA = 2,
+ GV_RLM_COMPLEX = 3
+} GvRasterLayerMode;
+
+typedef struct _GvRasterLayerTexObj
+{
+ struct _GvRasterLayerTexObj *prev;
+ struct _GvRasterLayerTexObj *next;
+ GvRasterLayer *layer;
+
+ int texture;
+ GLuint tex_obj; /* Name of the texture object for this tile */
+ int lod;
+ int size;
+ int last_render;
+} GvRasterLayerTexObj;
+
+
+struct _GvRasterLayerGLDispInfo
+{
+ /* Do we replace or modulate? */
+ gint tex_env_mode; /* GL_REPLACE and GL_MODULATE */
+ gint mag_filter;
+ gint min_filter;
+ gint s_wrap;
+ gint t_wrap;
+ GvColor fragment_color; /* Color if we modulate */
+
+ /* Is blending enabled? */
+ gint blend_enable;
+ gint blend_src, blend_dst; /* Src and dst parameters */
+
+ /* Is alpha test enabled? */
+ gint alpha_test;
+ gint alpha_test_mode;
+ GLfloat alpha_test_val;
+};
+
+typedef struct {
+
+ GvRaster *data;
+ unsigned char const_value; /* used for whole tile if data is NULL */
+ float max, min; /* for scaling */
+ unsigned char *lut; /* greyscale lut (uchar*256 or NULL) */
+
+ /* lut_rgba_composed is used only in the RGBA case in the presence */
+ /* of complex bands. It is equivalent to the pc_lut_composed */
+ /* used in the single complex band case, but since there are */
+ /* potentially multiple bands, it's stored here instead. */
+ unsigned char *lut_rgba_composed;
+
+ int nodata_active; /* flag indicating of nodata value meaningful*/
+ double nodata_real;
+ double nodata_imaginary;
+
+} GvRasterSource;
+
+#define MAX_RASTER_SOURCE 4
+
+struct _GvRasterLayer
+{
+ GvLayer layer;
+
+ GvRasterLayerMode mode;
+
+ gint mesh_is_raw;
+ gint mesh_is_dirty;
+ GvMesh *mesh;
+
+ int tile_x, tile_y;
+
+ GvRasterLayerTexObj **textures;
+
+ /* Sources list */
+
+ int source_count;
+ GvRasterSource source_list[MAX_RASTER_SOURCE];
+
+ GvRaster *prototype_data;
+
+ /* Final color table */
+ unsigned char *pc_lut;
+ unsigned char *pc_lut_composed;
+
+ /* LUT to use in RGB/RGBA case for any complex bands found */
+ unsigned char *pc_lut_rgba_complex;
+
+ /* OpenGL display properties */
+
+ struct _GvRasterLayerGLDispInfo gl_info;
+
+ /* Texture load information */
+
+ GArray *missing_tex;
+
+ /* Current tilelist display */
+
+ GArray *tile_list;
+};
+
+struct _GvRasterLayerClass
+{
+ GvLayerClass parent_class;
+};
+
+GtkType gv_raster_layer_get_type(void);
+GtkObject *gv_raster_layer_new(int mode,
+ GvRaster *prototype_data,
+ GvProperties prop);
+
+/* Raster value setup functions */
+long gv_raster_layer_texture_clamp_set( GvRasterLayer *layer, int s_clamp, int t_clamp );
+long gv_raster_layer_zoom_set( GvRasterLayer *layer, int mag_mode, int min_mode );
+long gv_raster_layer_zoom_get( GvRasterLayer *layer, int *mag_mode, int *min_mode );
+long gv_raster_layer_alpha_set( GvRasterLayer *layer, int alpha_mode, float alpha_check_val );
+long gv_raster_layer_texture_mode_set( GvRasterLayer *layer, int texture_mode, GvColor color );
+long gv_raster_layer_blend_mode_set( GvRasterLayer *layer, int blend_mode, int sfactor, int dfactor );
+void gv_raster_layer_purge_all_textures( GvRasterLayer *layer );
+
+/* Raster value query functions */
+int gv_raster_layer_get_mode( GvRasterLayer *layer );
+long gv_raster_layer_blend_mode_get( GvRasterLayer *layer, int *blend_mode, int *sfactor, int *dfactor );
+long gv_raster_layer_alpha_get( GvRasterLayer *layer, int *alpha_mode, float *alpha_check_val );
+long gv_raster_layer_texture_mode_get( GvRasterLayer *layer, int *texture_mode, GvColor *color );
+
+/* source related */
+float gv_raster_layer_max_get( GvRasterLayer *layer, int isource );
+float gv_raster_layer_min_get( GvRasterLayer *layer, int isource );
+unsigned char *gv_raster_layer_source_get_lut( GvRasterLayer *layer,
+ int isource );
+unsigned char gv_raster_layer_get_const_value( GvRasterLayer *layer,
+ int isource );
+
+GvRaster *gv_raster_layer_get_data( GvRasterLayer *layer, int isource );
+
+int gv_raster_layer_set_source( GvRasterLayer *layer, int isource,
+ GvRaster *data, float min, float max,
+ unsigned char const_value,
+ unsigned char *lut,
+ int nodata_active,
+ double nodata_real,
+ double nodata_imaginary );
+
+int gv_raster_layer_min_set( GvRasterLayer *layer, int isource, float min );
+int gv_raster_layer_max_set( GvRasterLayer *layer, int isource, float max );
+gint gv_raster_layer_nodata_set( GvRasterLayer *layer, int isource,
+ double nodata_real, double nodata_imaginary );
+gint gv_raster_layer_nodata_get( GvRasterLayer *layer, int isource,
+ double *nodata_real,
+ double *nodata_imaginary );
+GDALDataType gv_raster_layer_type_get( GvRasterLayer *layer, int isource );
+
+/* transformation */
+gint gv_raster_layer_pixel_to_view(GvRasterLayer *raster,
+ double *x, double *y, double *z );
+gint gv_raster_layer_view_to_pixel(GvRasterLayer *raster,
+ double *x, double *y, double *z );
+
+/* other */
+gint gv_raster_layer_autoscale_view( GvRasterLayer *rlayer, int isrc,
+ GvAutoScaleAlg alg, double alg_param,
+ double *out_min, double *out_max );
+
+gint gv_raster_layer_histogram_view( GvRasterLayer *rlayer, int isrc,
+ double scale_min, double scale_max,
+ int include_out_of_range,
+ int bucket_count, int *histogram );
+
+double gv_raster_layer_pixel_size( GvRasterLayer *layer );
+void gv_raster_layer_add_height( GvRasterLayer *layer,
+ GvRaster *height_raster,
+ double default_height);
+void gv_raster_layer_clamp_height( GvRasterLayer *layer,
+ int bclamp_min, int bclamp_max,
+ double min_height, double max_height );
+
+unsigned char *
+gv_raster_layer_srctile_xy_get( GvRasterLayer *layer, int isource,
+ int tile, int lod, int * needs_free,
+ unsigned char *nodata_mask);
+unsigned char *gv_raster_layer_gltile_get( GvRasterLayer *layer,
+ int tile, int lod,
+ int *format, int *type,
+ int *needs_free );
+
+int gv_raster_layer_set_raw( GvRasterLayer *layer, int raw_enable );
+void gv_raster_layer_refresh_mesh( GvRasterLayer *layer );
+
+/* texture cache functions */
+void gv_raster_layer_purge_texture( GvRasterLayer *layer, int texture );
+void gv_raster_layer_create_texture( GvRasterLayer *layer, int texture,
+ GLuint tex_obj, int lod, int size );
+void gv_raster_layer_touch_texture( GvRasterLayer *layer, int texture );
+void gv_raster_layer_reset_texture( GvRasterLayer *layer, int texture,
+ int lod, int size );
+void gv_texture_cache_set_max( int );
+int gv_texture_cache_get_max();
+int gv_texture_cache_get_used();
+void gv_texture_cache_dump();
+
+GArray *gv_mesh_tilelist_get( GvMesh *mesh, GvViewArea *view,
+ GvRasterLayer *rlayer, GArray *tilelist );
+#endif /* __GV_RASTER_LAYER_H__ */
+
Added: packages/openev/branches/upstream/current/gvrasterlut.c
===================================================================
--- packages/openev/branches/upstream/current/gvrasterlut.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterlut.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,831 @@
+/******************************************************************************
+ * $Id: gvrasterlut.c,v 1.31 2005/08/30 12:58:56 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Compute, and apply LUT to GvRaster.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterlut.c,v $
+ * Revision 1.31 2005/08/30 12:58:56 andrey_kiselev
+ * Make the return value of unsigned gv_raster_layer_lut_get().
+ *
+ * Revision 1.30 2004/06/23 14:35:05 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.29 2003/03/07 17:03:03 gmwalter
+ * Move last_complex_lut property setting down to c-level, fix magphase indeterminate
+ * phase colour setting.
+ *
+ * Revision 1.28 2003/02/26 16:43:00 warmerda
+ * don't crash on PCTs larger than 256 entries
+ *
+ * Revision 1.27 2002/05/27 19:34:02 warmerda
+ * set the center pixel to red for phase lut
+ *
+ * Revision 1.26 2001/10/17 16:23:52 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.25 2001/08/23 02:23:28 warmerda
+ * enable alpha blending if palette has any non-255 alpha values
+ *
+ * Revision 1.24 2001/07/24 21:21:45 warmerda
+ * added EV style phase colormap
+ *
+ * Revision 1.23 2001/01/30 19:34:11 warmerda
+ * added gv_raster_layer_purge_all_textures calls
+ *
+ * Revision 1.22 2000/08/25 20:10:18 warmerda
+ * modified phase to colour mapping to match EV
+ *
+ * Revision 1.21 2000/07/13 13:51:55 warmerda
+ * make 2d color luts in greyscale
+ *
+ * Revision 1.20 2000/07/07 14:29:23 srawlin
+ * removed debug print statement
+ *
+ * Revision 1.19 2000/06/27 21:26:04 warmerda
+ * removed use of invalidated
+ *
+ * Revision 1.18 2000/06/23 12:56:18 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.17 2000/06/20 14:32:06 warmerda
+ * fixed free/g_new mismatch
+ *
+ * Revision 1.16 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <gtk/gtk.h>
+#include "gvrastertypes.h"
+#include "gvrasterlut.h"
+#include "gdal.h"
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+static void gv_raster_layer_lut_hsv_to_rgb( float h, float s, float v, float *r, float *g, float *b );
+static int gv_raster_layer_lut_interpolate( guchar *lut, guchar start_color[4], guint start_index, guchar end_color[4], guint end_index );
+
+
+static unsigned char *phase_lut = "\377\000\000\377\000\000\377\000\000\377\000\000\377\017\000\377\017\000\377\017\000\377\017\000\375\043\000\375\043\000\375\043\000\375\043\000\371\067\000\371\067\000\371\067\000\371\067\000\364\112\000\364\112\000\364\112\000\364\112\000\357\130\000\357\130\000\357\130\000\357\130\000\350\153\000\350\153\000\350\153\000\350\153\000\336\175\000\336\175\000\336\175\000\336\175\000\324\216\000\324\216\000\324\216\000\324\216\000\313\232\000\313\232\000\313\232\000\313\232\000\277\251\000\277\251\000\277\251\000\277\251\000\261\270\000\261\270\000\261\270\000\261\270\000\242\305\000\242\305\000\242\305\000\242\305\000\226\316\000\226\316\000\226\316\000\226\316\000\205\331\000\205\331\000\205\331\000\205\331\000\164\343\000\164\343\000\164\343\000\164\343\000\142\354\000\142\354\000\142\354\000\142\354\000\124\361\000\124\361\000\124\361\000\124\361\000\074\370\000\074\370\000\074\370\000\074\370\000\050\374\000\050\374\000\050\374\000\050\374\000\031\376\000\031\376\000\031\376\000\031\376\000\005\377\000\005\377\000\005\377\000\005\377\000\000\377\017\000\377\017\000\377\017\000\377\017\000\375\043\000\375\043\000\375\043\000\375\043\000\372\062\000\372\062\000\372\062\000\372\062\000\365\105\000\365\105\000\365\105\000\365\105\000\357\130\000\357\130\000\357\130\000\357\130\000\350\153\000\350\153\000\350\153\000\350\153\000\341\170\000\341\170\000\341\170\000\341\170\000\327\211\000\327\211\000\327\211\000\327\211\000\313\232\000\313\232\000\313\232\000\313\232\000\277\251\000\277\251\000\277\251\000\277\251\000\264\264\000\264\264\000\264\264\000\264\264\000\246\302\000\246\302\000\246\302\000\246\302\000\226\316\000\226\316\000\226\316\000\226\316\000\201\334\000\201\334\000\201\334\000\201\334\000\164\343\000\164\343\000\164\343\000\164\343\000\142\354\000\142\354\000\142\354\000\142\354\000\117\363\000\117\363\000\117\363\000\117\363\000\074\370\000\074\370\000\074\370\000\074\370\000\055\373\000\055\373\000\055\373\000\055\373\000\031\376\000\031\376\000\031\376\000\031\376\000\005\377\000\005\377\000\005\377\000\005\377\017\000\377\017\000\377\017\000\377\017\000\377\036\000\375\036\000\375\036\000\375\036\000\375\062\000\372\062\000\372\062\000\372\062\000\372\105\000\365\105\000\365\105\000\365\105\000\365\130\000\357\130\000\357\130\000\357\130\000\357\146\000\352\146\000\352\146\000\352\146\000\352\170\000\341\170\000\341\170\000\341\170\000\341\211\000\327\211\000\327\211\000\327\211\000\327\232\000\313\232\000\313\232\000\313\232\000\313\251\000\277\251\000\277\251\000\277\251\000\277\270\000\261\270\000\261\270\000\261\270\000\261\305\000\242\305\000\242\305\000\242\305\000\242\321\000\222\321\000\222\321\000\222\321\000\222\331\000\205\331\000\205\331\000\205\331\000\205\343\000\164\343\000\164\343\000\164\343\000\164\354\000\142\354\000\142\354\000\142\354\000\142\363\000\117\363\000\117\363\000\117\363\000\117\367\000\100\367\000\100\367\000\100\367\000\100\373\000\055\373\000\055\373\000\055\373\000\055\376\000\031\376\000\031\376\000\031\376\000\031\377\000\000\377\000\000\377\000\000\377\000\000";
+
+int gv_raster_layer_lut_color_wheel_new_ev(
+ GvRasterLayer *layer, gint set_phase, gint set_magnitude )
+{
+ int i, q;
+ float f_i, f_q;
+ float magnitude, /* Calculated magnitude from I/Q data */
+ phase_angle; /* Calculated phase angle from I/Q data */
+ guchar *LUT;
+ guchar *ptr; /* This is the pointer we use to walk across the LUT table */
+
+
+ /* Allocate enough room to store the LUT */
+
+ if( ( LUT = g_new( guchar, 256 * 256 * 4 ) ) == NULL )
+ {
+ return 1;
+ } else {
+ ptr = LUT;
+
+ for( q = 0; q < 256; q++ )
+ {
+ for( i = 0; i < 256; i++ )
+ {
+ int cmap_entry;
+
+ f_i = -(( i - 127 ) / 128.0);
+ f_q = ( q - 127 ) / 128.0;
+
+ if( set_magnitude )
+ {
+ magnitude = sqrt( f_i * f_i + f_q * f_q );
+ magnitude = MAX(0.0,MIN(1.0,magnitude));
+ }
+ else
+ magnitude = 1.0;
+
+ if( set_phase )
+ {
+ phase_angle = atan2( f_q, f_i ) - M_PI*0.5;
+ if( phase_angle < 0.0 )
+ phase_angle += 2 * M_PI;
+
+ cmap_entry = phase_angle * 256 / (2 * M_PI);
+ cmap_entry = MIN(255,MAX(0,cmap_entry));
+
+ if ((q == 127) && (i == 127))
+ {
+ /* We want the "indetermininate phase" LUT entry to be hardcoded
+ to red (0 phase). */
+
+ *ptr++ = (int) (255*magnitude + 0.5);
+ *ptr++ = 0;
+ *ptr++ = 0;
+ *ptr++ = 255;
+ }
+ else
+ {
+ *ptr++ = (int) (phase_lut[cmap_entry*3+0]*magnitude + 0.5);
+ *ptr++ = (int) (phase_lut[cmap_entry*3+1]*magnitude + 0.5);
+ *ptr++ = (int) (phase_lut[cmap_entry*3+2]*magnitude + 0.5);
+ *ptr++ = 255;
+ }
+ }
+ else
+ {
+ *ptr++ = (int) (255 * magnitude + 0.5);
+ *ptr++ = (int) (255 * magnitude + 0.5);
+ *ptr++ = (int) (255 * magnitude + 0.5);
+ *ptr++ = 255;
+ }
+ }
+ }
+
+ }
+
+ if ( gv_raster_layer_lut_put( layer, LUT, 256 ) )
+ {
+ g_free(LUT);
+ return 1;
+ }
+
+ if (set_phase && set_magnitude )
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","magphase");
+ else if (set_magnitude)
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","magnitude");
+ else if (set_phase)
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","phase");
+ else
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","unnamed");
+
+ g_free(LUT);
+ return 0;
+}
+
+int gv_raster_layer_lut_color_wheel_new( GvRasterLayer *layer, gint h_type, gfloat h_param, gint s_type, gfloat s_param, gint v_type, gfloat v_param )
+{
+ int i, q;
+ float f_i, f_q;
+ float magnitude, /* Calculated magnitude from I/Q data */
+ phase_angle; /* Calculated phase angle from I/Q data */
+ float *h=NULL, *s=NULL, *v=NULL;
+ float r, g, b;
+ guchar *LUT;
+ guchar *ptr; /* This is the pointer we use to walk across the LUT table */
+ int use_hsv = TRUE;
+
+
+ /* Allocate enough room to store the LUT */
+
+ if( ( LUT = g_new( guchar, 256 * 256 * 4 ) ) == NULL )
+ {
+ return 1;
+ } else {
+ /* Figure out the HSV mapping for the data -- each channel of H, S and V can be independantly specified as either
+ Magnitude - GV_RASTER_LAYER_LUT_MAGNITUDE,
+ Phase Angle - GV_RASTER_LAYER_LUT_PHASE_ANGLE,
+ Scalar - GV_RASTER_LAYER_LUT_SCALAR */
+
+ switch( h_type )
+ {
+ case GV_RASTER_LAYER_LUT_MAGNITUDE:
+ h = &magnitude;
+ break;
+ case GV_RASTER_LAYER_LUT_PHASE_ANGLE:
+ h = &phase_angle;
+ break;
+ case GV_RASTER_LAYER_LUT_SCALAR:
+ h = &h_param;
+ if( h_param < 0.0 )
+ use_hsv = FALSE;
+ break;
+ case GV_RASTER_LAYER_LUT_REAL:
+ h = &f_q;
+ break;
+ case GV_RASTER_LAYER_LUT_IMAGINARY:
+ h = &f_i;
+ break;
+ default:
+ return 1;
+ }
+
+ switch( s_type )
+ {
+ case GV_RASTER_LAYER_LUT_MAGNITUDE:
+ s = &magnitude;
+ break;
+ case GV_RASTER_LAYER_LUT_PHASE_ANGLE:
+ s = &phase_angle;
+ break;
+ case GV_RASTER_LAYER_LUT_SCALAR:
+ s = &s_param;
+ break;
+ case GV_RASTER_LAYER_LUT_REAL:
+ s = &f_q;
+ break;
+ case GV_RASTER_LAYER_LUT_IMAGINARY:
+ s = &f_i;
+ break;
+ default:
+ return 1;
+ }
+
+ switch( v_type )
+ {
+ case GV_RASTER_LAYER_LUT_MAGNITUDE:
+ v = &magnitude;
+ break;
+ case GV_RASTER_LAYER_LUT_PHASE_ANGLE:
+ v = &phase_angle;
+ break;
+ case GV_RASTER_LAYER_LUT_SCALAR:
+ v = &v_param;
+ break;
+ case GV_RASTER_LAYER_LUT_REAL:
+ v = &f_q;
+ break;
+ case GV_RASTER_LAYER_LUT_IMAGINARY:
+ v = &f_i;
+ break;
+ default:
+ return 1;
+ }
+
+ ptr = LUT;
+
+ for( q = 0;q < 256; q++ )
+ {
+ for( i = 0; i < 256; i++ )
+ {
+ f_i = -(( i - 127 ) / 128.0);
+ f_q = ( q - 127 ) / 128.0;
+
+ phase_angle = (atan2( f_q, f_i ) - M_PI*0.5) / ( 2 * M_PI );
+ if( phase_angle < 0.0 )
+ phase_angle += 1.0;
+
+ magnitude = sqrt( f_i * f_i + f_q * f_q );
+
+ f_i = MAX(0,MIN(1,-1*f_i*0.5 + 0.5));
+ f_q = MAX(0,MIN(1,f_q*0.5 + 0.5));
+
+ if( magnitude > 1.0 )
+ magnitude = 1.0;
+
+ if( use_hsv )
+ gv_raster_layer_lut_hsv_to_rgb( *h, *s, *v, &r, &g, &b );
+ else
+ r = g = b = *v;
+
+ *ptr++ = (unsigned char) ( r * 255 );
+ *ptr++ = (unsigned char) ( g * 255 );
+ *ptr++ = (unsigned char) ( b * 255 );
+ *ptr++ = 255;
+
+ }
+ }
+ }
+
+ if ( gv_raster_layer_lut_put( layer, LUT, 256 ) )
+ {
+ g_free(LUT);
+ return 1;
+ }
+
+ if ((h_type == GV_RASTER_LAYER_LUT_SCALAR) &&
+ (s_type == GV_RASTER_LAYER_LUT_SCALAR) &&
+ (v_type == GV_RASTER_LAYER_LUT_REAL))
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","real");
+ else if ((h_type == GV_RASTER_LAYER_LUT_SCALAR) &&
+ (s_type == GV_RASTER_LAYER_LUT_SCALAR) &&
+ (v_type == GV_RASTER_LAYER_LUT_IMAGINARY))
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","imaginary");
+ else
+ gv_data_set_property(GV_DATA(layer),"last_complex_lut","unnamed");
+
+ g_free(LUT);
+ return 0;
+}
+
+int
+gv_raster_layer_lut_color_wheel_1d_new( GvRasterLayer *layer, float s, float v, float offset )
+{
+ float r, g, b, h;
+ int i, e;
+ guchar *lut;
+
+ if( ( lut = g_new( guchar, 256 * 4 ) ) != NULL )
+ {
+
+ for( e = 0, i = 0; i < 256; i++ )
+ {
+ h = ( i / 255.0 + offset );
+
+ gv_raster_layer_lut_hsv_to_rgb( h, s, v, &r, &g, &b );
+
+ lut[e++] = (char) (r * 255.0);
+ lut[e++] = (char) (g * 255.0);
+ lut[e++] = (char) (b * 255.0);
+ lut[e++] = 255;
+ }
+ }
+
+ if( gv_raster_layer_lut_put( layer, lut, 1 ) )
+ {
+ g_free( lut );
+ return 1;
+ }
+
+ g_free( lut );
+ return 0;
+}
+
+int
+gv_raster_layer_lut_interpolated_new( GvRasterLayer *layer, GvRasterLayerLutInterpolate *color_pair, int offset )
+{
+ int i;
+ guchar *lut;
+
+ if( ( lut = g_new( guchar, 256 * 4 ) ) != NULL )
+ {
+ for( i = 0; color_pair[i+1].index != -1; i++ )
+ {
+ gv_raster_layer_lut_interpolate( lut, color_pair[i].color, color_pair[i].index+offset, color_pair[i+1].color, color_pair[i+1].index+offset );
+ }
+
+ if ( gv_raster_layer_lut_put( layer, lut, 1 ) )
+ {
+ g_free(lut);
+ return 1;
+ }
+ else
+ g_free(lut);
+
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+gv_raster_layer_lut_interpolate( guchar *lut, guchar start_color[4], guint start_index, guchar end_color[4], guint end_index )
+{
+ float spread = ( end_index - start_index );
+ float step_r, step_g, step_b;
+ int i, e;
+
+ g_return_val_if_fail( lut != NULL, 1 );
+
+ step_r = ( end_color[0] - start_color[0] ) / spread;
+ step_g = ( end_color[1] - start_color[1] ) / spread;
+ step_b = ( end_color[2] - start_color[2] ) / spread;
+
+ for( e = start_index * 4, i = 0; i < end_index-start_index; i++ )
+ {
+ lut[e++%1024] = start_color[0] + (guchar) ( step_r * i );
+ lut[e++%1024] = start_color[1] + (guchar) ( step_g * i );
+ lut[e++%1024] = start_color[2] + (guchar) ( step_b * i );
+ lut[e++%1024] = 255;
+ }
+
+ lut[e++%1024] = end_color[0];
+ lut[e++%1024] = end_color[1];
+ lut[e++%1024] = end_color[2];
+ lut[e%1024] = 255;
+
+ return 0;
+}
+
+/*
+** The following function creates pc_lut_compose based on taking a 2D (complex)
+** PCT in pc_lut and "precomposing" the LUT in the first raster source. This
+** is intended to simulate "magnitude" enhancements inexpensively.
+**
+** The compose operation only does something if a 1D GvRasterSource LUT
+** exists, and the PCT is 2D.
+*/
+
+int
+gv_raster_layer_lut_compose( GvRasterLayer *layer )
+
+{
+ unsigned char *lut;
+ int x, y, src;
+
+ if( layer->pc_lut_composed != NULL )
+ {
+ g_free( layer->pc_lut_composed );
+ layer->pc_lut_composed = NULL;
+ }
+
+ /*
+ ** Do we want to generate a composed PCT?
+ */
+ if( ( layer->mode != GV_RLM_COMPLEX
+ || layer->pc_lut == NULL
+ || layer->source_list[0].lut == NULL ) &&
+ ( layer->mode != GV_RLM_RGBA
+ || layer->pc_lut_rgba_complex == NULL ) )
+ return TRUE;
+
+
+ if( layer->mode == GV_RLM_COMPLEX )
+ {
+ /*
+ ** Create the composed PCT.
+ */
+ layer->pc_lut_composed = g_new( guchar, 256 * 4 * 256 );
+ lut = layer->source_list[0].lut;
+ for( x = 0; x < 256; x++ )
+ {
+ for( y = 0; y < 256; y++ )
+ {
+ float p_mag, mp_mag;
+ int dx, dy;
+
+ dx = x - 128;
+ dy = y - 128;
+
+ /* compute magnitude scaled between 0.0 and 1.0 */
+ p_mag = sqrt((double)(dx*dx+dy*dy)) / 128.0;
+
+ if( p_mag > 1.0 )
+ p_mag = 1.0;
+
+ /* compute modified pseudo magnitude */
+ mp_mag = lut[(int) (p_mag * 255.99)] / 255.0;
+
+ if( dx != 0 || dy != 0 )
+ {
+ dx = (int) floor(dx * mp_mag / p_mag + 0.5);
+ dy = (int) floor(dy * mp_mag / p_mag + 0.5);
+
+ dx = MIN(MAX(-128,dx),127);
+ dy = MIN(MAX(-128,dy),127);
+ }
+
+ memcpy( layer->pc_lut_composed + (x + y*256)*4,
+ layer->pc_lut + ((dx+128)+(dy+128)*256)*4,
+ 4 );
+ }
+ }
+ }
+ else
+ {
+ for( src = 0 ; src < layer->source_count; src++ )
+ {
+ if (layer->source_list[src].lut_rgba_composed != NULL)
+ {
+ g_free(layer->source_list[src].lut_rgba_composed);
+ layer->source_list[src].lut_rgba_composed = NULL;
+ }
+ if ( layer->source_list[src].lut != NULL )
+ {
+
+ /*
+ ** Create the composed PCT.
+ */
+ layer->source_list[src].lut_rgba_composed = \
+ g_new( guchar, 256 * 4 * 256 );
+ lut = layer->source_list[src].lut;
+ for( x = 0; x < 256; x++ )
+ {
+ for( y = 0; y < 256; y++ )
+ {
+ float p_mag, mp_mag;
+ int dx, dy;
+
+ dx = x - 128;
+ dy = y - 128;
+
+ /* compute magnitude scaled between 0.0 and 1.0 */
+ p_mag = sqrt((double)(dx*dx+dy*dy)) / 128.0;
+
+ if( p_mag > 1.0 )
+ p_mag = 1.0;
+
+ /* compute modified pseudo magnitude */
+ mp_mag = lut[(int) (p_mag * 255.99)] / 255.0;
+
+ if( dx != 0 || dy != 0 )
+ {
+ dx = (int) floor(dx * mp_mag / p_mag + 0.5);
+ dy = (int) floor(dy * mp_mag / p_mag + 0.5);
+
+ dx = MIN(MAX(-128,dx),127);
+ dy = MIN(MAX(-128,dy),127);
+ }
+
+ memcpy( layer->source_list[src].lut_rgba_composed +
+ (x + y*256)*4,
+ layer->pc_lut_rgba_complex +
+ ((dx+128)+(dy+128)*256)*4,
+ 4 );
+ }
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+int
+gv_raster_layer_lut_put( GvRasterLayer *layer, guchar *lut, gint height )
+{
+ int i;
+
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+
+ if (layer->mode == GV_RLM_RGBA && height == 256)
+ {
+ /* Lut to apply to complex bands in rgba mode */
+ if( layer->pc_lut_rgba_complex )
+ {
+ g_free( layer->pc_lut_rgba_complex );
+ layer->pc_lut_rgba_complex = NULL;
+ }
+
+ if( lut == NULL )
+ {
+ layer->pc_lut_rgba_complex = NULL;
+ }
+ else
+ {
+ layer->pc_lut_rgba_complex = g_new( guchar, 256 * 4 * height );
+ memcpy( layer->pc_lut_rgba_complex, lut, 256 * 4 * height );
+ }
+ /*
+ ** Turn on Alpha blending if any of the colors have a non-255 alpha
+ ** value.
+ */
+ for( i = 0; layer->pc_lut_rgba_complex != NULL && i < 256 * height;
+ i++ )
+ {
+ if( layer->pc_lut_rgba_complex[i*4 + 3] != 255 )
+ {
+ gv_raster_layer_blend_mode_set( layer,
+ GV_RASTER_LAYER_BLEND_MODE_FILTER,
+ 0, 0 );
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ if( layer->pc_lut )
+ {
+ g_free( layer->pc_lut );
+ layer->pc_lut = NULL;
+ }
+
+ if( lut == NULL )
+ {
+ layer->pc_lut = NULL;
+ }
+ else if( (layer->mode == GV_RLM_COMPLEX && height != 256)
+ || (layer->mode != GV_RLM_COMPLEX && height != 1) )
+ {
+ g_warning( "Attempt to apply lut of inappropriate height in"
+ " gv_raster_layer_lut_put()." );
+ return 1;
+ }
+ else
+ {
+ layer->pc_lut = g_new( guchar, 256 * 4 * height );
+ memcpy( layer->pc_lut, lut, 256 * 4 * height );
+ }
+ /*
+ ** Turn on Alpha blending if any of the colors have a non-255 alpha
+ ** value.
+ */
+ for( i = 0; layer->pc_lut != NULL && i < 256 * height; i++ )
+ {
+ if( layer->pc_lut[i*4 + 3] != 255 )
+ {
+ gv_raster_layer_blend_mode_set( layer,
+ GV_RASTER_LAYER_BLEND_MODE_FILTER,
+ 0, 0 );
+ break;
+ }
+ }
+
+ }
+
+
+ /*
+ ** Purge old textures, to force regeneration and notify all of change.
+ */
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+
+ /*
+ ** Regenerate 2D composed Complex lut if needed.
+ */
+ gv_raster_layer_lut_compose( layer );
+
+ return 0;
+}
+
+
+/* April 2004 note: modified to include rgba_complex argument */
+/* so that real or complex lut can be selected for rgba case */
+/* (before there was no complex or mixed real-complex rgba mode). */
+unsigned char *
+gv_raster_layer_lut_get( GvRasterLayer *layer, int *width, int *height,
+ int rgba_complex )
+{
+ int width_ret=256, height_ret;
+
+ /* The argument rgba_complex indicates whether a complex or real
+ * lut should be returned in the rgba case. If rgba_complex is 1,
+ * the complex lut will be returned. Otherwise, the real one
+ * will be returned. The rgba_complex argument is IGNORED if the
+ * layer mode is not RGBA.
+ */
+ g_return_val_if_fail( layer != NULL, NULL );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), NULL );
+
+ if( layer->mode == GV_RLM_COMPLEX )
+ height_ret = 256;
+ else if ( layer->mode == GV_RLM_RGBA )
+ {
+ if (rgba_complex == 1)
+ height_ret = 256;
+ else
+ height_ret = 1;
+ }
+ else
+ height_ret = 1;
+
+ if ( layer->mode == GV_RLM_RGBA )
+ {
+ if((rgba_complex != 1) && ( layer->pc_lut == NULL ))
+ {
+ width_ret = 0;
+ height_ret = 0;
+ }
+ else if((rgba_complex == 1) && ( layer->pc_lut_rgba_complex == NULL ))
+ {
+ width_ret = 0;
+ height_ret = 0;
+ }
+ }
+ else
+ {
+ if( layer->pc_lut == NULL )
+ {
+ width_ret = 0;
+ height_ret = 0;
+ }
+ }
+
+ if( width != NULL )
+ *width = width_ret;
+
+ if( height != NULL )
+ *height = height_ret;
+
+ if ((layer->mode == GV_RLM_RGBA) && (rgba_complex == 1))
+ return layer->pc_lut_rgba_complex;
+ else
+ return layer->pc_lut;
+}
+
+
+long
+gv_raster_layer_lut_type_get( GvRasterLayer *layer )
+{
+ g_return_val_if_fail( layer != NULL, -1 );
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), -1 );
+
+ if( layer->mode == GV_RLM_COMPLEX )
+ return GV_RASTER_LAYER_LUT_2D;
+ else if( layer->mode == GV_RLM_SINGLE )
+ return GV_RASTER_LAYER_LUT_1D;
+ else
+ return GV_RASTER_LAYER_LUT_NONE;
+}
+
+static void
+gv_raster_layer_lut_hsv_to_rgb( float h, float s, float v, float *r, float *g, float *b )
+{
+ float f;
+ int i;
+
+ /* Find hue at max saturation */
+ h *= 6;
+ i = (int)h;
+ f = h - i;
+
+ switch(i)
+ {
+ case 0:
+ case 6:
+ *r = 1.0;
+ *g = f;
+ *b = 0.0;
+ break;
+
+ case 1:
+ *r = 1.0 - f;
+ *g = 1.0;
+ *b = 0.0;
+ break;
+
+ case 2:
+ *r = 0.0;
+ *g = 1.0;
+ *b = f;
+ break;
+
+ case 3:
+ *r = 0.0;
+ *g = 1.0-f;
+ *b = 1.0;
+ break;
+
+ case 4:
+ *r = f;
+ *g = 0.0;
+ *b = 1.0;
+ break;
+
+ case 5:
+ *r = 1.0;
+ *g = 0.0;
+ *b = 1.0-f;
+ break;
+
+ }
+
+ f = ( 0.3086 * *r + 0.6094 * *g + 0.082 * *b ) * (1.0 - s );
+ *r = f + *r * s;
+ *g = f + *g * s;
+ *b = f + *b * s;
+
+ /* Scale towards 0,0,0 using value */
+
+ *r *= v;
+ *g *= v;
+ *b *= v;
+}
+
+gint
+gv_raster_layer_apply_gdal_color_table( GvRasterLayer *layer,
+ GDALColorTableH color_table )
+
+{
+ guchar lut[256*4];
+ int i;
+
+ memset( lut, 0, 256*4 );
+
+ if( GDALGetColorEntryCount( color_table ) > 256 )
+ {
+ CPLDebug( "OpenEV", "gv_raster_layer_apply_gdal_color_table(): "
+ "PCT has %d entries, only using 256.",
+ GDALGetColorEntryCount( color_table ) );
+ }
+
+ for( i = 0; i < MIN(256,GDALGetColorEntryCount( color_table )); i++ )
+ {
+ GDALColorEntry entry;
+
+ GDALGetColorEntryAsRGB( color_table, i, &entry );
+
+ lut[i*4 ] = entry.c1;
+ lut[i*4+1] = entry.c2;
+ lut[i*4+2] = entry.c3;
+ lut[i*4+3] = entry.c4;
+ }
+
+ return gv_raster_layer_lut_put( layer, lut, 1 );
+}
Added: packages/openev/branches/upstream/current/gvrasterlut.h
===================================================================
--- packages/openev/branches/upstream/current/gvrasterlut.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrasterlut.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * $Id: gvrasterlut.h,v 1.15 2005/08/30 12:58:56 andrey_kiselev Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Compute, and apply LUT to GvRaster.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrasterlut.h,v $
+ * Revision 1.15 2005/08/30 12:58:56 andrey_kiselev
+ * Make the return value of unsigned gv_raster_layer_lut_get().
+ *
+ * Revision 1.14 2004/06/23 14:35:05 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.13 2001/10/17 16:23:52 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.12 2001/07/24 21:21:45 warmerda
+ * added EV style phase colormap
+ *
+ * Revision 1.11 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef _GV_RASTER_LAYER_LUT_H_
+#define _GV_RASTER_LAYER_LUT_H_
+
+#include <gtk/gtk.h>
+#include "gvrasterlayer.h"
+
+enum {
+ GV_RASTER_LAYER_LUT_MAGNITUDE,
+ GV_RASTER_LAYER_LUT_PHASE_ANGLE,
+ GV_RASTER_LAYER_LUT_SCALAR,
+ GV_RASTER_LAYER_LUT_REAL,
+ GV_RASTER_LAYER_LUT_IMAGINARY
+};
+
+enum {
+ GV_RASTER_LAYER_LUT_NONE = 0,
+ GV_RASTER_LAYER_LUT_1D,
+ GV_RASTER_LAYER_LUT_2D
+};
+
+typedef struct _GvRasterLayerLutInterpolate GvRasterLayerLutInterpolate;
+
+struct _GvRasterLayerLutInterpolate {
+ guchar color[4];
+ gint index;
+};
+
+int gv_raster_layer_lut_color_wheel_new_ev(
+ GvRasterLayer *layer, gint set_phase, gint set_magnitude );
+int gv_raster_layer_lut_color_wheel_new( GvRasterLayer *layer, gint h_type, gfloat h_param, gint s_type, gfloat s_param, gint v_type, gfloat v_param );
+int gv_raster_layer_lut_color_wheel_1d_new( GvRasterLayer *layer, float s, float v, float offset );
+int gv_raster_layer_lut_interpolated_new( GvRasterLayer *layer, GvRasterLayerLutInterpolate *color_pair, int offset );
+int gv_raster_layer_lut_new( GvRasterLayer *layer, gint h_type, gfloat h_param, gint s_type, gfloat s_param, gint v_type, gfloat v_param );
+int gv_raster_layer_lut_put( GvRasterLayer *layer, guchar *lut, gint height );
+unsigned char *gv_raster_layer_lut_get( GvRasterLayer *layer,
+ int *width, int *height,
+ int rgba_complex);
+int gv_raster_layer_lut_compose( GvRasterLayer *layer );
+long gv_raster_layer_lut_type_get( GvRasterLayer *layer );
+int gv_raster_layer_apply_gdal_color_table( GvRasterLayer *layer,
+ GDALColorTableH color_table );
+
+#endif
Added: packages/openev/branches/upstream/current/gvrastersource.c
===================================================================
--- packages/openev/branches/upstream/current/gvrastersource.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrastersource.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,715 @@
+/******************************************************************************
+ * $Id: gvrastersource.c,v 1.16 2004/06/23 14:35:05 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Code related to handling of GvRasterSource on a GvRasterLayer.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrastersource.c,v $
+ * Revision 1.16 2004/06/23 14:35:05 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.15 2004/04/02 17:01:02 gmwalter
+ * Updated nodata support for complex and
+ * rgb data.
+ *
+ * Revision 1.14 2004/02/20 12:32:23 andrey_kiselev
+ * Use turn on alfa blending in gv_raster_layer_nodata_set().
+ *
+ * Revision 1.13 2004/02/18 16:55:32 andrey_kiselev
+ * Don't change the min/max levels in gv_raster_layer_set_source().
+ *
+ * Revision 1.12 2004/02/17 14:28:43 warmerda
+ * check for NULL data in layer
+ *
+ * Revision 1.11 2004/01/22 20:45:27 andrey_kiselev
+ * Added methods gv_raster_layer_nodata_set() and gv_raster_layer_nodata_get() to
+ * work with nodata_* layer properties and method gv_raster_layer_type_get() to
+ * query raster data type.
+ *
+ * Revision 1.10 2003/03/06 22:55:58 gmwalter
+ * Fix pure phase display to remove residual dependence on magnitude.
+ *
+ * Revision 1.9 2001/10/19 13:30:58 warmerda
+ * include gvrasterlut.h for compose call
+ *
+ * Revision 1.8 2001/10/17 16:23:52 warmerda
+ * added support for composing complex lut and pct
+ *
+ * Revision 1.7 2001/01/30 19:34:11 warmerda
+ * added gv_raster_layer_purge_all_textures calls
+ *
+ * Revision 1.6 2000/08/25 20:11:07 warmerda
+ * added preliminary nodata support
+ *
+ * Revision 1.5 2000/08/16 20:58:46 warmerda
+ * produce proper constant complex images
+ *
+ * Revision 1.4 2000/08/09 17:38:23 warmerda
+ * keep reference on source GvRasters
+ *
+ * Revision 1.3 2000/08/02 19:17:21 warmerda
+ * return NULL on illegal source in get_data()
+ *
+ * Revision 1.2 2000/06/27 21:26:24 warmerda
+ * removed use of invalidated
+ *
+ * Revision 1.1 2000/06/23 12:51:07 warmerda
+ * New
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
+#include "gvrasterlayer.h"
+#include "gvrastertypes.h"
+#include "gvrasterlut.h"
+
+#ifndef sign
+# define sign(a) ( (a < 0.0 )?-1.0:1.0 )
+#endif
+
+static unsigned char *
+gv_scale_tile_to_byte( void *src_data,
+ int tile_x, int tile_y,
+ float min, float max,
+ GDALDataType gdal_type )
+
+{
+ float scale;
+ unsigned char *ret_data;
+ int i, pixel_count = tile_x * tile_y;
+
+ if( max == min )
+ scale = 1.0;
+ else
+ scale = 255.0 / (max - min);
+
+ if( gdal_type == GDT_Byte )
+ {
+ unsigned char *raw_data = (unsigned char *) src_data;
+ float f;
+
+ ret_data = (unsigned char *) g_malloc(pixel_count);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ f = (raw_data[i] - min) * scale;
+ if( f < 0.0 )
+ ret_data[i] = 0;
+ else if( f > 255 )
+ ret_data[i] = 255;
+ else
+ ret_data[i] = (int) f;
+ }
+ }
+ else if( gdal_type == GDT_Float32 )
+ {
+ float *raw_data = (float *) src_data;
+ float f;
+
+ ret_data = (unsigned char *) g_malloc(pixel_count);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ f = (raw_data[i] - min) * scale;
+ if( f < 0.0 )
+ ret_data[i] = 0;
+ else if( f > 255 )
+ ret_data[i] = 255;
+ else
+ ret_data[i] = (int) f;
+ }
+ }
+ else if( gdal_type == GDT_CFloat32 )
+ {
+ float *raw_data = (float *) src_data;
+
+ if( max == 0.0 )
+ scale = 1.0;
+ else
+ scale = 0.5 / max;
+
+ ret_data = (unsigned char *) g_malloc(pixel_count*2);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ float temp_i, temp_q;
+
+ temp_i = raw_data[i*2] * scale;
+ temp_q = raw_data[i*2+1] * scale;
+
+ if( fabs( temp_i ) > 0.5 )
+ {
+ temp_q *= 0.5 / fabs( temp_i );
+ temp_i = 0.5 * sign( temp_i );
+ }
+
+ if( fabs( temp_q ) > 0.5 )
+ {
+ temp_i *= 0.5 / fabs( temp_q );
+ temp_q = 0.5 * sign( temp_q );
+ }
+
+ temp_i += 0.5;
+ temp_q += 0.5;
+
+ ret_data[i*2 ] = (int) (temp_i * 255.0);
+ ret_data[i*2+1] = (int) (temp_q * 255.0);
+ }
+ }
+ else
+ {
+ ret_data = (unsigned char *) g_malloc(pixel_count);
+
+ g_warning( "unhandled data type in gv_scale_tile_to_byte().\n" );
+ memset( ret_data, 0, pixel_count );
+ }
+
+ return ret_data;
+}
+
+static unsigned char *
+gv_scale_pure_phase_tile_to_byte( void *src_data,
+ int tile_x, int tile_y,
+ GDALDataType gdal_type )
+
+{
+ unsigned char *ret_data;
+ int i, pixel_count = tile_x * tile_y;
+
+ if( gdal_type == GDT_CFloat32 )
+ {
+ float *raw_data = (float *) src_data;
+
+ ret_data = (unsigned char *) g_malloc(pixel_count*2);
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ float temp_i, temp_q;
+
+ temp_i = raw_data[i*2];
+ temp_q = raw_data[i*2+1];
+
+ if ((temp_i == 0) && (temp_q == 0))
+ {
+ ret_data[i*2]=127;
+ ret_data[i*2+1]=127;
+ }
+ else if (fabs(temp_i ) > fabs(temp_q))
+ {
+ ret_data[i*2]=(int) (0.5*(1.0+sign(temp_i))*255);
+ ret_data[i*2+1]=(int) (0.5*(1.0+temp_q/fabs(temp_i))*255);
+ }
+ else
+ {
+ ret_data[i*2]=(int) (0.5*(1.0+temp_i/fabs(temp_q))*255);
+ ret_data[i*2+1]=(int) (0.5*(1.0+sign(temp_q))*255);
+ }
+ }
+ }
+ else
+ {
+ ret_data = (unsigned char *) g_malloc(pixel_count);
+
+ g_warning( "unhandled data type in gv_scale_pure_phase_tile_to_byte().\n" );
+ memset( ret_data, 0, pixel_count );
+ }
+
+ return ret_data;
+}
+
+static void
+gv_raster_layer_srctile_check_nodata( GvRasterSource *source, int pixels,
+ unsigned char *data,
+ unsigned char *nodata_mask )
+
+{
+ int i;
+
+ if( nodata_mask == NULL || !source->nodata_active )
+ return;
+
+ /* assume all valid data in constant sources */
+ if( source->data == NULL )
+ return;
+
+ if( source->data->gdal_type == GDT_Byte )
+ {
+ unsigned char nodata = (unsigned char) source->nodata_real;
+
+ for( i = 0; i < pixels; i++ )
+ {
+ if( data[i] == nodata )
+ nodata_mask[i] = 0;
+ }
+ }
+ else if( source->data->gdal_type == GDT_Float32 )
+ {
+ float nodata = (float) source->nodata_real;
+
+ for( i = 0; i < pixels; i++ )
+ {
+ if( ((float *) data)[i] == nodata )
+ nodata_mask[i] = 0;
+ }
+ }
+ else if( source->data->gdal_type == GDT_CFloat32 )
+ {
+ float *f_data = (float *) data;
+
+ for( i = 0; i < pixels; i++ )
+ {
+ if( f_data[i*2] == (float) source->nodata_real
+ && f_data[i*2+1] == (float) source->nodata_imaginary )
+ nodata_mask[i] = 0;
+ }
+ }
+ else
+ {
+ g_warning( "unhandled type in gv_raster_layer_srctile_check_nodata()");
+ }
+}
+
+
+unsigned char *
+gv_raster_layer_srctile_xy_get( GvRasterLayer * layer, int isource,
+ int tile, int lod, int * needs_free,
+ unsigned char * nodata_mask )
+
+{
+ GvRasterSource *source;
+ unsigned char * ret_data;
+ int pixel_count;
+
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), NULL );
+ g_return_val_if_fail( layer != NULL, NULL );
+ g_return_val_if_fail( isource >= 0
+ && isource < layer->source_count, NULL );
+
+ source = layer->source_list + isource;
+ pixel_count = (layer->tile_x >> lod) * (layer->tile_y >> lod);
+
+ if( source->data != NULL )
+ {
+ *needs_free = FALSE;
+
+ ret_data = gv_raster_tile_get( source->data, tile, lod );
+ if( ret_data == NULL )
+ return NULL;
+
+ if( nodata_mask != NULL && source->nodata_active )
+ gv_raster_layer_srctile_check_nodata( source, pixel_count,
+ ret_data, nodata_mask );
+
+ if( source->data->gdal_type != GDT_Byte
+ || source->min != 0.0
+ || source->max != 255.0 )
+ {
+ *needs_free = TRUE;
+
+ if (( layer->mode == GV_RLM_COMPLEX ) &&
+ (gv_data_get_property( GV_DATA(layer),"last_complex_lut" ) != NULL) &&
+ (strcmp(gv_data_get_property( GV_DATA(layer),"last_complex_lut" ),"phase") == 0))
+ {
+ ret_data = gv_scale_pure_phase_tile_to_byte( ret_data,
+ layer->tile_x >> lod,
+ layer->tile_y >> lod,
+ source->data->gdal_type );
+ }
+ else if (( layer->mode == GV_RLM_RGBA ) &&
+ (gv_data_get_property( GV_DATA(layer),"last_complex_lut" ) != NULL) &&
+ (strcmp(gv_data_get_property( GV_DATA(layer),"last_complex_lut" ),"phase") == 0) &&
+ (source->data->gdal_type == GDT_CFloat32) )
+ {
+ ret_data = gv_scale_pure_phase_tile_to_byte( ret_data,
+ layer->tile_x >> lod,
+ layer->tile_y >> lod,
+ source->data->gdal_type );
+ }
+ else
+ {
+ ret_data = gv_scale_tile_to_byte( ret_data,
+ layer->tile_x >> lod,
+ layer->tile_y >> lod,
+ source->min, source->max,
+ source->data->gdal_type );
+ }
+ }
+
+ }
+ else if( layer->mode == GV_RLM_COMPLEX )
+ {
+ int i;
+
+ ret_data = (unsigned char *) g_malloc(pixel_count*2);
+ *needs_free = TRUE;
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ ret_data[i*2 ] = source->const_value;
+ ret_data[i*2+1] = 0;
+ }
+ }
+ else
+ {
+ ret_data = (unsigned char *) g_malloc(pixel_count);
+ *needs_free = TRUE;
+
+ memset( ret_data, source->const_value, pixel_count );
+ }
+
+ /* Do we have an LUT to apply? */
+ if( source->lut != NULL && layer->mode != GV_RLM_COMPLEX &&
+ ((source->data == NULL) ||
+ (source->data != NULL && source->data->gdal_type != GDT_CFloat32)))
+ {
+ int i;
+ unsigned char *lut = source->lut;
+
+ if( ! *needs_free )
+ {
+ unsigned char *temp;
+
+ temp = (unsigned char *) g_malloc(pixel_count);
+ memcpy( temp, ret_data, pixel_count );
+ ret_data = temp;
+ *needs_free = TRUE;
+ }
+
+ for( i = 0; i < pixel_count; i++ )
+ {
+ ret_data[i] = lut[ret_data[i]];
+ }
+ }
+
+ return ret_data;
+}
+
+unsigned char *
+gv_raster_layer_source_get_lut( GvRasterLayer * layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), NULL );
+ g_return_val_if_fail( layer != NULL, NULL );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count,NULL);
+
+ return layer->source_list[isource].lut;
+}
+
+unsigned char
+gv_raster_layer_get_const_value( GvRasterLayer * layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 0 );
+ g_return_val_if_fail( layer != NULL, 0 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 0 );
+
+ return layer->source_list[isource].const_value;
+}
+
+GvRaster *
+gv_raster_layer_get_data( GvRasterLayer * layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), NULL );
+ g_return_val_if_fail( layer != NULL, NULL );
+ if( isource < 0 || isource >= layer->source_count )
+ return NULL;
+ else
+ return layer->source_list[isource].data;
+}
+
+int
+gv_raster_layer_min_set( GvRasterLayer *layer, int isource, float min )
+{
+ GvRasterSource *source;
+
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 1 );
+
+ source = layer->source_list + isource;
+
+ if( min != source->min )
+ {
+ source->min = min;
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+ }
+
+ return 0;
+}
+
+float
+gv_raster_layer_min_get( GvRasterLayer *layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 1 );
+
+ return layer->source_list[isource].min;
+}
+
+int
+gv_raster_layer_max_set( GvRasterLayer *layer, int isource, float max )
+{
+ GvRasterSource *source;
+
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 1 );
+
+ source = layer->source_list + isource;
+
+ if( max != source->max )
+ {
+ source->max = max;
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+ }
+
+ return 0;
+}
+
+float gv_raster_layer_max_get( GvRasterLayer *layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 1 );
+
+ return layer->source_list[isource].max;
+}
+
+/************************************************************************/
+/* gv_raster_layer_nodata_set() */
+/************************************************************************/
+
+/**
+ * Sets NODATA value for the specified layer.
+ *
+ * @param layer Pointer to GvRasterLayer object.
+ *
+ * @param isource Source index.
+ *
+ * @param nodata_real Real part of the variable containing NODATA value.
+ *
+ * @param nodata_imaginary Imaginary part of the variable containing
+ * NODATA value.
+ *
+ * @return TRUE in case of success and FALSE otherwise.
+ */
+
+gint
+gv_raster_layer_nodata_set( GvRasterLayer *layer, int isource,
+ double nodata_real, double nodata_imaginary )
+{
+ GvRasterSource *source;
+
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), FALSE );
+ g_return_val_if_fail( layer != NULL, FALSE );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count,
+ FALSE );
+
+ source = layer->source_list + isource;
+ if( nodata_real != source->nodata_real
+ || nodata_imaginary != source->nodata_imaginary )
+ {
+ source->nodata_real = nodata_real;
+ source->nodata_imaginary = nodata_imaginary;
+ source->nodata_active = TRUE;
+ gv_raster_layer_blend_mode_set( layer,
+ GV_RASTER_LAYER_BLEND_MODE_FILTER,
+ 0, 0 );
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+ }
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_raster_layer_nodata_get() */
+/************************************************************************/
+
+/**
+ * Queries NODATA value for the specified layer.
+ *
+ * @param layer Pointer to GvRasterLayer object.
+ *
+ * @param isource Source index.
+ *
+ * @param nodata_real Pointer to the varible which will be filled with real
+ * part of the NODATA value, may be NULL
+ *
+ * @param nodata_imaginary Pointer to the varible which will be filled with
+ * imaginary part of the NODATA value, may be NULL.
+ *
+ * @return TRUE if specified layer has NODATA set and FALSE otherwise.
+ */
+
+gint
+gv_raster_layer_nodata_get( GvRasterLayer *layer, int isource,
+ double *nodata_real, double *nodata_imaginary )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), FALSE );
+ g_return_val_if_fail( layer != NULL, FALSE );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count,
+ FALSE );
+
+ if ( layer->source_list[isource].nodata_active )
+ {
+ if ( nodata_real )
+ *nodata_real = layer->source_list[isource].nodata_real;
+ if ( nodata_imaginary )
+ *nodata_imaginary = layer->source_list[isource].nodata_imaginary;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_raster_layer_type_get() */
+/************************************************************************/
+
+/**
+ * Queries type of the values for specified layer and source.
+ *
+ * @param layer Pointer to GvRasterLayer object.
+ *
+ * @param isource Source index.
+ *
+ * @return GDAL dtat type of the specified raster.
+ */
+
+GDALDataType
+gv_raster_layer_type_get( GvRasterLayer *layer, int isource )
+{
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 0 );
+ g_return_val_if_fail( layer != NULL, 0 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 0 );
+ g_return_val_if_fail( layer->source_list[isource].data != NULL, 0 );
+
+ return layer->source_list[isource].data->gdal_type;
+}
+
+int gv_raster_layer_set_source( GvRasterLayer *layer, int isource,
+ GvRaster *data, float min, float max,
+ unsigned char const_value,
+ unsigned char *lut,
+ int nodata_active,
+ double nodata_real,
+ double nodata_imaginary )
+
+{
+ GvRasterSource *source;
+
+ g_return_val_if_fail( GV_IS_RASTER_LAYER( layer ), 1 );
+ g_return_val_if_fail( layer != NULL, 1 );
+ g_return_val_if_fail( isource >= 0 && isource < layer->source_count, 1 );
+
+ if( !nodata_active )
+ {
+ nodata_real = -1e8;
+ nodata_imaginary = 0.0;
+ }
+
+ if( data != NULL )
+ {
+ if( data->tile_x != layer->tile_x
+ || data->tile_y != layer->tile_y
+ || data->width != layer->prototype_data->width
+ || data->height != layer->prototype_data->height )
+ {
+ g_warning( "Attempt to use different GvRaster that doesn't match\n"
+ "prototype raster in gv_raster_layer_set_source()." );
+ return 1;
+ }
+ }
+
+ source = layer->source_list + isource;
+
+ if( source->data == data
+ && source->min == min
+ && source->max == max
+ && source->const_value == const_value
+ && !source->nodata_active == !nodata_active
+ && source->nodata_real == nodata_real
+ && source->nodata_imaginary == nodata_imaginary
+ && source->lut == NULL
+ && lut == NULL )
+ return 0;
+
+ /* Manage a reference for each source */
+
+ if( source->data != NULL )
+ gtk_object_unref( GTK_OBJECT(source->data) );
+
+ if( data != NULL )
+ {
+ gtk_object_ref( GTK_OBJECT(data) );
+ gtk_object_sink( GTK_OBJECT(data) );
+ }
+
+ source->data = data;
+ source->min = min;
+ source->max = max;
+ source->const_value = const_value;
+ source->nodata_active = nodata_active;
+ source->nodata_real = nodata_real;
+ source->nodata_imaginary = nodata_imaginary;
+
+ if( source->lut != NULL )
+ {
+ g_free( source->lut );
+ source->lut = NULL;
+ }
+
+ if( lut != NULL )
+ {
+ source->lut = (unsigned char *) g_malloc(256);
+ memcpy( source->lut, lut, 256 );
+ }
+
+ if( source->lut_rgba_composed != NULL )
+ {
+ g_free( source->lut_rgba_composed );
+ source->lut_rgba_composed = NULL;
+ }
+
+ gv_raster_layer_purge_all_textures( layer );
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+
+ /*
+ ** Regenerate 2D composed Complex lut if needed.
+ */
+ gv_raster_layer_lut_compose( layer );
+
+ /* If we have a nodata value, we have to ensure that we have
+ alpha blending turned on */
+ if( source->nodata_active )
+ gv_raster_layer_blend_mode_set( layer,
+ GV_RASTER_LAYER_BLEND_MODE_FILTER,
+ 0, 0 );
+
+ return 0;
+}
+
Added: packages/openev/branches/upstream/current/gvrastertypes.h
===================================================================
--- packages/openev/branches/upstream/current/gvrastertypes.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrastertypes.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * $Id: gvrastertypes.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Raster data types.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrastertypes.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef _GV_RASTER_TYPES_H_
+#define _GV_RASTER_TYPES_H_
+
+enum {
+ GV_RASTER_BYTE_RGBA = 0,
+ GV_RASTER_BYTE_RGB,
+ GV_RASTER_BYTE_REAL,
+ GV_RASTER_BYTE_COMPLEX,
+ GV_RASTER_SHORT_RGBA,
+ GV_RASTER_SHORT_RGB,
+ GV_RASTER_SHORT_REAL,
+ GV_RASTER_SHORT_COMPLEX,
+ GV_RASTER_INT_RGBA,
+ GV_RASTER_INT_RGB,
+ GV_RASTER_INT_REAL,
+ GV_RASTER_INT_COMPLEX,
+ GV_RASTER_FLOAT_RGBA,
+ GV_RASTER_FLOAT_RGB,
+ GV_RASTER_FLOAT_REAL,
+ GV_RASTER_FLOAT_COMPLEX
+};
+
+#endif
Added: packages/openev/branches/upstream/current/gvrecords.c
===================================================================
--- packages/openev/branches/upstream/current/gvrecords.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrecords.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,801 @@
+/******************************************************************************
+ * $Id: gvrecords.c,v 1.5 2003/08/06 22:26:03 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvRecords implementation (GvShapes like collection of records)
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrecords.c,v $
+ * Revision 1.5 2003/08/06 22:26:03 warmerda
+ * added progress monitor to gv_records load/save funcs
+ *
+ * Revision 1.4 2003/08/06 17:07:44 warmerda
+ * added support to save only selected records in gv_records_to_dbf
+ *
+ * Revision 1.3 2003/07/27 04:57:28 warmerda
+ * complete implementation
+ *
+ * Revision 1.2 2003/06/23 15:51:28 warmerda
+ * added header
+ *
+ * Revision 1.1 2003/05/23 20:43:08 warmerda
+ * New
+ *
+ */
+
+#include "gvrecords.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "shapefil.h"
+
+static void gv_records_class_init(GvRecordsClass *klass);
+static void gv_records_init(GvRecords *points);
+static void gv_records_finalize(GtkObject *object);
+
+GtkType
+gv_records_get_type(void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GtkTypeInfo records_info =
+ {
+ "GvRecords",
+ sizeof(GvRecords),
+ sizeof(GvRecordsClass),
+ (GtkClassInitFunc) gv_records_class_init,
+ (GtkObjectInitFunc) gv_records_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique(gv_data_get_type(), &records_info);
+ }
+ return type;
+}
+
+static void
+gv_records_init(GvRecords *records)
+{
+ records->nRecordLength = 0;
+
+ records->nFieldCount = 0;
+ records->panFieldOffset = NULL;
+ records->panFieldWidth = NULL;
+ records->panFieldType = NULL;
+
+ records->nRecordCount = 0;
+
+ records->nMainDataSize = 0;
+ records->pachMainData = NULL;
+
+ records->nUsedFieldCount = 0;
+ records->panUsedFieldList = NULL;
+}
+
+static void
+gv_records_class_init(GvRecordsClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+ data_class = (GvDataClass*) klass;
+
+ object_class->finalize = gv_records_finalize;
+}
+
+GvData *
+gv_records_new(void)
+{
+ GvData *data;
+
+ data = GV_DATA(gtk_type_new(gv_records_get_type()));
+
+ return data;
+}
+
+/************************************************************************/
+/* gv_records_create_records() */
+/* */
+/* Creates the requested number of new records, all initialized */
+/* to NULL values. Returns the record index of the first new */
+/* record. */
+/************************************************************************/
+
+gint gv_records_create_records( GvRecords *psRecords, int nNewRecords )
+
+{
+ int nFirstRecord = psRecords->nRecordCount;
+
+ if( psRecords->nRecordLength * (psRecords->nRecordCount + nNewRecords)
+ > psRecords->nMainDataSize )
+ {
+ int nNewMainSize =
+ psRecords->nRecordLength * (psRecords->nRecordCount + nNewRecords)
+ + 100000;
+
+ psRecords->pachMainData =
+ g_renew( char, psRecords->pachMainData, nNewMainSize );
+ psRecords->nMainDataSize = nNewMainSize;
+ }
+
+ psRecords->nRecordCount += nNewRecords;
+
+ memset( (char *) gv_records_get_raw_record_data( psRecords, nFirstRecord ),
+ GV_NULL_MARKER, nNewRecords * psRecords->nRecordLength );
+
+ return nFirstRecord;
+}
+
+/************************************************************************/
+/* gv_record_to_dbf() */
+/************************************************************************/
+
+int gv_records_to_dbf( GvRecords *psRecords, const char *pszFilename,
+ int nSelectionCount, int *panSelectionList,
+ GDALProgressFunc pfnProgress, void * pCBData )
+
+{
+ DBFHandle dbf_handle;
+ int field_index, field_count=0, shape_index, i;
+ GvProperties *properties;
+
+ if( pfnProgress == NULL )
+ pfnProgress = GDALDummyProgress;
+
+ if( !pfnProgress( 0.0, "", pCBData ) )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Try to create the named file(s). */
+/* -------------------------------------------------------------------- */
+ dbf_handle = DBFCreate( pszFilename );
+ if( dbf_handle == NULL )
+ {
+ g_warning( "Failed to create DBF file." );
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the fields on the DBF file, if any. */
+/* -------------------------------------------------------------------- */
+ properties = gv_data_get_properties( GV_DATA(psRecords) );
+ for( field_index = 0; TRUE; field_index++ )
+ {
+ int width, precision = 0, field_type;
+ char prop_name[64];
+ const char *prop_value;
+
+ sprintf( prop_name, "_field_width_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ width = atoi(prop_value);
+
+ sprintf( prop_name, "_field_precision_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value != NULL )
+ precision = atoi(prop_value);
+
+ sprintf( prop_name, "_field_type_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ prop_value = "string";
+
+ if( g_strcasecmp(prop_value,"integer") == 0 )
+ field_type = FTInteger;
+ else if( g_strcasecmp(prop_value,"float") == 0 )
+ field_type = FTDouble;
+ else
+ field_type = FTString;
+
+ sprintf( prop_name, "_field_name_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ DBFAddField( dbf_handle, prop_value, field_type, width, precision );
+ field_count++;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add a dummy field if there are none. */
+/* -------------------------------------------------------------------- */
+ if( field_count == 0 )
+ {
+ g_warning( "No attributes to save in DBF file." );
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Start writing shapes, ignoring any that don't match our */
+/* desired type. */
+/* -------------------------------------------------------------------- */
+ if( panSelectionList == NULL )
+ nSelectionCount = gv_records_num_records(psRecords);
+
+ for( i = 0; i < nSelectionCount; i++ )
+ {
+ if( panSelectionList != NULL )
+ shape_index = panSelectionList[i];
+ else
+ shape_index = i;
+
+ /* Write the attributes of this shape that match the DBF schema */
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ char field_name[32];
+ const char * field_value;
+ int field_type;
+
+ /* FIXME: This will fail for truncated field names! */
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ field_name, NULL, NULL);
+
+ field_value =
+ gv_records_get_raw_field_data( psRecords, shape_index,
+ field_index);
+
+ if( field_value == NULL )
+ {
+ DBFWriteNULLAttribute( dbf_handle, i, field_index );
+ }
+ else
+ {
+ if( field_type == FTDouble )
+ DBFWriteDoubleAttribute( dbf_handle, i, field_index,
+ atof(field_value) );
+ else if( field_type == FTInteger )
+ DBFWriteIntegerAttribute( dbf_handle, i, field_index,
+ atoi(field_value) );
+ else
+ DBFWriteStringAttribute( dbf_handle, i, field_index,
+ field_value );
+ }
+ }
+
+ if( !pfnProgress( (i+1) / (double) nSelectionCount, "", pCBData ) )
+ {
+ DBFClose( dbf_handle );
+ VSIUnlink( pszFilename );
+ return FALSE;
+ }
+ }
+
+ DBFClose( dbf_handle );
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_records_from_dbf() */
+/************************************************************************/
+
+GvData* gv_records_from_dbf( const char *filename,
+ GDALProgressFunc pfnProgress, void * pCBData )
+
+{
+ DBFHandle dbf_handle;
+ int shape_count, shape_index, field_count = 0, field_index;
+ GvRecords *shapes_data;
+ GvProperties *properties;
+ int cancelled = FALSE;
+
+ if( pfnProgress == NULL )
+ pfnProgress = GDALDummyProgress;
+
+ if( !pfnProgress( 0.0, "", pCBData ) )
+ return FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Open the .shp and .dbf file. */
+/* -------------------------------------------------------------------- */
+ dbf_handle = DBFOpen( filename, "rb" );
+ if( dbf_handle == NULL )
+ {
+ g_warning( "Invalid DBF." );
+ return NULL;
+ }
+ else
+ field_count = DBFGetFieldCount( dbf_handle );
+
+ shape_count = DBFGetRecordCount( dbf_handle );
+
+/* -------------------------------------------------------------------- */
+/* Create shapes layer, and assign some metadata about the */
+/* field definitions. */
+/* -------------------------------------------------------------------- */
+ shapes_data = GV_RECORDS(gv_records_new());
+ properties = gv_data_get_properties( GV_DATA(shapes_data) );
+
+ //set the filename property
+ gv_properties_set( properties, "_filename", filename );
+
+ for(field_index = 0; field_index < field_count; field_index++ )
+ {
+ char prop_value[64];
+ int field_type, width, precision;
+ int rfld_type;
+
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ prop_value, &width, &precision );
+
+ if( field_type == FTInteger )
+ rfld_type = GV_RFT_INTEGER;
+ else if( field_type == FTDouble )
+ rfld_type = GV_RFT_FLOAT;
+ else
+ rfld_type = GV_RFT_STRING;
+
+ gv_records_add_field( shapes_data, prop_value, rfld_type,
+ width, precision );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Copy all the shapes, and their attributes. */
+/* -------------------------------------------------------------------- */
+ gv_records_create_records( shapes_data, shape_count );
+
+ for( shape_index = 0;
+ shape_index < shape_count && !cancelled;
+ shape_index++ )
+ {
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ const char *field_value;
+
+ if( DBFIsAttributeNULL(dbf_handle,shape_index,field_index) )
+ field_value = NULL;
+ else
+ field_value = DBFReadStringAttribute( dbf_handle, shape_index,
+ field_index );
+
+ gv_records_set_raw_field_data( shapes_data, shape_index,
+ field_index, field_value );
+ }
+
+ cancelled =
+ !pfnProgress( (shape_index+1) / (double) shape_count,
+ "", pCBData );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ if( dbf_handle != NULL )
+ DBFClose( dbf_handle );
+
+ if( cancelled )
+ {
+ gtk_object_unref( GTK_OBJECT(shapes_data) );
+ return NULL;
+ }
+ else
+ {
+ gv_data_set_name( GV_DATA(shapes_data), filename );
+
+ return GV_DATA(shapes_data);
+ }
+}
+
+CPL_C_START
+int CPL_DLL RECGetFieldCount( FILE *fp);
+int CPL_DLL RECGetFieldDefinition( FILE *fp, char *pszFieldName, int *pnType,
+ int *pnWidth, int *pnPrecision );
+int CPL_DLL RECReadRecord( FILE *fp, char *pszRecBuf, int nRecordLength );
+const char CPL_DLL *RECGetField( const char *pszSrc, int nStart, int nWidth );
+CPL_C_END
+
+/************************************************************************/
+/* gv_records_from_rec() */
+/************************************************************************/
+
+GvData* gv_records_from_rec( const char *filename,
+ GDALProgressFunc pfnProgress, void * pCBData )
+
+{
+ int record_index, field_count = 0, field_index;
+ int *foffset, *fwidth, cancelled = FALSE;
+ GvRecords *records_data;
+ GvProperties *properties;
+ FILE *fpRec;
+ long first_record_offset, all_records_length;
+ int record_length = 0, raw_field_count, approx_record_count;
+ char *raw_record;
+
+ if( pfnProgress == NULL )
+ pfnProgress = GDALDummyProgress;
+
+ if( !pfnProgress( 0.0, "", pCBData ) )
+ return NULL;
+
+/* -------------------------------------------------------------------- */
+/* Open the .rec file. */
+/* -------------------------------------------------------------------- */
+ fpRec = VSIFOpen( filename, "rb" );
+ if( fpRec == NULL )
+ {
+ g_warning( "Unable to open requested .rec file." );
+ return NULL;
+ }
+
+ raw_field_count = RECGetFieldCount( fpRec );
+ if( raw_field_count < 1 )
+ {
+ VSIFClose( fpRec );
+ g_warning( "Unable to get field count from .rec, corrupt?" );
+ return NULL;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create shapes layer, and assign some metadata about the */
+/* field definitions. */
+/* -------------------------------------------------------------------- */
+ foffset = (int *) g_new(int,raw_field_count);
+ fwidth = (int *) g_new(int,raw_field_count);
+
+ records_data = GV_RECORDS(gv_records_new());
+ properties = gv_data_get_properties( GV_DATA(records_data) );
+
+ //set the filename property
+ gv_properties_set( properties, "_filename", filename );
+
+ for(field_index = 0, field_count = 0, record_length = 0;
+ field_index < raw_field_count; field_index++ )
+ {
+ char fieldname[128];
+ int field_type, width, precision;
+ int rfld_type;
+
+ if( !RECGetFieldDefinition( fpRec, fieldname, &field_type,
+ &width, &precision ) )
+ {
+ g_warning( "corrupt field definition line." );
+ return NULL;
+ }
+
+ if( width == 0 )
+ continue;
+
+ if( field_type == 0 /* OFTInteger */ )
+ rfld_type = GV_RFT_INTEGER;
+ else if( field_type == 2 /* OFTReal */ )
+ rfld_type = GV_RFT_FLOAT;
+ else
+ rfld_type = GV_RFT_STRING;
+
+ gv_records_add_field( records_data, fieldname, rfld_type,
+ width, precision );
+
+ fwidth[field_count] = width;
+ foffset[field_count++] = record_length;
+ record_length += width;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute the approximate number of records in the file. */
+/* -------------------------------------------------------------------- */
+ first_record_offset = VSIFTell( fpRec );
+ VSIFSeek( fpRec, 0, SEEK_END );
+
+ all_records_length = VSIFTell( fpRec ) - first_record_offset;
+ VSIFSeek( fpRec, first_record_offset, SEEK_SET );
+
+ approx_record_count = all_records_length / record_length;
+
+/* -------------------------------------------------------------------- */
+/* Copy all the shapes, and their attributes. */
+/* -------------------------------------------------------------------- */
+ gv_records_create_records( records_data, approx_record_count );
+ raw_record = g_new( char, record_length + 10 );
+
+ for( record_index = 0;
+ record_index < approx_record_count && !cancelled;
+ record_index++ )
+ {
+ if( !RECReadRecord( fpRec, raw_record, record_length ) )
+ {
+ records_data->nRecordCount = record_index;
+ break;
+ }
+
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ const char *field_value = RECGetField( raw_record,
+ foffset[field_index]+1,
+ fwidth[field_index] );
+
+ if( field_value != NULL && *field_value == '\0' )
+ field_value = NULL;
+
+ gv_records_set_raw_field_data( records_data, record_index,
+ field_index, field_value );
+ }
+
+
+ cancelled =
+ !pfnProgress( (record_index+1) / (double) approx_record_count,
+ "", pCBData );
+ }
+
+ if( !cancelled )
+ cancelled = !pfnProgress( 1.0, "", pCBData );
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ g_free( foffset );
+ g_free( fwidth );
+ g_free( raw_record );
+
+ VSIFClose( fpRec );
+
+ if( !cancelled )
+ {
+ gv_data_set_name( GV_DATA(records_data), filename );
+ return GV_DATA(records_data);
+ }
+ else
+ {
+ gtk_object_unref( GTK_OBJECT(records_data) );
+ return NULL;
+ }
+}
+
+/************************************************************************/
+/* gv_records_finalize() */
+/************************************************************************/
+static void
+gv_records_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvRecords *records = GV_RECORDS(object);
+
+ CPLDebug( "OpenEV", "gv_records_finalize(%s/%p)",
+ gv_data_get_name( GV_DATA(object) ), object );
+
+ if( records->pachMainData )
+ g_free( records->pachMainData );
+
+ if( records->papszFieldName != NULL )
+ {
+ int i;
+ for( i = 0; i < records->nFieldCount; i++ )
+ g_free( records->papszFieldName[i] );
+ g_free( records->papszFieldName );
+
+ g_free( records->panFieldOffset );
+ g_free( records->panFieldWidth );
+ g_free( records->panFieldType );
+ }
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+/************************************************************************/
+/* gv_records_get_raw_record_data() */
+/************************************************************************/
+
+const char *gv_records_get_raw_record_data( GvRecords *psRecords,
+ int iRecord )
+
+{
+ if( iRecord < 0 || iRecord >= psRecords->nRecordCount )
+ return NULL;
+ else
+ return psRecords->pachMainData + psRecords->nRecordLength * iRecord;
+}
+
+/************************************************************************/
+/* gv_records_get_raw_field_data() */
+/************************************************************************/
+
+const char *gv_records_get_raw_field_data( GvRecords *psRecords,
+ int iRecord, int iField )
+
+{
+ const char *pszResult;
+
+ if( iRecord < 0 || iRecord >= psRecords->nRecordCount
+ || iField < 0 || iField >= psRecords->nFieldCount )
+ return NULL;
+
+ pszResult = psRecords->pachMainData + psRecords->nRecordLength * iRecord
+ + psRecords->panFieldOffset[iField];
+
+ if( *pszResult == GV_NULL_MARKER )
+ return NULL;
+ else
+ return pszResult;
+}
+
+/************************************************************************/
+/* gv_records_set_raw_field_data() */
+/************************************************************************/
+
+void gv_records_set_raw_field_data( GvRecords *psRecords,
+ int iRecord, int iField,
+ const char *pszNewValue )
+
+{
+ char *pszTarget;
+
+ if( iRecord < 0 || iRecord >= psRecords->nRecordCount
+ || iField < 0 || iField >= psRecords->nFieldCount )
+ return;
+
+ pszTarget = psRecords->pachMainData + psRecords->nRecordLength * iRecord
+ + psRecords->panFieldOffset[iField];
+
+ if( pszNewValue != NULL )
+ {
+ strncpy( pszTarget, pszNewValue, psRecords->panFieldWidth[iField] );
+ pszTarget[psRecords->panFieldWidth[iField]] = '\0';
+ }
+ else
+ {
+ pszTarget[0] = GV_NULL_MARKER;
+ pszTarget[1] = '\0';
+ }
+}
+
+/************************************************************************/
+/* gv_records_num_records() */
+/************************************************************************/
+
+int gv_records_num_records( GvRecords *psRecords )
+
+{
+ return psRecords->nRecordCount;
+}
+
+/************************************************************************/
+/* gv_records_add_field() */
+/************************************************************************/
+
+gint gv_records_add_field( GvRecords *psRecords, const char *field_name,
+ int field_type, int width, int precision )
+
+{
+ char szPropName[256], szPropValue[256];
+ GvProperties *properties;
+
+ int iField = psRecords->nFieldCount;
+
+ (void) precision;
+
+/* -------------------------------------------------------------------- */
+/* Grow the field list array. */
+/* -------------------------------------------------------------------- */
+ psRecords->nFieldCount++;
+
+ psRecords->papszFieldName =
+ g_renew( char *, psRecords->papszFieldName, psRecords->nFieldCount );
+ psRecords->panFieldOffset =
+ g_renew( int, psRecords->panFieldOffset, psRecords->nFieldCount );
+ psRecords->panFieldWidth =
+ g_renew( int, psRecords->panFieldWidth, psRecords->nFieldCount );
+ psRecords->panFieldType =
+ g_renew( int, psRecords->panFieldType, psRecords->nFieldCount );
+
+/* -------------------------------------------------------------------- */
+/* Add the new values. */
+/* -------------------------------------------------------------------- */
+ psRecords->papszFieldName[iField] = g_strdup( field_name );
+ psRecords->panFieldWidth[iField] = width;
+ psRecords->panFieldType[iField] = field_type;
+ psRecords->panFieldOffset[iField] = psRecords->nRecordLength;
+
+/* -------------------------------------------------------------------- */
+/* Increase the record size. */
+/* -------------------------------------------------------------------- */
+ psRecords->nRecordLength += width + 1;
+
+/* -------------------------------------------------------------------- */
+/* Add the new field to the layer properties for easy access */
+/* from python. */
+/* -------------------------------------------------------------------- */
+ properties = gv_data_get_properties( GV_DATA(psRecords) );
+
+ sprintf( szPropName, "_field_name_%d", iField+1 );
+ gv_properties_set( properties, szPropName, field_name );
+
+ sprintf( szPropName, "_field_width_%d", iField+1 );
+ sprintf( szPropValue, "%d", width );
+ gv_properties_set( properties, szPropName, szPropValue );
+
+ sprintf( szPropName, "_field_precision_%d", iField+1 );
+ sprintf( szPropValue, "%d", precision );
+ gv_properties_set( properties, szPropName, szPropValue );
+
+ if( field_type == GV_RFT_FLOAT )
+ {
+ sprintf( szPropName, "_field_precision_%d", iField+1 );
+ sprintf( szPropValue, "%d", precision );
+ gv_properties_set( properties, szPropName, szPropValue );
+ }
+
+ sprintf( szPropName, "_field_type_%d", iField+1 );
+ if( field_type == GV_RFT_INTEGER )
+ gv_properties_set( properties, szPropName, "integer" );
+ else if( field_type == GV_RFT_FLOAT )
+ gv_properties_set( properties, szPropName, "float" );
+ else
+ gv_properties_set( properties, szPropName, "string" );
+
+/* -------------------------------------------------------------------- */
+/* If data already exists we need to do a big reshuffle. */
+/* -------------------------------------------------------------------- */
+ if( psRecords->nRecordCount != 0 )
+ {
+ int iRec;
+ int old_rec_length = psRecords->nRecordLength - width - 1;
+
+ if( psRecords->nMainDataSize <
+ psRecords->nRecordCount * psRecords->nRecordLength )
+ {
+ psRecords->nMainDataSize =
+ psRecords->nRecordCount * psRecords->nRecordLength;
+ psRecords->pachMainData =
+ g_renew( char, psRecords->pachMainData,
+ psRecords->nMainDataSize );
+ }
+
+ for( iRec = psRecords->nRecordCount-1; iRec >= 0; iRec-- )
+ {
+ char *pszNew = psRecords->pachMainData
+ + iRec * psRecords->nRecordLength + old_rec_length;
+
+ memmove( psRecords->pachMainData + iRec * psRecords->nRecordLength,
+ psRecords->pachMainData + iRec * old_rec_length,
+ old_rec_length );
+ memset( pszNew, 0, psRecords->nRecordLength - old_rec_length );
+ pszNew[0] = GV_NULL_MARKER;
+ }
+ }
+
+ return iField;
+}
+
+/************************************************************************/
+/* gv_records_set_used_properties() */
+/************************************************************************/
+
+void gv_records_set_used_properties(GvRecords *psRecords, int nFieldCount,
+ int *panFieldList )
+
+{
+ if( psRecords->nUsedFieldCount != 0 )
+ g_free( psRecords->panUsedFieldList );
+
+ psRecords->panUsedFieldList = g_new( int, nFieldCount );
+ memcpy( psRecords->panUsedFieldList, panFieldList,
+ sizeof(int) * nFieldCount );
+ psRecords->nUsedFieldCount = nFieldCount;
+}
+
Added: packages/openev/branches/upstream/current/gvrecords.h
===================================================================
--- packages/openev/branches/upstream/current/gvrecords.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrecords.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,115 @@
+/******************************************************************************
+ * $Id: gvrecords.h,v 1.5 2003/08/06 22:26:03 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvRecords declarations.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrecords.h,v $
+ * Revision 1.5 2003/08/06 22:26:03 warmerda
+ * added progress monitor to gv_records load/save funcs
+ *
+ * Revision 1.4 2003/08/06 17:07:44 warmerda
+ * added support to save only selected records in gv_records_to_dbf
+ *
+ * Revision 1.3 2003/07/27 04:57:28 warmerda
+ * complete implementation
+ *
+ * Revision 1.2 2003/05/23 20:44:25 warmerda
+ * fixed header
+ *
+ * Revision 1.1 2003/05/23 20:43:08 warmerda
+ * New
+ *
+ */
+
+#ifndef __GV_RECORDS_H__
+#define __GV_RECORDS_H__
+
+#include "gvdata.h"
+#include "gdal.h"
+
+#define GV_TYPE_RECORDS (gv_records_get_type ())
+#define GV_RECORDS(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_RECORDS,\
+ GvRecords))
+#define GV_RECORDS_CLASS(klass) (GTK_CHECK_CLASS_CAST((klass),GV_TYPE_RECORDS,\
+ GvRecordsClass))
+#define GV_IS_RECORDS(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_RECORDS))
+#define GV_IS_RECORDS_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_SHAPES))
+
+#define GV_RFT_INTEGER 1
+#define GV_RFT_FLOAT 2
+#define GV_RFT_STRING 3
+
+#define GV_NULL_MARKER '\01'
+
+typedef struct
+{
+ GvDataClass parent_class;
+} GvRecordsClass;
+
+typedef struct
+{
+ GvData data;
+
+ int nRecordLength;
+
+ int nFieldCount;
+ char **papszFieldName;
+ int *panFieldOffset;
+ int *panFieldWidth;
+ int *panFieldType;
+
+ int nRecordCount;
+
+ int nMainDataSize;
+ char *pachMainData;
+
+ int nUsedFieldCount;
+ int *panUsedFieldList;
+
+} GvRecords;
+
+GtkType gv_records_get_type (void);
+GvData* gv_records_new(void);
+GvData* gv_records_from_dbf(const char *, GDALProgressFunc, void * );
+int gv_records_to_dbf(GvRecords *, const char *, int, int *,
+ GDALProgressFunc, void * );
+GvData* gv_records_from_rec(const char *, GDALProgressFunc, void * );
+
+gint gv_records_create_records(GvRecords *, int);
+gint gv_records_num_records(GvRecords *);
+gint gv_records_add_field(GvRecords *, const char *field_name,
+ int field_type, int width, int precision );
+const char *gv_records_get_raw_record_data(GvRecords *, int);
+const char *gv_records_get_raw_field_data(GvRecords *, int, int);
+void gv_records_set_raw_field_data(GvRecords *, int, int, const char *);
+void gv_records_set_used_properties(GvRecords *, int nCount, int *panList);
+int *gv_records_get_used_properties(GvRecords *, int *pnCount);
+
+#endif /* ndef __GV_RECORDS_H__ */
+
+
+
+
+
+
Added: packages/openev/branches/upstream/current/gvrecttool.c
===================================================================
--- packages/openev/branches/upstream/current/gvrecttool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrecttool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,571 @@
+/******************************************************************************
+ * $Id: gvrecttool.c,v 1.7 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Rectangle editing mode in GvShapesLayer.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrecttool.c,v $
+ * Revision 1.7 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.6 2001/08/08 17:44:12 warmerda
+ * use gv_shape_type() macro
+ *
+ * Revision 1.5 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.4 2000/08/03 18:11:51 warmerda
+ * don't create zero sized rectangles
+ *
+ * Revision 1.3 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.2 2000/07/27 17:52:09 warmerda
+ * allow edit of existing rectangles
+ *
+ * Revision 1.1 2000/07/25 23:34:03 warmerda
+ * New
+ *
+ */
+
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include "gvrecttool.h"
+#include "gvundo.h"
+#include <GL/gl.h>
+
+static void gv_rect_tool_class_init(GvRectToolClass *klass);
+static void gv_rect_tool_init(GvRectTool *tool);
+static void gv_rect_tool_draw(GvRectTool *tool);
+static void gv_rect_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_rect_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_rect_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_rect_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_rect_tool_deactivate(GvTool *tool, GvViewArea *view);
+static gint gv_rect_tool_configure(GvRectTool *tool);
+
+/* Return values for gv_roi_tool_pick_border() */
+enum
+{
+ PICK_NONE = 0,
+ PICK_CORNER_TOPLEFT,
+ PICK_CORNER_BOTTOMLEFT,
+ PICK_CORNER_BOTTOMRIGHT,
+ PICK_CORNER_TOPRIGHT,
+ PICK_SIDE_TOP,
+ PICK_SIDE_RIGHT,
+ PICK_SIDE_BOTTOM,
+ PICK_SIDE_LEFT
+};
+
+GtkType
+gv_rect_tool_get_type(void)
+{
+ static GtkType rect_tool_type = 0;
+
+ if (!rect_tool_type)
+ {
+ static const GtkTypeInfo rect_tool_info =
+ {
+ "GvRectTool",
+ sizeof(GvRectTool),
+ sizeof(GvRectToolClass),
+ (GtkClassInitFunc) gv_rect_tool_class_init,
+ (GtkObjectInitFunc) gv_rect_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ rect_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &rect_tool_info);
+ }
+ return rect_tool_type;
+}
+
+static void
+gv_rect_tool_class_init(GvRectToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_rect_tool_deactivate;
+ tool_class->button_press = gv_rect_tool_button_press;
+ tool_class->button_release = gv_rect_tool_button_release;
+ tool_class->motion_notify = gv_rect_tool_motion_notify;
+ tool_class->key_press = gv_rect_tool_key_press;
+}
+
+static void
+gv_rect_tool_init(GvRectTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->layer = NULL;
+ tool->named_layer = NULL;
+ tool->drawing = FALSE;
+}
+
+GvTool *
+gv_rect_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_RECT_TOOL));
+}
+
+static gint gv_rect_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvRectTool *tool = (GvRectTool *) data;
+
+ if( tool->layer == GV_SHAPES_LAYER(layer) )
+ gv_rect_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_rect_tool_set_layer(GvRectTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_rect_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_rect_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ if (tool->drawing)
+ {
+ tool->drawing = FALSE;
+ }
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+
+ if( layer == NULL )
+ tool->layer = NULL;
+ else
+ tool->layer = GV_SHAPES_LAYER(layer);
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_rect_tool_draw),
+ GTK_OBJECT(tool));
+ /* Recover if layer destroyed */
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_rect_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+void
+gv_rect_tool_set_named_layer(GvRectTool *tool, gchar *name)
+{
+ if (tool->named_layer)
+ {
+ g_free(tool->named_layer);
+ tool->named_layer = NULL;
+ }
+ if (name)
+ {
+ tool->named_layer = g_strdup(name);
+ }
+ /* Tool layer will be updated next time it is configured */
+}
+
+/********************************************************/
+
+static void
+gv_rect_tool_draw(GvRectTool *tool)
+{
+ if (tool->drawing)
+ {
+ /* Color is set when the layer is drawn,
+ so we don't need to repeat it here */
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glEnd();
+ }
+}
+
+static void
+gv_rect_tool_reshape( GvRectTool *r_tool, gvgeocoord x, gvgeocoord y )
+
+{
+ GvShape *shape;
+ gvgeocoord x1, y1, x2, y2;
+
+ gv_tool_clamp_to_bounds( GV_TOOL(r_tool), &x, &y );
+
+ shape = gv_shapes_get_shape( r_tool->layer->data, r_tool->shape_id );
+ if( shape == NULL || gv_shape_get_nodes( shape, 0 ) != 5 )
+ return;
+
+ shape = gv_shape_copy( shape );
+
+ x1 = gv_shape_get_x(shape,0,0);
+ y1 = gv_shape_get_y(shape,0,0);
+ x2 = gv_shape_get_x(shape,0,2);
+ y2 = gv_shape_get_y(shape,0,2);
+
+ if( r_tool->picked == PICK_SIDE_TOP )
+ y1 = y;
+ else if( r_tool->picked == PICK_SIDE_RIGHT )
+ x2 = x;
+ else if( r_tool->picked == PICK_SIDE_BOTTOM )
+ y2 = y;
+ else if( r_tool->picked == PICK_SIDE_LEFT )
+ x1 = x;
+ else if( r_tool->picked == PICK_CORNER_TOPLEFT )
+ {
+ x1 = x;
+ y1 = y;
+ }
+ else if( r_tool->picked == PICK_CORNER_TOPRIGHT )
+ {
+ x2 = x;
+ y1 = y;
+ }
+ else if( r_tool->picked == PICK_CORNER_BOTTOMRIGHT )
+ {
+ x2 = x;
+ y2 = y;
+ }
+ else if( r_tool->picked == PICK_CORNER_BOTTOMLEFT )
+ {
+ x1 = x;
+ y2 = y;
+ }
+
+ gv_shape_set_xyz( shape, 0, 0, x1, y1, 0 );
+ gv_shape_set_xyz( shape, 0, 1, x1, y2, 0 );
+ gv_shape_set_xyz( shape, 0, 2, x2, y2, 0 );
+ gv_shape_set_xyz( shape, 0, 3, x2, y1, 0 );
+ gv_shape_set_xyz( shape, 0, 4, x1, y1, 0 );
+
+ gv_shapes_replace_shapes( r_tool->layer->data, 1, &(r_tool->shape_id),
+ &shape, FALSE );
+}
+
+static void
+gv_rect_tool_button_press(GvTool *r_tool, GdkEventButton *event)
+{
+ GvRectTool *tool = GV_RECT_TOOL(r_tool);
+
+ if (event->button == 1 && !tool->drawing )
+ {
+ GvNodeInfo edit_node;
+ int before, shape_id, is_rectangle = FALSE;
+
+ if (!gv_rect_tool_configure(tool)) return;
+
+ if (gv_shape_layer_pick_shape(GV_SHAPE_LAYER(tool->layer),
+ GV_TOOL(tool)->view,
+ event->x, event->y, &shape_id))
+ {
+ GvShape *shape;
+
+ /* Is the shape a rectangle? */
+ shape = gv_shapes_get_shape( tool->layer->data, shape_id );
+ if( shape != NULL
+ && gv_shape_type(shape) == GVSHAPE_AREA
+ && gv_shape_get_rings( shape ) == 1
+ && gv_shape_get_nodes( shape, 0 ) == 5 )
+ {
+ gvgeocoord x1, y1, x2, y2;
+
+ x1 = gv_shape_get_x(shape,0,0);
+ y1 = gv_shape_get_y(shape,0,0);
+ x2 = gv_shape_get_x(shape,0,2);
+ y2 = gv_shape_get_y(shape,0,2);
+
+ tool->winding = 1;
+ is_rectangle = gv_shape_get_x(shape,0,1) == x1
+ && gv_shape_get_y(shape,0,1) == y2
+ && gv_shape_get_x(shape,0,3) == x2
+ && gv_shape_get_y(shape,0,3) == y1
+ && gv_shape_get_x(shape,0,4) == x1
+ && gv_shape_get_y(shape,0,4) == y1;
+
+ if( !is_rectangle )
+ {
+ tool->winding = 0;
+ is_rectangle = gv_shape_get_x(shape,0,1) == x2
+ && gv_shape_get_y(shape,0,1) == y1
+ && gv_shape_get_x(shape,0,3) == x1
+ && gv_shape_get_y(shape,0,3) == y2
+ && gv_shape_get_x(shape,0,4) == x1
+ && gv_shape_get_y(shape,0,4) == y1;
+ }
+
+ if( is_rectangle )
+ {
+ gv_shape_layer_clear_selection(
+ GV_SHAPE_LAYER(tool->layer));
+ gv_shape_layer_select_shape(
+ GV_SHAPE_LAYER(tool->layer), shape_id);
+ }
+ }
+ }
+
+ /* Is the user selecting an existing rectangles edge/corner? */
+ if (is_rectangle
+ && gv_shape_layer_pick_node(GV_SHAPE_LAYER(tool->layer),
+ GV_TOOL(tool)->view,
+ event->x, event->y, &before,
+ &edit_node) )
+ {
+ if( tool->winding == 0 )
+ {
+ if( before )
+ edit_node.node_id = 5 - edit_node.node_id;
+ else
+ edit_node.node_id = 4 - edit_node.node_id;
+ }
+
+ if( before && edit_node.node_id == 1 )
+ tool->picked = PICK_SIDE_LEFT;
+ else if( before && edit_node.node_id == 2 )
+ tool->picked = PICK_SIDE_BOTTOM;
+ else if( before && edit_node.node_id == 3 )
+ tool->picked = PICK_SIDE_RIGHT;
+ else if( before && edit_node.node_id == 4 )
+ tool->picked = PICK_SIDE_TOP;
+ else if( edit_node.node_id == 0 )
+ tool->picked = PICK_CORNER_TOPLEFT;
+ else if( edit_node.node_id == 1 )
+ tool->picked = PICK_CORNER_BOTTOMLEFT;
+ else if( edit_node.node_id == 2 )
+ tool->picked = PICK_CORNER_BOTTOMRIGHT;
+ else if( edit_node.node_id == 3 )
+ tool->picked = PICK_CORNER_TOPRIGHT;
+ else if( edit_node.node_id == 4 )
+ tool->picked = PICK_CORNER_TOPLEFT;
+ else
+ {
+ g_warning( "Yikes! What node is this?" );
+ return;
+ }
+
+ tool->reshaping = TRUE;
+ tool->shape_id = edit_node.shape_id;
+
+ /* Close down undo. A single operation describing the new
+ ring will be pushed to undo when drawing stops. */
+ gv_undo_close();
+ gv_undo_disable();
+
+ return;
+ }
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ if( gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_tail.x, tool->v_tail.y ) )
+ {
+ /* Start a new rect */
+ tool->drawing = TRUE;
+ tool->v_head = tool->v_tail;
+ }
+ }
+}
+
+static void
+gv_rect_tool_button_release(GvTool *r_tool, GdkEventButton *event)
+{
+ GvRectTool *tool = GV_RECT_TOOL(r_tool);
+
+ if (event->button == 1 && tool->drawing )
+ {
+ GvShape *shape;
+
+ if (!gv_rect_tool_configure(tool)) return;
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &tool->v_tail.x, &tool->v_tail.y );
+
+
+ if( tool->v_tail.x != tool->v_head.x
+ && tool->v_tail.y != tool->v_head.y )
+ {
+ /* create the new rectangle */
+ shape = gv_shape_new( GVSHAPE_AREA );
+
+ gv_shape_add_node( shape, 0, tool->v_tail.x, tool->v_tail.y, 0 );
+ gv_shape_add_node( shape, 0, tool->v_tail.x, tool->v_head.y, 0 );
+ gv_shape_add_node( shape, 0, tool->v_head.x, tool->v_head.y, 0 );
+ gv_shape_add_node( shape, 0, tool->v_head.x, tool->v_tail.y, 0 );
+ gv_shape_add_node( shape, 0, tool->v_tail.x, tool->v_tail.y, 0 );
+
+ gv_shapes_layer_select_new_shape( GV_SHAPES_LAYER(tool->layer),
+ shape );
+ }
+
+ tool->drawing = FALSE;
+ return;
+ }
+
+ if (event->button == 1 && tool->reshaping )
+ {
+ if (!gv_rect_tool_configure(tool)) return;
+
+ /* Reopen undo. Push a memento describing the ring addition */
+ gv_undo_enable();
+ gv_undo_open();
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ gv_rect_tool_reshape( tool, tool->v_tail.x, tool->v_tail.y );
+
+ tool->reshaping = FALSE;
+ }
+}
+
+static void
+gv_rect_tool_motion_notify(GvTool *r_tool, GdkEventMotion *event)
+{
+ GvRectTool *tool = GV_RECT_TOOL(r_tool);
+
+ if (tool->drawing)
+ {
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &tool->v_tail.x, &tool->v_tail.y );
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+
+ if (tool->reshaping)
+ {
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ gv_rect_tool_reshape( tool, tool->v_tail.x, tool->v_tail.y );
+ }
+}
+
+static void
+gv_rect_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvRectTool *tool = GV_RECT_TOOL(rtool);
+
+ if (!gv_rect_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ case GDK_Escape:
+ if( tool->drawing )
+ {
+ tool->drawing = FALSE;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ if( tool->reshaping )
+ {
+ /* Reopen undo. Push a memento describing the ring addition */
+ gv_undo_enable();
+ gv_undo_open();
+
+ tool->reshaping = FALSE;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ break;
+ }
+}
+
+static void
+gv_rect_tool_deactivate(GvTool *r_tool, GvViewArea *view)
+{
+ GvRectTool *tool = GV_RECT_TOOL(r_tool);
+
+ /* Disconnect from layer */
+ if (tool->layer)
+ {
+ gv_rect_tool_set_layer(tool, NULL);
+ }
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static gint
+gv_rect_tool_configure(GvRectTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ if (tool->named_layer)
+ {
+ /* Look for named layer if given */
+ layer = gv_view_area_get_named_layer(GV_TOOL(tool)->view,
+ tool->named_layer);
+ }
+ else
+ {
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPES_LAYER,
+ FALSE);
+ }
+
+ if (!layer)
+ {
+ g_warning("gv_rect_tool_configure(): no shapes layer in view");
+ return FALSE;
+ }
+
+ gv_rect_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+ return tool->layer != NULL;
+}
Added: packages/openev/branches/upstream/current/gvrecttool.h
===================================================================
--- packages/openev/branches/upstream/current/gvrecttool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrecttool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * $Id: gvrecttool.h,v 1.3 2000/07/27 20:06:23 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Rectangle (in GvShapesLayer) editing mode.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrecttool.h,v $
+ * Revision 1.3 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.2 2000/07/27 17:52:09 warmerda
+ * allow edit of existing rectangles
+ *
+ * Revision 1.1 2000/07/25 23:34:03 warmerda
+ * New
+ *
+ */
+
+#ifndef __GV_RECT_TOOL_H__
+#define __GV_RECT_TOOL_H__
+
+#include "gvtool.h"
+#include "gvshapeslayer.h"
+
+#define GV_TYPE_RECT_TOOL (gv_rect_tool_get_type ())
+#define GV_RECT_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_RECT_TOOL, GvRectTool))
+#define GV_RECT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_RECT_TOOL, GvRectToolClass))
+#define GV_IS_RECT_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_RECT_TOOL))
+#define GV_IS_RECT_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_RECT_TOOL))
+
+typedef struct _GvRectTool GvRectTool;
+typedef struct _GvRectToolClass GvRectToolClass;
+
+struct _GvRectTool
+{
+ GvTool tool;
+
+ GvShapesLayer *layer;
+ gchar *named_layer;
+
+ guint drawing : 1;
+ GvVertex v_head, v_tail;
+
+ guint reshaping : 1;
+ int picked; /* which corner or edge */
+ int shape_id; /* shapeid of rectangle being reshaped */
+ int winding; /* 1 = counterclockwise, 0 = clockwise */
+
+};
+
+struct _GvRectToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_rect_tool_get_type(void);
+GvTool* gv_rect_tool_new(void);
+void gv_rect_tool_set_layer(GvRectTool *tool, GvShapeLayer *layer);
+void gv_rect_tool_set_named_layer(GvRectTool *tool, gchar *name);
+
+#endif /* __GV_RECT_TOOL_H__ */
+
+
+
Added: packages/openev/branches/upstream/current/gvrenderinfo.c
===================================================================
--- packages/openev/branches/upstream/current/gvrenderinfo.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrenderinfo.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,847 @@
+/******************************************************************************
+ * $Id: gvrenderinfo.c,v 1.23 2003/06/25 16:42:18 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Parse OGRFeatureStyle rendering information and build
+ * GvRenderPart structures. This module is essentially associated
+ * with the GvShapeLayer.
+ * Author: Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrenderinfo.c,v $
+ * Revision 1.23 2003/06/25 16:42:18 warmerda
+ * gv_get_ogr_arg() made public as gv_ogrfs_get_arg().
+ * gv_split_tools() made public as gv_ogrfs_split_tools().
+ *
+ * Revision 1.22 2003/05/27 15:17:42 warmerda
+ * set pattern from pen id if available
+ *
+ * Revision 1.21 2003/05/16 18:26:32 pgs
+ * added initial code for propogating colors to sub-symbols
+ *
+ * Revision 1.20 2003/04/09 16:52:21 pgs
+ * added shadow, halo and bgcolor to LABELs
+ *
+ * Revision 1.19 2003/04/07 15:10:10 pgs
+ * added pattern support to pen objects
+ *
+ * Revision 1.18 2003/03/02 17:05:11 warmerda
+ * removed unit_vector from renderinfo args
+ *
+ * Revision 1.17 2003/02/28 16:49:06 warmerda
+ * split up renderinfo parsing to use for vector symbols
+ *
+ * Revision 1.16 2003/02/27 03:59:59 warmerda
+ * set scale_dep flag when updating renderinfo
+ *
+ * Revision 1.15 2003/02/14 20:12:43 pgs
+ * added support for line widths in PENs
+ *
+ * Revision 1.14 2002/11/15 05:04:43 warmerda
+ * added LABEL anchor point support
+ *
+ * Revision 1.13 2002/11/14 22:04:59 warmerda
+ * implement offsets for symbols
+ *
+ * Revision 1.12 2002/11/14 20:11:21 warmerda
+ * preliminary support for gvsymbolmanager from Paul
+ *
+ * Revision 1.11 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.10 2002/05/07 02:51:15 warmerda
+ * preliminary support for GVSHAPE_COLLECTION
+ *
+ * Revision 1.9 2002/03/21 15:48:51 warmerda
+ * added support for geometry specific _ogr_ogrfs_... layer properties
+ *
+ * Revision 1.8 2002/02/22 20:16:07 warmerda
+ * added brush tool support
+ *
+ * Revision 1.7 2002/02/22 19:27:16 warmerda
+ * added support for pen tools
+ *
+ * Revision 1.6 2002/01/21 20:45:39 warmerda
+ * Avoid reporting "unsupported tool" too many times.
+ *
+ * Revision 1.5 2001/08/21 21:41:24 warmerda
+ * recover if no text provided
+ *
+ * Revision 1.4 2001/05/01 19:27:09 warmerda
+ * Create an X sized box for empty labels
+ *
+ * Revision 1.3 2001/04/25 20:35:03 warmerda
+ * added proper support for descenders in label text
+ *
+ * Revision 1.2 2001/04/23 14:09:57 warmerda
+ * ensure that GVP_LAST_PART is set if the tool list is corrupt or empty
+ *
+ * Revision 1.1 2001/04/09 18:22:54 warmerda
+ * New
+ *
+ */
+
+#include "gvrenderinfo.h"
+#include "gvshapeslayer.h"
+#include "cpl_string.h"
+#include <GL/gl.h>
+
+/************************************************************************/
+/* gv_get_ogr_arg() */
+/************************************************************************/
+
+const char *
+gv_ogrfs_get_arg( const char *def, char **next_def,
+ char **value, int *value_len )
+
+{
+ const char *ret;
+ int vlen;
+
+ /* skip to the first argument. It will be preceeded by '(' or ',' */
+ while( *def != '(' && *def != ',' && *def != '\0' )
+ def++;
+
+ if( *def == '\0' )
+ return NULL;
+
+ def++;
+ ret = def;
+
+ /* find start of value */
+ while( *def != ':' )
+ {
+ if( *def == '\0' )
+ return NULL;
+
+ def++;
+ }
+
+ def++;
+
+ if( *def == '"' )
+ {
+ def++;
+ if( value != NULL )
+ *value = (char *) def;
+
+ vlen = 0;
+ while( *def != '"' && *def != '\0' )
+ {
+ def++;
+ vlen++;
+ }
+ if( *def == '"' )
+ def++;
+ }
+ else
+ {
+ if( value != NULL )
+ *value = (char *) def;
+
+ vlen = 0;
+ while( *def != ')' && *def != ',' && *def != '\0' )
+ {
+ def++;
+ vlen++;
+ }
+ }
+
+ if( value_len != NULL )
+ *value_len = vlen;
+
+ if( next_def != NULL )
+ *next_def = (char *) def;
+
+ return ret;
+}
+
+/************************************************************************/
+/* gv_get_ogr_color() */
+/************************************************************************/
+
+static int
+gv_get_ogr_color( const char * sym_def, GvColor color )
+
+{
+ int red, green, blue, alpha = 255;
+
+ if( EQUALN(sym_def,"c:",2) )
+ sym_def += 2;
+
+ if( *sym_def != '#' )
+ return FALSE;
+
+ if( sscanf( sym_def+1, "%2x%2x%2x%2x", &red, &green, &blue, &alpha ) < 3 )
+ return FALSE;
+
+ color[0] = red / 255.0;
+ color[1] = green / 255.0;
+ color[2] = blue / 255.0;
+ color[3] = alpha / 255.0;
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_parse_label() */
+/************************************************************************/
+
+static guint
+gv_parse_label( GvShapesLayer *layer, GvShape *shape, const char * sym_def,
+ int *scale_dep )
+
+{
+ const char *id;
+ char *next, *value=NULL;
+ guint part_index = GVP_UNINITIALIZED_PART;
+ int value_len;
+ GvLabelRenderPart *label_info;
+
+ if( !EQUALN(sym_def,"LABEL",5) )
+ {
+ g_warning( "not a label" );
+ return part_index;
+ }
+
+ *scale_dep = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Create the new part. */
+/* -------------------------------------------------------------------- */
+ part_index = gv_shape_layer_create_part( GV_SHAPE_LAYER(layer),
+ GvLabelPart );
+
+ label_info = (GvLabelRenderPart *)
+ gv_shape_layer_get_part( GV_SHAPE_LAYER(layer), part_index );
+
+ g_assert( label_info != NULL );
+
+ label_info->font = -1;
+
+/* -------------------------------------------------------------------- */
+/* Parse the tool information, and apply to the renderinfo part. */
+/* -------------------------------------------------------------------- */
+
+ while( (id = gv_ogrfs_get_arg( sym_def, &next, &value,
+ &value_len )) != NULL )
+ {
+ if( EQUALN(id,"c:",2) )
+ {
+ gv_get_ogr_color( value, label_info->color );
+ label_info->b_color_initialized = 1;
+ }
+ if( EQUALN(id,"b:",2) )
+ {
+ gv_get_ogr_color( value, label_info->background_color );
+ label_info->b_background_color_initialized = 1;
+ }
+ else if( EQUALN(id,"f:",2) )
+ {
+ char *font;
+
+ font = g_strdup(value);
+ font[value_len] = '\0';
+
+ label_info->font = gv_view_area_bmfont_load(
+ GV_VIEW_AREA(GV_LAYER(layer)->view), font );
+
+ g_free( font );
+ }
+ else if( EQUALN(id,"t:",2) )
+ {
+ if( value[0] == '{' )
+ {
+ GvProperties *properties = gv_shape_get_properties(shape);
+ char *field_name;
+
+ field_name = g_strdup(value+1);
+ field_name[value_len-1] = '\0';
+ if( field_name[value_len-2] == '}' )
+ field_name[value_len-2] = '\0';
+
+ label_info->text = g_strdup(
+ gv_properties_get( properties, field_name ));
+
+ g_free( field_name );
+ }
+ else
+ {
+ label_info->text = g_malloc(value_len+1);
+ strncpy( label_info->text, value, value_len );
+ label_info->text[value_len] = '\0';
+ }
+ }
+ else if( EQUALN(id,"a:",2) )
+ {
+ label_info->angle = atof(value);
+ }
+ else if( EQUALN(id,"p:",2) )
+ {
+ label_info->anchor = atoi(value);
+ if( label_info->anchor < 1 || label_info->anchor > 9 )
+ {
+ CPLDebug( "GVRENDERINFO",
+ "Illegal anchor position in label (%d), ignoring.",
+ label_info->anchor );
+ label_info->anchor = GLRA_LOWER_LEFT;
+ }
+ }
+ else if( EQUALN(id,"s:",2) )
+ {
+ label_info->scale = atof(value);
+ if( label_info->scale == 0.0 )
+ label_info->scale = 1.0;
+ }
+ else if( EQUALN(id,"dx:",3) )
+ {
+ if( EQUALN(value+value_len-1,"g",1) )
+ label_info->x_offset_g = atof(value);
+ else
+ label_info->x_offset_px = atof(value);
+ }
+ else if( EQUALN(id,"dy:",3) )
+ {
+ if( EQUALN(value+value_len-1,"g",1) )
+ label_info->y_offset_g = atof(value);
+ else
+ label_info->y_offset_px = atof(value);
+ }
+ else if( EQUALN(id,"h",1) )
+ {
+ label_info->halo = TRUE;
+ }
+ else if( EQUALN(id,"sh",2) )
+ {
+ label_info->shadow = TRUE;
+ }
+
+ sym_def = next;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Default font to fixed. */
+/* -------------------------------------------------------------------- */
+ if( label_info->font == -1 )
+ label_info->font = gv_view_area_bmfont_load(
+ GV_VIEW_AREA(GV_LAYER(layer)->view), "fixed" );
+
+/* -------------------------------------------------------------------- */
+/* Did we miss out on any critical components? If so, remove */
+/* this part. */
+/* -------------------------------------------------------------------- */
+ if( label_info->text == NULL || label_info->font == -1 )
+ {
+ label_info->text = g_strdup("");
+ g_warning( "missing text or font for label" );
+ /*gv_shape_layer_clear_part( GV_SHAPE_LAYER(layer), part_index );*/
+ }
+
+/* -------------------------------------------------------------------- */
+/* Get string extents. */
+/* -------------------------------------------------------------------- */
+ if( label_info->font != -1 )
+ {
+ guint lbearing, rbearing, ascent, descent;
+ GvBMFontInfo *font_info;
+ const char *pszText;
+
+ font_info = gv_view_area_bmfont_get_info(
+ GV_VIEW_AREA(GV_LAYER(layer)->view), label_info->font );
+
+ if( label_info->text[0] == '\0' )
+ pszText = "X";
+ else
+ pszText = label_info->text;
+
+ gdk_string_extents( font_info->gdkfont, pszText,
+ &lbearing, &rbearing, &(label_info->width),
+ &ascent, &descent );
+
+#ifdef WIN32
+ //gdk on win32 reports the total height as the ascent
+ label_info->height = ascent - descent - 1;
+ label_info->descent = descent - 1;
+#else
+ label_info->height = ascent + descent;
+ label_info->descent = descent;
+#endif
+ }
+
+/* -------------------------------------------------------------------- */
+/* Adjust pixel offset to take into account the anchor point */
+/* (justification). */
+/* -------------------------------------------------------------------- */
+ switch( label_info->anchor )
+ {
+ case GLRA_LOWER_CENTER:
+ label_info->x_offset_px -= label_info->width / 2.0;
+ break;
+
+ case GLRA_LOWER_RIGHT:
+ label_info->x_offset_px -= label_info->width;
+ break;
+
+ case GLRA_CENTER_LEFT:
+ label_info->y_offset_px += label_info->height / 2.0;
+ break;
+
+ case GLRA_CENTER_CENTER:
+ label_info->x_offset_px -= label_info->width / 2.0;
+ label_info->y_offset_px += label_info->height / 2.0;
+ break;
+
+ case GLRA_CENTER_RIGHT:
+ label_info->x_offset_px -= label_info->width;
+ label_info->y_offset_px += label_info->height / 2.0;
+ break;
+
+ case GLRA_UPPER_LEFT:
+ label_info->y_offset_px += label_info->height;
+ break;
+
+ case GLRA_UPPER_CENTER:
+ label_info->x_offset_px -= label_info->width / 2.0;
+ label_info->y_offset_px += label_info->height;
+ break;
+
+ case GLRA_UPPER_RIGHT:
+ label_info->x_offset_px -= label_info->width;
+ label_info->y_offset_px += label_info->height;
+ break;
+
+ case GLRA_LOWER_LEFT:
+ default:
+ break;
+ }
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_parse_symbol() */
+/************************************************************************/
+
+static guint
+gv_parse_symbol( GvShapesLayer *layer, GvShape *shape, const char * sym_def,
+ int *scale_dep )
+
+{
+ const char *id;
+ char *next, *value;
+ int value_len;
+ guint part_index = GVP_UNINITIALIZED_PART;
+ GvSymbolRenderPart *symbol_info;
+
+ if( !EQUALN(sym_def,"SYMBOL",6) )
+ {
+ g_warning( "not a symbol" );
+ return part_index;
+ }
+
+ *scale_dep = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Create the new part. */
+/* -------------------------------------------------------------------- */
+ part_index = gv_shape_layer_create_part( GV_SHAPE_LAYER(layer),
+ GvSymbolPart );
+
+ symbol_info = (GvSymbolRenderPart *)
+ gv_shape_layer_get_part( GV_SHAPE_LAYER(layer), part_index );
+
+ g_assert( symbol_info != NULL );
+
+/* -------------------------------------------------------------------- */
+/* Parse the tool arguments. */
+/* -------------------------------------------------------------------- */
+ while( (id = gv_ogrfs_get_arg( sym_def, &next, &value,
+ &value_len )) != NULL )
+ {
+ if( EQUALN(id,"c:",2) )
+ {
+ gv_get_ogr_color( value, symbol_info->color );
+ symbol_info->b_color_initialized = 1;
+ }
+ else if( EQUALN(id,"id:",3) )
+ {
+ symbol_info->symbol_id = g_malloc(value_len+1);
+ strncpy( symbol_info->symbol_id, value, value_len );
+ symbol_info->symbol_id[value_len] = '\0';
+ }
+ else if( EQUALN(id,"a:",2) )
+ {
+ symbol_info->angle = atof(value);
+ }
+ else if( EQUALN(id,"s:",2) )
+ {
+ symbol_info->scale = atof(value);
+ if( symbol_info->scale == 0.0 )
+ symbol_info->scale = 1.0;
+ }
+ else if( EQUALN(id,"dx:",3) )
+ {
+ if( EQUALN(value+value_len-1,"g",1) )
+ symbol_info->x_offset_g = atof(value);
+ else
+ symbol_info->x_offset_px = atof(value);
+ }
+ else if( EQUALN(id,"dy:",3) )
+ {
+
+ if( EQUALN(value+value_len-1,"g",1) )
+ symbol_info->y_offset_g = atof(value);
+ else
+ symbol_info->y_offset_px = atof(value);
+ }
+
+ sym_def = next;
+ }
+
+ if( symbol_info->symbol_id == NULL )
+ {
+ symbol_info->symbol_id = g_strdup("ogr-sym-0");
+ }
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_parse_pen() */
+/************************************************************************/
+
+static guint
+gv_parse_pen( GvShapesLayer *layer, GvShape *shape, const char * sym_def,
+ int *scale_dep )
+
+{
+ const char *id;
+ char *next, *value;
+ int value_len;
+ guint part_index = GVP_UNINITIALIZED_PART;
+ GvPenRenderPart *pen_info;
+
+ if( !EQUALN(sym_def,"PEN",3) )
+ {
+ g_warning( "not a pen" );
+ return part_index;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the new part. */
+/* -------------------------------------------------------------------- */
+ part_index = gv_shape_layer_create_part( GV_SHAPE_LAYER(layer),
+ GvPenPart );
+
+ pen_info = (GvPenRenderPart *)
+ gv_shape_layer_get_part( GV_SHAPE_LAYER(layer), part_index );
+
+ g_assert( pen_info != NULL );
+
+/* -------------------------------------------------------------------- */
+/* Parse the tool arguments. */
+/* -------------------------------------------------------------------- */
+ while( (id = gv_ogrfs_get_arg( sym_def, &next, &value,
+ &value_len )) != NULL )
+ {
+ if( EQUALN(id,"c:",2) )
+ {
+ gv_get_ogr_color( value, pen_info->color );
+ pen_info->b_color_initialized = 1;
+ }
+ else if( EQUALN(id,"w:",2) )
+ {
+ pen_info->width = atof(value);
+ //TODO: should validate using
+ //glGetFloatv( GL_ALIAS_LINE_WIDTH_RANGE ) or
+ //glGetFloatv( GL_SMOOTH_LINE_WIDTH_RANGE ) but
+ //these constants aren't defined on Windows
+ if (pen_info->width < 0.0)
+ pen_info->width = 1.0;
+
+ }
+ else if (EQUALN(id, "p:", 2) )
+ {
+ //define a pattern for the pen
+ pen_info->pattern = g_malloc(value_len+1);
+ strncpy( pen_info->pattern, value, value_len );
+ pen_info->pattern[value_len] = '\0';
+
+ }
+ else if (EQUALN(id, "id:", 3) && EQUALN(value,"ogr-pen-",8) )
+ {
+ //define a pattern for the pen
+ pen_info->pattern = g_malloc(value_len+1);
+ strncpy( pen_info->pattern, value, value_len );
+ pen_info->pattern[value_len] = '\0';
+ }
+
+ sym_def = next;
+ }
+
+ if( pen_info->pattern == NULL )
+ {
+ pen_info->pattern = g_strdup("ogr-pen-0");
+ }
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_parse_brush() */
+/************************************************************************/
+
+static guint
+gv_parse_brush( GvShapesLayer *layer, GvShape *shape, const char * sym_def,
+ int *scale_dep )
+
+{
+ const char *id;
+ char *next, *value;
+ int value_len;
+ guint part_index = GVP_UNINITIALIZED_PART;
+ GvBrushRenderPart *brush_info;
+
+ if( !EQUALN(sym_def,"BRUSH",5) )
+ {
+ g_warning( "not a brush" );
+ return part_index;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the new part. */
+/* -------------------------------------------------------------------- */
+ part_index = gv_shape_layer_create_part( GV_SHAPE_LAYER(layer),
+ GvBrushPart );
+
+ brush_info = (GvBrushRenderPart *)
+ gv_shape_layer_get_part( GV_SHAPE_LAYER(layer), part_index );
+
+ g_assert( brush_info != NULL );
+
+/* -------------------------------------------------------------------- */
+/* Parse the tool arguments. */
+/* -------------------------------------------------------------------- */
+ while( (id = gv_ogrfs_get_arg( sym_def, &next, &value,
+ &value_len )) != NULL )
+ {
+ if( EQUALN(id,"fc:",3) )
+ {
+ gv_get_ogr_color( value, brush_info->fore_color );
+ brush_info->b_fore_color_initialized = 1;
+ }
+
+ sym_def = next;
+ }
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_ogrfs_split_tools() */
+/************************************************************************/
+
+char **gv_ogrfs_split_tools( const char *tool_list_in )
+
+{
+ int i_src, word_start=0;
+ char **result = NULL, *tool_list;
+
+ tool_list = g_strdup(tool_list_in);
+
+ /* split on semi-colons that are not part of quoted strings */
+
+ for( i_src = 0; tool_list[i_src] != '\0'; i_src++ )
+ {
+ if( tool_list[i_src] == '"' )
+ {
+ for( i_src++;
+ tool_list[i_src] != '\0' && tool_list[i_src] != '"';
+ i_src++ ) {}
+ }
+ else if( tool_list[i_src] == ';' )
+ {
+ tool_list[i_src] = '\0';
+
+ result = CSLAddString( result, tool_list + word_start );
+ word_start = i_src + 1;
+ }
+ }
+
+ result = CSLAddString( result, tool_list + word_start );
+
+ g_free( tool_list );
+
+ return result;
+}
+
+/************************************************************************/
+/* gv_shape_layer_build_renderinfo() */
+/************************************************************************/
+
+guint gv_shape_layer_build_renderinfo( GvShapeLayer *s_layer,
+ GvShape *shape_obj,
+ int *scale_dep )
+
+{
+ int tool_index;
+ guint base_part_index = GVP_UNINITIALIZED_PART;
+ GvShapesLayer *layer = GV_SHAPES_LAYER( s_layer );
+ const char *ogrfs;
+ char **tool_list;
+
+/* -------------------------------------------------------------------- */
+/* Get the ogrfs string to apply. */
+/* -------------------------------------------------------------------- */
+ ogrfs = gv_properties_get( gv_shape_get_properties(shape_obj),
+ "_gv_ogrfs" );
+
+ if( ogrfs == NULL )
+ {
+ if( gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ ogrfs = gv_properties_get(&(GV_DATA(layer)->properties),
+ "_gv_ogrfs_point");
+ else if( gv_shape_type(shape_obj) == GVSHAPE_LINE )
+ ogrfs = gv_properties_get(&(GV_DATA(layer)->properties),
+ "_gv_ogrfs_line");
+ else if( gv_shape_type(shape_obj) == GVSHAPE_AREA )
+ ogrfs = gv_properties_get(&(GV_DATA(layer)->properties),
+ "_gv_ogrfs_area");
+ }
+
+ if( ogrfs == NULL )
+ ogrfs = gv_properties_get(&(GV_DATA(layer)->properties),"_gv_ogrfs");
+
+ if( ogrfs == NULL )
+ return GVP_LAST_PART;
+
+/* -------------------------------------------------------------------- */
+/* Split tool actions apart. */
+/* -------------------------------------------------------------------- */
+ tool_list = gv_ogrfs_split_tools( ogrfs );
+
+ for( tool_index = 0; tool_index < CSLCount(tool_list); tool_index++ )
+ {
+ guint part_index = GVP_UNINITIALIZED_PART;
+
+ if( EQUALN(tool_list[tool_index],"LABEL",5)
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ {
+ part_index =
+ gv_parse_label( layer, shape_obj,
+ tool_list[tool_index], scale_dep );
+ }
+ else if( EQUALN(tool_list[tool_index],"SYMBOL",6)
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ {
+ part_index =
+ gv_parse_symbol( layer, shape_obj,
+ tool_list[tool_index], scale_dep );
+ }
+ else if( EQUALN(tool_list[tool_index],"PEN",3)
+ && (gv_shape_type(shape_obj) == GVSHAPE_LINE
+ || gv_shape_type(shape_obj) == GVSHAPE_AREA
+ || gv_shape_type(shape_obj) == GVSHAPE_COLLECTION) )
+ {
+ part_index =
+ gv_parse_pen( layer, shape_obj,
+ tool_list[tool_index], scale_dep );
+ }
+ else if( EQUALN(tool_list[tool_index],"BRUSH",5)
+ && (gv_shape_type(shape_obj) == GVSHAPE_AREA
+ || gv_shape_type(shape_obj) == GVSHAPE_COLLECTION) )
+ {
+ part_index =
+ gv_parse_brush( layer, shape_obj,
+ tool_list[tool_index], scale_dep );
+ }
+ else
+ {
+ static int nReportedUnsupportedTools = 0;
+ char message[512];
+ const char *object = "unknown";
+
+ if( gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ object = "point";
+ else if( gv_shape_type(shape_obj) == GVSHAPE_LINE )
+ object = "line";
+ else if( gv_shape_type(shape_obj) == GVSHAPE_AREA )
+ object = "area";
+
+ sprintf( message, "Unsupported tool (%s) for %s object.",
+ tool_list[tool_index], object);
+
+ if( nReportedUnsupportedTools++ < 15 )
+ g_warning(message);
+ else if( nReportedUnsupportedTools++ == 15 )
+ g_warning("Unsupported tool - rest of warnings supressed.");
+
+ if( nReportedUnsupportedTools < 100 )
+ CPLDebug( "GVRENDERINFO", "%s", message );
+
+ }
+
+ if( part_index != GVP_UNINITIALIZED_PART )
+ base_part_index =
+ gv_shape_layer_chain_part( s_layer, base_part_index,
+ part_index);
+ }
+
+ CSLDestroy( tool_list );
+
+ return base_part_index;
+}
+
+/************************************************************************/
+/* gv_shape_layer_update_renderinfo() */
+/************************************************************************/
+
+void gv_shape_layer_update_renderinfo( GvShapeLayer *s_layer, int shape_id )
+
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER( s_layer );
+ GvShape *shape_obj;
+ int scale_dep = FALSE;
+ guint base_part_index;
+
+ base_part_index = gv_shape_layer_get_first_part_index( s_layer, shape_id );
+ if( base_part_index != GVP_UNINITIALIZED_PART )
+ return;
+
+ if( !GV_IS_SHAPES_LAYER( s_layer ) )
+ return;
+
+ if( s_layer->render_index == NULL )
+ gv_shape_layer_initialize_renderindex( s_layer );
+
+ shape_obj = gv_shapes_get_shape(layer->data,shape_id);
+
+ base_part_index = gv_shape_layer_build_renderinfo( s_layer, shape_obj,
+ &scale_dep );
+
+ if( base_part_index == GVP_UNINITIALIZED_PART )
+ base_part_index = GVP_LAST_PART;
+
+ g_array_index(s_layer->render_index,guint,shape_id) = base_part_index;
+
+ gv_shape_layer_set_scale_dep( s_layer, shape_id, scale_dep );
+}
+
Added: packages/openev/branches/upstream/current/gvrenderinfo.h
===================================================================
--- packages/openev/branches/upstream/current/gvrenderinfo.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrenderinfo.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,242 @@
+/******************************************************************************
+ * $Id: gvrenderinfo.h,v 1.15 2003/06/25 16:42:18 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Functions for managing per-shape rendering information in
+ * in the GvShapeLayer. Actual rendering of shapes using the
+ * rendering information is still in GvShapesLayer.
+ * Author: Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrenderinfo.h,v $
+ * Revision 1.15 2003/06/25 16:42:18 warmerda
+ * gv_get_ogr_arg() made public as gv_ogrfs_get_arg().
+ * gv_split_tools() made public as gv_ogrfs_split_tools().
+ *
+ * Revision 1.14 2003/05/16 18:26:32 pgs
+ * added initial code for propogating colors to sub-symbols
+ *
+ * Revision 1.13 2003/04/09 16:52:22 pgs
+ * added shadow, halo and bgcolor to LABELs
+ *
+ * Revision 1.12 2003/04/07 15:10:12 pgs
+ * added pattern support to pen objects
+ *
+ * Revision 1.11 2003/03/02 17:05:11 warmerda
+ * removed unit_vector from renderinfo args
+ *
+ * Revision 1.10 2003/02/28 16:49:05 warmerda
+ * split up renderinfo parsing to use for vector symbols
+ *
+ * Revision 1.9 2003/02/14 20:12:43 pgs
+ * added support for line widths in PENs
+ *
+ * Revision 1.8 2002/11/15 05:04:43 warmerda
+ * added LABEL anchor point support
+ *
+ * Revision 1.7 2002/11/14 22:05:00 warmerda
+ * implement offsets for symbols
+ *
+ * Revision 1.6 2002/11/14 20:11:21 warmerda
+ * preliminary support for gvsymbolmanager from Paul
+ *
+ * Revision 1.5 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.4 2002/02/22 20:16:07 warmerda
+ * added brush tool support
+ *
+ * Revision 1.3 2002/02/22 19:27:16 warmerda
+ * added support for pen tools
+ *
+ * Revision 1.2 2001/04/25 20:36:01 warmerda
+ * added proper support for descenders in label text
+ *
+ * Revision 1.1 2001/04/09 18:22:54 warmerda
+ * New
+ *
+ */
+
+#ifndef __GV_RENDER_INFO_H__
+#define __GV_RENDER_INFO_H__
+
+#include "gvshapeslayer.h"
+
+#define GvReservedPart 0x00
+#define GvLabelPart 0x01
+#define GvSymbolPart 0x02
+#define GvPenPart 0x03
+#define GvBrushPart 0x04
+
+#define gv_part_index_to_type(x) ((x) & 0x07)
+#define gv_part_index_to_index(x) ((x) >>3)
+
+/* -------------------------------------------------------------------- */
+/* It is intended that GvRenderPart is like a subclass of the */
+/* more specific render infos, but for symplicity of */
+/* referencing fields we don't make this relationship explicit. */
+/* -------------------------------------------------------------------- */
+
+#define GVP_UNINITIALIZED_PART 0x00
+#define GVP_LAST_PART 0x08
+
+typedef struct
+{
+ unsigned int next_part; /* 0 means this object is uninitialized.
+ * 8 means this is the last part
+ * Otherwise mask the GvXXXPart number
+ * out of the lower 3 bits, and shift the
+ * remainder down for the index into the table.
+ */
+
+} GvRenderPart;
+
+typedef struct
+{
+ /* From GvRenderPart */
+ guint next_part;
+
+ /* Specific to GvLabelRenderPart */
+ GvColor color;
+ /* for tracking if the color was actually initialized
+ as part of the symbol definition */
+ int b_color_initialized;
+ GvColor background_color;
+ /* for tracking if the color was actually initialized
+ as part of the symbol definition */
+ int b_background_color_initialized;
+ char *text;
+ gint font;
+ gvgeocoord x_offset_px;
+ gvgeocoord y_offset_px;
+ gvgeocoord x_offset_g;
+ gvgeocoord y_offset_g;
+ gvgeocoord angle;
+ gvgeocoord scale;
+
+ int width;
+ int height;
+ int descent;
+
+ int anchor; /* GLRA_ * */
+
+ gboolean shadow;
+ gboolean halo;
+
+} GvLabelRenderPart;
+
+#define GLRA_LOWER_LEFT 1
+#define GLRA_LOWER_CENTER 2
+#define GLRA_LOWER_RIGHT 3
+#define GLRA_CENTER_LEFT 4
+#define GLRA_CENTER_CENTER 5
+#define GLRA_CENTER_RIGHT 6
+#define GLRA_UPPER_LEFT 7
+#define GLRA_UPPER_CENTER 8
+#define GLRA_UPPER_RIGHT 9
+
+typedef struct
+{
+ /* From GvRenderPart */
+ guint next_part;
+
+ /* Specific to GvSymbolRenderPart */
+ GvColor color;
+ gchar *symbol_id;
+ gvgeocoord scale;
+ gvgeocoord angle;
+
+ gvgeocoord x_offset_g;
+ gvgeocoord y_offset_g;
+ gvgeocoord x_offset_px;
+ gvgeocoord y_offset_px;
+
+ /* for tracking if the color was actually initialized
+ as part of the symbol definition */
+ int b_color_initialized;
+
+ int part_index; /* for vector symbols */
+
+} GvSymbolRenderPart;
+
+typedef struct
+{
+ /* From GvRenderPart */
+ guint next_part;
+
+ /* Specific to GvPenRenderPart */
+ GvColor color;
+ /* for tracking if the color was actually initialized
+ as part of the pen definition */
+ int b_color_initialized;
+
+ float width;
+ gchar *pattern;
+} GvPenRenderPart;
+
+typedef struct
+{
+ /* From GvRenderPart */
+ guint next_part;
+
+ /* Specific to GvBrushRenderPart */
+ GvColor fore_color;
+ /* for tracking if the color was actually initialized
+ as part of the brush definition */
+ int b_fore_color_initialized;
+} GvBrushRenderPart;
+
+/* -------------------------------------------------------------------- */
+/* Functions for operating on rendering info within */
+/* GvShapeLayer, really an extension to GvShapeLayer API. */
+/* -------------------------------------------------------------------- */
+GvRenderPart *gv_shape_layer_get_part( GvShapeLayer *layer, guint part_index );
+guint gv_shape_layer_get_first_part_index( GvShapeLayer *layer, gint shape_id);
+
+guint gv_shape_layer_add_part( GvShapeLayer *layer, gint shape_id,
+ gint part_type );
+guint gv_shape_layer_create_part( GvShapeLayer *layer, gint part_type );
+guint gv_shape_layer_chain_part( GvShapeLayer *layer, gint base_part_index,
+ gint new_part_index );
+void gv_shape_layer_clear_shape_parts( GvShapeLayer *layer, gint shape_id );
+void gv_shape_layer_clear_part( GvShapeLayer *layer, guint part_index );
+void gv_shape_layer_clear_all_renderinfo( GvShapeLayer *layer );
+
+guint gv_shape_layer_build_renderinfo( GvShapeLayer *s_layer,
+ GvShape *shape_obj,
+ int *scale_dep );
+void gv_shape_layer_update_renderinfo( GvShapeLayer *s_layer, int shape_id );
+void gv_shape_layer_initialize_renderindex( GvShapeLayer *layer );
+
+/* -------------------------------------------------------------------- */
+/* Helper functions for ogrfs parsing ... used in a few other */
+/* places. */
+/* -------------------------------------------------------------------- */
+char **gv_ogrfs_split_tools( const char *tool_list_in );
+const char *gv_ogrfs_get_arg( const char *def, char **next_def,
+ char **value, int *value_len );
+
+
+
+#endif /*__GV_RENDER_INFO_H__ */
+
+
+
Added: packages/openev/branches/upstream/current/gvroitool.c
===================================================================
--- packages/openev/branches/upstream/current/gvroitool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvroitool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,605 @@
+/******************************************************************************
+ * $Id: gvroitool.c,v 1.11 2002/11/04 21:42:06 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Region of interest (box in raster coordinates) editing mode.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvroitool.c,v $
+ * Revision 1.11 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.10 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.9 2000/06/30 18:04:55 srawlin
+ * added ability to set ROI constraints
+ *
+ * Revision 1.8 2000/06/30 14:05:36 srawlin
+ * fixed bug where ROI selected then zoom in
+ *
+ * Revision 1.7 2000/06/29 21:18:10 srawlin
+ * Added CHANGED and CHANGING Signals
+ *
+ * Revision 1.6 2000/06/29 16:15:55 srawlin
+ * added function to create new ROI
+ *
+ * Revision 1.5 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvroitool.h"
+#include <gtk/gtksignal.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdio.h>
+
+#define PICK_SIZE 6.0
+
+/* Return values for gv_roi_tool_pick_border() */
+enum
+{
+ PICK_NONE = 0,
+ PICK_CORNER_TOPLEFT,
+ PICK_CORNER_BOTTOMLEFT,
+ PICK_CORNER_BOTTOMRIGHT,
+ PICK_CORNER_TOPRIGHT,
+ PICK_SIDE_TOP,
+ PICK_SIDE_RIGHT,
+ PICK_SIDE_BOTTOM,
+ PICK_SIDE_LEFT
+};
+
+/* Signals */
+enum
+{
+ ROI_CHANGED,
+ ROI_CHANGING,
+ LAST_SIGNAL
+};
+
+static void gv_roi_tool_class_init(GvRoiToolClass *klass);
+static void gv_roi_tool_init(GvRoiTool *tool);
+static void gv_roi_tool_draw(GvTool *tool);
+static void gv_roi_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_roi_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_roi_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_roi_tool_deactivate(GvTool *tool, GvViewArea *view);
+static void gv_roi_tool_start_resize(GvRoiTool *tool, gint pick, gvgeocoord pointer_x, gvgeocoord pointer_y);
+static gint gv_roi_tool_pick_border(GvRoiTool *tool, gvgeocoord x, gvgeocoord y);
+
+static guint roitool_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_roi_tool_get_type(void)
+{
+ static GtkType roi_tool_type = 0;
+
+ if (!roi_tool_type)
+ {
+ static const GtkTypeInfo roi_tool_info =
+ {
+ "GvRoiTool",
+ sizeof(GvRoiTool),
+ sizeof(GvRoiToolClass),
+ (GtkClassInitFunc) gv_roi_tool_class_init,
+ (GtkObjectInitFunc) gv_roi_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ roi_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &roi_tool_info);
+ }
+ return roi_tool_type;
+}
+
+static void
+gv_roi_tool_class_init(GvRoiToolClass *klass)
+{
+ GvToolClass *tool_class;
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+ tool_class = (GvToolClass*)klass;
+
+ roitool_signals[ROI_CHANGED] =
+ gtk_signal_new ("roi_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvRoiToolClass,roi_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ roitool_signals[ROI_CHANGING] =
+ gtk_signal_new ("roi_changing",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvRoiToolClass,roi_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 0 );
+
+ gtk_object_class_add_signals(object_class, roitool_signals, LAST_SIGNAL);
+
+ klass->roi_changed = NULL;
+ klass->roi_changing = NULL;
+
+ tool_class->deactivate = gv_roi_tool_deactivate;
+ tool_class->draw = gv_roi_tool_draw;
+ tool_class->button_press = gv_roi_tool_button_press;
+ tool_class->button_release = gv_roi_tool_button_release;
+ tool_class->motion_notify = gv_roi_tool_motion_notify;
+}
+static void
+gv_roi_tool_init(GvRoiTool *tool)
+{
+ tool->pick = PICK_NONE;
+
+ tool->roi_marked = FALSE;
+ tool->banding = FALSE;
+}
+
+GvTool *
+gv_roi_tool_new(void)
+{
+ GvTool *tool;
+
+ tool = GV_TOOL(gtk_type_new(GV_TYPE_ROI_TOOL));
+
+
+
+ return tool;
+
+}
+
+gint
+gv_roi_tool_get_rect(GvRoiTool *tool, GvRect *rect)
+{
+ if (!tool->roi_marked)
+ {
+ return FALSE;
+ }
+
+ rect->x = MIN(tool->v_head.x, tool->v_tail.x);
+ rect->y = MIN(tool->v_head.y, tool->v_tail.y);
+ rect->width = tool->v_tail.x - tool->v_head.x;
+ rect->height = tool->v_tail.y - tool->v_head.y;
+ rect->width = ABS(rect->width);
+ rect->height = ABS(rect->height);
+
+ return TRUE;
+}
+
+gint
+gv_roi_tool_new_rect(GvRoiTool *tool, GvRect *rect)
+{
+ /* Create new ROI */
+ tool->roi_marked = TRUE;
+
+ tool->v_head.x = rect->x;
+ tool->v_head.y = rect->y;
+ tool->v_tail.x = rect->x + ABS(rect->width);
+ tool->v_tail.y = rect->y + ABS(rect->height);
+
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_head.x), &(tool->v_head.y) );
+ gv_tool_clamp_to_bounds( GV_TOOL(tool),
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ /* Check input parameters */
+ if (rect->width <=0 || rect->height <= 0)
+ {
+ tool->roi_marked = FALSE;
+ return FALSE;
+ }
+
+ gtk_signal_emit(GTK_OBJECT(tool),
+ roitool_signals[ROI_CHANGED]);
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+
+ return TRUE;
+}
+
+/**************************************************************/
+
+static void
+gv_roi_tool_button_press(GvTool *rtool, GdkEventButton *event)
+{
+ GvRoiTool *tool = GV_ROI_TOOL(rtool);
+
+ if ((event->button == 1) && !(event->state & GDK_CONTROL_MASK)
+ && !(event->state & GDK_SHIFT_MASK) )
+ {
+ if (tool->roi_marked)
+ {
+ /* Check for contact with ROI border */
+ gint pick;
+ gvgeocoord pointer_x, pointer_y;
+
+ pick = gv_roi_tool_pick_border(tool, event->x, event->y);
+
+ if (pick != PICK_NONE)
+ {
+ /* Start ROI resize dragging operation */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view,
+ event->x, event->y,
+ &pointer_x, &pointer_y);
+ gv_roi_tool_start_resize(tool, pick, pointer_x, pointer_y);
+ return;
+ }
+ }
+
+ /* Set head and tail vertex to pointer position */
+ /* Map pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ tool->v_head = tool->v_tail;
+
+ if( gv_tool_check_bounds( GV_TOOL(tool),
+ tool->v_tail.x, tool->v_tail.y ) )
+ {
+ /* Begin rubber band */
+ tool->banding = TRUE;
+ tool->roi_marked = TRUE;
+
+ /* No drag offset for initial rubber banding */
+ tool->v_drag_offset.x = tool->v_drag_offset.y = 0.0;
+ tool->drag_right = tool->drag_bottom = TRUE;
+ }
+ }
+}
+
+static void
+gv_roi_tool_button_release(GvTool *rtool, GdkEventButton *event)
+{
+ GvRoiTool *tool = GV_ROI_TOOL(rtool);
+
+ if (event->button == 1 && tool->banding)
+ {
+ gvgeocoord pointer_x, pointer_y;
+
+ /* End rubber band */
+ tool->banding = FALSE;
+
+ /* Map pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &pointer_x, &pointer_y);
+
+ /* Reposition tail vertex */
+ if (tool->drag_right)
+ {
+ tool->v_tail.x = pointer_x + tool->v_drag_offset.x;
+ }
+ if (tool->drag_bottom)
+ {
+ tool->v_tail.y = pointer_y + tool->v_drag_offset.y;
+ }
+
+ gv_tool_clamp_to_bounds( rtool,
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ /* Reject empty regions */
+ if (tool->v_tail.x == tool->v_head.x ||
+ tool->v_tail.y == tool->v_head.y)
+ {
+ tool->roi_marked = FALSE;
+ }
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+
+ gtk_signal_emit(GTK_OBJECT(tool),
+ roitool_signals[ROI_CHANGED]);
+ }
+}
+
+static void
+gv_roi_tool_motion_notify(GvTool *rtool, GdkEventMotion *event)
+{
+ GvRoiTool *tool = GV_ROI_TOOL(rtool);
+
+ if (tool->banding)
+ {
+ gvgeocoord pointer_x, pointer_y;
+
+ /* Resize rubber band */
+ /* Map pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &pointer_x, &pointer_y);
+
+ /* Reposition tail vertex */
+ if (tool->drag_right)
+ {
+ tool->v_tail.x = pointer_x + tool->v_drag_offset.x;
+ }
+ if (tool->drag_bottom)
+ {
+ tool->v_tail.y = pointer_y + tool->v_drag_offset.y;
+ }
+
+ gv_tool_clamp_to_bounds( rtool,
+ &(tool->v_tail.x), &(tool->v_tail.y) );
+
+ gtk_signal_emit(GTK_OBJECT(tool),
+ roitool_signals[ROI_CHANGING]);
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ else if (tool->roi_marked)
+ {
+ /* Highlight roi sides to indicate the effect of a click & drag */
+ gint pick;
+
+ pick = gv_roi_tool_pick_border(tool, event->x, event->y);
+ if (pick != tool->pick)
+ {
+ tool->pick = pick;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ }
+}
+
+static void
+gv_roi_tool_draw(GvTool *rtool)
+{
+ GvRoiTool *tool = GV_ROI_TOOL(rtool);
+
+ if (tool->roi_marked)
+ {
+ glColor3f(1.0, 0.5, 0.0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glEnd();
+
+ if (tool->pick != PICK_NONE)
+ {
+ glColor3f(1.0, 0.0, 0.0);
+ glBegin(GL_LINES);
+ switch (tool->pick)
+ {
+ case PICK_CORNER_TOPLEFT:
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ break;
+
+ case PICK_CORNER_BOTTOMLEFT:
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ break;
+
+ case PICK_CORNER_BOTTOMRIGHT:
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ break;
+
+ case PICK_CORNER_TOPRIGHT:
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ break;
+
+ case PICK_SIDE_TOP:
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ break;
+
+ case PICK_SIDE_RIGHT:
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ break;
+
+ case PICK_SIDE_BOTTOM:
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ break;
+
+ case PICK_SIDE_LEFT:
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ break;
+ }
+ glEnd();
+ }
+ }
+}
+
+static void
+gv_roi_tool_deactivate(GvTool *rtool, GvViewArea *view)
+{
+ GvRoiTool *tool = GV_ROI_TOOL(rtool);
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+
+ tool->roi_marked = FALSE;
+ tool->banding = FALSE;
+
+ gv_view_area_queue_draw(view);
+}
+
+static void
+gv_roi_tool_start_resize(GvRoiTool *tool, gint pick, gvgeocoord pointer_x,
+ gvgeocoord pointer_y)
+{
+ gvgeocoord temp;
+#define SWAP(a,b) {temp=a; a=b; b=temp;}
+
+ /* Reposition the head and tail vertexes so we are always dragging
+ the bottom right corner */
+ switch (pick)
+ {
+ case PICK_CORNER_TOPLEFT:
+ case PICK_SIDE_TOP:
+ case PICK_SIDE_LEFT:
+ /* Swap head and tail */
+ SWAP(tool->v_head.x, tool->v_tail.x);
+ SWAP(tool->v_head.y, tool->v_tail.y);
+ break;
+
+ case PICK_CORNER_TOPRIGHT:
+ /* Swap y coords only */
+ SWAP(tool->v_head.y, tool->v_tail.y);
+ break;
+
+ case PICK_CORNER_BOTTOMLEFT:
+ /* Swap x coords only */
+ SWAP(tool->v_head.x, tool->v_tail.x);
+ break;
+ }
+
+ /* Set the drag flags for side or corner dragging */
+ switch (pick)
+ {
+ case PICK_SIDE_TOP:
+ case PICK_SIDE_BOTTOM:
+ tool->drag_right = FALSE;
+ tool->drag_bottom = TRUE;
+ tool->pick = PICK_SIDE_BOTTOM;
+ break;
+
+ case PICK_SIDE_LEFT:
+ case PICK_SIDE_RIGHT:
+ tool->drag_right = TRUE;
+ tool->drag_bottom = FALSE;
+ tool->pick = PICK_SIDE_RIGHT;
+ break;
+
+ default:
+ tool->drag_right = TRUE;
+ tool->drag_bottom = TRUE;
+ tool->pick = PICK_CORNER_BOTTOMRIGHT;
+ break;
+ }
+
+ /* Set the drag offset vector */
+ tool->v_drag_offset.x = tool->v_tail.x - pointer_x;
+ tool->v_drag_offset.y = tool->v_tail.y - pointer_y;
+
+ /* Enable dragging */
+ tool->banding = TRUE;
+
+#undef SWAP
+}
+
+static gint
+gv_roi_tool_pick_border(GvRoiTool *tool, gvgeocoord x, gvgeocoord y)
+{
+ GvViewArea *view;
+ GLuint buf[16];
+ GLint hits;
+ GLint vp[4];
+
+ /* FIXME: need to make the view area current GL context */
+
+ view = GV_TOOL(tool)->view;
+ vp[0] = vp[1] = 0;
+ vp[2] = (GLint)view->state.shape_x;
+ vp[3] = (GLint)view->state.shape_y;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPickMatrix(x, vp[3]-y, PICK_SIZE, PICK_SIZE, vp);
+ gluOrtho2D(-vp[2]/2.0, vp[2]/2.0, -vp[3]/2.0, vp[3]/2.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+
+ glSelectBuffer(16, buf);
+ glRenderMode(GL_SELECT);
+
+ glInitNames();
+ glPushName(-1);
+
+ /* Top */
+ glLoadName(0);
+ glBegin(GL_LINES);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glEnd();
+
+ /* Right */
+ glLoadName(1);
+ glBegin(GL_LINES);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glEnd();
+
+ /* Bottom */
+ glLoadName(2);
+ glBegin(GL_LINES);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glEnd();
+
+ /* Left */
+ glLoadName(3);
+ glBegin(GL_LINES);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glEnd();
+
+ hits = glRenderMode(GL_RENDER);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ if (hits > 1)
+ {
+ /* We've picked a corner */
+ if (buf[3] == 0 && buf[7] == 1)
+ return PICK_CORNER_TOPRIGHT;
+ if (buf[3] == 1)
+ return PICK_CORNER_BOTTOMRIGHT;
+ if (buf[3] == 2)
+ return PICK_CORNER_BOTTOMLEFT;
+ if (buf[3] == 0 && buf[7] == 3)
+ return PICK_CORNER_TOPLEFT;
+ }
+ else if (hits == 1)
+ {
+ /* We've picked a side */
+ return PICK_SIDE_TOP + buf[3];
+ }
+
+ /* No hits */
+ return PICK_NONE;
+}
Added: packages/openev/branches/upstream/current/gvroitool.h
===================================================================
--- packages/openev/branches/upstream/current/gvroitool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvroitool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * $Id: gvroitool.h,v 1.8 2000/07/27 20:06:23 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Region of interest (box in raster coordinates) editing mode.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvroitool.h,v $
+ * Revision 1.8 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.7 2000/06/30 18:04:57 srawlin
+ * added ability to set ROI constraints
+ *
+ * Revision 1.6 2000/06/29 21:18:08 srawlin
+ * Added CHANGED and CHANGING Signals
+ *
+ * Revision 1.5 2000/06/29 16:15:57 srawlin
+ * added function to create new ROI
+ *
+ * Revision 1.4 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_ROI_TOOL_H__
+#define __GV_ROI_TOOL_H__
+
+#include "gvtypes.h"
+#include "gvtool.h"
+
+#define GV_TYPE_ROI_TOOL (gv_roi_tool_get_type ())
+#define GV_ROI_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_ROI_TOOL, GvRoiTool))
+#define GV_ROI_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_ROI_TOOL, GvRoiToolClass))
+#define GV_IS_ROI_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_ROI_TOOL))
+#define GV_IS_ROI_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_ROI_TOOL))
+
+typedef struct _GvRoiTool GvRoiTool;
+typedef struct _GvRoiToolClass GvRoiToolClass;
+
+struct _GvRoiTool
+{
+ GvTool tool;
+
+ gint pick;
+
+ gint roi_marked : 1;
+ gint banding : 1;
+ gint drag_right : 1;
+ gint drag_bottom : 1;
+ GvVertex v_head, v_tail, v_drag_offset;
+};
+
+struct _GvRoiToolClass
+{
+ GvToolClass parent_class;
+
+ void (* roi_changed)(GvRoiTool *tool);
+ void (* roi_changing)(GvRoiTool *tool);
+};
+
+GtkType gv_roi_tool_get_type(void);
+GvTool* gv_roi_tool_new(void);
+
+gint gv_roi_tool_get_rect(GvRoiTool *tool, GvRect *rect);
+gint gv_roi_tool_new_rect(GvRoiTool *tool, GvRect *rect);
+
+#endif /* __GV_ROI_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvrotatetool.c
===================================================================
--- packages/openev/branches/upstream/current/gvrotatetool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvrotatetool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,756 @@
+/******************************************************************************
+ * $Id: gvrotatetool.c,v 1.2 2003/06/25 17:07:22 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Rotation and Scaling editing mode in GvShapesLayer.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrotatetool.c,v $
+ * Revision 1.2 2003/06/25 17:07:22 warmerda
+ * moved a bunch of stuff to gvshape.c
+ *
+ * Revision 1.1 2003/06/25 16:40:44 warmerda
+ * New
+ *
+ */
+
+#include <stdio.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include "gvrotatetool.h"
+#include "gvundo.h"
+#include "cpl_error.h"
+#include <GL/gl.h>
+#include <math.h>
+
+static void gv_rotate_tool_class_init(GvRotateToolClass *klass);
+static void gv_rotate_tool_init(GvRotateTool *tool);
+static void gv_rotate_tool_draw(GvRotateTool *tool);
+static void gv_rotate_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_rotate_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_rotate_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_rotate_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_rotate_tool_deactivate(GvTool *tool, GvViewArea *view);
+static gint gv_rotate_tool_configure(GvRotateTool *tool);
+
+#define HEAD_SIZE 6
+#define ARROW_SIZE 45
+
+enum
+{
+ RRMODE_DISPLAY,
+ RRMODE_ROTATE,
+ RRMODE_SCALE,
+ RRMODE_ROTATESCALE
+};
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+GtkType
+gv_rotate_tool_get_type(void)
+{
+ static GtkType rotate_tool_type = 0;
+
+ if (!rotate_tool_type)
+ {
+ static const GtkTypeInfo rotate_tool_info =
+ {
+ "GvRotateTool",
+ sizeof(GvRotateTool),
+ sizeof(GvRotateToolClass),
+ (GtkClassInitFunc) gv_rotate_tool_class_init,
+ (GtkObjectInitFunc) gv_rotate_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ rotate_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &rotate_tool_info);
+ }
+ return rotate_tool_type;
+}
+
+static void
+gv_rotate_tool_class_init(GvRotateToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_rotate_tool_deactivate;
+ tool_class->button_press = gv_rotate_tool_button_press;
+ tool_class->button_release = gv_rotate_tool_button_release;
+ tool_class->motion_notify = gv_rotate_tool_motion_notify;
+ tool_class->key_press = gv_rotate_tool_key_press;
+}
+
+static void
+gv_rotate_tool_init(GvRotateTool *tool)
+{
+ GV_TOOL(tool)->cursor = gdk_cursor_new(GDK_TCROSS);
+ tool->layer = NULL;
+ tool->named_layer = NULL;
+ tool->rrmode = RRMODE_DISPLAY;
+ tool->shape_id = -1;
+ tool->rotation = 0.0;
+ tool->scaling = 1.0;
+ tool->original = NULL;
+}
+
+GvTool *
+gv_rotate_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_ROTATE_TOOL));
+}
+
+static gint gv_rotate_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvRotateTool *tool = (GvRotateTool *) data;
+
+ if( tool->layer == GV_SHAPES_LAYER(layer) )
+ gv_rotate_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+/************************************************************************/
+/* gv_rotate_tool_terminate() */
+/* */
+/* This breaks out of a non-display mode, restores the original */
+/* shape and generally restores a sane state. */
+/************************************************************************/
+
+void
+gv_rotate_tool_terminate( GvRotateTool *tool )
+{
+ if( tool->rrmode == RRMODE_DISPLAY )
+ return;
+
+ if( tool->original != NULL
+ && gv_shapes_get_shape( tool->layer->data, tool->shape_id) != NULL )
+ {
+ gv_shapes_replace_shapes( tool->layer->data, 1, &(tool->shape_id),
+ &(tool->original), FALSE );
+ tool->original = NULL;
+ gv_undo_enable();
+ gv_undo_open();
+ }
+ else if( tool->original != NULL )
+ {
+ gv_shape_delete( tool->original );
+ tool->original = NULL;
+ gv_undo_enable();
+ gv_undo_open();
+ }
+
+ tool->shape_id = -1;
+ tool->rrmode = RRMODE_DISPLAY;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+}
+
+/************************************************************************/
+/* gv_rotate_tool_set_layer() */
+/************************************************************************/
+void
+gv_rotate_tool_set_layer(GvRotateTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ g_warning("gv_rotate_tool_set_layer(): inactive tool");
+ return;
+ }
+
+ if( layer != NULL && gv_data_is_read_only( GV_DATA(layer) ) )
+ {
+ g_warning( "gv_rotate_tool_set_layer(): layer is read-only" );
+ return;
+ }
+
+ gv_rotate_tool_terminate( tool );
+ tool->shape_id = -1;
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ tool->rrmode = RRMODE_DISPLAY;
+
+ /** TODO: Not sure that we need to unselect ... try to remove later */
+
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+
+ if( layer == NULL )
+ tool->layer = NULL;
+ else
+ tool->layer = GV_SHAPES_LAYER(layer);
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_rotate_tool_draw),
+ GTK_OBJECT(tool));
+ /* Recover if layer destroyed */
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_rotate_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+/************************************************************************/
+/* gv_rotate_tool_set_named_layer() */
+/************************************************************************/
+
+void
+gv_rotate_tool_set_named_layer(GvRotateTool *tool, gchar *name)
+{
+ if (tool->named_layer)
+ {
+ g_free(tool->named_layer);
+ tool->named_layer = NULL;
+ }
+ if (name)
+ {
+ tool->named_layer = g_strdup(name);
+ }
+ /* Tool layer will be updated next time it is configured */
+}
+
+/************************************************************************/
+/* gv_rotate_tool_setup_arrows() */
+/* */
+/* This function will compute the pivot location for the */
+/* selected shape, and the corresponding up and right vectors */
+/* for drawing the rotate/resize arrows. */
+/************************************************************************/
+
+static gint gv_rotate_tool_setup_arrows( GvRotateTool *tool )
+
+{
+ GvVertex3d pivot_3d;
+ GvShape *shape = gv_shapes_get_shape( tool->layer->data,
+ tool->shape_id );
+
+ if( shape == NULL )
+ {
+ CPLDebug( "OpenEV", "gv_rotate_tool_setup_arrows(), shape==NULL!" );
+ tool->shape_id = -1;
+ return 0;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute the pivot location. */
+/* -------------------------------------------------------------------- */
+ if( !gv_shape_get_center( shape, &pivot_3d ) )
+ return 0;
+
+ tool->v_pivot.x = pivot_3d.x;
+ tool->v_pivot.y = pivot_3d.y;
+
+/* -------------------------------------------------------------------- */
+/* Compute the up vector. */
+/* -------------------------------------------------------------------- */
+ gv_view_area_correct_for_transform( GV_TOOL(tool)->view, 0.0, 1.0,
+ &(tool->v_up.x),
+ &(tool->v_up.y) );
+ gv_view_area_correct_for_transform( GV_TOOL(tool)->view, 1.0, 0.0,
+ &(tool->v_right.x),
+ &(tool->v_right.y) );
+
+ tool->rotation = 0.0;
+ tool->scaling = 1.0;
+
+ return 1;
+}
+
+/************************************************************************/
+/* gv_rotate_tool_classify_hit() */
+/* */
+/* Does the mouse location in geo-coordinates hit near the head */
+/* of the rotate or resize tool? */
+/************************************************************************/
+
+int gv_rotate_tool_classify_hit( GvRotateTool *tool, gvgeocoord x, gvgeocoord y )
+
+{
+ gvgeocoord x_focus, y_focus, x_ul, y_ul, x_lr, y_lr;
+
+ x_focus = tool->v_pivot.x + tool->v_up.x * ARROW_SIZE;
+ y_focus = tool->v_pivot.y + tool->v_up.y * ARROW_SIZE;
+
+ x_ul = x_focus - tool->v_right.x * (HEAD_SIZE*2+3) - tool->v_up.x*HEAD_SIZE;
+ y_ul = y_focus - tool->v_right.y * (HEAD_SIZE*2+3) - tool->v_up.y*HEAD_SIZE;
+ x_lr = x_focus + tool->v_right.x * (HEAD_SIZE*2+3) + tool->v_up.x*HEAD_SIZE;
+ y_lr = y_focus + tool->v_right.y * (HEAD_SIZE*2+3) + tool->v_up.y*HEAD_SIZE;
+
+ if( x >= MIN(x_ul,x_lr) && x <= MAX(x_ul,x_lr)
+ && y >= MIN(y_ul,y_lr) && y <= MAX(y_ul,y_lr) )
+ {
+ return RRMODE_ROTATE;
+ }
+
+ x_focus = tool->v_pivot.x + tool->v_right.x * ARROW_SIZE;
+ y_focus = tool->v_pivot.y + tool->v_right.y * ARROW_SIZE;
+
+ x_ul = x_focus - tool->v_right.x * HEAD_SIZE - tool->v_up.x * HEAD_SIZE;
+ y_ul = y_focus - tool->v_right.y * HEAD_SIZE - tool->v_up.y * HEAD_SIZE;
+ x_lr = x_focus + tool->v_right.x * 3 + tool->v_up.x * HEAD_SIZE;
+ y_lr = y_focus + tool->v_right.y * 3 + tool->v_up.y * HEAD_SIZE;
+
+ if( x >= MIN(x_ul,x_lr) && x <= MAX(x_ul,x_lr)
+ && y >= MIN(y_ul,y_lr) && y <= MAX(y_ul,y_lr) )
+ {
+ return RRMODE_SCALE;
+ }
+
+ return RRMODE_DISPLAY;
+}
+
+/************************************************************************/
+/* gv_rotate_tool_draw() */
+/* */
+/* Draw callback invoked by system after all regular layers are */
+/* drawn. */
+/************************************************************************/
+
+static void
+gv_rotate_tool_draw(GvRotateTool *tool)
+{
+/* -------------------------------------------------------------------- */
+/* If we have a selected shape, we need to draw the */
+/* rotate/resize arrow handles. */
+/* -------------------------------------------------------------------- */
+ if (tool->shape_id != -1 )
+ {
+ GvVertex v_up, v_right;
+ double rad_rot;
+
+ /*
+ ** In display mode recompute the pivot, up and right vector each
+ ** redraw.
+ */
+ if( tool->rrmode == RRMODE_DISPLAY )
+ {
+ if( !gv_rotate_tool_setup_arrows( tool ) )
+ return;
+ }
+
+ /*
+ ** Apply scaling and rotation.
+ */
+
+ rad_rot = (tool->rotation / 180.0) * M_PI;
+ v_up.x = tool->v_up.x*cos(rad_rot) + tool->v_up.y*sin(rad_rot);
+ v_up.y = - tool->v_up.x*sin(rad_rot) + tool->v_up.y*cos(rad_rot);
+ v_right.x = tool->v_right.x*cos(rad_rot) + tool->v_right.y*sin(rad_rot);
+ v_right.y = -tool->v_right.x*sin(rad_rot) + tool->v_right.y*cos(rad_rot);
+
+ v_up.x *= tool->scaling;
+ v_up.y *= tool->scaling;
+ v_right.x *= tool->scaling;
+ v_right.y *= tool->scaling;
+
+ glColor4f( 1.0, 0.0, 0.0, 1.0 );
+
+ if( tool->rrmode != RRMODE_SCALE )
+ {
+ /** Upward line with left/right rotate arrow heads **/
+ glBegin( GL_LINES );
+ glVertex2( tool->v_pivot.x, tool->v_pivot.y );
+ glVertex2( tool->v_pivot.x + v_up.x * ARROW_SIZE,
+ tool->v_pivot.y + v_up.y * ARROW_SIZE );
+
+ /* left pointing arrow */
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ - v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ - v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x + v_up.x * ARROW_SIZE,
+ tool->v_pivot.y + v_up.y * ARROW_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ - v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ - v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x
+ + v_up.x * (ARROW_SIZE+HEAD_SIZE)
+ - v_right.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_up.y * (ARROW_SIZE+HEAD_SIZE)
+ - v_right.y * HEAD_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ - v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ - v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x
+ + v_up.x * (ARROW_SIZE-HEAD_SIZE)
+ - v_right.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_up.y * (ARROW_SIZE-HEAD_SIZE)
+ - v_right.y * HEAD_SIZE );
+
+ /* rightward pointing arrow */
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ + v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ + v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x + v_up.x * ARROW_SIZE,
+ tool->v_pivot.y + v_up.y * ARROW_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ + v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ + v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x
+ + v_up.x * (ARROW_SIZE+HEAD_SIZE)
+ + v_right.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_up.y * (ARROW_SIZE+HEAD_SIZE)
+ + v_right.y * HEAD_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_up.x * ARROW_SIZE
+ + v_right.x * HEAD_SIZE*2,
+ tool->v_pivot.y
+ + v_up.y * ARROW_SIZE
+ + v_right.y * HEAD_SIZE*2 );
+ glVertex2( tool->v_pivot.x
+ + v_up.x * (ARROW_SIZE-HEAD_SIZE)
+ + v_right.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_up.y * (ARROW_SIZE-HEAD_SIZE)
+ + v_right.y * HEAD_SIZE );
+
+ glEnd();
+ }
+
+ if( tool->rrmode != RRMODE_ROTATE )
+ {
+
+ /** Rightward arrow for resizing. **/
+ glBegin( GL_LINES );
+ glVertex2( tool->v_pivot.x, tool->v_pivot.y );
+ glVertex2( tool->v_pivot.x + v_right.x * ARROW_SIZE,
+ tool->v_pivot.y + v_right.y * ARROW_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_right.x * (ARROW_SIZE-HEAD_SIZE)
+ + v_up.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_right.y * (ARROW_SIZE-HEAD_SIZE)
+ + v_up.y * HEAD_SIZE );
+ glVertex2( tool->v_pivot.x + v_right.x * ARROW_SIZE,
+ tool->v_pivot.y + v_right.y * ARROW_SIZE );
+
+ glVertex2( tool->v_pivot.x
+ + v_right.x * (ARROW_SIZE-HEAD_SIZE)
+ - v_up.x * HEAD_SIZE,
+ tool->v_pivot.y
+ + v_right.y * (ARROW_SIZE-HEAD_SIZE)
+ - v_up.y * HEAD_SIZE );
+ glVertex2( tool->v_pivot.x + v_right.x * ARROW_SIZE,
+ tool->v_pivot.y + v_right.y * ARROW_SIZE );
+
+ glEnd();
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_rotate_tool_button_press() */
+/************************************************************************/
+
+static void
+gv_rotate_tool_button_press(GvTool *r_tool, GdkEventButton *event)
+{
+ GvRotateTool *tool = GV_ROTATE_TOOL(r_tool);
+
+ if( event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK) )
+ return;
+
+/* -------------------------------------------------------------------- */
+/* Have we selected an active control point on the scale/rotate */
+/* dohickey? */
+/* -------------------------------------------------------------------- */
+ if( tool->rrmode == RRMODE_DISPLAY && tool->shape_id != -1 )
+ {
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_head.x, &tool->v_head.y);
+
+ /*
+ ** Is this location a hit on an arrow head?
+ */
+ tool->rrmode =
+ gv_rotate_tool_classify_hit( tool, tool->v_head.x, tool->v_head.y );
+
+ /*
+ ** Copy the original state of this shape, and disable undo till we are
+ ** done.
+ */
+ if( tool->rrmode != RRMODE_DISPLAY )
+ {
+ if( event->button != 1 )
+ tool->rrmode = RRMODE_ROTATESCALE;
+
+ tool->original = gv_shape_copy(
+ gv_shapes_get_shape( tool->layer->data, tool->shape_id ));
+
+ gv_undo_close();
+ gv_undo_disable();
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Are we selecting a shape? Note, currently we cannot clear */
+/* our selection in resize/rotate mode - should we be able to? */
+/* -------------------------------------------------------------------- */
+ if (event->button == 1 && tool->rrmode == RRMODE_DISPLAY )
+ {
+ int shape_id;
+
+ if (!gv_rotate_tool_configure(tool)) return;
+
+ if (gv_shape_layer_pick_shape(GV_SHAPE_LAYER(tool->layer),
+ GV_TOOL(tool)->view,
+ event->x, event->y, &shape_id))
+ {
+ GvShape *shape;
+
+ /* Is the shape rotatable? */
+ shape = gv_shapes_get_shape( tool->layer->data, shape_id );
+
+ if( TRUE )
+ {
+ gv_shape_layer_clear_selection(
+ GV_SHAPE_LAYER(tool->layer));
+ gv_shape_layer_select_shape(
+ GV_SHAPE_LAYER(tool->layer), shape_id);
+ tool->shape_id = shape_id;
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ }
+ return;
+ }
+
+}
+
+/************************************************************************/
+/* gv_rotate_tool_button_release() */
+/************************************************************************/
+
+static void
+gv_rotate_tool_button_release(GvTool *r_tool, GdkEventButton *event)
+{
+ GvRotateTool *tool = GV_ROTATE_TOOL(r_tool);
+
+ if( tool->rrmode == RRMODE_DISPLAY )
+ return;
+
+ /* Put back original shape. */
+ gv_shapes_replace_shapes( tool->layer->data, 1, &(tool->shape_id),
+ &(tool->original), TRUE );
+
+ /* re-enable undo */
+ gv_undo_enable();
+ gv_undo_open();
+
+ /* Apply rotation or scaling to working shape. */
+ if( tool->rrmode == RRMODE_SCALE
+ || tool->rrmode == RRMODE_ROTATESCALE )
+ gv_shape_scale( tool->original, tool->scaling );
+
+ if( tool->rrmode == RRMODE_ROTATE
+ || tool->rrmode == RRMODE_ROTATESCALE )
+ gv_shape_rotate( tool->original, tool->rotation );
+
+ /* Apply to the shapes object ... this will be undoable */
+ gv_shapes_replace_shapes( tool->layer->data, 1, &(tool->shape_id),
+ &(tool->original), TRUE );
+ tool->original = NULL;
+
+ tool->rrmode = RRMODE_DISPLAY;
+}
+
+/************************************************************************/
+/* gv_rotate_tool_motion_notify() */
+/************************************************************************/
+static void
+gv_rotate_tool_motion_notify(GvTool *r_tool, GdkEventMotion *event)
+{
+ GvRotateTool *tool = GV_ROTATE_TOOL(r_tool);
+ GvShape *wrk_shape;
+
+ if (tool->rrmode == RRMODE_DISPLAY )
+ return;
+
+
+ wrk_shape = gv_shape_copy(tool->original);
+
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ /* Compute rotation from base. */
+ if( tool->rrmode == RRMODE_ROTATE
+ || tool->rrmode == RRMODE_ROTATESCALE )
+ {
+ double dx = tool->v_tail.x - tool->v_pivot.x;
+ double dy = tool->v_tail.y - tool->v_pivot.y;
+
+ if( fabs(dy) < fabs(dx)/1000000.0 )
+ tool->rotation = M_PI/2;
+ else
+ tool->rotation = atan(fabs(dx/dy));
+
+
+ if( dy < 0.0 && dx >= 0.0 )
+ tool->rotation = M_PI - tool->rotation;
+ else if( dy >= 0.0 && dx < 0.0 )
+ tool->rotation = -tool->rotation;
+ else if( dy < 0.0 && dx < 0.0 )
+ tool->rotation -= M_PI;
+
+
+ tool->rotation = (tool->rotation / M_PI) * 180;
+
+ gv_shape_rotate( wrk_shape, tool->rotation );
+ }
+
+ /* Compute Scaling from base. */
+ if( tool->rrmode == RRMODE_SCALE
+ || tool->rrmode == RRMODE_ROTATESCALE )
+ {
+ double dx, dy, old_length, new_length;
+
+ dx = tool->v_tail.x - tool->v_pivot.x;
+ dy = tool->v_tail.y - tool->v_pivot.y;
+ new_length = sqrt(dx*dx + dy*dy);
+
+ dx = tool->v_head.x - tool->v_pivot.x;
+ dy = tool->v_head.y - tool->v_pivot.y;
+ old_length = sqrt(dx*dx + dy*dy);
+
+ tool->scaling = new_length / old_length;
+
+ gv_shape_scale( wrk_shape, tool->scaling );
+ }
+
+ /* Apply to the shapes object ... this will create an undo step */
+ gv_shapes_replace_shapes( tool->layer->data, 1, &(tool->shape_id),
+ &wrk_shape, FALSE );
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+}
+
+/************************************************************************/
+/* gv_rotate_tool_key_press() */
+/************************************************************************/
+
+static void
+gv_rotate_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvRotateTool *tool = GV_ROTATE_TOOL(rtool);
+
+ if (!gv_rotate_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ case GDK_Escape:
+ if( tool->rrmode != RRMODE_DISPLAY )
+ {
+ gv_rotate_tool_terminate( tool );
+ }
+ break;
+ }
+}
+
+static void
+gv_rotate_tool_deactivate(GvTool *r_tool, GvViewArea *view)
+{
+ GvRotateTool *tool = GV_ROTATE_TOOL(r_tool);
+
+ /* terminate any active modes */
+ gv_rotate_tool_terminate( tool );
+
+ /* Disconnect from layer */
+ if (tool->layer)
+ {
+ gv_rotate_tool_set_layer(tool, NULL);
+ }
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static gint
+gv_rotate_tool_configure(GvRotateTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ if (tool->named_layer)
+ {
+ /* Look for named layer if given */
+ layer = gv_view_area_get_named_layer(GV_TOOL(tool)->view,
+ tool->named_layer);
+ }
+ else
+ {
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPES_LAYER,
+ FALSE);
+ }
+
+ if (!layer)
+ {
+ g_warning("gv_rotate_tool_configure(): no shapes layer in view");
+ return FALSE;
+ }
+
+ gv_rotate_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+ return tool->layer != NULL;
+}
Added: packages/openev/branches/upstream/current/gvrotatetool.h
===================================================================
--- packages/openev/branches/upstream/current/gvrotatetool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvrotatetool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * $Id: gvrotatetool.h,v 1.1 2003/06/25 16:40:44 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Rotation and Scaling editing mode.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvrotatetool.h,v $
+ * Revision 1.1 2003/06/25 16:40:44 warmerda
+ * New
+ *
+ */
+
+#ifndef __GV_ROTATE_TOOL_H__
+#define __GV_ROTATE_TOOL_H__
+
+#include "gvtool.h"
+#include "gvshapeslayer.h"
+
+#define GV_TYPE_ROTATE_TOOL (gv_rotate_tool_get_type ())
+#define GV_ROTATE_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_ROTATE_TOOL, GvRotateTool))
+#define GV_ROTATE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_ROTATE_TOOL, GvRotateToolClass))
+#define GV_IS_ROTATE_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_ROTATE_TOOL))
+#define GV_IS_ROTATE_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_ROTATE_TOOL))
+
+typedef struct _GvRotateTool GvRotateTool;
+typedef struct _GvRotateToolClass GvRotateToolClass;
+
+struct _GvRotateTool
+{
+ GvTool tool;
+
+ GvShapesLayer *layer;
+ gchar *named_layer;
+
+ GvVertex v_pivot;
+ GvVertex v_up, v_right;
+
+ GvVertex v_head, v_tail;
+
+ int rrmode; /* current mode */
+ int shape_id; /* shapeid of rectangle being reshaped */
+
+ double rotation;
+ double scaling;
+
+ GvShape *original;
+};
+
+struct _GvRotateToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_rotate_tool_get_type(void);
+GvTool* gv_rotate_tool_new(void);
+void gv_rotate_tool_set_layer(GvRotateTool *tool, GvShapeLayer *layer);
+void gv_rotate_tool_set_named_layer(GvRotateTool *tool, gchar *name);
+
+#endif /* __GV_ROTATE_TOOL_H__ */
+
+
+
Added: packages/openev/branches/upstream/current/gvselecttool.c
===================================================================
--- packages/openev/branches/upstream/current/gvselecttool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvselecttool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,445 @@
+/******************************************************************************
+ * $Id: gvselecttool.c,v 1.17 2003/09/16 15:43:11 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Shape selection tool.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvselecttool.c,v $
+ * Revision 1.17 2003/09/16 15:43:11 gmwalter
+ * Add single selection mode to select tool, checked in developer tutorials.
+ *
+ * Revision 1.16 2002/11/04 21:42:06 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.15 2002/01/18 04:53:28 warmerda
+ * fixed shift-leftclick to add/subtract from selection
+ *
+ * Revision 1.14 2001/10/23 02:43:45 pgs
+ * changed deactivate to call base class last
+ *
+ * Revision 1.13 2001/05/07 19:08:03 warmerda
+ * draw text with origin off viewport properly
+ *
+ * Revision 1.12 2001/04/09 18:16:22 warmerda
+ * honour read-only layers
+ *
+ * Revision 1.11 2000/08/23 16:48:00 warmerda
+ * don't drag select box if control/shift pressed
+ *
+ * Revision 1.10 2000/08/10 18:33:46 warmerda
+ * removed a warning
+ *
+ * Revision 1.9 2000/08/08 20:58:47 warmerda
+ * recover from layer destruction
+ *
+ * Revision 1.8 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.7 2000/06/29 14:38:58 warmerda
+ * don't emit a warning if gvselecttool configure without layers
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <string.h>
+#include "gvselecttool.h"
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <GL/gl.h>
+
+static void gv_selection_tool_class_init(GvSelectionToolClass *klass);
+static void gv_selection_tool_init(GvSelectionTool *tool);
+static void gv_selection_tool_draw(GvTool *tool);
+static void gv_selection_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_selection_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_selection_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_selection_tool_key_press(GvTool *tool, GdkEventKey *event);
+static void gv_selection_tool_deactivate(GvTool *tool, GvViewArea *view);
+static gint gv_selection_tool_configure(GvSelectionTool *tool);
+
+GtkType
+gv_selection_tool_get_type(void)
+{
+ static GtkType selection_tool_type = 0;
+
+ if (!selection_tool_type)
+ {
+ static const GtkTypeInfo selection_tool_info =
+ {
+ "GvSelectionTool",
+ sizeof(GvSelectionTool),
+ sizeof(GvSelectionToolClass),
+ (GtkClassInitFunc) gv_selection_tool_class_init,
+ (GtkObjectInitFunc) gv_selection_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ selection_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &selection_tool_info);
+ }
+ return selection_tool_type;
+}
+
+static void
+gv_selection_tool_class_init(GvSelectionToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_selection_tool_deactivate;
+ tool_class->button_press = gv_selection_tool_button_press;
+ tool_class->button_release = gv_selection_tool_button_release;
+ tool_class->motion_notify = gv_selection_tool_motion_notify;
+ tool_class->key_press = gv_selection_tool_key_press;
+}
+static void
+gv_selection_tool_init(GvSelectionTool *tool)
+{
+ tool->layer = NULL;
+ tool->banding = FALSE;
+ tool->dragging = FALSE;
+}
+
+GvTool *
+gv_selection_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_SELECTION_TOOL));
+}
+
+static gint gv_selection_tool_layer_destroy( GtkObject *layer, gpointer data )
+
+{
+ GvSelectionTool *tool = (GvSelectionTool *) data;
+
+ if( tool->layer == GV_SHAPE_LAYER(layer) )
+ gv_selection_tool_set_layer( tool, NULL );
+
+ return 0;
+}
+
+void
+gv_selection_tool_set_layer(GvSelectionTool *tool, GvShapeLayer *layer)
+{
+ if (GV_TOOL(tool)->view == NULL)
+ {
+ return;
+ }
+
+ /* Disconnect from the previous layer (for draw) */
+ if (tool->layer)
+ {
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(tool->layer));
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->layer), (gpointer)tool);
+ }
+
+ tool->layer = layer;
+
+ if (layer)
+ {
+ gv_view_area_set_active_layer(GV_TOOL(tool)->view, GTK_OBJECT(layer));
+
+ /* Redraw when the layer draws */
+ gtk_signal_connect_object_after(GTK_OBJECT(layer), "draw",
+ GTK_SIGNAL_FUNC(gv_selection_tool_draw),
+ GTK_OBJECT(tool));
+
+ /* Recover if layer is destroyed */
+ gtk_signal_connect(
+ GTK_OBJECT(layer), "destroy",
+ GTK_SIGNAL_FUNC(gv_selection_tool_layer_destroy),
+ GTK_OBJECT(tool));
+ }
+}
+
+/**************************************************************/
+
+static void
+gv_selection_tool_button_press(GvTool *rtool, GdkEventButton *event)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+ /* ignore control corded buttons -- these are for zooming and panning */
+ if( event->state & GDK_CONTROL_MASK )
+ return;
+
+ if (event->button == 1)
+ {
+ gint shape_id;
+
+ if (!gv_selection_tool_configure(tool)) return;
+
+ if (gv_shape_layer_pick_shape(tool->layer, GV_TOOL(tool)->view,
+ event->x, event->y, &shape_id))
+ {
+ if ((event->state & GDK_SHIFT_MASK) &&
+ ((gv_data_get_property( GV_DATA(tool->layer),
+ "selection_mode" ) == NULL) ||
+ (strcmp(gv_data_get_property( GV_DATA(tool->layer),
+ "selection_mode" ),"single") != 0)))
+ {
+ /* Shift click (de)selects without clearing other selections */
+ if (gv_shape_layer_is_selected(tool->layer, shape_id))
+ {
+ gv_shape_layer_deselect_shape(tool->layer, shape_id);
+ }
+ else
+ {
+ gv_shape_layer_select_shape(tool->layer, shape_id);
+ }
+ }
+ else if (!(event->state & GDK_SHIFT_MASK))
+ {
+ /* Non-shift click */
+ if (!gv_shape_layer_is_selected(tool->layer, shape_id))
+ {
+ /* Select this shape (and only this shape) */
+ gv_shape_layer_clear_selection(tool->layer);
+ gv_shape_layer_select_shape(tool->layer, shape_id);
+ }
+
+ if( !gv_data_is_read_only( GV_DATA(tool->layer) ) )
+ {
+ /* Start a drag operation */
+ tool->dragging = TRUE;
+
+ /* Capture pointer position */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view,
+ event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ tool->v_head = tool->v_tail;
+
+ /* Delay drawing the selected shapes */
+ gv_shape_layer_draw_selected(tool->layer, GV_LATER, NULL);
+ }
+ }
+ }
+ else if ((event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == 0 )
+ {
+ if ((gv_data_get_property( GV_DATA(tool->layer),
+ "selection_mode" ) != NULL) &&
+ (strcmp(gv_data_get_property( GV_DATA(tool->layer),
+ "selection_mode" ),"single") == 0))
+ {
+ gv_shape_layer_clear_selection(tool->layer);
+ }
+ else
+ {
+ /* Begin rubber band */
+ gv_shape_layer_clear_selection(tool->layer);
+
+ /* Capture pointer position */
+ tool->v_tail.x = event->x - GV_TOOL(tool)->view->state.tx;
+ tool->v_tail.y = (GV_TOOL(tool)->view->state.shape_y -
+ event->y) - GV_TOOL(tool)->view->state.ty;
+ tool->v_head = tool->v_tail;
+
+ tool->banding = TRUE;
+ }
+ }
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_selection_tool_button_release(GvTool *rtool, GdkEventButton *event)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+ if (tool->banding && event->button == 1)
+ {
+ /* End rubber band */
+ gvgeocoord ax, ay, bx, by;
+ GvRect rect;
+ GvViewAreaState *state = &GV_TOOL(tool)->view->state;
+
+ tool->banding = FALSE;
+
+ /* Get view center coords for rubber band */
+ ax = tool->v_head.x + state->tx - state->shape_x/2.0;
+ ay = tool->v_head.y + state->ty - state->shape_y/2.0;
+ bx = event->x - state->shape_x/2.0;
+ by = state->shape_y/2.0 - event->y;
+
+ rect.x = MIN(ax, bx);
+ rect.y = MIN(ay, by);
+ rect.width = ABS(ax - bx);
+ rect.height = ABS(ay - by);
+
+ /* Pick shapes in region */
+ gv_shape_layer_select_region(tool->layer, GV_TOOL(tool)->view, &rect);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ else if (tool->dragging && event->button == 1)
+ {
+ /* End dragging */
+ tool->dragging = FALSE;
+ gv_shape_layer_draw_selected(tool->layer, GV_ALWAYS, NULL);
+
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+
+ /* Filter out clicks that wern't really drags */
+ if (tool->v_tail.x != tool->v_head.x ||
+ tool->v_tail.y != tool->v_head.y)
+ {
+ /* Translate shapes */
+ gv_shape_layer_translate_selected(tool->layer,
+ tool->v_tail.x - tool->v_head.x,
+ tool->v_tail.y - tool->v_head.y);
+ }
+ }
+}
+
+static void
+gv_selection_tool_motion_notify(GvTool *rtool, GdkEventMotion *event)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+ if (tool->banding)
+ {
+ /* Resize rubber band */
+ /* Capture pointer position to tail vertex */
+ tool->v_tail.x = event->x - GV_TOOL(tool)->view->state.tx;
+ tool->v_tail.y = (GV_TOOL(tool)->view->state.shape_y - event->y) -
+ GV_TOOL(tool)->view->state.ty;
+
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+ else if (tool->dragging)
+ {
+ /* Drag selected shapes */
+ /* Map pointer position to tail vertex */
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &tool->v_tail.x, &tool->v_tail.y);
+ gv_view_area_queue_draw(GV_TOOL(tool)->view);
+ }
+}
+
+static void
+gv_selection_tool_key_press(GvTool *rtool, GdkEventKey *event)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+ if (!gv_selection_tool_configure(tool)) return;
+
+ switch (event->keyval)
+ {
+ case GDK_Delete:
+ case GDK_BackSpace:
+ /* Delete the currently selected lines (forces redraw) */
+ if( !gv_data_is_read_only( GV_DATA(tool->layer) ) )
+ gv_shape_layer_delete_selected(tool->layer);
+ break;
+ }
+}
+
+static void
+gv_selection_tool_draw(GvTool *rtool)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+ if (tool->banding)
+ {
+ /* Resolve head and tail positions in view coordinates */
+ GvViewAreaState *state = &GV_TOOL(tool)->view->state;
+
+ /* Draw the rubber band rectangle */
+ glColor3f(1.0, 0.0, 0.0);
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslate(state->tx - state->shape_x/2.0,
+ state->ty - state->shape_y/2.0, 0.0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2(tool->v_head.x, tool->v_head.y);
+ glVertex2(tool->v_head.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_tail.y);
+ glVertex2(tool->v_tail.x, tool->v_head.y);
+ glEnd();
+ glPopMatrix();
+ }
+ else if (tool->dragging)
+ {
+ gvgeocoord dx, dy;
+
+ /* Inform layer of shape motion */
+ dx = tool->v_tail.x - tool->v_head.x;
+ dy = tool->v_tail.y - tool->v_head.y;
+ gv_shape_layer_selected_motion(tool->layer, dx, dy);
+
+ /* Draw selected objects translated */
+ glPushMatrix();
+ glTranslate(dx, dy, 0.0);
+ gv_shape_layer_draw_selected(tool->layer, GV_NOW,
+ GV_TOOL(tool)->view);
+ glPopMatrix();
+ gv_shape_layer_selected_motion(tool->layer, 0.0, 0.0 );
+ }
+}
+
+static void
+gv_selection_tool_deactivate(GvTool *rtool, GvViewArea *view)
+{
+ GvSelectionTool *tool = GV_SELECTION_TOOL(rtool);
+
+
+ if (tool->layer)
+ {
+ if (tool->dragging)
+ {
+ gv_shape_layer_draw_selected(tool->layer, GV_ALWAYS, NULL);
+ }
+ gv_shape_layer_clear_selection(tool->layer);
+ gv_view_area_queue_draw(view);
+ gv_selection_tool_set_layer(tool, NULL);
+ }
+ tool->banding = FALSE;
+ tool->dragging = FALSE;
+
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+}
+
+static gint
+gv_selection_tool_configure(GvSelectionTool *tool)
+{
+ /* Check that we still are working on the active layer */
+ if (!tool->layer || GTK_OBJECT(tool->layer) !=
+ gv_view_area_active_layer(GV_TOOL(tool)->view))
+ {
+ GtkObject *layer;
+
+ /* Attempt to find a line layer to edit */
+ layer = gv_view_area_get_layer_of_type(GV_TOOL(tool)->view,
+ GV_TYPE_SHAPE_LAYER,
+ TRUE);
+ if (!layer)
+ return FALSE;
+
+ gv_selection_tool_set_layer(tool, GV_SHAPE_LAYER(layer));
+ }
+ return TRUE;
+}
Added: packages/openev/branches/upstream/current/gvselecttool.h
===================================================================
--- packages/openev/branches/upstream/current/gvselecttool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvselecttool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: gvselecttool.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Shape selection tool.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvselecttool.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_SELECTION_TOOL_H__
+#define __GV_SELECTION_TOOL_H__
+
+#include "gvtool.h"
+#include "gvshapelayer.h"
+
+#define GV_TYPE_SELECTION_TOOL (gv_selection_tool_get_type ())
+#define GV_SELECTION_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_SELECTION_TOOL, GvSelectionTool))
+#define GV_SELECTION_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_SELECTION_TOOL, GvSelectionToolClass))
+#define GV_IS_SELECTION_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_SELECTION_TOOL))
+#define GV_IS_SELECTION_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_SELECTION_TOOL))
+
+typedef struct _GvSelectionTool GvSelectionTool;
+typedef struct _GvSelectionToolClass GvSelectionToolClass;
+
+struct _GvSelectionTool
+{
+ GvTool tool;
+
+ GvShapeLayer *layer;
+ gint banding : 1;
+ gint dragging : 1;
+ GvVertex v_head, v_tail;
+};
+
+struct _GvSelectionToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_selection_tool_get_type(void);
+GvTool* gv_selection_tool_new(void);
+void gv_selection_tool_set_layer(GvSelectionTool *tool, GvShapeLayer *layer);
+
+#endif /* __GV_SELECTION_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvshape.c
===================================================================
--- packages/openev/branches/upstream/current/gvshape.c (rev 0)
+++ packages/openev/branches/upstream/current/gvshape.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1755 @@
+/******************************************************************************
+ * $Id: gvshape.c,v 1.21 2005/01/04 18:50:29 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvShape (point/line/area/collection vector object)
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshape.c,v $
+ * Revision 1.21 2005/01/04 18:50:29 gmwalter
+ * Checked in Aude's new gvshape function changes.
+ *
+ * Revision 1.20 2003/09/02 18:17:51 warmerda
+ * Added support for serializing collection shapes
+ *
+ * Revision 1.19 2003/08/29 20:52:43 warmerda
+ * added to/from xml translation for GvShape
+ *
+ * Revision 1.18 2003/06/26 02:46:21 pgs
+ * added define for M_PI if it is not already defined
+ *
+ * Revision 1.17 2003/06/25 17:06:06 warmerda
+ * added gv_shape_rotate(), gv_shape_scale() and related stuff
+ *
+ * Revision 1.16 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.15 2002/05/07 02:51:15 warmerda
+ * preliminary support for GVSHAPE_COLLECTION
+ *
+ * Revision 1.14 2002/03/07 18:31:56 warmerda
+ * added preliminary gv_shape_clip_to_rect() implementation
+ *
+ * Revision 1.13 2001/12/08 04:49:38 warmerda
+ * added point in polygon test
+ *
+ * Revision 1.12 2001/08/08 17:45:48 warmerda
+ * GvShape now referenced counted
+ *
+ * Revision 1.11 2000/09/11 13:54:33 warmerda
+ * fixed some bugs computing area of line features
+ *
+ * Revision 1.10 2000/09/11 13:47:24 warmerda
+ * fixed bug in computing extents of area features
+ *
+ * Revision 1.9 2000/07/14 14:51:01 warmerda
+ * fixed insert, and delete node support
+ *
+ * Revision 1.8 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+#include <assert.h>
+#include <string.h>
+#include "gvshapes.h"
+#include "gvrenderinfo.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+static int gv_shape_count = 0;
+
+/************************************************************************/
+/* gv_shape_get_count() */
+/************************************************************************/
+
+int gv_shape_get_count()
+
+{
+ return gv_shape_count;
+}
+
+/************************************************************************/
+/* gv_shape_new() */
+/* */
+/* Note that the initial ref count of shapes returned by */
+/* gv_shape_new() is zero. If the caller wants to retain a */
+/* reference to the shape (other than just adding to a */
+/* GvShapes, or some other operation that increments the ref */
+/* count) it should call gv_shape_ref(). */
+/************************************************************************/
+
+GvShape *gv_shape_new( gint type )
+
+{
+ GvShape *shape;
+
+ gv_shape_count++;
+
+ if( type == GVSHAPE_POINT )
+ {
+ shape = (GvShape *) g_new0( GvPointShape, 1 );
+ }
+ else if( type == GVSHAPE_LINE )
+ {
+ shape = (GvShape *) g_new0( GvLineShape, 1 );
+ }
+ else if( type == GVSHAPE_AREA )
+ {
+ shape = (GvShape *) g_new0( GvAreaShape, 1 );
+ ((GvAreaShape *) shape)->fill_objects = -1;
+ }
+ else if( type == GVSHAPE_COLLECTION )
+ {
+ shape = (GvShape *) g_new0( GvCollectionShape, 1 );
+ }
+ else
+ {
+ g_warning( "Illegal shape type in gv_shape_new()" );
+ shape = NULL;
+ }
+
+ if( shape != NULL )
+ {
+ shape->flags = type | 0;
+ shape->ref_count = 0;
+ gv_properties_init( &(shape->properties) );
+ }
+
+ return shape;
+}
+
+/************************************************************************/
+/* gv_shape_ref() */
+/************************************************************************/
+
+void gv_shape_ref( GvShape *shape )
+
+{
+ shape->ref_count++;
+}
+
+/************************************************************************/
+/* gv_shape_unref() */
+/************************************************************************/
+
+void gv_shape_unref( GvShape *shape )
+
+{
+ if( --shape->ref_count <= 0 )
+ gv_shape_delete( shape );
+}
+
+/************************************************************************/
+/* gv_shape_get_ref() */
+/************************************************************************/
+
+int gv_shape_get_ref( GvShape *shape )
+
+{
+ return shape->ref_count;
+}
+
+/************************************************************************/
+/* gv_shape_delete() */
+/************************************************************************/
+void gv_shape_delete( GvShape *shape )
+
+{
+ gv_shape_count--;
+
+ gv_properties_destroy( gv_shape_get_properties( shape ) );
+
+ switch( gv_shape_type(shape) )
+ {
+ case GVSHAPE_AREA:
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+ int ring;
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ g_free( area->xyz_ring_nodes[ring] );
+ }
+ if( area->xyz_ring_nodes != NULL )
+ g_free( area->xyz_ring_nodes );
+ if( area->num_ring_nodes != NULL )
+ g_free( area->num_ring_nodes );
+
+ if( area->fill )
+ g_array_free( area->fill, TRUE );
+ if( area->mode_offset )
+ g_array_free( area->mode_offset, TRUE );
+ }
+ break;
+
+ case GVSHAPE_LINE:
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ if( line->xyz_nodes != NULL )
+ g_free( line->xyz_nodes );
+ }
+ break;
+
+ case GVSHAPE_COLLECTION:
+ {
+ GvCollectionShape *col = (GvCollectionShape *) shape;
+ int i;
+
+ for( i = 0; i < col->geom_count; i++ )
+ gv_shape_delete( col->geom_list[i] );
+
+ if( col->geom_list != NULL )
+ g_free( col->geom_list );
+ col->geom_list = NULL;
+ }
+ break;
+
+ case GVSHAPE_POINT:
+ default:
+ break;
+ }
+
+ g_free( shape );
+}
+
+/************************************************************************/
+/* gv_shape_copy() */
+/************************************************************************/
+GvShape *gv_shape_copy( GvShape *source )
+
+{
+ GvShape *target;
+
+ target = gv_shape_new( gv_shape_type(source) );
+
+ gv_properties_copy( &(source->properties), &(target->properties) );
+ target->flags = source->flags;
+
+ switch( gv_shape_type(source) )
+ {
+ case GVSHAPE_AREA:
+ {
+ GvAreaShape *tarea = (GvAreaShape *) target;
+ GvAreaShape *sarea = (GvAreaShape *) source;
+
+ tarea->num_rings = sarea->num_rings;
+ if( sarea->num_rings > 0 )
+ {
+ int ring;
+
+ tarea->num_ring_nodes = g_new(int,sarea->num_rings);
+ memcpy( tarea->num_ring_nodes, sarea->num_ring_nodes,
+ sizeof(int) * sarea->num_rings );
+
+ tarea->xyz_ring_nodes = g_new(gvgeocoord *,sarea->num_rings);
+ for( ring = 0; ring < sarea->num_rings; ring++ )
+ {
+ tarea->xyz_ring_nodes[ring] =
+ g_new(gvgeocoord,3*tarea->num_ring_nodes[ring]);
+ memcpy( tarea->xyz_ring_nodes[ring],
+ sarea->xyz_ring_nodes[ring],
+ sizeof(gvgeocoord) * 3 * tarea->num_ring_nodes[ring] );
+ }
+ }
+ }
+ break;
+
+ case GVSHAPE_LINE:
+ {
+ int num_nodes = ((GvLineShape *) source)->num_nodes;
+
+ ((GvLineShape *) target)->num_nodes = num_nodes;
+
+ ((GvLineShape *) target)->xyz_nodes = g_new(gvgeocoord, 3 * num_nodes);
+ memcpy( ((GvLineShape *) target)->xyz_nodes,
+ ((GvLineShape *) source)->xyz_nodes,
+ sizeof(gvgeocoord) * 3 * num_nodes );
+ }
+ break;
+
+ case GVSHAPE_POINT:
+ ((GvPointShape *) target)->x = ((GvPointShape *) source)->x;
+ ((GvPointShape *) target)->y = ((GvPointShape *) source)->y;
+ ((GvPointShape *) target)->z = ((GvPointShape *) source)->z;
+ break;
+
+ case GVSHAPE_COLLECTION:
+ {
+ GvCollectionShape *source_col = (GvCollectionShape *) source;
+ int i;
+
+ for( i = 0; i < source_col->geom_count; i++ )
+ gv_shape_collection_add_shape(
+ target, gv_shape_copy( source_col->geom_list[i] ) );
+ }
+ break;
+
+ default:
+ assert(FALSE);
+ }
+
+ return target;
+}
+
+/************************************************************************/
+/* gv_shape_get_rings() */
+/************************************************************************/
+gint gv_shape_get_rings( GvShape *shape )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_AREA )
+ return ((GvAreaShape *) shape)->num_rings;
+ else
+ return 1;
+}
+
+/************************************************************************/
+/* gv_shape_get_nodes() */
+/************************************************************************/
+gint gv_shape_get_nodes( GvShape *shape, int ring )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_AREA
+ && ring >= 0 && ring < ((GvAreaShape *) shape)->num_rings )
+ {
+ return ((GvAreaShape *) shape)->num_ring_nodes[ring];
+ }
+ else if( ring == 0 && gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ return ((GvLineShape *) shape)->num_nodes;
+ }
+ else if( ring == 0 && gv_shape_type(shape) == GVSHAPE_POINT )
+ return 1;
+ else
+ return 0;
+}
+
+/************************************************************************/
+/* gv_shape_get_xyz() */
+/************************************************************************/
+gvgeocoord gv_shape_get_xyz( GvShape *shape, gint ring, gint node, gint off )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+
+ if( ring >= 0 && ring < area->num_rings
+ && node >= 0 && node < area->num_ring_nodes[ring] )
+ return area->xyz_ring_nodes[ring][node*3+off];
+ else
+ return 0.0;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ if( ring == 0 && node >= 0 && node < line->num_nodes )
+ return line->xyz_nodes[node*3+off];
+ else
+ return 0.0;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_POINT )
+ {
+ GvPointShape *point = (GvPointShape *) shape;
+
+ if( ring != 0 || node != 0 )
+ return 0.0;
+ else if( off == 0 )
+ return point->x;
+ else if( off == 1 )
+ return point->y;
+ else if( off == 2 )
+ return point->z;
+ }
+
+ return 0.0;
+}
+
+/************************************************************************/
+/* gv_shape_set_xyz() */
+/************************************************************************/
+gint gv_shape_set_xyz( GvShape *shape, gint ring, gint node,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+
+ if( ring < 0 || node < 0 )
+ return FALSE;
+
+ /* do we need to grow the ring list? */
+ if( ring >= area->num_rings )
+ {
+ area->num_ring_nodes =
+ g_renew(int, area->num_ring_nodes, ring+1 );
+ memset( area->num_ring_nodes + area->num_rings, 0,
+ sizeof(int) * (ring + 1 - area->num_rings) );
+
+ area->xyz_ring_nodes =
+ g_renew(gvgeocoord *, area->xyz_ring_nodes, ring+1 );
+ memset( area->xyz_ring_nodes + area->num_rings, 0,
+ sizeof(gvgeocoord *) * (ring + 1 - area->num_rings) );
+ area->num_rings = ring+1;
+ }
+
+ /* do we need to grow the list of nodes? */
+ if( area->num_ring_nodes[ring] <= node )
+ {
+ area->xyz_ring_nodes[ring] =
+ g_renew(gvgeocoord, area->xyz_ring_nodes[ring], 3*(node+1) );
+ memset( area->xyz_ring_nodes[ring] + 3*area->num_ring_nodes[ring],
+ 0, sizeof(gvgeocoord)*3*(node+1-area->num_ring_nodes[ring]) );
+ area->num_ring_nodes[ring] = node+1;
+ }
+
+ area->xyz_ring_nodes[ring][node*3 ] = x;
+ area->xyz_ring_nodes[ring][node*3+1] = y;
+ area->xyz_ring_nodes[ring][node*3+2] = z;
+
+ area->fill_objects = -1;
+
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ if( ring != 0 || node < 0 )
+ return FALSE;
+
+ if( node >= line->num_nodes )
+ {
+ line->xyz_nodes = g_renew(gvgeocoord, line->xyz_nodes, 3*(node+1));
+
+ memset( line->xyz_nodes + line->num_nodes*3,
+ 0, (node + 1 - line->num_nodes) * 3 * sizeof(gvgeocoord) );
+
+ line->num_nodes = node+1;
+ }
+
+ line->xyz_nodes[node*3 ] = x;
+ line->xyz_nodes[node*3+1] = y;
+ line->xyz_nodes[node*3+2] = z;
+
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_POINT )
+ {
+ GvPointShape *point = (GvPointShape *) shape;
+
+ if( ring != 0 || node != 0 )
+ return FALSE;
+
+ point->x = x;
+ point->y = y;
+ point->z = z;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_shape_add_node() */
+/************************************************************************/
+gint gv_shape_add_node( GvShape *shape, gint ring, gvgeocoord x, gvgeocoord y, gvgeocoord z )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_POINT )
+ {
+ gv_shape_set_xyz( shape, ring, 0, x, y, z );
+ return 0;
+ }
+ else
+ {
+ int new_node = gv_shape_get_nodes( shape, ring );
+
+ gv_shape_set_xyz( shape, ring, new_node, x, y, z );
+
+ return new_node;
+ }
+}
+
+/************************************************************************/
+/* gv_shape_insert_node() */
+/************************************************************************/
+gint gv_shape_insert_node( GvShape *shape, gint ring, int node,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z )
+
+{
+ int i;
+
+ if( node > gv_shape_get_nodes( shape, ring ) )
+ return -1;
+
+ for( i = gv_shape_get_nodes(shape,ring)-1; i >= node; i-- )
+ {
+ gv_shape_set_xyz( shape, ring, i+1,
+ gv_shape_get_x( shape, ring, i ),
+ gv_shape_get_y( shape, ring, i ),
+ gv_shape_get_z( shape, ring, i ) );
+ }
+
+ gv_shape_set_xyz( shape, ring, node, x, y, z );
+
+ return node;
+}
+
+/************************************************************************/
+/* gv_shape_delete_ring() */
+/************************************************************************/
+gint gv_shape_delete_ring( GvShape *shape, gint ring )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_POINT && ring == 0 )
+ {
+ ((GvPointShape *) shape)->x = 0.0;
+ ((GvPointShape *) shape)->y = 0.0;
+ ((GvPointShape *) shape)->z = 0.0;
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_LINE && ring == 0 )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ line->num_nodes = 0;
+
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_AREA
+ && ring >= 0
+ && ring < gv_shape_get_rings(shape) )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+
+ g_free( area->xyz_ring_nodes[ring] );
+ memmove( area->xyz_ring_nodes + ring,
+ area->xyz_ring_nodes + ring + 1,
+ sizeof(void*) * (area->num_rings - ring - 1) );
+ memmove( area->num_ring_nodes + ring,
+ area->num_ring_nodes + ring + 1,
+ sizeof(int) * (area->num_rings - ring - 1) );
+ area->fill_objects = -1;
+ area->num_rings--;
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+/************************************************************************/
+/* gv_shape_delete_node() */
+/************************************************************************/
+gint gv_shape_delete_node( GvShape *shape, gint ring, gint node )
+
+{
+ if( gv_shape_type(shape) == GVSHAPE_POINT && ring == 0 && node == 0 )
+ {
+ ((GvPointShape *) shape)->x = 0.0;
+ ((GvPointShape *) shape)->y = 0.0;
+ ((GvPointShape *) shape)->z = 0.0;
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_LINE && ring == 0
+ && node >= 0 && node < gv_shape_get_nodes(shape,ring) )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ memmove( line->xyz_nodes + node*3,
+ line->xyz_nodes + (node+1)*3,
+ sizeof(gvgeocoord) * 3 * (line->num_nodes - node - 1) );
+ line->num_nodes--;
+ return TRUE;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_AREA
+ && ring < gv_shape_get_rings(shape)
+ && node < gv_shape_get_nodes(shape,ring) )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+
+ memmove( area->xyz_ring_nodes[ring] + node*3,
+ area->xyz_ring_nodes[ring] + (node+1)*3,
+ sizeof(gvgeocoord) * 3 * (area->num_ring_nodes[ring] - node - 1) );
+ area->num_ring_nodes[ring]--;
+ area->fill_objects = -1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_shape_get_extents() */
+/************************************************************************/
+void gv_shape_get_extents( GvShape *shape, GvRect *rect )
+
+{
+ rect->x = rect->y = rect->width = rect->height = 0.0;
+
+ if( gv_shape_type(shape) == GVSHAPE_POINT )
+ {
+ GvPointShape *point = (GvPointShape *) shape;
+
+ rect->x = point->x;
+ rect->y = point->y;
+ rect->width = 0.0;
+ rect->height = 0.0;
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+ int i;
+
+ if( line->num_nodes > 0 )
+ {
+ rect->x = line->xyz_nodes[0];
+ rect->y = line->xyz_nodes[1];
+ rect->width = 0.0;
+ rect->height = 0.0;
+ }
+
+ for( i = 1; i < line->num_nodes; i++ )
+ {
+ gvgeocoord x = line->xyz_nodes[i*3 ];
+ gvgeocoord y = line->xyz_nodes[i*3+1];
+
+ if( x < rect->x )
+ {
+ rect->width = rect->x + rect->width - x;
+ rect->x = x;
+ }
+ else if( x > rect->x + rect->width )
+ {
+ rect->width = x - rect->x;
+ }
+
+ if( y < rect->y )
+ {
+ rect->height = rect->y + rect->height - y;
+ rect->y = y;
+ }
+ else if( y > rect->y + rect->height )
+ {
+ rect->height = y - rect->y;
+ }
+ }
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+ int ring, node, first = TRUE;
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ for( node = 0; node < area->num_ring_nodes[ring]; node++ )
+ {
+ gvgeocoord x = area->xyz_ring_nodes[ring][node*3 ];
+ gvgeocoord y = area->xyz_ring_nodes[ring][node*3+1];
+
+ if( first )
+ {
+ rect->x = x;
+ rect->width = 0;
+ rect->y = y;
+ rect->height = 0;
+ first = FALSE;
+ }
+
+ if( x < rect->x )
+ {
+ rect->width = rect->x + rect->width - x;
+ rect->x = x;
+ }
+ else if( x > rect->x + rect->width )
+ {
+ rect->width = x - rect->x;
+ }
+
+ if( y < rect->y )
+ {
+ rect->height = rect->y + rect->height - y;
+ rect->y = y;
+ }
+ else if( y > rect->y + rect->height )
+ {
+ rect->height = y - rect->y;
+ }
+ }
+ }
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_COLLECTION )
+ {
+ GvCollectionShape *col = (GvCollectionShape *) shape;
+ int geom;
+
+ for( geom = 0; geom < col->geom_count; geom++ )
+ {
+ if( geom == 0 )
+ gv_shape_get_extents( col->geom_list[geom], rect );
+ else
+ {
+ GvRect this_rect;
+
+ gv_shape_get_extents( col->geom_list[geom], &this_rect );
+
+ if( this_rect.x < rect->x )
+ {
+ rect->width += (rect->x - this_rect.x);
+ rect->x = this_rect.x;
+ }
+ if( this_rect.y < rect->y )
+ {
+ rect->height += (rect->y - this_rect.y);
+ rect->y = this_rect.y;
+ }
+ if( this_rect.x + this_rect.width >
+ rect->x + rect->width )
+ {
+ rect->width = this_rect.x + this_rect.width - rect->x;
+ }
+ if( this_rect.y + this_rect.height >
+ rect->y + rect->height )
+ {
+ rect->height = this_rect.y + this_rect.height - rect->y;
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shape_point_in_polygon() */
+/* */
+/* Algorithm as presented by Darel R. Finley at */
+/* http://freeweb.pdq.net/smokin/polygon/ */
+/************************************************************************/
+
+gint gv_shape_point_in_polygon( GvShape *shape_poly, double x, double y )
+
+{
+ int ring;
+ int oddNODES = FALSE;
+ GvAreaShape *area = (GvAreaShape *) shape_poly;
+
+ if( gv_shape_type(shape_poly) != GVSHAPE_AREA )
+ return FALSE;
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ int edge;
+
+ for( edge = 0; edge < area->num_ring_nodes[ring]; edge++ )
+ {
+ int j;
+ gvgeocoord *pt1, *pt2;
+
+ if( edge == area->num_ring_nodes[ring]-1 )
+ j = 0;
+ else
+ j = edge + 1;
+
+ pt1 = area->xyz_ring_nodes[ring] + edge * 3;
+ pt2 = area->xyz_ring_nodes[ring] + j * 3;
+
+ if( (pt1[1] < y && pt2[1] >= y)
+ || (pt2[1] < y && pt1[1] >= y) )
+ {
+ if( pt1[0] + (y-pt1[1]) / (pt2[1]-pt1[1]) * (pt2[0]-pt1[0])
+ < x )
+ oddNODES = !oddNODES;
+ }
+ }
+ }
+
+ return oddNODES;
+}
+
+/************************************************************************/
+/* gv_shape_distance_from_polygon() */
+/* */
+/************************************************************************/
+gdouble gv_shape_distance_from_polygon( GvShape *shape_poly, double x, double y )
+
+{
+ int ring;
+ int vertical, horizontal;
+ GvAreaShape *area = (GvAreaShape *) shape_poly;
+ gvgeocoord *ptA, *ptB, ptD[2];
+ gdouble min_dist, dist, a,b,c;
+
+ if ( gv_shape_type(shape_poly) != GVSHAPE_AREA )
+ return -1.;
+
+ /*initialize min distance*/
+ ptA = area->xyz_ring_nodes[0];
+ min_dist = sqrt( pow((ptA[0]-x),2) + pow((ptA[1]-y),2));
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ int edge;
+
+ for( edge = 0; edge < area->num_ring_nodes[ring]; edge++ )
+ {
+ int j;
+
+ if( edge == area->num_ring_nodes[ring]-1 )
+ j = 0;
+ else
+ j = edge + 1;
+
+ ptA = area->xyz_ring_nodes[ring] + edge * 3;
+ ptB = area->xyz_ring_nodes[ring] + j * 3;
+
+ vertical = ( fabs(ptA[0] - ptB[0]) < 1.e-10 );
+ horizontal = ( fabs(ptA[1] - ptB[1]) < 1.e-10 );
+ if (vertical && horizontal)
+ {
+ dist = sqrt( pow((ptA[0]-x),2) + pow((ptA[1]-y),2));
+ if ( dist < min_dist )
+ min_dist = dist;
+ continue;
+ }
+ else if ( vertical )
+ {
+ ptD[0] = ptA[0];
+ ptD[1] = y;
+ }
+ else if ( horizontal )
+ {
+ ptD[0] = x;
+ ptD[1] = ptA[0];
+ }
+ else
+ {
+ /*Compute equation of line AB of the form y = ax + b */
+ a = (ptA[1] - ptB[1]) / ( ptA[0] - ptB[0] );
+ b = ptA[1] - a * ptA[0];
+
+ /*Given D the intersection of AB and the perpendicular to (AB) passing by C,
+ compute equation of (CD) of the form y = -a x + c */
+ c = y + x / a;
+
+ /*Location of D*/
+ ptD[1] = (a*a * c + b) / (1. + a*a);
+ ptD[0] = (ptD[1] - b)/ a;
+
+ }
+ /* Make sure D is within segment AB, if not compute distance from A or B, whichever is the closet */
+ if ( ptA[0] < ptB[0] )
+ {
+ if ( ptD[0] < ptA[0] )
+ {
+ ptD[0] = ptA[0];
+ ptD[1] = ptA[1];
+ }
+
+ else if ( ptD[0] > ptB[0] )
+ {
+ ptD[0] = ptB[0];
+ ptD[1] = ptB[1];
+ }
+ }
+ else if ( ptB[0] < ptA[0] )
+ {
+ if ( ptD[0] < ptB[0] )
+ {
+ ptD[0] = ptB[0];
+ ptD[1] = ptB[1];
+ }
+
+ else if ( ptD[0] > ptA[0] )
+ {
+ ptD[0] = ptA[0];
+ ptD[1] = ptA[1];
+ }
+ }
+ else if ( ptA[1] < ptB[1] )
+ {
+ if ( ptD[1] < ptA[1] )
+ {
+ ptD[0] = ptA[0];
+ ptD[1] = ptA[1];
+ }
+ else if ( ptD[1] > ptB[1] )
+ {
+ ptD[0] = ptB[0];
+ ptD[1] = ptB[1];
+ }
+ }
+ else if ( ptB[1] < ptA[1] )
+ {
+ if ( ptD[1] < ptB[1] )
+ {
+ ptD[0] = ptB[0];
+ ptD[1] = ptB[1];
+ }
+ else if ( ptD[1] > ptA[1] )
+ {
+ ptD[0] = ptA[0];
+ ptD[1] = ptA[1];
+ }
+ }
+
+
+
+ dist = sqrt( pow((ptD[0]-x),2) + pow((ptD[1]-y),2));
+ if ( dist < min_dist )
+ min_dist = dist;
+
+ }
+ }
+
+ return min_dist;
+}
+
+
+
+/************************************************************************/
+/* _gv_intersect() */
+/************************************************************************/
+
+static void _gv_intersect( double *x1, double *y1, double *x2, double *y2,
+ double cut_line, int greater_flag )
+
+{
+ double f;
+
+ if( !greater_flag && (*x1 < cut_line && *x2 < cut_line) )
+ return;
+ else if( greater_flag && (*x1 < cut_line && *x2 < cut_line) )
+ return;
+
+ if( !greater_flag )
+ {
+ *x1 = - *x1;
+ *x2 = - *x2;
+ cut_line = - cut_line;
+ }
+
+ if( *x1 < cut_line && *x2 >= cut_line )
+ {
+ f = (cut_line - *x1) / (*x2 - *x1);
+ *y1 = *y1 + (*y2 - *y1) * f;
+ *x1 = *x1 + (*x2 - *x1) * f;
+ }
+ else if( *x2 < cut_line && *x1 >= cut_line )
+ {
+ f = (cut_line - *x2) / (*x1 - *x2);
+ *y2 = *y2 + (*y1 - *y2) * f;
+ *x2 = *x2 + (*x1 - *x2) * f;
+ }
+
+ if( !greater_flag )
+ {
+ *x1 = - *x1;
+ *x2 = - *x2;
+ cut_line = - cut_line;
+ }
+}
+
+/************************************************************************/
+/* gv_line_intersect_rect() */
+/************************************************************************/
+
+int gv_line_intersect_rect( double *x1, double *y1,
+ double *x2, double *y2,
+ GvRect *rect )
+
+{
+ _gv_intersect( x1, y1, x2, y2, rect->x, TRUE );
+ _gv_intersect( x1, y1, x2, y2, rect->x + rect->width, FALSE );
+ _gv_intersect( y1, x1, y2, x2, rect->y, TRUE );
+ _gv_intersect( y1, x1, y2, x2, rect->y + rect->height, FALSE );
+
+ if( *x1 < rect->x || *x2 < rect->x
+ || *y1 < rect->y || *y2 < rect->y
+ || *x1 > rect->x + rect->width
+ || *x2 > rect->x + rect->width
+ || *y1 > rect->y + rect->height
+ || *y2 > rect->y + rect->height )
+ return 0;
+
+ return 1;
+}
+
+
+/************************************************************************/
+/* gv_shape_clip_to_rect() */
+/************************************************************************/
+
+GvShape *gv_shape_clip_to_rect( GvShape *shape, GvRect *rect )
+
+{
+ GvRect extents;
+ int ring, out_ring = 0;
+ GvShape *new_shape;
+
+/* -------------------------------------------------------------------- */
+/* Get shape extents, and check for trivial cases of complete */
+/* exclusion or inclusion. */
+/* -------------------------------------------------------------------- */
+ gv_shape_get_extents( shape, &extents );
+
+ if( extents.height < 0.0 )
+ {
+ extents.y = extents.y + extents.height;
+ extents.height = -extents.height;
+ }
+
+ if( extents.x > rect->x + rect->width
+ || extents.y > rect->y + rect->height
+ || extents.x + extents.width < rect->x
+ || extents.y + extents.height < rect->y )
+ return NULL;
+
+ if( extents.x >= rect->x
+ && extents.x + extents.width <= rect->x + rect->width
+ && extents.y >= rect->y
+ && extents.y + extents.height <= rect->y + rect->height )
+ return gv_shape_copy( shape );
+
+ if( gv_shape_type(shape) == GVSHAPE_POINT )
+ return gv_shape_copy( shape );
+
+/* -------------------------------------------------------------------- */
+/* Process line segment by line segment */
+/* -------------------------------------------------------------------- */
+ new_shape = gv_shape_new( gv_shape_type(shape) );
+ gv_properties_copy( &(shape->properties), &(new_shape->properties) );
+
+
+ for( ring = 0; ring < gv_shape_get_rings(shape); ring++ )
+ {
+ double last_x, last_y, last_z, x, y;
+ int node, last_inside, have_last_point;
+
+ last_x = x = gv_shape_get_x(shape, ring, 0);
+ last_y = y = gv_shape_get_y(shape, ring, 0);
+ last_z = gv_shape_get_z(shape, ring, 0);
+
+ if( x < rect->x || x > rect->x + rect->width
+ || y < rect->y || y > rect->y + rect->height )
+ last_inside = FALSE;
+ else
+ {
+ last_inside = TRUE;
+ gv_shape_add_node( new_shape, out_ring, last_x, last_y, last_z );
+ }
+
+ have_last_point = last_inside;
+
+ for( node = 1; node < gv_shape_get_nodes(shape,ring); node++ )
+ {
+ int this_inside, z;
+
+ x = gv_shape_get_x(shape, ring, node);
+ y = gv_shape_get_y(shape, ring, node);
+ z = gv_shape_get_z(shape,ring,node);
+
+ if( x < rect->x || x > rect->x + rect->width
+ || y < rect->y || y > rect->y + rect->height )
+ this_inside = FALSE;
+ else
+ this_inside = TRUE;
+
+ if( this_inside && last_inside )
+ {
+ last_x = x;
+ last_y = y;
+ last_z = z;
+
+ gv_shape_add_node( new_shape, out_ring, x, y, z );
+ }
+ else if( last_inside && !this_inside )
+ {
+ gv_line_intersect_rect( &last_x, &last_y, &x, &y, rect );
+ last_x = x;
+ last_y = y;
+ last_z = z;
+
+ gv_shape_add_node( new_shape, out_ring, x, y, z );
+ }
+ else if( !last_inside )
+ {
+ double x_i, y_i;
+
+ x_i = gv_shape_get_x(shape,ring,node-1);
+ y_i = gv_shape_get_y(shape,ring,node-1);
+
+ if( !gv_line_intersect_rect( &x_i, &y_i, &x, &y, rect ) )
+ {
+ last_inside = FALSE;
+ continue;
+ }
+
+ if( have_last_point && (x_i != last_x && y_i != last_y) )
+ {
+ if( (x_i == rect->x && last_x == rect->x + rect->width)
+ || (x_i == rect->x + rect->width
+ && last_x == rect->x) )
+ {
+ gv_shape_add_node( new_shape, out_ring,
+ last_x, rect->y, z );
+ gv_shape_add_node( new_shape, out_ring,
+ x_i, rect->y, z );
+ }
+ else if( (y_i == rect->y
+ && last_y == rect->y + rect->height)
+ || (y_i == rect->y + rect->height
+ && last_y == rect->y) )
+ {
+ gv_shape_add_node( new_shape, out_ring,
+ rect->x, last_y, z );
+ gv_shape_add_node( new_shape, out_ring,
+ rect->x, y_i, z );
+ }
+ else if( x_i == rect->x || x_i == rect->x + rect->width )
+ gv_shape_add_node( new_shape, out_ring,
+ x_i, last_y, z );
+ else
+ gv_shape_add_node( new_shape, out_ring,
+ last_x, y_i, z );
+ }
+
+ gv_shape_add_node( new_shape, out_ring, x_i, y_i, z );
+ gv_shape_add_node( new_shape, out_ring, x, y, z );
+
+ last_x = x;
+ last_y = y;
+ }
+
+ last_inside = this_inside;
+ }
+
+ if( gv_shape_get_nodes(new_shape,out_ring) > 0 )
+ out_ring++;
+ }
+
+ return new_shape;
+}
+
+/************************************************************************/
+/* gv_shape_collection_add_shape() */
+/* */
+/* Add a shape to a collection. The passed shape is added */
+/* directly (not copied), but the reference count is incremented. */
+/************************************************************************/
+
+void gv_shape_collection_add_shape( GvShape *col_shape, GvShape *shape )
+
+{
+ GvCollectionShape *collection = (GvCollectionShape *) col_shape;
+
+ if( gv_shape_type(col_shape) != GVSHAPE_COLLECTION )
+ return;
+
+ collection->geom_list = (GvShape **)
+ g_renew(GvShape*, collection->geom_list, collection->geom_count+1);
+
+ collection->geom_list[collection->geom_count] = shape;
+ gv_shape_ref( shape );
+
+ collection->geom_count++;
+}
+
+/************************************************************************/
+/* gv_shape_collection_get_count() */
+/************************************************************************/
+
+int gv_shape_collection_get_count( GvShape *col_shape )
+
+{
+ GvCollectionShape *collection = (GvCollectionShape *) col_shape;
+
+ if( gv_shape_type(col_shape) != GVSHAPE_COLLECTION )
+ return 0;
+ else
+ return collection->geom_count;
+}
+
+/************************************************************************/
+/* gv_shape_collection_get_shape() */
+/************************************************************************/
+
+GvShape *gv_shape_collection_get_shape( GvShape *col_shape, int shp_index )
+
+{
+ GvCollectionShape *collection = (GvCollectionShape *) col_shape;
+
+ if( gv_shape_type(col_shape) != GVSHAPE_COLLECTION )
+ return NULL;
+
+ else if( shp_index < 0 || shp_index >= collection->geom_count )
+ return NULL;
+
+ else
+ return collection->geom_list[shp_index];
+}
+
+/************************************************************************/
+/* gv_shape_get_center() */
+/************************************************************************/
+
+gint gv_shape_get_center( GvShape *shape, GvVertex3d *xyz )
+
+{
+ GvRect extent;
+
+ gv_shape_get_extents( shape, &extent );
+ xyz->x = extent.x + extent.width * 0.5;
+ xyz->y = extent.y + extent.height * 0.5;
+ xyz->z = 0.0;
+
+ return 1;
+}
+
+/************************************************************************/
+/* gv_shape_update_attribute() */
+/************************************************************************/
+
+gint gv_shape_update_attribute( GvShape *shape,
+ const char *tool,
+ const char *attribute,
+ const char *update_value )
+
+{
+ const char *original_ogrfs;
+ int ret = 0, tool_index, tool_count;
+ char **tool_list;
+
+/* -------------------------------------------------------------------- */
+/* Get the ogrfs to operate on and split it. */
+/* -------------------------------------------------------------------- */
+ original_ogrfs =
+ gv_properties_get( gv_shape_get_properties(shape), "_gv_ogrfs" );
+ if( original_ogrfs == NULL )
+ return 0;
+
+ tool_list = gv_ogrfs_split_tools( original_ogrfs );
+
+/* -------------------------------------------------------------------- */
+/* Loop over tools changing them. */
+/* -------------------------------------------------------------------- */
+ tool_count = CSLCount( tool_list );
+ for( tool_index = 0; tool_index < tool_count; tool_index++ )
+ {
+ const char *id;
+ char *remaining, *value, *next_remaining;
+ int value_len;
+ char *new_tool_string = NULL;
+
+ if( tool != NULL && !EQUALN(tool_list[tool_index],tool,strlen(tool)) )
+ continue;
+
+ /* Loop over args */
+
+ remaining = tool_list[tool_index];
+ while( (id = gv_ogrfs_get_arg( remaining, &next_remaining, &value,
+ &value_len )) != NULL )
+ {
+ if( EQUALN(id,attribute,strlen(attribute)) )
+ {
+ char *replacement_value = NULL;
+ int value_offset = value - tool_list[tool_index];
+
+ if( EQUAL(attribute,"a") )
+ {
+ char new_value[100];
+
+ sprintf( new_value, "%.3g", atof(update_value)+atof(value) );
+ replacement_value = CPLStrdup( new_value );
+ }
+ else if( EQUAL(attribute,"s") )
+ {
+ char new_value[100];
+
+ sprintf( new_value, "%.8g", atof(update_value)*atof(value) );
+ replacement_value = CPLStrdup( new_value );
+ }
+ else
+ replacement_value = CPLStrdup( update_value );
+
+ new_tool_string = (char *)
+ CPLCalloc(1,strlen(tool_list[tool_index])+strlen(replacement_value)+1);
+ strcpy( new_tool_string, tool_list[tool_index] );
+ strcpy( new_tool_string+value_offset, replacement_value );
+ strcat( new_tool_string, value + value_len );
+ break;
+ }
+ remaining = next_remaining;
+ }
+
+ /* We got to the end of the args without the attribute, add it now. */
+ if( id == NULL )
+ {
+ new_tool_string = (char *)
+ CPLCalloc(1,strlen(tool_list[tool_index])+strlen(update_value) + strlen(attribute) + 10);
+ strcpy( new_tool_string, tool_list[tool_index] );
+ sprintf( new_tool_string + strlen(new_tool_string) - 1,
+ ",%s:%s)", attribute, update_value );
+ ret = 1;
+ }
+
+ CPLFree( tool_list[tool_index] );
+ tool_list[tool_index] = new_tool_string;
+ ret = 1;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we got a replacement, update the _gv_ogrfs attribute. */
+/* -------------------------------------------------------------------- */
+ if( ret )
+ {
+ int sum_tool_len = 1;
+ char *new_ogrfs;
+
+ for( tool_index = 0; tool_index < tool_count; tool_index++ )
+ sum_tool_len += strlen(tool_list[tool_index]) + 1;
+
+ new_ogrfs = (char *) CPLMalloc(sum_tool_len);
+
+ for( tool_index = 0; tool_index < tool_count; tool_index++ )
+ {
+ if( tool_index == 0 )
+ strcpy( new_ogrfs, tool_list[tool_index] );
+ else
+ {
+ strcat( new_ogrfs, ";" );
+ strcat( new_ogrfs, tool_list[tool_index] );
+ }
+ }
+
+ gv_properties_set( gv_shape_get_properties(shape), "_gv_ogrfs",
+ new_ogrfs );
+ CPLFree( new_ogrfs );
+ }
+
+ CSLDestroy( tool_list );
+
+ return ret;
+}
+
+/************************************************************************/
+/* gv_shape_rotate() */
+/************************************************************************/
+
+gint gv_shape_rotate( GvShape *shape, double angle_in_degrees )
+
+{
+ if( gv_shape_type( shape ) == GVSHAPE_POINT )
+ {
+ char angle_as_string[60];
+
+ /* ogrfs angles are counter clockwise, angle_in_degrees is clockwise*/
+ sprintf( angle_as_string, "%.3g", - angle_in_degrees );
+ return gv_shape_update_attribute( shape, "SYMBOL", "a", angle_as_string);
+ }
+ else
+ {
+ GvVertex3d pivot;
+ int ring_count, ring;
+
+ if( !gv_shape_get_center( shape, &pivot ) )
+ return 0;
+
+ ring_count = gv_shape_get_rings( shape );
+ for( ring = 0; ring < ring_count; ring++ )
+ {
+ int node_count, node;
+
+ node_count = gv_shape_get_nodes( shape, ring );
+ for( node = 0; node < node_count; node++ )
+ {
+ double new_x, new_y, rad_rot, dx, dy;
+
+ rad_rot = (angle_in_degrees / 180.0) * M_PI;
+
+ dx = gv_shape_get_x(shape,ring,node) - pivot.x;
+ dy = gv_shape_get_y(shape,ring,node) - pivot.y;
+
+ new_x = pivot.x + dx * cos(rad_rot) + dy * sin(rad_rot);
+ new_y = pivot.y - dx * sin(rad_rot) + dy * cos(rad_rot);
+
+ gv_shape_set_xyz( shape, ring, node,
+ new_x, new_y,
+ gv_shape_get_z( shape, ring, node ) );
+ }
+ }
+ }
+
+ return 0;
+}
+
+/************************************************************************/
+/* gv_shape_scale() */
+/************************************************************************/
+
+gint gv_shape_scale( GvShape *shape, double new_scale )
+
+{
+ if( gv_shape_type( shape ) == GVSHAPE_POINT )
+ {
+ char scale_as_string[60];
+
+ sprintf( scale_as_string, "%.3g", new_scale );
+ return gv_shape_update_attribute( shape, "SYMBOL", "s", scale_as_string);
+ }
+ else
+ {
+ GvVertex3d pivot;
+ int ring_count, ring;
+
+ if( !gv_shape_get_center( shape, &pivot ) )
+ return 0;
+
+ ring_count = gv_shape_get_rings( shape );
+ for( ring = 0; ring < ring_count; ring++ )
+ {
+ int node_count, node;
+
+ node_count = gv_shape_get_nodes( shape, ring );
+ for( node = 0; node < node_count; node++ )
+ {
+ double new_x, new_y;
+
+ new_x = (gv_shape_get_x(shape,ring,node) - pivot.x) * new_scale
+ + pivot.x;
+ new_y = (gv_shape_get_y(shape,ring,node) - pivot.y) * new_scale
+ + pivot.y;
+
+ gv_shape_set_xyz( shape, ring, node,
+ new_x, new_y,
+ gv_shape_get_z( shape, ring, node ) );
+ }
+ }
+ }
+
+ return 0;
+}
+
+/************************************************************************/
+/* gv_shape_add_ring_from_xml() */
+/* */
+/* This is just intended for local use to avoid */
+/* gv_shape_from_xml_tree() from being too complex. */
+/************************************************************************/
+
+static void gv_shape_add_ring_from_xml( GvShape *psShape, CPLXMLNode *psNode )
+
+{
+ int ring = gv_shape_get_rings( psShape );
+
+ if( psNode == NULL || !EQUAL(psNode->pszValue,"ring") || psNode->psChild == NULL )
+ return;
+
+ if( gv_shape_type(psShape) != GVSHAPE_AREA )
+ ring = 0;
+
+/* -------------------------------------------------------------------- */
+/* The "new" case is that the contents of the ring element are */
+/* one text value with a coordinate list in a similar format to */
+/* what GML does. */
+/* -------------------------------------------------------------------- */
+ if( psNode->psChild->psNext == NULL
+ && psNode->psChild->eType == CXT_Text )
+ {
+ char **triplets, **coords;
+ const char *value;
+ int node;
+
+ value = psNode->psChild->pszValue;
+ triplets = CSLTokenizeStringComplex( value, " \t\r\n",
+ FALSE, FALSE );
+ node = 0;
+ while ( triplets[node] )
+ {
+ coords = CSLTokenizeStringComplex( triplets[node], ",",
+ FALSE, FALSE );
+ if( CSLCount(coords) == 3 )
+ {
+ gv_shape_add_node( psShape, ring, atof(coords[0]),
+ atof(coords[1]), atof(coords[2]) );
+ }
+ else if ( CSLCount(coords) == 2 )
+ {
+ gv_shape_add_node( psShape, ring, atof(coords[0]),
+ atof(coords[1]), 0.0 );
+ }
+ node++;
+
+ if( coords )
+ CSLDestroy( coords );
+ }
+
+ if( triplets )
+ CSLDestroy( triplets );
+ }
+/* -------------------------------------------------------------------- */
+/* The "old" case is having each node as a subelement, and each */
+/* x, y, z ordinate as a subelement. */
+/* -------------------------------------------------------------------- */
+ else
+ {
+ for( psNode = psNode->psChild; psNode != NULL; psNode = psNode->psNext)
+ {
+ if( EQUAL(psNode->pszValue,"node") )
+ {
+ double x, y, z;
+
+ x = atof(CPLGetXMLValue(psNode,"x", "0.0"));
+ y = atof(CPLGetXMLValue(psNode,"y", "0.0"));
+ z = atof(CPLGetXMLValue(psNode,"z", "0.0"));
+
+ gv_shape_add_node( psShape, ring, x, y, z );
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shape_property_from_xml() */
+/************************************************************************/
+
+static void gv_shape_property_from_xml( GvShape *psShape,
+ CPLXMLNode *psProperty )
+
+{
+ const char *pszName, *pszValue;
+
+ pszName = CPLGetXMLValue( psProperty, "name", "" );
+ pszValue = CPLGetXMLValue( psProperty, "value", NULL );
+
+ if( pszValue == NULL && psProperty->psChild != NULL
+ && psProperty->psChild->psNext != NULL
+ && psProperty->psChild->psNext->eType == CXT_Text )
+ pszValue = psProperty->psChild->psNext->pszValue;
+
+ if( strlen(pszName) > 0 && pszValue != NULL )
+ {
+ gv_properties_set( &(psShape->properties),
+ pszName, pszValue );
+ }
+}
+
+/************************************************************************/
+/* gv_shape_from_xml_tree() */
+/* */
+/* Convert an XML tree representation of a GvShape into an */
+/* instance. */
+/************************************************************************/
+
+GvShape *gv_shape_from_xml_tree( CPLXMLNode *psTree )
+
+{
+ int nGType;
+ GvShape *psShape;
+ static const char *pszError = "Invalid GvShape XML tree in gv_shape_from_xml_tree()";
+
+ if( psTree == NULL || psTree->eType != CXT_Element
+ || !EQUAL(psTree->pszValue,"GvShape") )
+ {
+ CPLError( CE_Failure, CPLE_AppDefined, pszError );
+ return NULL;
+ }
+
+ nGType = atoi(CPLGetXMLValue( psTree, "type", "-1" ));
+ if( nGType == -1 )
+ {
+ CPLError( CE_Failure, CPLE_AppDefined, pszError );
+ return NULL;
+ }
+
+ psShape = gv_shape_new( nGType );
+ if( psShape == NULL )
+ return NULL;
+
+ for( psTree = psTree->psChild; psTree != NULL; psTree = psTree->psNext )
+ {
+ if( EQUAL(psTree->pszValue,"rings") )
+ {
+ CPLXMLNode *psRing;
+
+ for( psRing = psTree->psChild; psRing != NULL;
+ psRing = psRing->psNext )
+ {
+ if( EQUAL(psRing->pszValue,"ring") )
+ {
+ gv_shape_add_ring_from_xml( psShape, psRing );
+ }
+ }
+ }
+ else if( EQUAL(psTree->pszValue,"Properties") )
+ {
+ CPLXMLNode *psProperty;
+
+ for( psProperty = psTree->psChild; psProperty != NULL;
+ psProperty = psProperty->psNext )
+ {
+ gv_shape_property_from_xml( psShape, psProperty );
+ }
+ }
+ /* The old format has properties directly below the GvShape */
+ else if( EQUAL(psTree->pszValue,"Property") )
+ {
+ gv_shape_property_from_xml( psShape, psTree );
+ }
+ else if( EQUAL(psTree->pszValue,"SubShapes") )
+ {
+ CPLXMLNode *psChild;
+
+ for( psChild = psTree->psChild; psChild != NULL;
+ psChild = psChild->psNext )
+ {
+ GvShape *psSubshape = gv_shape_from_xml_tree( psChild );
+ if( psSubshape != NULL )
+ gv_shape_collection_add_shape( psShape, psSubshape );
+ }
+ }
+ }
+
+ return psShape;
+}
+
+/************************************************************************/
+/* gv_shape_to_xml_tree() */
+/************************************************************************/
+
+CPLXMLNode *gv_shape_to_xml_tree( GvShape *psShape )
+
+{
+ CPLXMLNode *psRoot;
+ int iRing, nRingCount, nPropertyCount;
+ char szText[100];
+ GvProperties *psProps;
+
+ psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GvShape" );
+
+ sprintf( szText, "%d", gv_shape_type(psShape) );
+ CPLCreateXMLNode(
+ CPLCreateXMLNode( psRoot, CXT_Attribute, "type" ),
+ CXT_Text, szText );
+
+/* -------------------------------------------------------------------- */
+/* Translate "rings" into coordinate lists. */
+/* -------------------------------------------------------------------- */
+ if( gv_shape_get_rings( psShape ) > 0
+ && gv_shape_get_nodes( psShape, 0 ) > 0 )
+ {
+ CPLXMLNode *psRings = CPLCreateXMLNode( psRoot, CXT_Element, "rings");
+
+ nRingCount = gv_shape_get_rings( psShape );
+ for( iRing = 0; iRing < nRingCount; iRing++ )
+ {
+ char *pszCoordList;
+ int nMaxLen, nUsed = 0, iNode;
+ int nNodeCount = gv_shape_get_nodes( psShape, iRing );
+
+ nMaxLen = nNodeCount * 60;
+ pszCoordList = (char *) CPLMalloc(nMaxLen);
+
+ for( iNode = 0; iNode < nNodeCount; iNode++ )
+ {
+ double x, y, z;
+
+ if( iNode > 0 )
+ pszCoordList[nUsed++] = ' ';
+
+ x = gv_shape_get_x( psShape, iRing, iNode );
+ y = gv_shape_get_y( psShape, iRing, iNode );
+ z = gv_shape_get_z( psShape, iRing, iNode );
+
+ if( x == (int) x && y == (int) y && z == (int) z )
+ sprintf( pszCoordList+nUsed, "%d,%d,%d",
+ (int) x, (int) y, (int) z );
+ else if( fabs(x) < 370 && fabs(y) < 370 )
+ sprintf( pszCoordList+nUsed, "%.16g,%.16g,%.16g",
+ x, y, z );
+ else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0
+ || fabs(z) > 100000000.0 )
+ sprintf( pszCoordList+nUsed, "%.16g,%.16g,%.16g",
+ x, y, z );
+ else
+ sprintf( pszCoordList+nUsed, "%.3f,%.3f,%.3f", x, y, z );
+ nUsed += strlen(pszCoordList+nUsed);
+ }
+
+ CPLCreateXMLElementAndValue( psRings, "ring", pszCoordList );
+ CPLFree( pszCoordList );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Translate properties. */
+/* -------------------------------------------------------------------- */
+ psProps = gv_shape_get_properties(psShape);
+ nPropertyCount = gv_properties_count( psProps );
+
+ if( nPropertyCount > 0 )
+ {
+ int iProperty;
+ CPLXMLNode *psPRoot = CPLCreateXMLNode( psRoot, CXT_Element,
+ "Properties" );
+
+ for( iProperty = 0; iProperty < nPropertyCount; iProperty++ )
+ {
+ CPLXMLNode *psProperty;
+
+ psProperty = CPLCreateXMLNode( psPRoot, CXT_Element, "Property" );
+
+ CPLCreateXMLNode(
+ CPLCreateXMLNode( psProperty, CXT_Attribute, "name" ),
+ CXT_Text, gv_properties_get_name_by_index(psProps,iProperty) );
+ CPLCreateXMLNode( psProperty, CXT_Text,
+ gv_properties_get_value_by_index(psProps,iProperty) );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Translate sub-shapes. */
+/* -------------------------------------------------------------------- */
+ if( gv_shape_collection_get_count( psShape ) > 0 )
+ {
+ CPLXMLNode *psSubShapes = CPLCreateXMLNode( psRoot, CXT_Element,
+ "SubShapes");
+ int iShape, nShapeCount;
+
+ nShapeCount = gv_shape_collection_get_count( psShape );
+ for( iShape = 0; iShape < nShapeCount; iShape++ )
+ {
+ CPLAddXMLChild(
+ psSubShapes,
+ gv_shape_to_xml_tree(
+ gv_shape_collection_get_shape( psShape, iShape ) ) );
+ }
+ }
+
+ return psRoot;
+}
Added: packages/openev/branches/upstream/current/gvshapefile.c
===================================================================
--- packages/openev/branches/upstream/current/gvshapefile.c (rev 0)
+++ packages/openev/branches/upstream/current/gvshapefile.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,704 @@
+/******************************************************************************
+ * $Id: gvshapefile.c,v 1.21 2003/05/27 21:32:40 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Read/write link to ESRI Shapefiles from GvShapes.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapefile.c,v $
+ * Revision 1.21 2003/05/27 21:32:40 warmerda
+ * added support for reading multi-part arcs as a collection of lines
+ *
+ * Revision 1.20 2002/09/30 20:16:54 warmerda
+ * ensure area rings are forced closed on save
+ *
+ * Revision 1.19 2002/09/12 15:20:39 warmerda
+ * use DBFIsAttributeNULL() call
+ *
+ * Revision 1.18 2002/08/19 17:12:48 pgs
+ * don't set property if source value is NULL, and when writing out a dbf file
+ * make sure to write null values.
+ *
+ * Revision 1.17 2002/08/07 17:12:42 pgs
+ * added missing include for CPLDebug
+ *
+ * Revision 1.16 2002/08/02 20:53:20 warmerda
+ * dont produce g_warning() if dbf file missing
+ *
+ * Revision 1.15 2002/07/24 20:32:30 warmerda
+ * minor performance improvements
+ *
+ * Revision 1.14 2002/07/18 19:33:57 pgs
+ * added gv_shapes_to_dbf
+ *
+ * Revision 1.13 2002/07/15 18:42:10 pgs
+ * added _filename to gv_shapes that come from shape files or ogr
+ *
+ * Revision 1.12 2001/08/08 17:43:33 warmerda
+ * avoid leak of SHPObjects when reading
+ *
+ * Revision 1.11 2001/03/29 15:00:18 warmerda
+ * find first _non-NULL_ shape when saving as template
+ *
+ * Revision 1.10 2001/03/19 21:40:12 pgs
+ * use binary mode for dbfopen dummy
+ *
+ * Revision 1.9 2000/10/29 18:17:06 warmerda
+ * add dummy field when saving shapefiles with no fields
+ *
+ * Revision 1.8 2000/08/25 20:08:18 warmerda
+ * added better checking for empty shape layers
+ *
+ * Revision 1.7 2000/08/08 17:17:39 warmerda
+ * fixed return value on save
+ *
+ * Revision 1.6 2000/08/04 14:17:28 warmerda
+ * GvShapes shape ids now persistent
+ *
+ * Revision 1.5 2000/06/12 20:16:02 warmerda
+ * added shapefile write support
+ *
+ */
+
+#include "shapefil.h"
+#include "gvshapes.h"
+#include <stdlib.h>
+#include "cpl_conv.h"
+
+/************************************************************************/
+/* gv_shapes_from_shapefile() */
+/************************************************************************/
+
+GvData *gv_shapes_from_shapefile(const char *filename)
+
+{
+ SHPHandle shp_handle;
+ DBFHandle dbf_handle;
+ int shape_count, shape_index, field_count = 0, field_index;
+ int field_type;
+ GvShapes *shapes_data;
+ GvProperties *properties;
+ char **field_names = NULL;
+
+
+/* -------------------------------------------------------------------- */
+/* Open the .shp and .dbf file. */
+/* -------------------------------------------------------------------- */
+ shp_handle = SHPOpen( filename, "rb" );
+ dbf_handle = DBFOpen( filename, "rb" );
+ if( dbf_handle == NULL && shp_handle == NULL )
+ {
+ g_warning( "Invalid shapefile and DBF." );
+ return NULL;
+ }
+ else if( dbf_handle == NULL )
+ g_warning( "Unable to open DBF file ... continuing anyways." );
+ else
+ field_count = DBFGetFieldCount( dbf_handle );
+
+
+ if ( shp_handle != NULL )
+ SHPGetInfo( shp_handle, &shape_count, NULL, NULL, NULL );
+ else
+ {
+ CPLDebug( "OpenEV", "Unable to open shapefile, just using .dbf file.");
+ shape_count = DBFGetRecordCount( dbf_handle );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create shapes layer, and assign some metadata about the */
+/* field definitions. */
+/* -------------------------------------------------------------------- */
+ shapes_data = GV_SHAPES(gv_shapes_new());
+ properties = gv_data_get_properties( GV_DATA(shapes_data) );
+
+ //set the filename property
+ gv_properties_set( properties, "_filename", filename );
+
+ field_names = (char **) g_new( char *, field_count+1 );
+
+ for(field_index = 0; field_index < field_count; field_index++ )
+ {
+ char prop_value[64], prop_name[64];
+ int field_type, width, precision;
+
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ prop_value, &width, &precision );
+
+ sprintf( prop_name, "_field_name_%d", field_index+1 );
+ gv_properties_set( properties, prop_name, prop_value );
+
+ field_names[field_index] = g_strdup( prop_value );
+
+ sprintf( prop_name, "_field_width_%d", field_index+1 );
+ sprintf( prop_value, "%d", width );
+ gv_properties_set( properties, prop_name, prop_value );
+
+ if( field_type == FTDouble )
+ {
+ sprintf( prop_name, "_field_precision_%d", field_index+1 );
+ sprintf( prop_value, "%d", precision );
+ gv_properties_set( properties, prop_name, prop_value );
+ }
+
+ sprintf( prop_name, "_field_type_%d", field_index+1 );
+ if( field_type == FTInteger )
+ gv_properties_set( properties, prop_name, "integer" );
+ else if( field_type == FTDouble )
+ gv_properties_set( properties, prop_name, "float" );
+ else
+ gv_properties_set( properties, prop_name, "string" );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Copy all the shapes, and their attributes. */
+/* -------------------------------------------------------------------- */
+
+ for( shape_index = 0; shape_index < shape_count; shape_index++ )
+ {
+ SHPObject *src_shape;
+ GvShape *gv_shape = NULL;
+
+ if ( shp_handle != NULL )
+ {
+ src_shape = SHPReadObject( shp_handle, shape_index );
+ if( src_shape == NULL )
+ continue;
+
+ if( src_shape->nSHPType == SHPT_POINT
+ || src_shape->nSHPType == SHPT_POINTM
+ || src_shape->nSHPType == SHPT_POINTZ )
+ {
+ gv_shape = gv_shape_new( GVSHAPE_POINT );
+ gv_shape_set_xyz( gv_shape, 0, 0,
+ src_shape->padfX[0],
+ src_shape->padfY[0],
+ src_shape->padfZ[0] );
+ }
+
+ else if( src_shape->nSHPType == SHPT_ARC
+ || src_shape->nSHPType == SHPT_ARCM
+ || src_shape->nSHPType == SHPT_ARCZ )
+ {
+ int node;
+
+ if( src_shape->nParts == 1 )
+ {
+ gv_shape = gv_shape_new( GVSHAPE_LINE );
+ for( node = src_shape->nVertices-1; node >= 0; node-- )
+ gv_shape_set_xyz( gv_shape, 0, node,
+ src_shape->padfX[node],
+ src_shape->padfY[node],
+ src_shape->padfZ[node] );
+ }
+ else
+ {
+ int part;
+
+ gv_shape = gv_shape_new( GVSHAPE_COLLECTION );
+
+ for( part = 0; part < src_shape->nParts; part++ )
+ {
+ GvShape *line;
+ int node, node_count, start;
+
+ start = src_shape->panPartStart[part];
+
+ if( part == src_shape->nParts-1 )
+ node_count = src_shape->nVertices - start;
+ else
+ node_count = src_shape->panPartStart[part+1] - start;
+
+ line = gv_shape_new( GVSHAPE_LINE );
+
+ for( node = node_count - 1; node >= 0; node-- )
+ gv_shape_set_xyz( line, 0, node,
+ src_shape->padfX[node+start],
+ src_shape->padfY[node+start],
+ src_shape->padfZ[node+start] );
+
+ gv_shape_collection_add_shape( gv_shape, line );
+ }
+ }
+ }
+
+ else if( src_shape->nSHPType == SHPT_POLYGON
+ || src_shape->nSHPType == SHPT_POLYGONM
+ || src_shape->nSHPType == SHPT_POLYGONZ )
+ {
+ int part;
+
+ gv_shape = gv_shape_new( GVSHAPE_AREA );
+ for( part = 0; part < src_shape->nParts; part++ )
+ {
+ int node, node_count, start;
+
+ start = src_shape->panPartStart[part];
+
+ if( part == src_shape->nParts-1 )
+ node_count = src_shape->nVertices - start;
+ else
+ node_count = src_shape->panPartStart[part+1] - start;
+
+ for( node = node_count - 1; node >= 0; node-- )
+ gv_shape_set_xyz( gv_shape, part, node,
+ src_shape->padfX[node+start],
+ src_shape->padfY[node+start],
+ src_shape->padfZ[node+start] );
+ }
+ }
+
+ SHPDestroyObject( src_shape );
+ }
+ else
+ gv_shape = gv_shape_new( GVSHAPE_COLLECTION );
+
+ /* add other types later */
+
+ if( gv_shape != NULL && dbf_handle != NULL )
+ {
+ properties = gv_shape_get_properties( gv_shape );
+
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ const char *field_value;
+
+ if( DBFIsAttributeNULL(dbf_handle,shape_index,field_index) )
+ continue;
+
+ field_value = DBFReadStringAttribute( dbf_handle, shape_index,
+ field_index );
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ NULL, NULL, NULL);
+
+ gv_properties_set( properties,
+ field_names[field_index],
+ field_value );
+ }
+ }
+
+ if( gv_shape != NULL )
+ gv_shapes_add_shape( shapes_data, gv_shape );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+ if( dbf_handle != NULL )
+ DBFClose( dbf_handle );
+ if( shp_handle != NULL )
+ SHPClose( shp_handle );
+
+ for( field_index = 0; field_index < field_count; field_index++ )
+ g_free( field_names[field_index] );
+ g_free( field_names );
+
+ gv_data_set_name( GV_DATA(shapes_data), filename );
+
+ return GV_DATA(shapes_data);
+}
+
+/************************************************************************/
+/* gv_shapes_to_shapefile() */
+/************************************************************************/
+
+int gv_shapes_to_shapefile(const char *filename, GvData *shapes_data,
+ int shp_type )
+
+{
+ GvShapes *shapes = GV_SHAPES(shapes_data);
+ GvShape *shape;
+ DBFHandle dbf_handle;
+ SHPHandle shp_handle;
+ int field_index, field_count=0, shape_count, shape_index;
+ GvProperties *properties;
+ int max_vertices = 0, fid = -1;
+ double *x=NULL, *y=NULL, *z=NULL;
+
+/* -------------------------------------------------------------------- */
+/* What sort of shapefile should we write? */
+/* -------------------------------------------------------------------- */
+ if( shp_type == SHPT_NULL )
+ {
+ int i = 0;
+
+ shape = NULL;
+ while( i < gv_shapes_num_shapes(shapes) && shape == NULL )
+ {
+ shape = gv_shapes_get_shape(shapes, i);
+ i++;
+ }
+
+ if( shape == NULL )
+ {
+ g_warning("no shapes in layer to save ... unable to default type");
+ return FALSE;
+ }
+
+ if( gv_shape_type(shape) == GVSHAPE_POINT )
+ shp_type = SHPT_POINT;
+ else if( gv_shape_type(shape) == GVSHAPE_LINE )
+ shp_type = SHPT_ARC;
+ else
+ shp_type = SHPT_POLYGON;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Try to create the named file(s). */
+/* -------------------------------------------------------------------- */
+ dbf_handle = DBFCreate( filename );
+ if( dbf_handle == NULL )
+ {
+ g_warning( "Failed to create DBF file." );
+ return FALSE;
+ }
+
+ shp_handle = SHPCreate( filename, shp_type );
+ if( shp_handle == NULL )
+ {
+ g_warning( "Failed to create SHP file." );
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the fields on the DBF file, if any. */
+/* -------------------------------------------------------------------- */
+ properties = gv_data_get_properties( shapes_data );
+ for( field_index = 0; TRUE; field_index++ )
+ {
+ int width, precision = 0, field_type;
+ char prop_name[64];
+ const char *prop_value;
+
+ sprintf( prop_name, "_field_width_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ width = atoi(prop_value);
+
+ sprintf( prop_name, "_field_precision_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value != NULL )
+ precision = atoi(prop_value);
+
+ sprintf( prop_name, "_field_type_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ prop_value = "string";
+
+ if( g_strcasecmp(prop_value,"integer") == 0 )
+ field_type = FTInteger;
+ else if( g_strcasecmp(prop_value,"float") == 0 )
+ field_type = FTDouble;
+ else
+ field_type = FTString;
+
+ sprintf( prop_name, "_field_name_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ DBFAddField( dbf_handle, prop_value, field_type, width, precision );
+ field_count++;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add a dummy field if there are none. */
+/* -------------------------------------------------------------------- */
+ if( field_count == 0 )
+ {
+ DBFAddField( dbf_handle, "FID", FTInteger, 10, 0 );
+ fid = 0;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Start writing shapes, ignoring any that don't match our */
+/* desired type. */
+/* -------------------------------------------------------------------- */
+ shape_count = gv_shapes_num_shapes(shapes);
+ for( shape_index = 0; shape_index < shape_count; shape_index++ )
+ {
+ SHPObject *shp_object;
+ int vertex_count, ring, shp_id;
+ int *ring_start = NULL, ring_count;
+
+ shape = gv_shapes_get_shape( shapes, shape_index );
+
+ if( shape == NULL )
+ continue;
+
+ /* skip shapes not matching desired type */
+ if( (shp_type == SHPT_POINT && gv_shape_type(shape) != GVSHAPE_POINT)
+ || (shp_type == SHPT_ARC && gv_shape_type(shape) != GVSHAPE_LINE)
+ || (shp_type == SHPT_POLYGON && gv_shape_type(shape) != GVSHAPE_AREA))
+ continue;
+
+ /* count all the vertices */
+ vertex_count = 0;
+ ring_count = gv_shape_get_rings(shape);
+ for( ring = 0; ring < ring_count; ring++ )
+ vertex_count += gv_shape_get_nodes( shape, ring );
+
+ if( max_vertices < vertex_count+1 )
+ {
+ if( x != NULL )
+ {
+ free(x);
+ free(y);
+ free(z);
+ }
+
+ max_vertices = vertex_count * 2 + 50;
+ x = (double *) malloc(sizeof(double) * max_vertices);
+ y = (double *) malloc(sizeof(double) * max_vertices);
+ z = (double *) malloc(sizeof(double) * max_vertices);
+ }
+
+ vertex_count = 0;
+ for( ring = 0; ring < ring_count; ring++ )
+ {
+ int node, node_count;
+
+ node_count = gv_shape_get_nodes( shape, ring );
+ for( node = 0; node < node_count; node++ )
+ {
+ x[vertex_count] = gv_shape_get_x(shape,ring,node);
+ y[vertex_count] = gv_shape_get_y(shape,ring,node);
+ z[vertex_count] = gv_shape_get_z(shape,ring,node);
+ vertex_count++;
+ }
+
+ /* force closing of unclosed area rings. */
+ if( gv_shape_type(shape) == GVSHAPE_AREA
+ && (gv_shape_get_x(shape,ring,0)
+ != gv_shape_get_x(shape,ring,node_count-1)
+ || gv_shape_get_y(shape,ring,0)
+ != gv_shape_get_y(shape,ring,node_count-1) ) )
+ {
+ x[vertex_count] = gv_shape_get_x(shape,ring,0);
+ y[vertex_count] = gv_shape_get_y(shape,ring,0);
+ z[vertex_count] = gv_shape_get_z(shape,ring,0);
+ vertex_count++;
+ }
+
+ if( ring_start != NULL )
+ ring_start[ring] = vertex_count;
+ }
+
+ if( gv_shape_get_rings( shape ) > 1 )
+ {
+ vertex_count = 0;
+ ring_start = (int *) malloc(sizeof(int) * ring_count);
+
+ for( ring = 0; ring < ring_count; ring++ )
+ {
+ ring_start[ring] = vertex_count;
+ vertex_count += gv_shape_get_nodes( shape, ring );
+ }
+ }
+
+ if( ring_count > 1 )
+ shp_object = SHPCreateObject( shp_type, -1, ring_count, ring_start,
+ NULL, vertex_count, x, y, z, NULL );
+ else
+ shp_object = SHPCreateObject( shp_type, -1, 0, NULL,
+ NULL, vertex_count, x, y, z, NULL );
+ if( ring_start != NULL )
+ {
+ free( ring_start );
+ ring_start = NULL;
+ }
+
+ shp_id = SHPWriteObject( shp_handle, -1, shp_object );
+ SHPDestroyObject( shp_object );
+
+ /* Write the attributes of this shape that match the DBF schema */
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ char field_name[32];
+ const char * field_value;
+ int field_type;
+
+ /* FIXME: This will fail for truncated field names! */
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ field_name, NULL, NULL);
+
+ field_value = gv_properties_get( gv_shape_get_properties(shape),
+ field_name);
+ if( field_value == NULL )
+ field_value = "";
+
+ if( field_type == FTDouble )
+ DBFWriteDoubleAttribute( dbf_handle, shp_id, field_index,
+ atof(field_value) );
+ else if( field_type == FTInteger )
+ DBFWriteIntegerAttribute( dbf_handle, shp_id, field_index,
+ atoi(field_value) );
+ else
+ DBFWriteStringAttribute( dbf_handle, shp_id, field_index,
+ field_value );
+ }
+
+ if( fid != -1 )
+ {
+ DBFWriteIntegerAttribute( dbf_handle, shp_id, fid, shp_id );
+ }
+ }
+
+ if( x != NULL )
+ {
+ free( x );
+ free( y );
+ free( z );
+ }
+
+ SHPClose( shp_handle );
+ DBFClose( dbf_handle );
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_shapes_to_dbf() */
+/************************************************************************/
+
+int gv_shapes_to_dbf(const char *filename, GvData *shapes_data )
+
+{
+ GvShapes *shapes = GV_SHAPES(shapes_data);
+ GvShape *shape;
+ DBFHandle dbf_handle;
+ int field_index, field_count=0, shape_count, shape_index;
+ GvProperties *properties;
+
+/* -------------------------------------------------------------------- */
+/* Try to create the named file(s). */
+/* -------------------------------------------------------------------- */
+ dbf_handle = DBFCreate( filename );
+ if( dbf_handle == NULL )
+ {
+ g_warning( "Failed to create DBF file." );
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create the fields on the DBF file, if any. */
+/* -------------------------------------------------------------------- */
+ properties = gv_data_get_properties( shapes_data );
+ for( field_index = 0; TRUE; field_index++ )
+ {
+ int width, precision = 0, field_type;
+ char prop_name[64];
+ const char *prop_value;
+
+ sprintf( prop_name, "_field_width_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ width = atoi(prop_value);
+
+ sprintf( prop_name, "_field_precision_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value != NULL )
+ precision = atoi(prop_value);
+
+ sprintf( prop_name, "_field_type_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ prop_value = "string";
+
+ if( g_strcasecmp(prop_value,"integer") == 0 )
+ field_type = FTInteger;
+ else if( g_strcasecmp(prop_value,"float") == 0 )
+ field_type = FTDouble;
+ else
+ field_type = FTString;
+
+ sprintf( prop_name, "_field_name_%d", field_index+1 );
+ prop_value = gv_properties_get( properties, prop_name );
+ if( prop_value == NULL )
+ break;
+
+ DBFAddField( dbf_handle, prop_value, field_type, width, precision );
+ field_count++;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Add a dummy field if there are none. */
+/* -------------------------------------------------------------------- */
+ if( field_count == 0 )
+ {
+ g_warning( "No attributes to save in DBF file." );
+ return FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Start writing shapes, ignoring any that don't match our */
+/* desired type. */
+/* -------------------------------------------------------------------- */
+ shape_count = gv_shapes_num_shapes(shapes);
+ for( shape_index = 0; shape_index < shape_count; shape_index++ )
+ {
+ shape = gv_shapes_get_shape( shapes, shape_index );
+
+ if( shape == NULL )
+ continue;
+
+ /* Write the attributes of this shape that match the DBF schema */
+ for( field_index = 0; field_index < field_count; field_index++ )
+ {
+ char field_name[32];
+ const char * field_value;
+ int field_type;
+
+ /* FIXME: This will fail for truncated field names! */
+ field_type = DBFGetFieldInfo( dbf_handle, field_index,
+ field_name, NULL, NULL);
+
+ field_value = gv_properties_get( gv_shape_get_properties(shape),
+ field_name);
+ if( field_value == NULL )
+ {
+ DBFWriteNULLAttribute( dbf_handle, shape_index, field_index );
+ }
+ else
+ {
+ if( field_type == FTDouble )
+ DBFWriteDoubleAttribute( dbf_handle, shape_index, field_index,
+ atof(field_value) );
+ else if( field_type == FTInteger )
+ DBFWriteIntegerAttribute( dbf_handle, shape_index, field_index,
+ atoi(field_value) );
+ else
+ DBFWriteStringAttribute( dbf_handle, shape_index, field_index,
+ field_value );
+ }
+ }
+
+ }
+
+ DBFClose( dbf_handle );
+
+ return TRUE;
+}
Added: packages/openev/branches/upstream/current/gvshapelayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvshapelayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvshapelayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1232 @@
+/******************************************************************************
+ * $Id: gvshapelayer.c,v 1.26 2003/05/16 18:26:33 pgs Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for vector display layers (eventually this will
+ * merge with GvShapesLayer).
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapelayer.c,v $
+ * Revision 1.26 2003/05/16 18:26:33 pgs
+ * added initial code for propogating colors to sub-symbols
+ *
+ * Revision 1.25 2003/04/17 13:56:12 warmerda
+ * added more assserts
+ *
+ * Revision 1.24 2003/04/09 16:52:23 pgs
+ * added shadow, halo and bgcolor to LABELs
+ *
+ * Revision 1.23 2003/04/07 15:10:14 pgs
+ * added pattern support to pen objects
+ *
+ * Revision 1.22 2003/02/28 16:47:25 warmerda
+ * split up render part handling to support vector symbols
+ *
+ * Revision 1.21 2003/02/27 04:00:18 warmerda
+ * added scale_dep flag handling
+ *
+ * Revision 1.20 2003/02/14 20:12:43 pgs
+ * added support for line widths in PENs
+ *
+ * Revision 1.19 2002/11/15 05:04:43 warmerda
+ * added LABEL anchor point support
+ *
+ * Revision 1.18 2002/11/14 20:11:22 warmerda
+ * preliminary support for gvsymbolmanager from Paul
+ *
+ * Revision 1.17 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.16 2002/09/30 20:50:18 warmerda
+ * removed restart debug message
+ *
+ * Revision 1.15 2002/09/30 17:36:04 warmerda
+ * Increate name buffer size in gv_shape_layer_pick_node(). This fixes an odd
+ * crash on Linux/XiGraphics combo, and ensures that a hit is detected even if
+ * there are overlapping nodes as occurs with the start node in a closed area.
+ *
+ * Revision 1.14 2002/02/22 20:16:07 warmerda
+ * added brush tool support
+ *
+ * Revision 1.13 2002/02/22 19:27:16 warmerda
+ * added support for pen tools
+ *
+ * Revision 1.12 2001/11/09 16:04:53 warmerda
+ * default color to white in renderinfo
+ *
+ * Revision 1.11 2001/04/09 18:17:34 warmerda
+ * added subselection, and renderinfo support
+ *
+ * Revision 1.10 2000/08/10 20:44:27 warmerda
+ * don't try to select shapes in a zero sized rectangle
+ *
+ * Revision 1.9 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvshapelayer.h"
+#include "gvrenderinfo.h"
+#include "cpl_error.h"
+#include <gtk/gtksignal.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#define PICK_SIZE 4.0
+
+enum
+{
+ DRAW_SELECTED,
+ DELETE_SELECTED,
+ TRANSLATE_SELECTED,
+ PICK_SHAPE,
+ PICK_NODE,
+ GET_NODE,
+ MOVE_NODE,
+ INSERT_NODE,
+ DELETE_NODE,
+ NODE_MOTION,
+ SELECTION_CHANGED,
+ SUBSELECTION_CHANGED,
+ LAST_SIGNAL
+};
+
+static void gv_shape_layer_class_init(GvShapeLayerClass *klass);
+static void gv_shape_layer_init(GvShapeLayer *layer);
+static void gv_shape_layer_finalize(GtkObject *object);
+static void gv_shape_layer_selection_changed(GvShapeLayer *layer);
+static void gv_shape_layer_subselection_changed(GvShapeLayer *layer);
+
+static guint shape_layer_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_shape_layer_get_type(void)
+{
+ static GtkType shape_layer_type = 0;
+
+ if (!shape_layer_type)
+ {
+ static const GtkTypeInfo shape_layer_info =
+ {
+ "GvShapeLayer",
+ sizeof(GvShapeLayer),
+ sizeof(GvShapeLayerClass),
+ (GtkClassInitFunc) gv_shape_layer_class_init,
+ (GtkObjectInitFunc) gv_shape_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ shape_layer_type = gtk_type_unique(gv_layer_get_type(),
+ &shape_layer_info);
+ }
+ return shape_layer_type;
+}
+
+static void
+gv_shape_layer_class_init(GvShapeLayerClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ shape_layer_signals[DRAW_SELECTED] =
+ gtk_signal_new ("draw-selected",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, draw_selected),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[DELETE_SELECTED] =
+ gtk_signal_new ("delete-selected",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, delete_selected),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ shape_layer_signals[TRANSLATE_SELECTED] =
+ gtk_signal_new ("translate-selected",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass,
+ translate_selected),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[PICK_SHAPE] =
+ gtk_signal_new ("pick-shape",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, pick_shape),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ shape_layer_signals[PICK_NODE] =
+ gtk_signal_new ("pick-node",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, pick_node),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ shape_layer_signals[GET_NODE] =
+ gtk_signal_new ("get-node",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, get_node),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[MOVE_NODE] =
+ gtk_signal_new ("move-node",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, move_node),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[INSERT_NODE] =
+ gtk_signal_new ("insert-node",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, insert_node),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[DELETE_NODE] =
+ gtk_signal_new ("delete-node",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, delete_node),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ shape_layer_signals[NODE_MOTION] =
+ gtk_signal_new ("node-motion",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvShapeLayerClass, node_motion),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_INT);
+
+ shape_layer_signals[SELECTION_CHANGED] =
+ gtk_signal_new ("selection-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET(GvShapeLayerClass,selection_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 0);
+
+ shape_layer_signals[SUBSELECTION_CHANGED] =
+ gtk_signal_new ("subselection-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET(GvShapeLayerClass,
+ subselection_changed),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals(object_class, shape_layer_signals,
+ LAST_SIGNAL);
+
+ object_class->finalize = gv_shape_layer_finalize;
+
+ klass->draw_selected = NULL;
+ klass->delete_selected = NULL;
+ klass->translate_selected = NULL;
+ klass->pick_shape = NULL;
+ klass->pick_node = NULL;
+ klass->get_node = NULL;
+ klass->move_node = NULL;
+ klass->insert_node = NULL;
+ klass->delete_node = NULL;
+ klass->node_motion = NULL;
+}
+
+static void
+gv_shape_layer_init(GvShapeLayer *layer)
+{
+ GvColor default_color = {1.0, 1.0, 1.0, 1.0};
+
+ layer->selected = g_array_new(FALSE, TRUE, sizeof(gint));
+ layer->flags = 0;
+ gv_color_copy(layer->color, default_color);
+
+ layer->subselection = -1;
+ layer->render_index = NULL;
+ layer->label_render = NULL;
+ layer->symbol_render = NULL;
+ layer->pen_render = NULL;
+ layer->brush_render = NULL;
+
+ layer->scale_dep_flags = NULL;
+}
+
+void
+gv_shape_layer_select_shape(GvShapeLayer *layer, gint shape_id)
+{
+ g_return_if_fail(shape_id >= 0 && shape_id < layer->selected->len);
+ if( g_array_index(layer->selected, gint, shape_id) == 0 )
+ {
+ g_array_index(layer->selected, gint, shape_id) = 1;
+ gv_shape_layer_selection_changed(layer);
+
+ gv_shape_layer_subselect_shape(layer, shape_id);
+ }
+}
+
+void
+gv_shape_layer_deselect_shape(GvShapeLayer *layer, gint shape_id)
+{
+ g_return_if_fail(shape_id >= 0 && shape_id < layer->selected->len);
+ if( g_array_index(layer->selected, gint, shape_id) != 0 )
+ {
+ if( layer->subselection == shape_id )
+ gv_shape_layer_subselect_shape(layer, -1);
+
+ g_array_index(layer->selected, gint, shape_id) = 0;
+ gv_shape_layer_selection_changed(layer);
+ }
+}
+
+void
+gv_shape_layer_clear_selection(GvShapeLayer *layer)
+{
+ gv_shape_layer_subselect_shape(layer, -1);
+
+ memset(layer->selected->data, 0, layer->selected->len * sizeof(gint));
+
+ gv_shape_layer_selection_changed(layer);
+}
+
+void
+gv_shape_layer_select_all(GvShapeLayer *layer)
+{
+ memset(layer->selected->data, 0xff, layer->selected->len * sizeof(gint));
+ gv_shape_layer_selection_changed(layer);
+}
+
+gint
+gv_shape_layer_is_selected(GvShapeLayer *layer, gint shape_id)
+{
+ g_return_val_if_fail(shape_id >= 0 && shape_id < layer->selected->len, 0);
+ return g_array_index(layer->selected, gint, shape_id);
+}
+
+gint
+gv_shape_layer_selected(GvShapeLayer *layer, gint what, void *retval)
+{
+ gint i, hit=FALSE;
+ GArray *shapes=NULL;
+
+ if (what == GV_ALL)
+ {
+ hit = FALSE;
+ shapes = (GArray*)retval;
+ }
+
+ for (i=0; i < layer->selected->len; ++i)
+ {
+ if (g_array_index(layer->selected, gint, i))
+ {
+ if (what == GV_ALL)
+ {
+ hit = TRUE;
+ g_array_append_val(shapes, i);
+ }
+ else
+ {
+ if (what == GV_FIRST) *(gint*)retval = i;
+ return TRUE;
+ }
+ }
+ }
+ return hit;
+}
+
+void
+gv_shape_layer_delete_selected(GvShapeLayer *layer)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[DELETE_SELECTED]);
+}
+
+void
+gv_shape_layer_translate_selected(GvShapeLayer *layer, gvgeocoord dx, gvgeocoord dy)
+{
+ GvVertex delta;
+
+ delta.x = dx;
+ delta.y = dy;
+ gtk_signal_emit(GTK_OBJECT(layer),
+ shape_layer_signals[TRANSLATE_SELECTED], &delta);
+}
+
+void
+gv_shape_layer_selected_motion(GvShapeLayer *layer, gvgeocoord dx, gvgeocoord dy)
+{
+ layer->selected_motion.x = dx;
+ layer->selected_motion.y = dy;
+}
+
+void
+gv_shape_layer_draw_selected(GvShapeLayer *layer, guint when, GvViewArea *view)
+{
+ switch (when)
+ {
+ case GV_ALWAYS:
+ layer->flags &= ~GV_DELAY_SELECTED;
+ break;
+
+ case GV_LATER:
+ layer->flags |= GV_DELAY_SELECTED;
+ break;
+
+ case GV_NOW:
+ gtk_signal_emit(GTK_OBJECT(layer),
+ shape_layer_signals[DRAW_SELECTED], view);
+ break;
+
+ default:
+ g_warning("gv_shape_layer_draw_selected(): invalid argument");
+ break;
+ }
+}
+
+void
+gv_shape_layer_get_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[GET_NODE], info);
+}
+
+void
+gv_shape_layer_move_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[MOVE_NODE], info);
+}
+
+void
+gv_shape_layer_insert_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[INSERT_NODE], info);
+}
+
+void
+gv_shape_layer_delete_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[DELETE_NODE], info);
+}
+
+void gv_shape_layer_node_motion(GvShapeLayer *layer, gint shape_id)
+{
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[NODE_MOTION],
+ shape_id);
+}
+
+void
+gv_shape_layer_select_region(GvShapeLayer *layer, GvViewArea *view,
+ GvRect *rect)
+{
+ GLuint *buf;
+ GLint hits, i;
+
+ if (layer->selected->len == 0) return;
+
+ if( rect->width == 0.0 || rect->height == 0.0 )
+ return;
+
+ buf = g_new(GLuint, layer->selected->len * 4);
+ g_return_if_fail(buf);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ /* Rect is in screen coordinates with origin in center of view */
+ gluOrtho2D(rect->x, rect->x + rect->width,
+ rect->y, rect->y + rect->height);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+
+ glSelectBuffer(layer->selected->len * 4, buf);
+ glRenderMode(GL_SELECT);
+
+ glInitNames();
+ glPushName(-1);
+
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[PICK_SHAPE]);
+
+ hits = glRenderMode(GL_RENDER);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ layer->flags |= GV_SUPPRESS_SELCHANGED;
+ gv_shape_layer_clear_selection(layer);
+
+ for (i=0; i < hits; ++i)
+ {
+ gv_shape_layer_select_shape(layer, (gint)buf[4*i+3]);
+ }
+
+ layer->flags &= ~GV_SUPPRESS_SELCHANGED;
+
+ gv_shape_layer_selection_changed(layer);
+
+ if( hits > 0 )
+ gv_shape_layer_subselect_shape( layer, (gint) buf[3] );
+
+ g_free(buf);
+}
+
+gint
+gv_shape_layer_pick_shape(GvShapeLayer *layer, GvViewArea *view,
+ gvgeocoord x, gvgeocoord y, gint *shape_id)
+{
+ GLuint *buf;
+ GLint hits;
+ GLint vp[4];
+
+ /* FIXME: need to make the view area current GL context */
+
+ if (layer->selected->len == 0) return FALSE;
+
+ buf = g_new(GLuint, layer->selected->len * 4);
+ g_return_val_if_fail(buf, FALSE);
+
+ vp[0] = vp[1] = 0;
+ vp[2] = (GLint)view->state.shape_x;
+ vp[3] = (GLint)view->state.shape_y;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPickMatrix(x, vp[3]-y, PICK_SIZE, PICK_SIZE, vp);
+ gluOrtho2D(-vp[2]/2.0, vp[2]/2.0, -vp[3]/2.0, vp[3]/2.0);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+
+ glSelectBuffer(layer->selected->len * 4, buf);
+ glRenderMode(GL_SELECT);
+
+ glInitNames();
+ glPushName(-1);
+
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[PICK_SHAPE]);
+
+ hits = glRenderMode(GL_RENDER);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ if (hits > 0 && shape_id)
+ {
+ /* If there is more than one hit, we arbitrarily pick the first one */
+ *shape_id = (gint)buf[3];
+ }
+
+ g_free(buf);
+ return (hits > 0);
+}
+
+gint
+gv_shape_layer_pick_node(GvShapeLayer *layer, GvViewArea *view,
+ gvgeocoord x, gvgeocoord y, gint *before,
+ GvNodeInfo *node_info)
+{
+ GLuint *buf;
+ GLint hits;
+ GLint vp[4];
+
+ /* FIXME: need to make the view area current GL context */
+
+ if (layer->selected->len == 0) return FALSE;
+
+ buf = g_new0(GLuint, 12*3);
+ g_return_val_if_fail(buf, FALSE);
+
+ vp[0] = vp[1] = 0;
+ vp[2] = (GLint)view->state.shape_x;
+ vp[3] = (GLint)view->state.shape_y;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPickMatrix(x, vp[3]-y, PICK_SIZE, PICK_SIZE, vp);
+ gluOrtho2D(-vp[2]/2.0, vp[2]/2.0, -vp[3]/2.0, vp[3]/2.0);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+
+ glSelectBuffer(12*3, buf);
+ glRenderMode(GL_SELECT);
+
+ glInitNames();
+ glPushName(-1);
+
+ gtk_signal_emit(GTK_OBJECT(layer), shape_layer_signals[PICK_NODE]);
+
+ hits = glRenderMode(GL_RENDER);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ if (hits > 0 && node_info)
+ {
+ /* If there is more than one hit, we arbitrarily pick the first one */
+
+ /* Contents of the name stack is encoded as follows:
+ buf[3] = 0 for node hit, 1 for segment hit
+ buf[4] = ring id (always 0 for lines)
+ buf[5] = node id
+ */
+ node_info->ring_id = (gint)buf[4];
+ node_info->node_id = (gint)buf[5];
+
+ gv_shape_layer_selected(layer, GV_FIRST, &node_info->shape_id);
+ }
+ if (hits > 0 && before)
+ {
+ *before = (gint)buf[3];
+ }
+ if( hits < 0 )
+ {
+ CPLDebug( "GvShapeLayer",
+ "Name buffer overflow in gv_shape_layer_pick_node()" );
+ }
+
+ g_free(buf);
+ return (hits > 0);
+}
+
+void
+gv_shape_layer_set_num_shapes(GvShapeLayer *layer, gint num_shapes)
+{
+ int old_scaledep_words, new_scaledep_words;
+
+ if (num_shapes == layer->selected->len)
+ return;
+
+ /* Do we need to grow the scaledep words array? */
+ new_scaledep_words = (num_shapes+31) / 32;
+ old_scaledep_words = (layer->selected->len+31) / 32;
+
+ if( new_scaledep_words > old_scaledep_words )
+ {
+ if( layer->scale_dep_flags != NULL )
+ layer->scale_dep_flags =
+ g_renew( gint, layer->scale_dep_flags, new_scaledep_words );
+ else
+ layer->scale_dep_flags =
+ g_new( gint, new_scaledep_words );
+
+ memset( layer->scale_dep_flags + old_scaledep_words,
+ 0, (new_scaledep_words - old_scaledep_words) * 4 );
+ }
+
+ /* reset the size of the selected array */
+ g_array_set_size(layer->selected, num_shapes);
+ gv_shape_layer_clear_selection(layer);
+
+ if( layer->render_index != NULL )
+ {
+ /* new entries automatically set to zero (GVP_UNINITIALIZED_PART) */
+ g_array_set_size(layer->render_index, num_shapes);
+ }
+}
+
+void
+gv_shape_layer_set_color(GvShapeLayer *layer, GvColor color)
+{
+ gv_color_copy(layer->color, color);
+ gv_layer_display_change( GV_LAYER(layer), NULL );
+}
+
+static void
+gv_shape_layer_selection_changed(GvShapeLayer *layer)
+
+{
+ if( !(layer->flags & GV_SUPPRESS_SELCHANGED) )
+ gtk_signal_emit(GTK_OBJECT(layer),
+ shape_layer_signals[SELECTION_CHANGED]);
+}
+
+static void
+gv_shape_layer_subselection_changed(GvShapeLayer *layer)
+
+{
+ if( !(layer->flags & GV_SUPPRESS_SELCHANGED) )
+ {
+ gtk_signal_emit(GTK_OBJECT(layer),
+ shape_layer_signals[SUBSELECTION_CHANGED]);
+ }
+}
+
+static void
+gv_shape_layer_finalize(GtkObject *object)
+{
+ GvLayerClass *parent_class;
+ GvShapeLayer *layer;
+
+ layer = GV_SHAPE_LAYER(object);
+
+ gv_shape_layer_clear_all_renderinfo( layer );
+
+ g_array_free(layer->selected, TRUE);
+ if( layer->scale_dep_flags != NULL )
+ g_free( layer->scale_dep_flags );
+
+ parent_class = gtk_type_class(gv_layer_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+/************************************************************************/
+/* gv_shape_layer_get_subselection() */
+/************************************************************************/
+
+gint gv_shape_layer_get_subselection( GvShapeLayer *layer )
+{
+ return layer->subselection;
+}
+
+/************************************************************************/
+/* gv_shape_layer_subselect_shape() */
+/************************************************************************/
+
+void gv_shape_layer_subselect_shape( GvShapeLayer *layer, gint shape_id )
+
+{
+ if( (shape_id == -1 || gv_shape_layer_is_selected(layer, shape_id))
+ && shape_id != layer->subselection )
+ {
+ layer->subselection = shape_id;
+ gv_shape_layer_subselection_changed(layer);
+ }
+}
+
+/************************************************************************/
+/* gv_shape_layer_get_part() */
+/************************************************************************/
+
+GvRenderPart *gv_shape_layer_get_part( GvShapeLayer *layer, guint part_index )
+
+
+{
+ int part_type, raw_index;
+
+ if( layer->render_index == NULL )
+ return NULL;
+
+ if( part_index == GVP_LAST_PART || part_index == GVP_UNINITIALIZED_PART )
+ return NULL;
+
+ raw_index = gv_part_index_to_index(part_index);
+ part_type = gv_part_index_to_type(part_index);
+
+ g_assert( raw_index >= 0 );
+ g_assert( part_type == GvLabelPart || part_type == GvSymbolPart
+ || part_type == GvPenPart || part_type == GvBrushPart );
+
+ if( part_type == GvLabelPart )
+ {
+ g_assert( raw_index < layer->label_render->len );
+
+ if( raw_index >= layer->label_render->len )
+ return NULL;
+
+ g_assert( g_array_index(layer->label_render,
+ GvLabelRenderPart,raw_index).next_part
+ != GVP_UNINITIALIZED_PART );
+
+ return (GvRenderPart *)
+ &(g_array_index(layer->label_render,
+ GvLabelRenderPart,raw_index));
+ }
+ else if( part_type == GvSymbolPart )
+ {
+ g_assert( raw_index < layer->symbol_render->len );
+
+ if( raw_index >= layer->symbol_render->len )
+ return NULL;
+
+ g_assert( g_array_index(layer->symbol_render,
+ GvSymbolRenderPart,raw_index).next_part
+ != GVP_UNINITIALIZED_PART );
+
+ return (GvRenderPart *)
+ &(g_array_index(layer->symbol_render,
+ GvSymbolRenderPart,raw_index));
+ }
+ else if( part_type == GvPenPart )
+ {
+ g_assert( raw_index < layer->pen_render->len );
+
+ if( raw_index >= layer->pen_render->len )
+ return NULL;
+
+ g_assert( g_array_index(layer->pen_render,
+ GvPenRenderPart,raw_index).next_part
+ != GVP_UNINITIALIZED_PART );
+
+ return (GvRenderPart *)
+ &(g_array_index(layer->pen_render,
+ GvPenRenderPart,raw_index));
+ }
+ else if( part_type == GvBrushPart )
+ {
+ g_assert( raw_index < layer->brush_render->len );
+
+ if( raw_index >= layer->brush_render->len )
+ return NULL;
+
+ g_assert( g_array_index(layer->brush_render,
+ GvBrushRenderPart,raw_index).next_part
+ != GVP_UNINITIALIZED_PART );
+
+ return (GvRenderPart *)
+ &(g_array_index(layer->brush_render,
+ GvBrushRenderPart,raw_index));
+ }
+ else
+ return NULL;
+}
+
+/************************************************************************/
+/* gv_shape_layer_get_first_part_index() */
+/************************************************************************/
+
+guint gv_shape_layer_get_first_part_index( GvShapeLayer *layer, gint shape_id)
+
+{
+ guint part_index;
+
+ if( layer->render_index == NULL )
+ return GVP_UNINITIALIZED_PART;
+
+ g_return_val_if_fail( shape_id >= 0 && shape_id < layer->render_index->len,
+ GVP_LAST_PART );
+
+ part_index = g_array_index(layer->render_index, guint, shape_id);
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_shape_layer_initialize_renderindex() */
+/************************************************************************/
+
+void gv_shape_layer_initialize_renderindex( GvShapeLayer *layer )
+
+{
+/* -------------------------------------------------------------------- */
+/* Allocate render_index if it doesn't exist yet. */
+/* -------------------------------------------------------------------- */
+ if( layer->render_index == NULL )
+ {
+ layer->render_index = g_array_new(FALSE, TRUE, sizeof(gint));
+ g_array_set_size(layer->render_index, layer->selected->len );
+
+ layer->label_render =
+ g_array_new(FALSE, TRUE, sizeof(GvLabelRenderPart));
+ layer->symbol_render =
+ g_array_new(FALSE, TRUE, sizeof(GvSymbolRenderPart));
+ layer->pen_render =
+ g_array_new(FALSE, TRUE, sizeof(GvPenRenderPart));
+ layer->brush_render =
+ g_array_new(FALSE, TRUE, sizeof(GvBrushRenderPart));
+ }
+}
+
+/************************************************************************/
+/* gv_shape_layer_create_part() */
+/************************************************************************/
+
+guint gv_shape_layer_create_part( GvShapeLayer *layer, gint part_type )
+
+{
+ int part_index;
+
+ g_return_val_if_fail( layer != NULL, GVP_UNINITIALIZED_PART );
+
+ if( layer->render_index == NULL )
+ gv_shape_layer_initialize_renderindex( layer );
+
+/* -------------------------------------------------------------------- */
+/* Find the new part index in the target part type table. */
+/* -------------------------------------------------------------------- */
+ if( part_type == GvLabelPart )
+ {
+ GvLabelRenderPart label_info;
+
+ memset( &label_info, 0, sizeof(label_info) );
+ label_info.next_part = GVP_LAST_PART;
+ label_info.scale = 1.0;
+ label_info.color[0] = 1.0;
+ label_info.color[1] = 1.0;
+ label_info.color[2] = 1.0;
+ label_info.color[3] = 1.0;
+ label_info.b_color_initialized = 0;
+ label_info.background_color[0] = 1.0;
+ label_info.background_color[1] = 1.0;
+ label_info.background_color[2] = 1.0;
+ label_info.background_color[3] = 1.0;
+ label_info.b_background_color_initialized = 0;
+ label_info.anchor = GLRA_LOWER_LEFT;
+ label_info.halo = FALSE;
+ label_info.shadow = FALSE;
+
+ part_index = ((layer->label_render->len) << 3) | GvLabelPart;
+ g_array_append_val( layer->label_render, label_info );
+
+ return part_index;
+ }
+ else if( part_type == GvSymbolPart )
+ {
+ GvSymbolRenderPart symbol_info;
+
+ memset( &symbol_info, 0, sizeof(symbol_info) );
+ symbol_info.next_part = GVP_LAST_PART;
+ symbol_info.scale = 1.0;
+ symbol_info.color[0] = 1.0;
+ symbol_info.color[1] = 1.0;
+ symbol_info.color[2] = 1.0;
+ symbol_info.color[3] = 1.0;
+ symbol_info.b_color_initialized = 0;
+ symbol_info.part_index = GVP_UNINITIALIZED_PART;
+
+ part_index = ((layer->symbol_render->len) << 3) | GvSymbolPart;
+ g_array_append_val( layer->symbol_render, symbol_info );
+
+ return part_index;
+ }
+ else if( part_type == GvPenPart )
+ {
+ GvPenRenderPart pen_info;
+
+ memset( &pen_info, 0, sizeof(pen_info) );
+ pen_info.next_part = GVP_LAST_PART;
+ pen_info.color[0] = 1.0;
+ pen_info.color[1] = 1.0;
+ pen_info.color[2] = 1.0;
+ pen_info.color[3] = 1.0;
+ pen_info.b_color_initialized = 0;
+ pen_info.width = 1.0;
+ pen_info.pattern = "ogr-pen-0";
+
+ part_index = ((layer->pen_render->len) << 3) | GvPenPart;
+ g_array_append_val( layer->pen_render, pen_info );
+
+ return part_index;
+ }
+ else if( part_type == GvBrushPart )
+ {
+ GvBrushRenderPart brush_info;
+
+ memset( &brush_info, 0, sizeof(brush_info) );
+ brush_info.next_part = GVP_LAST_PART;
+ brush_info.fore_color[0] = 1.0;
+ brush_info.fore_color[1] = 1.0;
+ brush_info.fore_color[2] = 1.0;
+ brush_info.fore_color[3] = 1.0;
+ brush_info.b_fore_color_initialized = 0;
+
+ part_index = ((layer->brush_render->len) << 3) | GvBrushPart;
+ g_array_append_val( layer->brush_render, brush_info );
+
+ return part_index;
+ }
+ else
+ {
+ return GVP_UNINITIALIZED_PART;
+ }
+}
+
+/************************************************************************/
+/* gv_shape_layer_chain_part() */
+/* */
+/* Append this part to the the chain of which the */
+/* base_part_index is the head (or at least a member). */
+/* */
+/* Returns the base part index, which may new_part_index if it */
+/* is the first in the chain. */
+/************************************************************************/
+
+guint gv_shape_layer_chain_part( GvShapeLayer *layer, gint base_part_index,
+ gint new_part_index )
+
+{
+ GvRenderPart *last_part;
+
+ if( base_part_index == GVP_LAST_PART
+ || base_part_index == GVP_UNINITIALIZED_PART )
+ return new_part_index;
+
+ last_part = gv_shape_layer_get_part( layer, base_part_index );
+
+ while( last_part != NULL && last_part->next_part != GVP_LAST_PART )
+ last_part = gv_shape_layer_get_part( layer, last_part->next_part );
+
+ if( last_part != NULL )
+ last_part->next_part = new_part_index;
+
+ return base_part_index;
+}
+
+/************************************************************************/
+/* gv_shape_layer_add_part() */
+/* */
+/* Returns GVP_UNITIALIZED_PART (0) if add fails. */
+/************************************************************************/
+
+guint gv_shape_layer_add_part( GvShapeLayer *layer, gint shape_id,
+ gint part_type )
+
+{
+ guint part_index;
+
+ g_return_val_if_fail( layer != NULL
+ && shape_id >= 0
+ && shape_id < layer->selected->len,
+ GVP_UNINITIALIZED_PART );
+
+ if( layer->render_index == NULL )
+ gv_shape_layer_initialize_renderindex( layer );
+
+/* -------------------------------------------------------------------- */
+/* A part type of GVP_LAST_PART is taken as an indication that */
+/* this shape should just have a GVP_LAST_PART code set for the */
+/* shape as a whole. There is no render information for this */
+/* shape, but it is initialized. */
+/* -------------------------------------------------------------------- */
+ if( part_type == GVP_LAST_PART )
+ {
+ g_array_index(layer->render_index,guint,shape_id) = GVP_LAST_PART;
+ return GVP_LAST_PART;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create and initialize the part. */
+/* -------------------------------------------------------------------- */
+ part_index = gv_shape_layer_create_part( layer, part_type );
+
+ if( part_index == GVP_UNINITIALIZED_PART )
+ return part_index;
+
+/* -------------------------------------------------------------------- */
+/* Chain this part at the end of any existing parts for this */
+/* shape, or if it is the first it will be set as the first part. */
+/* -------------------------------------------------------------------- */
+ g_array_index(layer->render_index,guint,shape_id) =
+ gv_shape_layer_chain_part(
+ layer,
+ gv_shape_layer_get_first_part_index(layer, shape_id),
+ part_index );
+
+ return part_index;
+}
+
+/************************************************************************/
+/* gv_shape_layer_clear_shape_parts() */
+/************************************************************************/
+
+void gv_shape_layer_clear_shape_parts( GvShapeLayer *layer, gint shape_id )
+
+{
+ if( layer == NULL || shape_id < 0 || shape_id >= layer->selected->len
+ || layer->render_index == NULL )
+ return;
+
+ gv_shape_layer_clear_part( layer,
+ gv_shape_layer_get_first_part_index( layer, shape_id ) );
+
+ g_array_index( layer->render_index, guint, shape_id )
+ = GVP_UNINITIALIZED_PART;
+}
+
+
+/************************************************************************/
+/* gv_shape_layer_clear_part() */
+/* */
+/* De-initialized the indicated part, and any parts linked */
+/* after it. Returns parts to GVP_UNINITIALIZED state. */
+/************************************************************************/
+
+void gv_shape_layer_clear_part( GvShapeLayer *layer, guint part_index )
+
+{
+ int part_type = gv_part_index_to_type(part_index);
+ GvRenderPart *part_info;
+
+ part_info = gv_shape_layer_get_part( layer, part_index );
+ if( part_info == NULL )
+ return;
+
+ if( part_info->next_part != GVP_LAST_PART )
+ gv_shape_layer_clear_part( layer, part_info->next_part );
+
+ if( part_type == GvLabelPart )
+ {
+ GvLabelRenderPart *label_info = (GvLabelRenderPart *) part_info;
+
+ if( label_info->text != NULL )
+ g_free( label_info->text );
+ }
+
+ if( part_type == GvSymbolPart )
+ {
+ GvSymbolRenderPart *symbol_info = (GvSymbolRenderPart *) part_info;
+
+ if( symbol_info->symbol_id != NULL )
+ g_free( symbol_info->symbol_id );
+ }
+
+ part_info->next_part = GVP_UNINITIALIZED_PART;
+}
+
+/************************************************************************/
+/* gv_shape_layer_clear_all_renderinfo() */
+/* */
+/* Quickly wipe all rendering info, and recover all memory */
+/* associated with keeping rendering info. */
+/************************************************************************/
+
+void gv_shape_layer_clear_all_renderinfo( GvShapeLayer *layer )
+
+{
+ int i;
+
+ /*
+ * When the render info changes, it is possible for the scale dependentness
+ * of things to change to, so clear the flags will be be rebuilt next
+ * time the features are drawn.
+ */
+ if( layer->scale_dep_flags != NULL
+ && layer->selected != NULL )
+ memset( layer->scale_dep_flags, 0,
+ ((layer->selected->len+31) / 32) * 4 );
+
+ if( layer->render_index == NULL )
+ return;
+
+ g_array_free( layer->render_index, TRUE );
+ layer->render_index = NULL;
+
+ for( i=0; i<layer->symbol_render->len; i++ )
+ {
+ GvSymbolRenderPart *symbol_info;
+ symbol_info = &(g_array_index(layer->symbol_render,
+ GvSymbolRenderPart, i));
+ if (symbol_info->next_part != GVP_UNINITIALIZED_PART)
+ if (symbol_info->symbol_id != NULL)
+ g_free( symbol_info->symbol_id );
+ }
+
+ g_array_free( layer->symbol_render, TRUE );
+ layer->symbol_render = NULL;
+
+ for( i = 0; i < layer->label_render->len; i++ )
+ {
+ GvLabelRenderPart *label_info;
+
+ label_info = &(g_array_index(layer->label_render,GvLabelRenderPart,i));
+ if( label_info->next_part != GVP_UNINITIALIZED_PART )
+ {
+ if( label_info->text != NULL )
+ g_free( label_info->text );
+ }
+ }
+
+ g_array_free( layer->label_render, TRUE );
+ layer->label_render = NULL;
+
+ g_array_free( layer->pen_render, TRUE );
+ layer->pen_render = NULL;
+
+ g_array_free( layer->brush_render, TRUE );
+ layer->pen_render = NULL;
+
+}
+
+/************************************************************************/
+/* gv_shape_layer_get_scale_dep() */
+/************************************************************************/
+
+int gv_shape_layer_get_scale_dep( GvShapeLayer *layer, gint shape_id )
+
+{
+ if( layer->scale_dep_flags == NULL )
+ return 0;
+
+ if( shape_id < 0 || shape_id >= layer->selected->len )
+ return 0;
+
+ return layer->scale_dep_flags[shape_id >> 5] & (1 << (shape_id & 0x1f) );
+}
+
+/************************************************************************/
+/* gv_shape_layer_set_scale_dep() */
+/************************************************************************/
+
+void gv_shape_layer_set_scale_dep( GvShapeLayer *layer, gint shape_id,
+ int scale_dep )
+
+{
+ if( layer->scale_dep_flags == NULL )
+ return;
+
+ if( shape_id < 0 || shape_id >= layer->selected->len )
+ return;
+
+ if( scale_dep )
+ layer->scale_dep_flags[shape_id >> 5] |= (1 << (shape_id & 0x1f) );
+ else
+ layer->scale_dep_flags[shape_id >> 5] &= ~(1 << (shape_id & 0x1f) );
+}
+
Added: packages/openev/branches/upstream/current/gvshapelayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvshapelayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvshapelayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * $Id: gvshapelayer.h,v 1.11 2003/02/27 04:00:19 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for vector display layers (eventually this will
+ * merge with GvShapesLayer).
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapelayer.h,v $
+ * Revision 1.11 2003/02/27 04:00:19 warmerda
+ * added scale_dep flag handling
+ *
+ * Revision 1.10 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.9 2002/02/22 20:16:07 warmerda
+ * added brush tool support
+ *
+ * Revision 1.8 2002/02/22 19:27:16 warmerda
+ * added support for pen tools
+ *
+ * Revision 1.7 2001/04/09 18:17:34 warmerda
+ * added subselection, and renderinfo support
+ *
+ * Revision 1.6 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_SHAPE_LAYER_H__
+#define __GV_SHAPE_LAYER_H__
+
+#include <gdk/gdk.h>
+#include "gvlayer.h"
+#include "gvviewarea.h"
+
+#define GV_TYPE_SHAPE_LAYER (gv_shape_layer_get_type ())
+#define GV_SHAPE_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_SHAPE_LAYER, GvShapeLayer))
+#define GV_SHAPE_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_SHAPE_LAYER, GvShapeLayerClass))
+#define GV_IS_SHAPE_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_SHAPE_LAYER))
+#define GV_IS_SHAPE_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_SHAPE_LAYER))
+
+/* Access macro for selected buffer (for use by subclass) */
+#define GV_SHAPE_LAYER_SELBUF(layer) \
+ ((gint*)(GV_SHAPE_LAYER(layer)->selected->data))
+
+typedef struct _GvShapeLayer GvShapeLayer;
+typedef struct _GvShapeLayerClass GvShapeLayerClass;
+
+struct _GvShapeLayer
+{
+ GvLayer layer;
+ GArray *selected;
+ gint subselection;
+ guint flags;
+ GvColor color;
+ GvVertex selected_motion;
+
+ /* All related to keeping feature rendering information */
+ GArray *render_index;
+
+ GArray *label_render;
+ GArray *symbol_render;
+ GArray *pen_render;
+ GArray *brush_render;
+
+ gint *scale_dep_flags;
+};
+
+struct _GvShapeLayerClass
+{
+ GvLayerClass parent_class;
+
+ void (* draw_selected) (GvShapeLayer *layer, GvViewArea *view);
+ void (* delete_selected) (GvShapeLayer *layer);
+ void (* translate_selected) (GvShapeLayer *layer, GvVertex *delta);
+ void (* pick_shape) (GvShapeLayer *layer);
+ void (* pick_node) (GvShapeLayer *layer);
+ void (* get_node) (GvShapeLayer *layer, GvNodeInfo *info);
+ void (* move_node) (GvShapeLayer *layer, GvNodeInfo *info);
+ void (* insert_node) (GvShapeLayer *layer, GvNodeInfo *info);
+ void (* delete_node) (GvShapeLayer *layer, GvNodeInfo *info);
+ void (* node_motion) (GvShapeLayer *layer, gint shape_id);
+ void (* selection_changed) (GvShapeLayer *layer);
+ void (* subselection_changed)(GvShapeLayer *layer);
+};
+
+GtkType gv_shape_layer_get_type (void);
+
+void gv_shape_layer_select_shape(GvShapeLayer *layer, gint shape_id);
+void gv_shape_layer_deselect_shape(GvShapeLayer *layer, gint shape_id);
+void gv_shape_layer_clear_selection(GvShapeLayer *layer);
+void gv_shape_layer_select_all(GvShapeLayer *layer);
+void gv_shape_layer_draw_selected(GvShapeLayer *layer, guint when, GvViewArea *view);
+gint gv_shape_layer_is_selected(GvShapeLayer *layer, gint shape_id);
+gint gv_shape_layer_selected(GvShapeLayer *layer, gint what, void *retval);
+void gv_shape_layer_delete_selected(GvShapeLayer *layer);
+void gv_shape_layer_translate_selected(GvShapeLayer *layer, gvgeocoord dx, gvgeocoord dy);
+void gv_shape_layer_selected_motion(GvShapeLayer *layer, gvgeocoord dx, gvgeocoord dy);
+
+void gv_shape_layer_subselect_shape(GvShapeLayer *layer, gint shape_id);
+gint gv_shape_layer_get_subselection(GvShapeLayer *layer);
+
+void gv_shape_layer_set_scale_dep(GvShapeLayer *layer, gint shape_id, int dep);
+int gv_shape_layer_get_scale_dep(GvShapeLayer *layer, gint shape_id );
+
+void gv_shape_layer_get_node (GvShapeLayer *layer, GvNodeInfo *info);
+void gv_shape_layer_move_node (GvShapeLayer *layer, GvNodeInfo *info);
+void gv_shape_layer_insert_node (GvShapeLayer *layer, GvNodeInfo *info);
+void gv_shape_layer_delete_node (GvShapeLayer *layer, GvNodeInfo *info);
+void gv_shape_layer_node_motion (GvShapeLayer *layer, gint shape_id);
+
+void gv_shape_layer_select_region (GvShapeLayer *layer, GvViewArea *view, GvRect *rect);
+gint gv_shape_layer_pick_shape (GvShapeLayer *layer, GvViewArea *view, gvgeocoord x, gvgeocoord y, gint *shape_id);
+gint gv_shape_layer_pick_node (GvShapeLayer *layer, GvViewArea *view, gvgeocoord x, gvgeocoord y, gint *before, GvNodeInfo *node_info);
+
+void gv_shape_layer_set_num_shapes(GvShapeLayer *layer, gint num_shapes);
+void gv_shape_layer_set_color(GvShapeLayer *layer, GvColor color);
+
+#endif /*__GV_SHAPE_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvshapes.c
===================================================================
--- packages/openev/branches/upstream/current/gvshapes.c (rev 0)
+++ packages/openev/branches/upstream/current/gvshapes.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,730 @@
+/******************************************************************************
+ * $Id: gvshapes.c,v 1.20 2005/01/14 16:51:51 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Vector shape container class.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapes.c,v $
+ * Revision 1.20 2005/01/14 16:51:51 gmwalter
+ * Checked in Aude's gv_shapes_add_shape_last function
+ * (allows shapes to be added without repeating
+ * indices if others have been deleted).
+ *
+ * Revision 1.19 2004/02/20 10:40:36 andrey_kiselev
+ * Use gv_raster_get_nodata() instead of GDALGetNoDataValue().
+ *
+ * Revision 1.18 2003/02/27 03:55:06 warmerda
+ * improved debug calls
+ *
+ * Revision 1.17 2003/01/06 21:20:03 warmerda
+ * added gv_shapes_from_ogr_layer
+ *
+ * Revision 1.16 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.15 2002/03/07 02:31:56 warmerda
+ * added default_height to add_height functions
+ *
+ * Revision 1.14 2001/08/08 17:45:48 warmerda
+ * GvShape now referenced counted
+ *
+ * Revision 1.13 2001/08/07 20:48:05 warmerda
+ * report the creation of GvShapes
+ *
+ * Revision 1.12 2001/03/29 03:39:33 warmerda
+ * improved add_height() to look around a bit when facing nodata values
+ *
+ * Revision 1.11 2001/01/26 13:57:13 warmerda
+ * fixed serious bugs in add_height code (x/y transformed)
+ *
+ * Revision 1.10 2001/01/18 16:48:14 warmerda
+ * added gv_shapes_add_height() and wrappers
+ *
+ * Revision 1.9 2000/08/08 20:09:41 warmerda
+ * added finalize debug statement
+ *
+ * Revision 1.8 2000/08/04 18:38:00 warmerda
+ * make some operations safer with illegal shapeids
+ *
+ * Revision 1.7 2000/08/04 14:14:12 warmerda
+ * GvShapes shape ids now persistent
+ *
+ * Revision 1.6 2000/07/14 14:51:01 warmerda
+ * fixed insert, and delete node support
+ *
+ * Revision 1.5 2000/07/13 19:08:37 warmerda
+ * added coping optional for gv_shapes_replace_shapes
+ *
+ * Revision 1.4 2000/06/28 13:10:42 warmerda
+ * added preliminary OGR support
+ *
+ * Revision 1.3 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gextra.h"
+#include "gvshapes.h"
+#include "gvraster.h"
+#include "cpl_error.h"
+
+typedef struct _GvShapesMemento GvShapesMemento;
+
+struct _GvShapesMemento
+{
+ GvDataMemento base;
+ GArray *ids;
+ GPtrArray *shapes;
+};
+
+static void gv_shapes_class_init(GvShapesClass *klass);
+static void gv_shapes_init(GvShapes *points);
+static void gv_shapes_get_memento(GvData *points, gpointer info,
+ GvDataMemento **memento);
+static void gv_shapes_set_memento(GvData *points, GvDataMemento *memento);
+static void gv_shapes_del_memento(GvData *points, GvDataMemento *memento);
+static void gv_shapes_changed(GvData *points, gpointer data);
+static void gv_shapes_finalize(GtkObject *object);
+
+GtkType
+gv_shapes_get_type(void)
+{
+ static GtkType type = 0;
+
+ if (!type)
+ {
+ static const GtkTypeInfo shapes_info =
+ {
+ "GvShapes",
+ sizeof(GvShapes),
+ sizeof(GvShapesClass),
+ (GtkClassInitFunc) gv_shapes_class_init,
+ (GtkObjectInitFunc) gv_shapes_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique(gv_data_get_type(), &shapes_info);
+ }
+ return type;
+}
+
+static void
+gv_shapes_init(GvShapes *shapes)
+{
+ shapes->shapes = g_ptr_array_new();
+ shapes->extents_valid = FALSE;
+ shapes->actual_num_shapes = 0;
+}
+
+static void
+gv_shapes_class_init(GvShapesClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvDataClass *data_class;
+
+ object_class = (GtkObjectClass*) klass;
+ data_class = (GvDataClass*) klass;
+
+ object_class->finalize = gv_shapes_finalize;
+
+ data_class->changed = gv_shapes_changed;
+ data_class->get_memento = gv_shapes_get_memento;
+ data_class->set_memento = gv_shapes_set_memento;
+ data_class->del_memento = gv_shapes_del_memento;
+}
+
+GvData *
+gv_shapes_new(void)
+{
+ GvData *data;
+
+ data = GV_DATA(gtk_type_new(gv_shapes_get_type()));
+
+ CPLDebug( "OpenEV", "gv_shapes_new(%p)", data );
+
+ return data;
+}
+
+gint
+gv_shapes_add_shape(GvShapes *shapes, GvShape *new_shape)
+
+{
+ int shape_id;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+ /* Identify where to put it, reuse old holes if available */
+ if( shapes->shapes->len != shapes->actual_num_shapes )
+ {
+ for( shape_id=0; shape_id < shapes->shapes->len; shape_id++ )
+ {
+ if( g_ptr_array_index(shapes->shapes, shape_id) == NULL )
+ break;
+ }
+ }
+ else
+ {
+ shape_id = shapes->shapes->len;
+ }
+
+ /* Make notification of impending change */
+ change_info.shape_id = &shape_id;
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ /* apply update */
+ if( shape_id == shapes->shapes->len )
+ g_ptr_array_add(shapes->shapes, new_shape );
+ else
+ g_ptr_array_index(shapes->shapes, shape_id) = new_shape;
+
+ gv_shape_ref( new_shape );
+ shapes->actual_num_shapes++;
+
+ /* notify of completed change */
+ gv_data_changed(GV_DATA(shapes), &change_info);
+
+ return shape_id;
+}
+
+/* same as gv_shape_add_shape but do not fill the holes, always append shape at the end*/
+gint
+gv_shapes_add_shape_last(GvShapes *shapes, GvShape *new_shape)
+
+{
+ int shape_id;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 1, NULL};
+
+
+ shape_id = shapes->shapes->len;
+
+ /* Make notification of impending change */
+ change_info.shape_id = &shape_id;
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ /* apply update */
+ if( shape_id == shapes->shapes->len )
+ g_ptr_array_add(shapes->shapes, new_shape );
+ else
+ g_ptr_array_index(shapes->shapes, shape_id) = new_shape;
+
+ gv_shape_ref( new_shape );
+ shapes->actual_num_shapes++;
+
+ /* notify of completed change */
+ gv_data_changed(GV_DATA(shapes), &change_info);
+
+ return shape_id;
+}
+
+void
+gv_shapes_delete_shapes(GvShapes *shapes, gint num_shapes, gint *id_list)
+{
+ GvShapeChangeInfo change_info = {GV_CHANGE_DELETE, 0, NULL};
+ GvShape *shape;
+ gint i;
+
+ change_info.num_shapes = num_shapes;
+ change_info.shape_id = id_list;
+
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ for( i = 0; i < num_shapes; i++ )
+ {
+ if( id_list[i] < 0 || id_list[i] >= shapes->shapes->len )
+ shape = NULL;
+ else
+ shape = g_ptr_array_index(shapes->shapes, id_list[i]);
+
+ if( shape != NULL )
+ {
+ g_ptr_array_index(shapes->shapes,id_list[i]) = NULL;
+ gv_shape_unref(shape);
+ shapes->actual_num_shapes--;
+ }
+ }
+
+ /* Boil NULLs off the end of the list */
+ while( shapes->shapes->len > 0
+ && g_ptr_array_index(shapes->shapes,
+ shapes->shapes->len-1) == NULL )
+ {
+ g_ptr_array_remove_index_fast( shapes->shapes,
+ shapes->shapes->len-1 );
+ }
+
+ gv_data_changed(GV_DATA(shapes), &change_info);
+}
+
+void
+gv_shapes_translate_shapes(GvShapes *shapes, gint num_shapes, gint *id_list,
+ gvgeocoord dx, gvgeocoord dy)
+{
+ GvShape *shape;
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_shapes;
+ change_info.shape_id = id_list;
+
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ for (i=0; i < num_shapes; ++i)
+ {
+ int ring;
+
+ shape = gv_shapes_get_shape(shapes,id_list[i]);
+ if( shape == NULL )
+ continue;
+
+ for( ring = gv_shape_get_rings(shape)-1; ring >= 0; ring-- )
+ {
+ int node;
+
+ for( node = gv_shape_get_nodes(shape,ring)-1;
+ node >= 0; node-- )
+ {
+ gv_shape_set_xyz( shape, ring, node,
+ gv_shape_get_x(shape, ring, node) + dx,
+ gv_shape_get_y(shape, ring, node) + dy,
+ gv_shape_get_z(shape, ring, node) );
+ }
+ }
+ }
+ gv_data_changed(GV_DATA(shapes), &change_info);
+}
+
+void
+gv_shapes_get_extents(GvShapes *shapes, GvRect *rect)
+{
+ if (!shapes->extents_valid)
+ {
+ gint i, num_shapes, valid_shapes = 0;
+ GvVertex vmax, vmin;
+
+ vmin.x = vmin.y = GV_MAXFLOAT;
+ vmax.x = vmax.y = -GV_MAXFLOAT;
+
+ num_shapes = gv_shapes_num_shapes(shapes);
+ for (i=0; i < num_shapes; ++i)
+ {
+ GvRect rect;
+ GvShape *shape = gv_shapes_get_shape(shapes,i);
+
+ if( shape == NULL )
+ continue;
+
+ gv_shape_get_extents( shape, &rect );
+
+ if( rect.x != 0 || rect.y != 0
+ || rect.width != 0 || rect.height != 0 )
+ {
+ valid_shapes++;
+ vmin.x = MIN(vmin.x,rect.x);
+ vmax.x = MAX(vmax.x,rect.x+rect.width);
+ vmin.y = MIN(vmin.y,rect.y);
+ vmax.y = MAX(vmax.y,rect.y+rect.height);
+ }
+ }
+
+ if (valid_shapes == 0)
+ {
+ shapes->extents.x = 0;
+ shapes->extents.y = 0;
+ shapes->extents.width = 0;
+ shapes->extents.height = 0;
+ }
+ else
+ {
+ shapes->extents.x = vmin.x;
+ shapes->extents.y = vmin.y;
+ shapes->extents.width = vmax.x - vmin.x;
+ shapes->extents.height = vmax.y - vmin.y;
+ }
+ shapes->extents_valid = TRUE;
+ }
+
+ *rect = shapes->extents;
+}
+
+void
+gv_shapes_replace_shapes(GvShapes *shapes, gint num_shapes, gint *shape_id,
+ GvShape **shps, int make_copy)
+{
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+
+ change_info.num_shapes = num_shapes;
+ change_info.shape_id = shape_id;
+
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ for (i=0; i < num_shapes; ++i)
+ {
+ GvShape *shape;
+
+ if( shape_id[i] < 0 || shape_id[i] >= shapes->shapes->len )
+ continue;
+ else if( gv_shapes_get_shape(shapes, shape_id[i]) != NULL )
+ gv_shape_unref( gv_shapes_get_shape(shapes, shape_id[i]) );
+ else
+ g_warning( "Missing shape in gv_shapes_replace_shapes()" );
+
+ if( make_copy )
+ shape = gv_shape_copy(shps[i]);
+ else
+ shape = shps[i];
+
+ gv_shape_ref( shape );
+ g_ptr_array_index(shapes->shapes, shape_id[i]) = shape;
+ }
+
+ gv_data_changed(GV_DATA(shapes), &change_info);
+}
+
+static void
+gv_shapes_insert_shapes(GvShapes *shapes, gint num_shapes, gint *shape_ids,
+ GvShape **shps)
+{
+ gint i;
+ GvShapeChangeInfo change_info = {GV_CHANGE_ADD, 0, NULL};
+
+ change_info.num_shapes = num_shapes;
+ change_info.shape_id = shape_ids;
+
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ for (i=0; i < num_shapes; ++i)
+ {
+ int id = shape_ids[i];
+
+ if( id >= shapes->shapes->len )
+ {
+ int old_length = shapes->shapes->len;
+
+ g_ptr_array_set_size( shapes->shapes, id+1 );
+ while( old_length < id )
+ {
+ g_ptr_array_index(shapes->shapes, old_length) = NULL;
+ old_length++;
+ }
+
+ gv_shape_ref( shps[i] );
+ g_ptr_array_index( shapes->shapes, id ) = shps[i];
+
+ shapes->actual_num_shapes++;
+ }
+ else if( g_ptr_array_index( shapes->shapes, id ) == NULL )
+ {
+ gv_shape_ref( shps[i] );
+ g_ptr_array_index( shapes->shapes, id ) = shps[i];
+ shapes->actual_num_shapes++;
+ }
+ else
+ {
+ g_warning( "gv_shapes_insert_shapes(): target shape_id not NULL!");
+ }
+ }
+
+ gv_data_changed(GV_DATA(shapes), &change_info);
+}
+
+static void
+gv_shapes_get_memento(GvData *gv_data, gpointer data,
+ GvDataMemento **memento)
+{
+ GvShapes *shapes = GV_SHAPES(gv_data);
+ GvShapesMemento *mem;
+ GvShapeChangeInfo *info = (GvShapeChangeInfo *) data;
+ int i;
+
+ mem = g_new(GvShapesMemento, 1);
+ mem->base.data = GV_DATA(shapes);
+ mem->base.type = info->change_type;
+
+ mem->ids = g_array_new(FALSE, FALSE, sizeof(gint));
+ g_array_append_vals(mem->ids, info->shape_id, info->num_shapes);
+
+ /* Grab in ascending order */
+ if (info->num_shapes > 1)
+ {
+ g_sort_type(mem->ids->data, gint, mem->ids->len);
+ }
+
+ if (info->change_type == GV_CHANGE_ADD)
+ {
+ mem->shapes = NULL;
+ }
+ else
+ {
+ mem->shapes = g_ptr_array_new();
+ for (i=0; i < info->num_shapes; ++i)
+ {
+ GvShape *shape = gv_shapes_get_shape(shapes,info->shape_id[i]);
+
+ shape = gv_shape_copy( shape );
+ gv_shape_ref( shape );
+ g_ptr_array_add(mem->shapes, shape );
+ }
+ }
+
+ *memento = (GvDataMemento*)mem;
+}
+
+static void
+gv_shapes_set_memento(GvData *gv_data, GvDataMemento *data_memento)
+{
+ GvShapes *shapes = GV_SHAPES(gv_data);
+ GvShapesMemento *memento = (GvShapesMemento *) data_memento;
+
+ switch (memento->base.type)
+ {
+ case GV_CHANGE_ADD:
+ gv_shapes_delete_shapes(shapes, memento->ids->len,
+ (gint*)memento->ids->data);
+ break;
+
+ case GV_CHANGE_REPLACE:
+ gv_shapes_replace_shapes(shapes, memento->ids->len,
+ (gint*)memento->ids->data,
+ (GvShape **)memento->shapes->pdata,
+ TRUE);
+ break;
+
+ case GV_CHANGE_DELETE:
+ gv_shapes_insert_shapes(shapes, memento->ids->len,
+ (gint*)memento->ids->data,
+ (GvShape **)memento->shapes->pdata);
+ break;
+ }
+
+ gv_shapes_del_memento((GvData *) shapes, (GvDataMemento *) memento);
+}
+
+static void
+gv_shapes_del_memento(GvData *gv_data, GvDataMemento *data_memento)
+{
+ GvShapesMemento *memento = (GvShapesMemento *) data_memento;
+
+ if (memento->shapes)
+ {
+ int i;
+
+ for (i=0; i < memento->shapes->len; ++i)
+ {
+ gv_shape_unref(g_ptr_array_index(memento->shapes, i));
+ }
+ g_ptr_array_free(memento->shapes, TRUE);
+
+ }
+ g_array_free(memento->ids, TRUE);
+ g_free(memento);
+}
+
+static void
+gv_shapes_changed(GvData *gv_data, gpointer data)
+{
+ GvShapes *shapes = GV_SHAPES(gv_data);
+
+ shapes->extents_valid = FALSE;
+}
+
+static void
+gv_shapes_finalize(GtkObject *object)
+{
+ GvDataClass *parent_class;
+ GvShapes *shapes = GV_SHAPES(object);
+ int i;
+
+ CPLDebug( "OpenEV", "gv_shapes_finalize(%s/%p)",
+ gv_data_get_name( GV_DATA(object) ), object );
+
+ for( i = 0; i < gv_shapes_num_shapes(shapes); i++ )
+ {
+ if( gv_shapes_get_shape(shapes, i) != NULL )
+ gv_shape_unref( gv_shapes_get_shape(shapes, i) );
+ }
+
+ g_ptr_array_free(shapes->shapes,TRUE);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_data_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+#ifndef HAVE_OGR
+GvData *gv_shapes_from_ogr(const char *filename, int iLayer)
+{
+ CPLDebug( "OpenEV",
+ "gv_shapes_from_ogr(%s) called, but OGR not configured",
+ filename );
+ return NULL;
+}
+
+GvData *gv_shapes_from_ogr_layer(void *)
+{
+ CPLDebug( "OpenEV", "gv_shapes_from_ogr_layer() called, "
+ "but OGR not configured" );
+ return NULL;
+}
+#endif
+
+void
+gv_shapes_add_height( GvShapes *shapes, GvData *raster_data, double offset,
+ double default_height )
+{
+ int success, i, num_shapes;
+ double x, y, z, last_z, imaginary, nodata_value;
+ GvRaster *raster = GV_RASTER(raster_data);
+ GvShapeChangeInfo change_info = {GV_CHANGE_REPLACE, 0, NULL};
+ int *id_list;
+
+ /*
+ * Notify of impending change.
+ */
+ num_shapes = gv_shapes_num_shapes(shapes);
+ id_list = g_new( int, num_shapes );
+
+ change_info.num_shapes = 0;
+ change_info.shape_id = id_list;
+
+ for (i=0; i < num_shapes; i++)
+ {
+ if( gv_shapes_get_shape(shapes,i) != NULL )
+ id_list[change_info.num_shapes++] = i;
+ }
+
+ gv_data_changing(GV_DATA(shapes), &change_info);
+
+ /*
+ * Establish the "nodata" value.
+ */
+ success = gv_raster_get_nodata( raster, &nodata_value );
+ if( !success )
+ nodata_value = -1e8;
+
+ /*
+ * Loop over all shapes, applying height.
+ */
+ for (i=0; i < num_shapes; i++)
+ {
+ GvShape *shape = gv_shapes_get_shape(shapes,i);
+ int ring, ring_count = gv_shape_get_rings( shape );
+
+ if( shape == NULL )
+ continue;
+
+ last_z = default_height;
+
+ for( ring = 0; ring < ring_count; ring++ )
+ {
+ int node, node_count = gv_shape_get_nodes( shape, ring );
+
+ for( node = 0; node < node_count; node++ )
+ {
+ double x_orig, y_orig;
+
+ /* get xy in image space */
+ x_orig = x = gv_shape_get_x( shape, ring, node );
+ y_orig = y = gv_shape_get_y( shape, ring, node );
+ z = 0.0;
+
+ if (!gv_raster_georef_to_pixel(raster, &x, &y, &z))
+ {
+ fprintf(stderr, "ERROR raster_georef_to_pixel failed!!!\n");
+ break;
+ }
+
+ if( x > -1.0 && x < 0.0 )
+ x = 0.0;
+ if( y > -1.0 && y < 0.0 )
+ y = 0.0;
+ if( x >= raster->width && x < raster->width+1 )
+ x = raster->width - 0.01;
+ if( y >= raster->height && y < raster->height+1 )
+ y = raster->height - 0.01;
+
+ /* Check if mesh xy values outside of height raster
+ - leave as 0 */
+ if( x >= 0.0 && x < raster->width
+ && y >= 0.0 && y < raster->height )
+ {
+ if (!gv_raster_get_sample(raster, x, y, &z, &imaginary))
+ {
+ fprintf(stderr,
+ "ERROR raster_get_sample failed for (x y z) %f %f\n",
+ x, y);
+ }
+ else
+ {
+ if( z == nodata_value && x > 0 )
+ gv_raster_get_sample(raster, x-1, y, &z,
+ &imaginary);
+
+ if( z == nodata_value && x < raster->width-1 )
+ gv_raster_get_sample(raster, x+1, y, &z,
+ &imaginary);
+
+ if( z == nodata_value && y > 0 )
+ gv_raster_get_sample(raster, x, y-1, &z,
+ &imaginary);
+
+ if( z == nodata_value && y < raster->height-1 )
+ gv_raster_get_sample(raster, x, y+1, &z,
+ &imaginary);
+
+ if( z == nodata_value && x > 1 )
+ gv_raster_get_sample(raster, x-2, y, &z,
+ &imaginary);
+
+ if( z == nodata_value && x < raster->width-2 )
+ gv_raster_get_sample(raster, x+2, y, &z,
+ &imaginary);
+
+ if( z == nodata_value && y > 1 )
+ gv_raster_get_sample(raster, x, y-2, &z,
+ &imaginary);
+
+ if( z == nodata_value && y < raster->height-2 )
+ gv_raster_get_sample(raster, x, y+2, &z,
+ &imaginary);
+
+ if( z == nodata_value )
+ z = last_z;
+ else
+ z += offset;
+
+ last_z = z;
+ }
+ }
+
+ gv_shape_set_xyz( shape, ring, node, x_orig, y_orig, z );
+ }
+ }
+ }
+
+ /* notify of completed change */
+ gv_data_changed(GV_DATA(shapes), &change_info);
+
+ g_free( id_list);
+}
Added: packages/openev/branches/upstream/current/gvshapes.h
===================================================================
--- packages/openev/branches/upstream/current/gvshapes.h (rev 0)
+++ packages/openev/branches/upstream/current/gvshapes.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,254 @@
+/******************************************************************************
+ * $Id: gvshapes.h,v 1.26 2005/01/14 16:51:51 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Definitions of GvShape (single object) and GvShapes (data
+ * container).
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapes.h,v $
+ * Revision 1.26 2005/01/14 16:51:51 gmwalter
+ * Checked in Aude's gv_shapes_add_shape_last function
+ * (allows shapes to be added without repeating
+ * indices if others have been deleted).
+ *
+ * Revision 1.25 2005/01/04 18:50:31 gmwalter
+ * Checked in Aude's new gvshape function changes.
+ *
+ * Revision 1.24 2003/08/29 20:52:43 warmerda
+ * added to/from xml translation for GvShape
+ *
+ * Revision 1.23 2003/06/25 17:06:06 warmerda
+ * added gv_shape_rotate(), gv_shape_scale() and related stuff
+ *
+ * Revision 1.22 2003/01/06 21:20:03 warmerda
+ * added gv_shapes_from_ogr_layer
+ *
+ * Revision 1.21 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.20 2002/07/18 19:33:57 pgs
+ * added gv_shapes_to_dbf
+ *
+ * Revision 1.19 2002/05/07 02:51:15 warmerda
+ * preliminary support for GVSHAPE_COLLECTION
+ *
+ * Revision 1.18 2002/03/07 18:31:56 warmerda
+ * added preliminary gv_shape_clip_to_rect() implementation
+ *
+ * Revision 1.17 2002/03/07 02:31:56 warmerda
+ * added default_height to add_height functions
+ *
+ * Revision 1.16 2001/12/08 04:49:38 warmerda
+ * added point in polygon test
+ *
+ * Revision 1.15 2001/08/08 17:45:48 warmerda
+ * GvShape now referenced counted
+ *
+ * Revision 1.14 2001/01/18 16:48:14 warmerda
+ * added gv_shapes_add_height() and wrappers
+ *
+ * Revision 1.13 2000/08/04 14:14:12 warmerda
+ * GvShapes shape ids now persistent
+ *
+ * Revision 1.12 2000/07/14 14:51:01 warmerda
+ * fixed insert, and delete node support
+ *
+ * Revision 1.11 2000/07/13 19:08:37 warmerda
+ * added coping optional for gv_shapes_replace_shapes
+ *
+ * Revision 1.10 2000/06/28 13:10:42 warmerda
+ * added preliminary OGR support
+ *
+ * Revision 1.9 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_SHAPES_H__
+#define __GV_SHAPES_H__
+
+#include "gvdata.h"
+#include "cpl_minixml.h"
+
+#define GV_TYPE_SHAPES (gv_shapes_get_type ())
+#define GV_SHAPES(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_SHAPES,\
+ GvShapes))
+#define GV_SHAPES_CLASS(klass) (GTK_CHECK_CLASS_CAST((klass),GV_TYPE_SHAPES,\
+ GvShapesClass))
+#define GV_IS_SHAPES(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_SHAPES))
+#define GV_IS_SHAPES_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_SHAPES))
+
+#define GVSHAPE_POINT 1
+#define GVSHAPE_LINE 2
+#define GVSHAPE_AREA 3
+#define GVSHAPE_COLLECTION 4
+
+#define GVSF_TYPE_MASK 0x07
+#define GVSF_CUSTOM_RENDER 0x08
+
+typedef struct
+{
+ guint flags;
+ guint ref_count;
+ GvProperties properties;
+} GvShape;
+
+typedef struct
+{
+ guint flags;
+ guint ref_count;
+ GvProperties properties;
+ gvgeocoord x;
+ gvgeocoord y;
+ gvgeocoord z;
+} GvPointShape;
+
+typedef struct
+{
+ guint flags;
+ guint ref_count;
+ GvProperties properties;
+ int num_nodes;
+ gvgeocoord *xyz_nodes;
+} GvLineShape;
+
+typedef struct
+{
+ guint flags;
+ guint ref_count;
+ GvProperties properties;
+ int num_rings;
+ int *num_ring_nodes;
+ gvgeocoord **xyz_ring_nodes;
+
+ /* tesselation information */
+ gint fill_objects; /* -1 is untesselated, -2 is `do not tesselate' */
+ GArray *mode_offset;
+ GArray *fill;
+} GvAreaShape;
+
+typedef struct
+{
+ guint flags;
+ guint ref_count;
+ GvProperties properties;
+ int geom_count;
+ GvShape **geom_list;
+} GvCollectionShape;
+
+typedef struct
+{
+ GvData data;
+
+ GPtrArray *shapes;
+ int actual_num_shapes; /* not including NULLs in GPtrArray */
+
+ GvRect extents;
+ guint extents_valid : 1;
+} GvShapes;
+
+typedef struct
+{
+ GvDataClass parent_class;
+} GvShapesClass;
+
+GvShape* gv_shape_new( gint type );
+GvShape* gv_shape_from_xml_tree( CPLXMLNode * );
+CPLXMLNode *gv_shape_to_xml_tree( GvShape *psShape );
+
+#define gv_shape_get_properties( shape ) (&(shape)->properties)
+#define gv_shape_type( shape ) ((shape)->flags & GVSF_TYPE_MASK)
+
+void gv_shape_unref( GvShape *shape );
+void gv_shape_ref( GvShape *shape );
+int gv_shape_get_ref( GvShape *shape );
+void gv_shape_delete( GvShape *shape );
+GvShape* gv_shape_copy( GvShape *shape );
+gint gv_shape_get_rings( GvShape *shape );
+gint gv_shape_get_nodes( GvShape *shape, gint ring );
+gvgeocoord gv_shape_get_xyz( GvShape *shape, gint ring, gint node, gint off );
+void gv_shape_get_extents( GvShape *shape, GvRect *rect );
+
+#define gv_shape_get_x(shape,ring,node) gv_shape_get_xyz(shape,ring,node,0)
+#define gv_shape_get_y(shape,ring,node) gv_shape_get_xyz(shape,ring,node,1)
+#define gv_shape_get_z(shape,ring,node) gv_shape_get_xyz(shape,ring,node,2)
+
+gint gv_shape_set_xyz( GvShape *shape, gint ring, gint node,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z );
+gint gv_shape_add_node( GvShape *shape, gint ring,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z );
+gint gv_shape_insert_node( GvShape *shape, gint ring, int node,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z );
+gint gv_shape_delete_node( GvShape *shape, gint ring, gint node );
+gint gv_shape_delete_ring( GvShape *shape, gint ring );
+gint gv_shape_point_in_polygon( GvShape *shape_poly, double x, double y );
+gdouble gv_shape_distance_from_polygon( GvShape *shape_poly, double x, double y );
+GvShape *gv_shape_clip_to_rect( GvShape *shape, GvRect *rect );
+
+void gv_shape_collection_add_shape( GvShape *collection, GvShape *shape );
+GvShape *gv_shape_collection_get_shape( GvShape *collection, int shp_index );
+int gv_shape_collection_get_count( GvShape *collection );
+
+GtkType gv_shapes_get_type (void);
+
+gint gv_area_shape_tessellate(GvAreaShape *area);
+
+int gv_shape_get_count(void);
+gint gv_shape_update_attribute( GvShape *shape, const char *tool,
+ const char *attribute,
+ const char *update_value );
+gint gv_shape_get_center( GvShape *shape, GvVertex3d *xyz );
+gint gv_shape_rotate( GvShape *shape, double angle_in_degrees );
+gint gv_shape_scale( GvShape *shape, double new_scale );
+
+GvData* gv_shapes_new(void);
+GvData* gv_shapes_from_shapefile(const char *);
+GvData* gv_shapes_from_ogr(const char *,int);
+GvData* gv_shapes_from_ogr_layer(void *);
+
+void gv_shapes_add_height(GvShapes *shapes, GvData *raster, double offset,
+ double default_height );
+int gv_shapes_to_shapefile(const char *,GvData *, int);
+int gv_shapes_to_dbf(const char *,GvData * );
+void gv_shapes_get_extents(GvShapes *shapes, GvRect *rect);
+gint gv_shapes_add_shape(GvShapes *shapes, GvShape *shape);
+gint gv_shapes_add_shape_last(GvShapes *shapes, GvShape *shape);
+void gv_shapes_replace_shapes(GvShapes *shapes, gint num_shapes,
+ gint *shape_id, GvShape **shps, int make_copy);
+void gv_shapes_delete_shapes(GvShapes *shapes, gint num_shapes, gint*shapeids);
+void gv_shapes_translate_shapes(GvShapes *shapes, gint num_shapes,
+ gint *shapeids, gvgeocoord dx, gvgeocoord dy );
+
+#define gv_shapes_num_shapes(adata) \
+ (adata->shapes->len)
+
+#define gv_shapes_get_shape(adata,id) \
+ ((GvShape*)g_ptr_array_index(adata->shapes, id))
+
+#ifdef HAVE_OGR
+#define gv_have_ogr_support() 1
+#else
+#define gv_have_ogr_support() 0
+#endif
+
+#endif /*__GV_SHAPES_H__ */
Added: packages/openev/branches/upstream/current/gvshapeslayer.c
===================================================================
--- packages/openev/branches/upstream/current/gvshapeslayer.c (rev 0)
+++ packages/openev/branches/upstream/current/gvshapeslayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2526 @@
+/******************************************************************************
+ * $Id: gvshapeslayer.c,v 1.73 2004/04/08 18:03:18 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for vector shapes.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapeslayer.c,v $
+ * Revision 1.73 2004/04/08 18:03:18 gmwalter
+ * Fix for line node editing, and for area
+ * editing in the case where the first
+ * and last nodes are different but share
+ * either the x or y coordinate.
+ *
+ * Revision 1.72 2004/03/22 19:21:15 gmwalter
+ * Fixed initialization problem.
+ *
+ * Revision 1.71 2004/03/08 18:23:43 gmwalter
+ * Make sure layer's _point_size property is used.
+ *
+ * Revision 1.70 2004/02/12 22:11:21 gmwalter
+ * Update selected shape display in Atlantis
+ * build case.
+ *
+ * Revision 1.69 2004/01/21 01:13:44 sduclos
+ * fix typo
+ *
+ * Revision 1.68 2004/01/20 16:13:01 warmerda
+ * added render plugin support for S52 viewer
+ *
+ * Revision 1.67 2003/09/12 17:35:42 warmerda
+ * Added logic to aggregate selection boxes in the drawinfo.selection_box
+ * rectangle when draw_mode == NORMAL_GET_BOX. This is intended to allow
+ * us to draw a selection box around a complex shapes consisting of multiple
+ * parts offset from the reference point. In the past we only drew the
+ * selection around the first part in such cases. This seems to work though
+ * the testing isn't ... extensive.
+ *
+ * Revision 1.66 2003/09/02 17:22:26 warmerda
+ * added per-layer symbol manager support
+ *
+ * Revision 1.65 2003/08/27 20:03:05 warmerda
+ * Added geo2screen_works to drawinfo structure. It is set to false for text
+ * drawn within symbols since symbol rescaling via glScale() will mess up
+ * the bmfont_draw() logic for ensuring text is drawn "on screen". True
+ * otherwise. It is passed on to gv_view_area_bmfont_draw().
+ *
+ * Revision 1.64 2003/07/03 16:12:05 pgs
+ * fixed bug in y offset of symbols (typo in var name)
+ *
+ * Revision 1.63 2003/05/16 21:31:26 warmerda
+ * added support for passing default color down to components of a symbol
+ *
+ * Revision 1.62 2003/05/16 18:26:33 pgs
+ * added initial code for propogating colors to sub-symbols
+ *
+ * Revision 1.61 2003/05/16 17:42:39 warmerda
+ * fix up pixel offsets for sub-symbols
+ *
+ * Revision 1.60 2003/05/08 19:51:05 warmerda
+ * Fixed node picking for gv_shapes_layer_draw_pen().
+ * Draw selection boxes as squares instead of diamonds.
+ */
+
+#include "gvshapeslayer.h"
+#include "gvutils.h"
+#include "gvrenderinfo.h"
+#include "gvsymbolmanager.h"
+#include "gvmanager.h"
+#include "cpl_error.h"
+#include <GL/gl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gtk/gtksignal.h>
+#include <gmodule.h>
+
+#define DEFAULT_POINT_SIZE 6
+#define DEFAULT_LINE_WIDTH 1.0
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
+#ifndef PI
+#define PI 3.1415927
+#endif
+
+static void gv_shapes_layer_class_init(GvShapesLayerClass *klass);
+static void gv_shapes_layer_init(GvShapesLayer *layer);
+static void gv_shapes_layer_display_change(GvLayer *data,gpointer change_info);
+static void gv_shapes_layer_selection_change(GvLayer *data,
+ gpointer change_info);
+static void gv_shapes_layer_extents(GvLayer *layer, GvRect *rect);
+static void gv_shapes_layer_data_change(GvData *layer, gpointer change_info);
+static void gv_shapes_layer_delete_selected(GvShapeLayer *layer);
+static void gv_shapes_layer_translate_selected(GvShapeLayer *layer,
+ GvVertex *delta);
+static void gv_shapes_layer_pick_shape(GvShapeLayer *layer);
+static void gv_shapes_layer_pick_node(GvShapeLayer *rlayer);
+static void gv_shapes_layer_get_node(GvShapeLayer *layer, GvNodeInfo *info);
+static void gv_shapes_layer_move_node(GvShapeLayer *layer, GvNodeInfo *info);
+static void gv_shapes_layer_insert_node(GvShapeLayer *layer, GvNodeInfo *info);
+static void gv_shapes_layer_delete_node(GvShapeLayer *layer, GvNodeInfo *info);
+static void gv_shapes_layer_node_motion(GvShapeLayer *layer, gint area_id);
+static void gv_shapes_layer_finalize(GtkObject *layer );
+static void gv_shapes_layer_destroy( GtkObject *object );
+
+/************************************************************************/
+/* gv_shapes_layer_get_type() */
+/************************************************************************/
+GtkType
+gv_shapes_layer_get_type(void)
+{
+ static GtkType shapes_layer_type = 0;
+
+ if (!shapes_layer_type)
+ {
+ static const GtkTypeInfo shapes_layer_info =
+ {
+ "GvShapesLayer",
+ sizeof(GvShapesLayer),
+ sizeof(GvShapesLayerClass),
+ (GtkClassInitFunc) gv_shapes_layer_class_init,
+ (GtkObjectInitFunc) gv_shapes_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ shapes_layer_type = gtk_type_unique(gv_shape_layer_get_type(),
+ &shapes_layer_info);
+ }
+ return shapes_layer_type;
+}
+
+/************************************************************************/
+/* gv_shapes_layer_class_init() */
+/************************************************************************/
+static void
+gv_shapes_layer_class_init(GvShapesLayerClass *klass)
+{
+ GvDataClass *data_class;
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ data_class = (GvDataClass*) klass;
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ data_class->changed = gv_shapes_layer_data_change;
+
+ layer_class->draw = gv_shapes_layer_draw;
+ layer_class->extents_request = gv_shapes_layer_extents;
+
+ shape_layer_class->draw_selected = gv_shapes_layer_draw_selected;
+ shape_layer_class->delete_selected = gv_shapes_layer_delete_selected;
+ shape_layer_class->translate_selected = gv_shapes_layer_translate_selected;
+ shape_layer_class->pick_shape = gv_shapes_layer_pick_shape;
+ shape_layer_class->pick_node = gv_shapes_layer_pick_node;
+ shape_layer_class->get_node = gv_shapes_layer_get_node;
+ shape_layer_class->move_node = gv_shapes_layer_move_node;
+ shape_layer_class->insert_node = gv_shapes_layer_insert_node;
+ shape_layer_class->delete_node = gv_shapes_layer_delete_node;
+ shape_layer_class->node_motion = gv_shapes_layer_node_motion;
+
+ ((GtkObjectClass *) klass)->destroy = gv_shapes_layer_destroy;
+ ((GtkObjectClass *) klass)->finalize = gv_shapes_layer_finalize;
+}
+
+/************************************************************************/
+/* gv_shapes_layer_init() */
+/************************************************************************/
+static void
+gv_shapes_layer_init(GvShapesLayer *layer)
+{
+ GvColor default_shapes_color = {0.5, 1.0, 0.5, 1.0};
+
+ /* 0 is always an invalid display list number. */
+ layer->display_list = 0;
+
+ layer->data = NULL;
+ layer->symbol_manager = NULL;
+
+ gv_color_copy(GV_SHAPE_LAYER(layer)->color, default_shapes_color);
+
+ gv_properties_set( &(GV_DATA(layer)->properties), "_point_color",
+ "0.5 1.0 0.5 1.0" );
+ gv_properties_set( &(GV_DATA(layer)->properties), "_line_color",
+ "0.5 1.0 0.5 1.0" );
+ gv_properties_set( &(GV_DATA(layer)->properties), "_line_width",
+ "1.0" );
+ gv_properties_set( &(GV_DATA(layer)->properties), "_area_edge_color",
+ "0.5 1.0 0.5 1.0" );
+ gv_properties_set( &(GV_DATA(layer)->properties), "_area_edge_width",
+ "1.0" );
+ gv_properties_set( &(GV_DATA(layer)->properties), "_area_fill_color",
+ "0.5 1.0 0.5 0.5" );
+
+ gtk_signal_connect_object(GTK_OBJECT(layer), "display-change",
+ GTK_SIGNAL_FUNC(gv_shapes_layer_display_change),
+ GTK_OBJECT(layer));
+ gtk_signal_connect_object(GTK_OBJECT(layer), "selection-changed",
+ GTK_SIGNAL_FUNC(gv_shapes_layer_selection_change),
+ GTK_OBJECT(layer));
+}
+
+/************************************************************************/
+/* gv_shape_layer_new() */
+/************************************************************************/
+GtkObject *
+gv_shapes_layer_new(GvShapes *data)
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER(gtk_type_new(
+ gv_shapes_layer_get_type()));
+
+ if( data != NULL )
+ gv_shapes_layer_set_data( layer, data );
+ else
+ gv_shapes_layer_set_data( layer, GV_SHAPES(gv_shapes_new()) );
+
+ return GTK_OBJECT(layer);
+}
+
+/************************************************************************/
+/* gv_shape_layer_set_data() */
+/************************************************************************/
+void gv_shapes_layer_set_data( GvShapesLayer *layer,
+ GvShapes *data )
+
+{
+ layer->data = data;
+ gv_data_set_parent(GV_DATA(layer), GV_DATA(layer->data));
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_shapes_num_shapes(layer->data));
+
+#ifdef GV_USE_RENDER_PLUGIN
+ {
+ const char *prop_name = "_ogr_driver_name";
+ GvProperties *properties = gv_data_get_properties(GV_DATA(data));
+ const char *prop_value = gv_properties_get(properties, prop_name);
+
+ if (g_module_supported() && (NULL != prop_value)) {
+ gchar* (*get_drv_name) ();
+ gchar *plugin = g_module_build_path("/usr/local/lib", "S52");
+ GModule *module = g_module_open(plugin, G_MODULE_BIND_LAZY);
+
+ if (NULL == module)
+ printf("module error:%s\n", g_module_error());
+ else {
+ if (g_module_symbol(module, prop_name, (gpointer) &get_drv_name)) {
+ void (*layer_init) (GvShapesLayer *layer);
+ gchar *drv_name = get_drv_name();
+
+ if (0 == strcmp(prop_value, drv_name)) {
+ if (g_module_symbol(module, "_layer_init",
+ (gpointer) & layer_init))
+ layer_init(layer);
+ else
+ printf("module error:%s\n", g_module_error());
+ }
+ } else
+ printf("module error:%s\n", g_module_error());
+ }
+ g_free(plugin);
+ }
+ }
+#endif
+
+}
+
+/************************************************************************/
+/* gv_shapes_layer_get_symbol_manager() */
+/************************************************************************/
+
+GtkObject *gv_shapes_layer_get_symbol_manager( GvShapesLayer *layer,
+ int ok_to_create )
+
+{
+ if( ok_to_create && layer->symbol_manager == NULL )
+ layer->symbol_manager = GTK_OBJECT(gv_symbol_manager_new());
+
+ return layer->symbol_manager;
+}
+
+/************************************************************************/
+/* gv_shapes_layer_select_new_shape() */
+/************************************************************************/
+
+gint gv_shapes_layer_select_new_shape( GvShapesLayer *layer, GvShape * shape )
+
+{
+ gint id;
+
+ id = gv_shapes_add_shape(layer->data, shape);
+
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_shapes_num_shapes(layer->data));
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(layer), id);
+
+ return id;
+}
+
+/************************************************************************/
+/* gv_shapes_layer_override_color() */
+/************************************************************************/
+
+void
+gv_shapes_layer_override_color( GvShape * shape, GvColor color,
+ const char * property_name )
+
+{
+ GvProperties *properties = gv_shape_get_properties(shape);
+
+ if( properties != NULL )
+ {
+ const char * user_color;
+
+ user_color = gv_properties_get( properties, property_name);
+
+ if( user_color != NULL )
+ {
+ gv_set_color_from_string( color, user_color,
+ color[0], color[1],
+ color[2], color[3] );
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_get_draw_info() */
+/************************************************************************/
+
+void
+gv_shapes_layer_get_draw_info(GvViewArea *view, GvShapesLayer *layer,
+ GvShapeDrawInfo *drawinfo )
+
+{
+ GvColor def_color;
+
+ gv_color_copy(def_color, GV_SHAPE_LAYER(layer)->color);
+ gv_color_copy(drawinfo->color, def_color );
+
+ gv_set_color_from_string(
+ drawinfo->point_color,
+ gv_properties_get( &(GV_DATA(layer)->properties), "_point_color"),
+ def_color[0], def_color[1], def_color[2], def_color[3]);
+
+ gv_set_color_from_string(
+ drawinfo->line_color,
+ gv_properties_get( &(GV_DATA(layer)->properties), "_line_color"),
+ def_color[0], def_color[1], def_color[2], def_color[3]);
+
+ if( gv_properties_get(&(GV_DATA(layer)->properties),"_line_width") != NULL)
+ drawinfo->line_width =
+ atof(gv_properties_get(&(GV_DATA(layer)->properties),"_line_width"));
+ else
+ drawinfo->line_width = DEFAULT_LINE_WIDTH;
+
+ gv_set_color_from_string(
+ drawinfo->area_edge_color,
+ gv_properties_get( &(GV_DATA(layer)->properties), "_area_edge_color"),
+ def_color[0], def_color[1], def_color[2], def_color[3]);
+
+ if( gv_properties_get(&(GV_DATA(layer)->properties),"_area_edge_width") != NULL)
+ drawinfo->area_edge_width =
+ atof(gv_properties_get(&(GV_DATA(layer)->properties),"_area_edge_width"));
+ else
+ drawinfo->area_edge_width = DEFAULT_LINE_WIDTH;
+
+ gv_set_color_from_string(
+ drawinfo->area_fill_color,
+ gv_properties_get( &(GV_DATA(layer)->properties), "_area_fill_color"),
+ def_color[0], def_color[1], def_color[2], 0.6);
+
+ if( gv_properties_get(&(GV_DATA(layer)->properties),"_point_size") != NULL)
+ drawinfo->point_size =
+ atof(gv_properties_get(&(GV_DATA(layer)->properties),"_point_size"));
+ else
+ drawinfo->point_size = DEFAULT_POINT_SIZE;
+
+ /*
+ * Transform a 1 pixel "right" vector into geo-space. We can compose
+ * a variety of deltas from this for selection boxes, crosshair sizes
+ * and so forth.
+ */
+ drawinfo->dx = 1.0;
+ drawinfo->dy = 0.0;
+ gv_view_area_correct_for_transform(view, drawinfo->dx, drawinfo->dy,
+ &(drawinfo->dx), &(drawinfo->dy) );
+ drawinfo->dunit =
+ sqrt( drawinfo->dx * drawinfo->dx + drawinfo->dy * drawinfo->dy );
+ drawinfo->dpixel = drawinfo->dunit;
+ drawinfo->geo2screen_works = TRUE;
+
+ drawinfo->box_set = FALSE;
+}
+
+/************************************************************************/
+/* gv_draw_info_aggregate_select_region() */
+/* */
+/* Add the passed point to the current selection_box stored in */
+/* the drawinfo. */
+/************************************************************************/
+
+void gv_draw_info_aggregate_select_region( GvShapeDrawInfo *drawinfo,
+ double x, double y )
+
+{
+ if( !drawinfo->box_set )
+ {
+ drawinfo->box_set = TRUE;
+ drawinfo->selection_box.x = x;
+ drawinfo->selection_box.y = y;
+ drawinfo->selection_box.width = 0;
+ drawinfo->selection_box.height = 0;
+ }
+ else
+ {
+ if( x < drawinfo->selection_box.x )
+ {
+ drawinfo->selection_box.width += drawinfo->selection_box.x - x;
+ drawinfo->selection_box.x = x;
+ }
+ else if( x > drawinfo->selection_box.x+drawinfo->selection_box.width )
+ {
+ drawinfo->selection_box.width = x - drawinfo->selection_box.x;
+ }
+
+ if( y < drawinfo->selection_box.y )
+ {
+ drawinfo->selection_box.height += drawinfo->selection_box.y - y;
+ drawinfo->selection_box.y = y;
+ }
+ else if( y > drawinfo->selection_box.y+drawinfo->selection_box.height )
+ {
+ drawinfo->selection_box.height = y - drawinfo->selection_box.y;
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_draw_info_grow_box() */
+/* */
+/* Expand the "selection box" by the indicated factor around */
+/* its center. This is used before drawing it to move it out a */
+/* bit from the object it encloses. Normally the growth factor */
+/* would be 1.2. */
+/************************************************************************/
+
+static void gv_draw_info_grow_box( GvShapeDrawInfo *drawinfo, double factor )
+
+{
+ double center_x, center_y;
+
+ center_x = drawinfo->selection_box.x + drawinfo->selection_box.width * 0.5;
+ center_y = drawinfo->selection_box.y + drawinfo->selection_box.height *0.5;
+
+ drawinfo->selection_box.width *= factor;
+ drawinfo->selection_box.height *= factor;
+
+ /* Don't let the width or height of a selection box be too much smaller
+ than the other dimension. */
+
+ if( drawinfo->selection_box.width < drawinfo->selection_box.height/4.0 )
+ drawinfo->selection_box.width = drawinfo->selection_box.height/4.0;
+
+ if( drawinfo->selection_box.height < drawinfo->selection_box.width/4.0 )
+ drawinfo->selection_box.height = drawinfo->selection_box.width/4.0;
+
+ drawinfo->selection_box.x = center_x - drawinfo->selection_box.width * 0.5;
+ drawinfo->selection_box.y = center_y - drawinfo->selection_box.height *0.5;
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_label() */
+/************************************************************************/
+
+static void
+gv_shapes_layer_draw_label( GvViewArea *view, GvShapesLayer *layer,
+ GvShape *shape, GvShapeDrawInfo *drawinfo,
+ gvgeocoord x, gvgeocoord y,
+ GvLabelRenderPart *label_info,
+ gv_draw_mode draw_mode )
+
+{
+ gvgeocoord x_offset; /* for shadow and halo effects */
+ gvgeocoord y_offset;
+/* -------------------------------------------------------------------- */
+/* Apply any offsets. */
+/* -------------------------------------------------------------------- */
+ x += label_info->x_offset_g;
+ y += label_info->y_offset_g;
+
+ if( label_info->x_offset_px != 0.0 || label_info->y_offset_px != 0.0 )
+ {
+ x += label_info->x_offset_px * drawinfo->dpixel;
+ y -= label_info->y_offset_px * drawinfo->dpixel;
+ }
+
+ /* draw text effects first */
+ if (label_info->halo || label_info->shadow)
+ {
+ x_offset = drawinfo->dpixel;
+ y_offset = drawinfo->dpixel;
+
+ if (label_info->halo)
+ {
+ glColor4fv(label_info->background_color);
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x - x_offset, y - y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x - x_offset, y ,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x - x_offset, y + y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x, y + y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x + x_offset, y + y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x + x_offset, y,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x + x_offset, y - y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x, y - y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ }
+
+ if (label_info->shadow)
+ {
+ glColor4fv(label_info->background_color);
+ gv_view_area_bmfont_draw( view, label_info->font,
+ x + x_offset, y + y_offset,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ }
+ }
+
+ if (label_info->b_color_initialized)
+ glColor4fv( label_info->color );
+ else
+ glColor4fv( drawinfo->color );
+
+/* -------------------------------------------------------------------- */
+/* Draw the text itself. */
+/* -------------------------------------------------------------------- */
+ if( draw_mode != PICKING )
+ {
+ /* When dragging text, there is an extra translation applied
+ which gv_view_Area_bmfont_draw() isn't able to account for
+ while trying to keep the RasterPos in the frustrum. Restore
+ the original translation value, and offset the x,y passed to
+ the bmfont drawer. */
+
+ if( draw_mode == SELECTED
+ && (GV_SHAPE_LAYER(layer)->selected_motion.x != 0
+ || GV_SHAPE_LAYER(layer)->selected_motion.y != 0) )
+ {
+ glTranslate(-GV_SHAPE_LAYER(layer)->selected_motion.x,
+ -GV_SHAPE_LAYER(layer)->selected_motion.y,
+ 0.0 );
+ gv_view_area_bmfont_draw(
+ view, label_info->font,
+ x + GV_SHAPE_LAYER(layer)->selected_motion.x,
+ y + GV_SHAPE_LAYER(layer)->selected_motion.y,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ glTranslate(GV_SHAPE_LAYER(layer)->selected_motion.x,
+ GV_SHAPE_LAYER(layer)->selected_motion.y,
+ 0.0 );
+ }
+ else
+ {
+ gv_view_area_bmfont_draw( view, label_info->font, x, y,
+ label_info->text,
+ !drawinfo->geo2screen_works );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Draw the selection box, or a filled polygon depending on mode. */
+/* -------------------------------------------------------------------- */
+ if( draw_mode != NORMAL )
+ {
+ gvgeocoord ll_px, ll_py, ur_px, ur_py, ur_geox, ur_geoy;
+ gvgeocoord ul_geox, ul_geoy, lr_geox, lr_geoy;
+
+ gv_view_area_inverse_map_pointer( view, x, y, &ll_px, &ll_py );
+ ll_px -= 2;
+ ll_py += 2 + label_info->descent;
+ ur_px = ll_px + label_info->width + 4;
+ ur_py = ll_py - label_info->height - 4;
+ gv_view_area_map_pointer( view, ur_px, ur_py, &ur_geox, &ur_geoy );
+ gv_view_area_map_pointer( view, ll_px, ll_py, &x, &y );
+ gv_view_area_map_pointer( view, ll_px, ur_py, &ul_geox, &ul_geoy );
+ gv_view_area_map_pointer( view, ur_px, ll_py, &lr_geox, &lr_geoy );
+
+ if( draw_mode == NORMAL_GET_BOX )
+ {
+ gv_draw_info_aggregate_select_region( drawinfo, x, y );
+ gv_draw_info_aggregate_select_region( drawinfo, ur_geox, ur_geoy );
+ }
+ else if( draw_mode == SELECTED )
+ {
+ /* Draw box around text */
+ glBegin(GL_LINE_LOOP);
+ glVertex3(x, y, 0.0);
+ glVertex3(ul_geox, ul_geoy, 0.0);
+ glVertex3(ur_geox, ur_geoy, 0.0);
+ glVertex3(lr_geox, lr_geoy, 0.0);
+ glEnd();
+ }
+ else /* picking ... draw filled box */
+ {
+ glBegin(GL_POLYGON);
+ glVertex3(x, y, 0.0);
+ glVertex3(ul_geox, ul_geoy, 0.0);
+ glVertex3(ur_geox, ur_geoy, 0.0);
+ glVertex3(lr_geox, lr_geoy, 0.0);
+ glVertex3(x, y, 0.0);
+ glEnd();
+
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_symbol() */
+/************************************************************************/
+
+static void
+gv_shapes_layer_draw_symbol( GvViewArea *view, GvShapesLayer *layer,
+ GvShape *shape, GvShapeDrawInfo *drawinfo,
+ gvgeocoord x, gvgeocoord y, gvgeocoord z,
+ GvSymbolRenderPart *symbol_info,
+ int part_index, gv_draw_mode draw_mode )
+
+{
+ guint sym_id = -1;
+ GvSymbolObj *poSymbol = NULL;
+
+ if( EQUALN(symbol_info->symbol_id, "ogr-sym-", 8) )
+ {
+ sym_id = atoi(symbol_info->symbol_id + 8);
+ }
+ else
+ {
+ if( layer->symbol_manager != NULL
+ && gv_symbol_manager_has_symbol(
+ GV_SYMBOL_MANAGER(layer->symbol_manager),
+ symbol_info->symbol_id ) )
+ poSymbol = gv_symbol_manager_get_symbol(
+ GV_SYMBOL_MANAGER(layer->symbol_manager),
+ symbol_info->symbol_id );
+ else
+ poSymbol = gv_symbol_manager_get_symbol( gv_get_symbol_manager(),
+ symbol_info->symbol_id );
+
+ if (poSymbol == NULL)
+ CPLDebug( "OpenEV", "poSymbol is NULL !!! " );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Render raster symbol. */
+/* -------------------------------------------------------------------- */
+ if( poSymbol != NULL && poSymbol->type == GV_SYMBOL_RASTER )
+ {
+ gvgeocoord bx, by;
+
+ /* Compute the lower left corner of the raster assuming it is to be
+ centered on the point before offsets */
+ bx = x + symbol_info->x_offset_g;
+ by = y + symbol_info->y_offset_g;
+
+ bx = bx + (symbol_info->x_offset_px - poSymbol->width/2)
+ * drawinfo->dpixel;
+ by = by - (symbol_info->y_offset_px - poSymbol->height/2)
+ * drawinfo->dpixel;
+
+ /* Draw an outline slightly larger than the raster to indicate
+ selection. Draw a filled polygon the same size as the raster
+ when picking */
+
+ if( draw_mode != NORMAL )
+ {
+ gvgeocoord geo_width, geo_height, mult_fac = 1.0, box_x, box_y;
+
+ if( draw_mode == SELECTED )
+ mult_fac = 1.2;
+
+ geo_width = poSymbol->width * mult_fac * drawinfo->dpixel;
+ geo_height = poSymbol->height * mult_fac * drawinfo->dpixel;
+
+ box_x = x + symbol_info->x_offset_g - geo_width/2.0
+ + symbol_info->x_offset_px * drawinfo->dpixel;
+ box_y = y + symbol_info->y_offset_g - geo_height/2.0
+ - symbol_info->y_offset_px * drawinfo->dpixel;
+
+ if( draw_mode == NORMAL_GET_BOX )
+ {
+ gv_draw_info_aggregate_select_region( drawinfo, box_x, box_y);
+ gv_draw_info_aggregate_select_region( drawinfo,
+ box_x + geo_width,
+ box_y + geo_height );
+ }
+ else
+ {
+ /* Draw box around symbol */
+ glBegin( draw_mode == SELECTED ? GL_LINE_LOOP : GL_POLYGON );
+ glVertex3(box_x,box_y,0.0);
+ glVertex3(box_x+geo_width,box_y,0.0);
+ glVertex3(box_x+geo_width,box_y+geo_height,0.0);
+ glVertex3(box_x,box_y+geo_height,0.0);
+ glVertex3(box_x,box_y,0.0);
+ glEnd();
+ }
+ }
+
+ /* Draw the raster (as long as we aren't picking) */
+ if( draw_mode != PICKING )
+ {
+ glRasterPos3d( bx, by, z );
+ glPixelZoom(1.0,-1.0);
+ glDrawPixels( poSymbol->width, poSymbol->height, GL_RGBA,
+ GL_UNSIGNED_INT_8_8_8_8_REV, poSymbol->buffer );
+ }
+
+ }
+
+/* -------------------------------------------------------------------- */
+/* Render vector symbols. */
+/* -------------------------------------------------------------------- */
+ else if( sym_id != -1
+ || (poSymbol != NULL && poSymbol->type == GV_SYMBOL_VECTOR) )
+ {
+ gvgeocoord cx, cy;
+ gvgeocoord base_vector = drawinfo->dunit * drawinfo->point_size;
+
+ if (symbol_info->b_color_initialized)
+ glColor4fv( symbol_info->color );
+ else
+ glColor4fv( drawinfo->color );
+
+ /* Perform any required pixel or georeferenced translation of the
+ center point */
+
+ cx = x + symbol_info->x_offset_g;
+ cy = y + symbol_info->y_offset_g;
+
+ if(symbol_info->x_offset_px != 0.0 || symbol_info->y_offset_px != 0.0)
+ {
+ cx = cx + symbol_info->x_offset_px * drawinfo->dpixel;
+ cy = cy - symbol_info->y_offset_px * drawinfo->dpixel;
+ }
+
+ glTranslate( cx, cy, z );
+
+ if( symbol_info->scale != 1.0 )
+ glScale( symbol_info->scale,
+ symbol_info->scale,
+ symbol_info->scale );
+
+ if( symbol_info->angle != 0.0 )
+ glRotate( symbol_info->angle, 0.0, 0.0, 1.0 );
+
+ switch( sym_id )
+ {
+ case -1: /* general vector symbol */
+ {
+ GvShape *shape_obj = (GvShape *) poSymbol->buffer;
+ gvgeocoord base_scale;
+ GvShapeDrawInfo sub_drawinfo;
+
+ /* Initialize renderinfo */
+ if( symbol_info->part_index == GVP_UNINITIALIZED_PART )
+ {
+ int scale_dep = FALSE;
+ int sub_part_index;
+
+ sub_part_index =
+ gv_shape_layer_build_renderinfo( GV_SHAPE_LAYER(layer),
+ shape_obj,
+ &scale_dep );
+
+ /* symbol_info may have moved, so re-fetch based on index */
+ symbol_info = (GvSymbolRenderPart *)
+ gv_shape_layer_get_part( GV_SHAPE_LAYER(layer),
+ part_index );
+ symbol_info->part_index = sub_part_index;
+ if( symbol_info->part_index == GVP_UNINITIALIZED_PART )
+ symbol_info->part_index = GVP_LAST_PART;
+ }
+
+ memcpy( &sub_drawinfo, drawinfo, sizeof(GvShapeDrawInfo) );
+ sub_drawinfo.dx = 1.0;
+ sub_drawinfo.dy = 0.0;
+ sub_drawinfo.dunit = 1.0;
+ sub_drawinfo.dpixel *= 1/(drawinfo->dunit * symbol_info->scale);
+ sub_drawinfo.geo2screen_works = FALSE;
+ sub_drawinfo.box_set = FALSE;
+
+ if (symbol_info->b_color_initialized)
+ gv_color_copy( sub_drawinfo.color, symbol_info->color );
+
+ base_scale = drawinfo->dunit;
+
+ glScale( base_scale, base_scale, base_scale );
+
+ gv_shapes_layer_draw_shape( view, layer, symbol_info->part_index,
+ shape_obj,
+ draw_mode == SELECTED ? NORMAL_GET_BOX : draw_mode,
+ &sub_drawinfo );
+
+ if( draw_mode == SELECTED && sub_drawinfo.box_set )
+ {
+ draw_mode = NORMAL; /* disable later selection drawing */
+
+ gv_draw_info_grow_box( &sub_drawinfo, 1.2 );
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2(
+ sub_drawinfo.selection_box.x,
+ sub_drawinfo.selection_box.y );
+ glVertex2(
+ sub_drawinfo.selection_box.x + sub_drawinfo.selection_box.width,
+ sub_drawinfo.selection_box.y );
+ glVertex2(
+ sub_drawinfo.selection_box.x + sub_drawinfo.selection_box.width,
+ sub_drawinfo.selection_box.y + sub_drawinfo.selection_box.height);
+ glVertex2(
+ sub_drawinfo.selection_box.x,
+ sub_drawinfo.selection_box.y + sub_drawinfo.selection_box.height);
+ glEnd();
+ }
+ else if( draw_mode == NORMAL_GET_BOX )
+ {
+ /* We should transform the box in sub_drawinfo and move
+ it into drawinto ... but thats hard so I am deferring
+ it till needed. */
+ }
+ glScale( 1.0/base_scale, 1.0/base_scale, 1.0/base_scale );
+ }
+ break;
+
+ case 0: /* cross */
+ glBegin(GL_LINES);
+ glVertex3(-base_vector, 0,0.0);
+ glVertex3( base_vector, 0,0.0);
+ glVertex3( 0, -base_vector,0.0);
+ glVertex3( 0, base_vector,0.0);
+ glEnd();
+ break;
+
+ case 1: /* X */
+ glBegin(GL_LINES);
+ glVertex3(-base_vector, -base_vector,0.0);
+ glVertex3( base_vector, base_vector,0.0);
+ glVertex3( -base_vector, base_vector,0.0);
+ glVertex3( base_vector, -base_vector,0.0);
+ glEnd();
+ break;
+
+ case 2: /* unfilled circle */
+ glBegin(GL_LINE_LOOP);
+ glVertex3(base_vector*0.0,base_vector*1.0,0.0);
+ glVertex3(base_vector*0.342020148171,
+ base_vector*0.939692619022,0.0);
+ glVertex3(base_vector*0.642787617587,
+ base_vector*0.76604443649,0.0);
+ glVertex3(base_vector*0.866025411519,
+ base_vector*0.499999986603,0.0);
+ glVertex3(base_vector*0.984807756594,
+ base_vector*0.173648157354,0.0);
+ glVertex3(base_vector*0.984807748535,
+ base_vector*-0.173648203059,0.0);
+ glVertex3(base_vector*0.866025388314,
+ base_vector*-0.500000026795,0.0);
+ glVertex3(base_vector*0.642787582035,
+ base_vector*-0.766044466322,0.0);
+ glVertex3(base_vector*0.34202010456,
+ base_vector*-0.939692634895,0.0);
+ glVertex3(base_vector*0,
+ base_vector*-1.0,0.0);
+ glVertex3(base_vector*-0.342020191783,
+ base_vector*-0.93969260314,0.0);
+ glVertex3(base_vector*-0.642787653139,
+ base_vector*-0.76604440665,0.0);
+ glVertex3(base_vector*-0.866025434725,
+ base_vector*-0.49999994641,0.0);
+ glVertex3(base_vector*-0.984807764653,
+ base_vector*-0.17364811164,0.0);
+ glVertex3(base_vector*-0.984807740476,
+ base_vector*0.173648248764,0.0);
+ glVertex3(base_vector*-0.866025365109,
+ base_vector*0.500000066987,0.0);
+ glVertex3(base_vector*-0.642787546482,
+ base_vector*0.766044496153,0.0);
+ glVertex3(base_vector*-0.342020060949,
+ base_vector*0.939692650769,0.0);
+ glVertex3(base_vector*9.28204133326e-08,
+ base_vector*1.0,0.0);
+ glEnd();
+ break;
+
+ case 3: /* filled circle */
+ glBegin(GL_POLYGON);
+ glVertex3(base_vector*0.0,base_vector*1.0,0.0);
+ glVertex3(base_vector*0.342020148171,
+ base_vector*0.939692619022,0.0);
+ glVertex3(base_vector*0.642787617587,
+ base_vector*0.76604443649,0.0);
+ glVertex3(base_vector*0.866025411519,
+ base_vector*0.499999986603,0.0);
+ glVertex3(base_vector*0.984807756594,
+ base_vector*0.173648157354,0.0);
+ glVertex3(base_vector*0.984807748535,
+ base_vector*-0.173648203059,0.0);
+ glVertex3(base_vector*0.866025388314,
+ base_vector*-0.500000026795,0.0);
+ glVertex3(base_vector*0.642787582035,
+ base_vector*-0.766044466322,0.0);
+ glVertex3(base_vector*0.34202010456,
+ base_vector*-0.939692634895,0.0);
+ glVertex3(base_vector*0,base_vector*-1.0,0.0);
+ glVertex3(base_vector*-0.342020191783,
+ base_vector*-0.93969260314,0.0);
+ glVertex3(base_vector*-0.642787653139,
+ base_vector*-0.76604440665,0.0);
+ glVertex3(base_vector*-0.866025434725,
+ base_vector*-0.49999994641,0.0);
+ glVertex3(base_vector*-0.984807764653,
+ base_vector*-0.17364811164,0.0);
+ glVertex3(base_vector*-0.984807740476,
+ base_vector*0.173648248764,0.0);
+ glVertex3(base_vector*-0.866025365109,
+ base_vector*0.500000066987,0.0);
+ glVertex3(base_vector*-0.642787546482,
+ base_vector*0.766044496153,0.0);
+ glVertex3(base_vector*-0.342020060949,
+ base_vector*0.939692650769,0.0);
+ glVertex3(base_vector*9.28204133326e-08,base_vector*1.0,0.0);
+ glEnd();
+ break;
+
+ case 4: /* square */
+ glBegin( GL_LINE_LOOP );
+ glVertex3( -base_vector, -base_vector ,0.0);
+ glVertex3( -base_vector, base_vector ,0.0);
+ glVertex3( base_vector, base_vector ,0.0);
+ glVertex3( base_vector, -base_vector ,0.0);
+ glVertex3( -base_vector, -base_vector ,0.0);
+ glEnd();
+ break;
+
+ case 5: /* filled square */
+ glBegin( GL_POLYGON );
+ glVertex3( -base_vector, -base_vector ,0.0);
+ glVertex3( -base_vector, base_vector ,0.0);
+ glVertex3( base_vector, base_vector ,0.0);
+ glVertex3( base_vector, -base_vector ,0.0);
+ glVertex3( -base_vector, -base_vector ,0.0);
+ glEnd();
+ break;
+
+ case 6: /* triangle */
+ glBegin(GL_LINE_LOOP);
+ glVertex3( 0, base_vector ,0.0);
+ glVertex3( -base_vector*0.866, -base_vector*0.5,0.0);
+ glVertex3( base_vector*0.866, -base_vector*0.5,0.0);
+ glVertex3( 0, base_vector ,0.0);
+ glEnd();
+ break;
+
+ case 7: /* filled triangle */
+ glBegin(GL_POLYGON);
+ glVertex3( 0, base_vector ,0.0);
+ glVertex3( base_vector*0.866, -base_vector*0.5,0.0);
+ glVertex3( -base_vector*0.866, -base_vector*0.5,0.0);
+ glVertex3( 0, base_vector ,0.0);
+ glEnd();
+ break;
+
+ case 8: /* star */
+ glBegin( GL_LINE_LOOP );
+ glVertex3(0.0,base_vector*1.0,0.0);
+ glVertex3(base_vector*0.587785222255,
+ base_vector*-0.809017016198,0.0);
+ glVertex3(base_vector*-0.951056493349,
+ base_vector*0.309017064997,0.0);
+ glVertex3(base_vector*0.951056522032,
+ base_vector*0.309016976719,0.0);
+ glVertex3(base_vector*-0.587785297348,
+ base_vector*-0.80901696164,0.0);
+ glVertex3(0.0,base_vector*1.0,0.0);
+ glEnd();
+ break;
+
+ case 9: /* filled star */
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * -0.195928, base_vector * 0.269672,0.0);
+ glVertex3(base_vector * 0.000000, base_vector * 1.000000,0.0);
+ glVertex3(base_vector * 0.195928, base_vector * 0.269672,0.0);
+ glEnd();
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * 0.195928, base_vector * 0.269672,0.0);
+ glVertex3(base_vector * 0.951057, base_vector * 0.309017,0.0);
+ glVertex3(base_vector * 0.317019, base_vector * -0.103006,0.0);
+ glEnd();
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * 0.317019, base_vector * -0.103006,0.0);
+ glVertex3(base_vector * 0.587785, base_vector * -0.809017,0.0);
+ glVertex3(base_vector * 0.000000, base_vector * -0.333333,0.0);
+ glEnd();
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * 0.000000, base_vector * -0.333333,0.0);
+ glVertex3(base_vector * -0.587785, base_vector * -0.809017,0.0);
+ glVertex3(base_vector * -0.317019, base_vector * -0.103006,0.0);
+ glEnd();
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * -0.317019, base_vector * -0.103006,0.0);
+ glVertex3(base_vector * -0.951057, base_vector * 0.309017,0.0);
+ glVertex3(base_vector * -0.195928, base_vector * 0.269672,0.0);
+ glEnd();
+ glBegin( GL_POLYGON );
+ glVertex3(base_vector * 0.195928, base_vector * 0.269672,0.0);
+ glVertex3(base_vector * 0.317019, base_vector * -0.103006,0.0);
+ glVertex3(base_vector * 0.000000, base_vector * -0.333333,0.0);
+ glVertex3(base_vector * -0.317019, base_vector * -0.103006,0.0);
+ glVertex3(base_vector * -0.195928, base_vector * 0.269672,0.0);
+ glEnd();
+
+ case 10: /* vertical bar */
+ glBegin(GL_LINES);
+ glVertex3( 0, 0 ,0.0);
+ glVertex3( 0, base_vector ,0.0);
+ glEnd();
+ break;
+ }
+
+ if( symbol_info->angle != 0.0 )
+ glRotatef( -symbol_info->angle,0.0,0.0, 1.0 );
+
+ if( draw_mode == SELECTED )
+ {
+ float bx = base_vector * 1.2;
+
+ /* Draw box around crosshairs */
+ glBegin(GL_LINE_LOOP);
+ glVertex3(-bx, -bx,0.0);
+ glVertex3( bx, -bx,0.0);
+ glVertex3( bx, bx,0.0);
+ glVertex3(-bx, bx,0.0);
+ glEnd();
+ }
+ else if( draw_mode == NORMAL_GET_BOX )
+ {
+ float bx = base_vector;
+
+ /* We do not currently take symbol rotation angle into account. */
+
+ gv_draw_info_aggregate_select_region( drawinfo,
+ cx - bx*symbol_info->scale,
+ cy - bx*symbol_info->scale );
+ gv_draw_info_aggregate_select_region( drawinfo,
+ cx + bx*symbol_info->scale,
+ cy + bx*symbol_info->scale );
+ }
+
+ if( symbol_info->scale != 1.0 )
+ {
+ float one_over_scale;
+
+ one_over_scale = 1/symbol_info->scale;
+ glScale( one_over_scale, one_over_scale, one_over_scale );
+ }
+
+ glTranslate( -cx, -cy, -z );
+ }
+ else
+ {
+ CPLDebug( "OpenEV", "symbol not understood" );
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_pen() */
+/************************************************************************/
+
+static void
+gv_shapes_layer_draw_pen( GvViewArea *view, GvShape *shape,
+ GvShapeDrawInfo *drawinfo,
+ GvPenRenderPart *pen_info,
+ gv_draw_mode draw_mode )
+
+{
+ double box_vector = drawinfo->dunit*(DEFAULT_POINT_SIZE+pen_info->width/2-1);
+ guint pen_id = -1;
+
+ GLint factor = 1;
+ GLushort stipple = 0xFFFF;
+
+ if (pen_info->b_color_initialized)
+ glColor4fv( pen_info->color );
+ else
+ glColor4fv( drawinfo->color );
+
+ glLineWidth( pen_info->width );
+
+ if( draw_mode != PICKING
+ && EQUALN(pen_info->pattern, "ogr-pen-", 8) )
+ {
+ pen_id = atoi(pen_info->pattern + 8);
+ }
+
+ /*
+ A note about pen stippling. According to the OpenGL spec,
+ the stipple pattern is a 16 bit number used as a mask. Any
+ bit that is set is visible in the output, any bit not set
+ ends up not visible. Factor is a linear multiplication of
+ the stipple pattern so a factor of 2 gives 32 bits but each
+ bit controls two pixels instead of 1. Another important
+ piece of information: stippling is used from the lowest bit
+ to the highest bit (right to left as you look at the number).
+
+ 0xFFFF is all bits on
+ 0x0000 is all bits off
+ 0x0F0F is a dash pattern with four on/four off
+
+ All patterns must have a repeat of 16.
+ */
+
+ if (pen_id != -1)
+ {
+ switch( pen_id )
+ {
+ case 0: /* default pen, don't use stippling */
+ pen_id = -1;
+ break;
+ case 1: /* invisible pen */
+ factor = 1;
+ stipple = 0x0000;
+ break;
+ case 2: /* dash */
+ factor = 1;
+ stipple = 0x0F0F;
+ break;
+ case 3: /* short dash */
+ factor = 1;
+ stipple = 0x0F0F;
+ break;
+ case 4: /* long dash */
+ factor = 3;
+ stipple = 0x0F0F;
+ break;
+ case 5: /* dot */
+ factor = 1;
+ stipple = 0x3333;
+ break;
+ case 6: /* dash-dot */
+ factor = 2;
+ stipple = 0x2727;
+ break;
+ case 7: /* dash-dot-dot */
+ factor = 2;
+ stipple = 0x333F;
+ break;
+ case 8: /*alternate pixels */
+ factor = 1;
+ stipple = 0x5555;
+ break;
+ default: /* default to pen 0 which is no stipple */
+ pen_id = -1;
+ }
+ }
+
+ if (pen_id != -1)
+ {
+ // On some ATI OpenGL drivers (eg Xpert2000) we need
+ // to set line width to 1 to get stipples working.
+ // glLineWidth( 1.0 );
+
+ glEnable( GL_LINE_STIPPLE );
+ glLineStipple( factor, stipple );
+ }
+
+ if( gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+ int j;
+
+ glVertexPointer( 3, GL_GEOCOORD, 0, line->xyz_nodes );
+ glDrawArrays( GL_LINE_STRIP, 0, line->num_nodes );
+
+ //revert line width for drawing the boxes
+ glLineWidth( 1.0 );
+ glLineStipple( 1, 0xffff );
+
+ /* Draw small box around each point, in picking mode we fill it. */
+ if( draw_mode == PICKING || draw_mode == SELECTED )
+ {
+ for (j=0; j < line->num_nodes; ++j)
+ {
+ gvgeocoord x, y;
+
+ x = line->xyz_nodes[j*3];
+ y = line->xyz_nodes[j*3+1];
+
+ if( draw_mode == PICKING )
+ glBegin(GL_POLYGON);
+ else
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x-box_vector, y-box_vector);
+ glVertex2(x+box_vector, y-box_vector);
+ glVertex2(x+box_vector, y+box_vector);
+ glVertex2(x-box_vector, y+box_vector);
+ glEnd();
+ }
+ }
+ else if( draw_mode == NORMAL_GET_BOX )
+ {
+ int j;
+ for (j=0; j < line->num_nodes; ++j)
+ {
+ gv_draw_info_aggregate_select_region( drawinfo,
+ line->xyz_nodes[j*3],
+ line->xyz_nodes[j*3+1] );
+ }
+ }
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+ int ring, j;
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ if( area->num_ring_nodes[ring] > 1 )
+ {
+ glVertexPointer( 3, GL_GEOCOORD, 0,
+ area->xyz_ring_nodes[ring] );
+ glDrawArrays( GL_LINE_STRIP, 0,
+ area->num_ring_nodes[ring] );
+ }
+ }
+ /* revert to 1 pixel lines for the boxes */
+ glLineWidth( 1.0 );
+ glLineStipple( 1, 0xffff );
+
+ /* selection/picking per-node work */
+ for( ring = 0;
+ ring < area->num_rings && draw_mode != NORMAL;
+ ring++ )
+ {
+ for (j=0; j < area->num_ring_nodes[ring]; ++j)
+ {
+ gvgeocoord x, y;
+
+ x = area->xyz_ring_nodes[ring][j*3];
+ y = area->xyz_ring_nodes[ring][j*3+1];
+
+ if( draw_mode == NORMAL_GET_BOX )
+ {
+ gv_draw_info_aggregate_select_region( drawinfo, x, y );
+ }
+ else
+ {
+ if( draw_mode == PICKING )
+ glBegin(GL_POLYGON);
+ else
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x-box_vector, y-box_vector);
+ glVertex2(x+box_vector, y-box_vector);
+ glVertex2(x+box_vector, y+box_vector);
+ glVertex2(x-box_vector, y+box_vector);
+ glEnd();
+ }
+ }
+ }
+ }
+ else if( gv_shape_type(shape) == GVSHAPE_COLLECTION )
+ {
+ int i, count = gv_shape_collection_get_count( shape );
+
+ for( i = 0; i < count; i++ )
+ gv_shapes_layer_draw_pen( view,
+ gv_shape_collection_get_shape(shape,i),
+ drawinfo, pen_info, draw_mode );
+ }
+ else
+ {
+ g_warning( "GvShapesLayer: pen tool on point ignored." );
+ }
+
+ if (pen_id != -1)
+ glDisable( GL_LINE_STIPPLE );
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_brush() */
+/************************************************************************/
+
+static void
+gv_shapes_layer_draw_brush( GvViewArea *view, GvShape *shape,
+ GvShapeDrawInfo *drawinfo,
+ GvBrushRenderPart *brush_info,
+ gv_draw_mode draw_mode )
+
+{
+
+ GvAreaShape *area = (GvAreaShape *) shape;
+ int fill_object, ring;
+ double box_vector = drawinfo->dunit * DEFAULT_POINT_SIZE;
+
+ if( gv_shape_type(shape) != GVSHAPE_AREA )
+ {
+ if( gv_shape_type(shape) == GVSHAPE_COLLECTION )
+ {
+ int i, count = gv_shape_collection_get_count( shape );
+
+ for( i = 0; i < count; i++ )
+ gv_shapes_layer_draw_brush(
+ view, gv_shape_collection_get_shape(shape,i),
+ drawinfo, brush_info, draw_mode );
+ }
+ else
+ {
+ static int bWarningIssued = FALSE;
+
+ if( !bWarningIssued )
+ {
+ bWarningIssued = TRUE;
+ g_warning( "GvShapesLayer: BRUSH tool on non-area ignored." );
+ }
+ }
+
+ return;
+ }
+
+ if (brush_info->b_fore_color_initialized)
+ glColor4fv( brush_info->fore_color );
+ else
+ glColor4fv( drawinfo->color );
+
+ if( area->fill_objects == -1 )
+ {
+ gv_area_shape_tessellate( area );
+ }
+
+ if( area->fill != NULL && area->fill_objects > 0 )
+ {
+ glVertexPointer(3, GL_GEOCOORD, 0, area->fill->data );
+
+ for( fill_object = 0;
+ fill_object < area->fill_objects;
+ fill_object++ )
+ {
+ int f_offset=g_array_index(area->mode_offset,gint,
+ fill_object*2+1);
+ int f_mode = g_array_index(area->mode_offset,gint,
+ fill_object*2);
+ int f_len;
+
+ if( fill_object == area->fill_objects-1 )
+ f_len = area->fill->len - f_offset;
+ else
+ f_len = g_array_index(area->mode_offset,gint,
+ fill_object*2+3)
+ - f_offset;
+
+ glDrawArrays(f_mode, f_offset, f_len);
+ }
+ }
+
+ /* Draw small box around each point in selected mode */
+ for( ring = 0;
+ ring < area->num_rings && draw_mode == SELECTED;
+ ring++ )
+ {
+ int j;
+
+ for (j=0; j < area->num_ring_nodes[ring]; ++j)
+ {
+ gvgeocoord x, y;
+
+ x = area->xyz_ring_nodes[ring][j*3];
+ y = area->xyz_ring_nodes[ring][j*3+1];
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x-box_vector, y-box_vector);
+ glVertex2(x+box_vector, y-box_vector);
+ glVertex2(x+box_vector, y+box_vector);
+ glVertex2(x-box_vector, y+box_vector);
+ glEnd();
+ }
+ }
+
+ if( draw_mode == NORMAL_GET_BOX )
+ {
+ int j;
+
+ for (j=0; j < area->num_ring_nodes[ring]; ++j)
+ {
+ gvgeocoord x, y;
+
+ x = area->xyz_ring_nodes[ring][j*3];
+ y = area->xyz_ring_nodes[ring][j*3+1];
+
+ gv_draw_info_aggregate_select_region( drawinfo, x, y );
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_shape() */
+/************************************************************************/
+
+void gv_shapes_layer_draw_shape( GvViewArea *view, GvShapesLayer *layer,
+ int part_index, GvShape *shape_obj,
+ gv_draw_mode draw_mode,
+ GvShapeDrawInfo *drawinfo )
+{
+ gvgeocoord x, y, z;
+ GvShapeDrawInfo sAltDrawInfo;
+
+/* -------------------------------------------------------------------- */
+/* If we weren't provided with layer drawing defaults, compute */
+/* some now. */
+/* -------------------------------------------------------------------- */
+ if( drawinfo == NULL )
+ {
+ gv_shapes_layer_get_draw_info( view, layer, &sAltDrawInfo );
+ drawinfo = &sAltDrawInfo;
+ }
+
+ if( part_index != GVP_LAST_PART )
+ {
+ int part_draw_mode = draw_mode;
+
+ while( part_index != GVP_LAST_PART )
+ {
+ GvRenderPart *part_info;
+ int part_type, next_part_index;
+
+ part_type = gv_part_index_to_type( part_index );
+ part_info = gv_shape_layer_get_part( GV_SHAPE_LAYER(layer),
+ part_index );
+ next_part_index = part_info->next_part;
+
+ /* if there are multiple parts, we need to aggregate
+ selection boxes. */
+
+ if( part_draw_mode == SELECTED
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT
+ && next_part_index != GVP_LAST_PART )
+ part_draw_mode = NORMAL_GET_BOX;
+
+
+ g_assert( part_info != NULL );
+
+ if( part_type == GvLabelPart
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ {
+ x = ((GvPointShape *) shape_obj)->x;
+ y = ((GvPointShape *) shape_obj)->y;
+ z = ((GvPointShape *) shape_obj)->z;
+
+ gv_shapes_layer_draw_label( view, layer, shape_obj, drawinfo,
+ x, y,
+ (GvLabelRenderPart *) part_info,
+ part_draw_mode );
+ }
+ else if( part_type == GvSymbolPart
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ {
+ x = ((GvPointShape *) shape_obj)->x;
+ y = ((GvPointShape *) shape_obj)->y;
+ z = ((GvPointShape *) shape_obj)->z;
+
+ gv_shapes_layer_draw_symbol( view, layer, shape_obj, drawinfo,
+ x, y, z,
+ (GvSymbolRenderPart *) part_info,
+ part_index, part_draw_mode );
+ }
+ else if( part_type == GvPenPart )
+ {
+ gv_shapes_layer_draw_pen( view, shape_obj, drawinfo,
+ (GvPenRenderPart *) part_info,
+ part_draw_mode );
+ }
+ else if( part_type == GvBrushPart )
+ {
+ gv_shapes_layer_draw_brush(view, shape_obj, drawinfo,
+ (GvBrushRenderPart *) part_info,
+ part_draw_mode );
+ }
+
+ part_index = next_part_index;
+
+ /* We only draw the first part with a selection box. */
+ if( part_draw_mode == SELECTED )
+ part_draw_mode = NORMAL;
+ }
+
+ /* do we need to draw the selection box now? */
+ if( part_draw_mode == NORMAL_GET_BOX && draw_mode == SELECTED )
+ {
+ gv_draw_info_grow_box( drawinfo, 1.2 );
+
+ /* draw box around cross hair */
+ glBegin(GL_LINE_LOOP);
+ glVertex2(
+ drawinfo->selection_box.x,
+ drawinfo->selection_box.y );
+ glVertex2(
+ drawinfo->selection_box.x + drawinfo->selection_box.width,
+ drawinfo->selection_box.y );
+ glVertex2(
+ drawinfo->selection_box.x + drawinfo->selection_box.width,
+ drawinfo->selection_box.y + drawinfo->selection_box.height);
+ glVertex2(
+ drawinfo->selection_box.x,
+ drawinfo->selection_box.y + drawinfo->selection_box.height);
+ glEnd();
+ }
+ }
+
+ else if( gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ {
+ if( draw_mode != PICKING )
+ {
+ GvColor point_color;
+ double dx = drawinfo->dx * drawinfo->point_size;
+ double dy = drawinfo->dy * drawinfo->point_size;
+
+ gv_color_copy( point_color, drawinfo->point_color );
+
+ gv_shapes_layer_override_color( shape_obj, point_color,
+ "_gv_color" );
+ glColor4fv(point_color);
+
+ x = ((GvPointShape *) shape_obj)->x;
+ y = ((GvPointShape *) shape_obj)->y;
+ z = ((GvPointShape *) shape_obj)->z;
+
+ /* default to simple cross */
+ glBegin(GL_LINES);
+ glVertex3(x-dx, y-dy, z);
+ glVertex3(x+dx, y+dy, z);
+ glVertex3(x+dy, y-dx, z);
+ glVertex3(x-dy, y+dx, z);
+ glEnd();
+ }
+
+ if( draw_mode == SELECTED || draw_mode == PICKING )
+ {
+ double delta = drawinfo->dunit *(drawinfo->point_size+2);
+
+ x = ((GvPointShape *) shape_obj)->x;
+ y = ((GvPointShape *) shape_obj)->y;
+ z = ((GvPointShape *) shape_obj)->z;
+
+ /* draw box around cross hair */
+ if( draw_mode == SELECTED )
+ glBegin(GL_LINE_LOOP);
+ else
+ glBegin(GL_POLYGON);
+
+ glVertex3(x-delta, y-delta, z);
+ glVertex3(x+delta, y-delta, z);
+ glVertex3(x+delta, y+delta, z);
+ glVertex3(x-delta, y+delta, z);
+ glEnd();
+ }
+ else if( draw_mode == NORMAL_GET_BOX )
+ {
+ double delta = drawinfo->dunit *(drawinfo->point_size+2);
+
+ x = ((GvPointShape *) shape_obj)->x;
+ y = ((GvPointShape *) shape_obj)->y;
+
+ gv_draw_info_aggregate_select_region( drawinfo,
+ x - delta, y - delta );
+ gv_draw_info_aggregate_select_region( drawinfo,
+ x + delta, y + delta );
+ }
+ }
+
+ else if( gv_shape_type(shape_obj) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape_obj;
+
+ if( draw_mode != PICKING )
+ {
+ GvColor color;
+
+ gv_color_copy( color, drawinfo->line_color );
+
+ gv_shapes_layer_override_color( shape_obj, color, "_gv_color" );
+ glColor4fv(color);
+ }
+
+ glLineWidth( drawinfo->line_width );
+
+ glVertexPointer( 3, GL_GEOCOORD, 0, line->xyz_nodes );
+ glDrawArrays( GL_LINE_STRIP, 0, line->num_nodes );
+
+ glLineWidth( DEFAULT_LINE_WIDTH );
+
+ if( draw_mode == SELECTED || draw_mode == PICKING )
+ {
+#ifdef ATLANTIS_BUILD
+ /* Atlantis builds: polygon selection draws small
+ diamonds around nodes instead of large squares */
+ double delta = drawinfo->dunit
+ * (DEFAULT_POINT_SIZE + drawinfo->line_width - 1 ) * 0.5;
+
+#else
+ double delta = drawinfo->dunit
+ * (DEFAULT_POINT_SIZE + drawinfo->line_width - 1 );
+#endif
+ int j;
+
+ /* Draw small box around each point */
+ for (j=0; j < line->num_nodes; ++j)
+ {
+ x = line->xyz_nodes[j*3];
+ y = line->xyz_nodes[j*3+1];
+
+ if( draw_mode == SELECTED )
+ glBegin(GL_LINE_LOOP);
+ else
+ glBegin(GL_POLYGON);
+#ifdef ATLANTIS_BUILD
+ glVertex2(x, y-delta);
+ glVertex2(x-delta, y);
+ glVertex2(x, y+delta);
+ glVertex2(x+delta, y);
+
+#else
+ glVertex2(x-delta, y-delta);
+ glVertex2(x+delta, y-delta);
+ glVertex2(x+delta, y+delta);
+ glVertex2(x-delta, y+delta);
+#endif
+ glEnd();
+ }
+ }
+ else if( draw_mode == NORMAL_GET_BOX )
+ {
+ int j;
+ for (j=0; j < line->num_nodes; ++j)
+ {
+ x = line->xyz_nodes[j*3];
+ y = line->xyz_nodes[j*3+1];
+
+ }
+ gv_draw_info_aggregate_select_region( drawinfo, x, y );
+ }
+ }
+
+ else if( gv_shape_type(shape_obj) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape_obj;
+ int want_fill = drawinfo->area_fill_color[3] > 0.001;
+ int fill_object, ring;
+ int gl_line_mode = GL_LINE_STRIP;
+ GvColor color;
+
+
+ if( want_fill && area->fill_objects == -1 )
+ gv_area_shape_tessellate( area );
+
+ if( area->fill != NULL && area->fill_objects > 0 && want_fill )
+ {
+ /* set fill color */
+ if( draw_mode != PICKING )
+ {
+ gv_color_copy( color, drawinfo->area_fill_color );
+
+ gv_shapes_layer_override_color( shape_obj, color,
+ "_gv_fill_color" );
+ glColor4fv(color);
+ }
+
+ glVertexPointer(3, GL_GEOCOORD, 0, area->fill->data );
+ gl_line_mode = GL_LINE_LOOP;
+ }
+
+ for( fill_object = 0;
+ fill_object < area->fill_objects && want_fill;
+ fill_object++ )
+ {
+ int f_offset=g_array_index(area->mode_offset,gint,
+ fill_object*2+1);
+ int f_mode = g_array_index(area->mode_offset,gint,
+ fill_object*2);
+ int f_len;
+
+ if( fill_object == area->fill_objects-1 )
+ f_len = area->fill->len - f_offset;
+ else
+ f_len = g_array_index(area->mode_offset,gint,
+ fill_object*2+3)
+ - f_offset;
+
+ glDrawArrays(f_mode, f_offset, f_len);
+ }
+
+ /* Get edge color */
+ gv_color_copy( color, drawinfo->area_edge_color );
+ gv_shapes_layer_override_color( shape_obj, color, "_gv_color" );
+
+ /* only draw the edge if it's not transparent */
+ if (color[3] > 0.001 || draw_mode != NORMAL )
+ {
+ glLineWidth( drawinfo->area_edge_width );
+
+ if( draw_mode != PICKING )
+ glColor4fv(color);
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ if( area->num_ring_nodes[ring] > 1 )
+ {
+ glVertexPointer( 3, GL_GEOCOORD, 0,
+ area->xyz_ring_nodes[ring] );
+ glDrawArrays( gl_line_mode, 0,
+ area->num_ring_nodes[ring] );
+ }
+ }
+ glLineWidth( DEFAULT_LINE_WIDTH );
+
+ if( draw_mode == SELECTED || draw_mode == PICKING )
+ {
+#ifdef ATLANTIS_BUILD
+ /* Atlantis builds: polygon selection draws small
+ diamonds around nodes instead of large squares */
+ double delta = drawinfo->dunit
+ * (DEFAULT_POINT_SIZE + drawinfo->line_width - 1 ) * 0.5;
+
+#else
+ double delta = drawinfo->dunit
+ * (DEFAULT_POINT_SIZE + drawinfo->line_width - 1 );
+#endif
+ int j;
+
+ for( ring = 0; ring < area->num_rings; ring++ )
+ {
+ /* Draw small box around each point */
+ if( draw_mode == SELECTED )
+ glColor4f(color[0], color[1], color[2], 1.0);
+
+ for (j=0; j < area->num_ring_nodes[ring]; ++j)
+ {
+ x = area->xyz_ring_nodes[ring][j*3];
+ y = area->xyz_ring_nodes[ring][j*3+1];
+
+ if( draw_mode == NORMAL_GET_BOX )
+ gv_draw_info_aggregate_select_region( drawinfo,
+ x, y );
+ else
+ {
+ if( draw_mode == SELECTED )
+ glBegin(GL_LINE_LOOP);
+ else
+ glBegin(GL_POLYGON);
+
+#ifdef ATLANTIS_BUILD
+ glVertex2(x, y-delta);
+ glVertex2(x-delta, y);
+ glVertex2(x, y+delta);
+ glVertex2(x+delta, y);
+
+#else
+ glVertex2(x-delta, y-delta);
+ glVertex2(x+delta, y-delta);
+ glVertex2(x+delta, y+delta);
+ glVertex2(x-delta, y+delta);
+#endif
+ glEnd();
+ }
+ }
+ }
+ }
+ }
+ }
+ else if( gv_shape_type(shape_obj) == GVSHAPE_COLLECTION )
+ {
+ int i_sub, count = gv_shape_collection_get_count( shape_obj );
+
+ for( i_sub = 0; i_sub < count; i_sub++ )
+ {
+ GvShape *sub_shape
+ = gv_shape_collection_get_shape(shape_obj, i_sub);
+
+ gv_shapes_layer_draw_shape( view, layer, GVP_LAST_PART,
+ sub_shape, draw_mode, drawinfo );
+ }
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw() */
+/************************************************************************/
+void
+gv_shapes_layer_draw(GvLayer *r_layer, GvViewArea *view)
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER(r_layer);
+ gint i, shape_count;
+ gint *selected, presentation;
+ GvShapeDrawInfo drawinfo;
+ gint bAntialiased, in_list_count = 0, out_list_count = 0;
+ const char * pszAntialiased;
+#ifdef ATLANTIS_BUILD
+ int bDisplayListsEnabled = 0; /* display lists unreliable */
+#else
+ int bDisplayListsEnabled =
+ gv_manager_get_preference(gv_get_manager(),"display_lists") == NULL
+ || EQUAL(gv_manager_get_preference(gv_get_manager(),
+ "display_lists"),"ON");
+#endif
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ shape_count = gv_shapes_num_shapes(layer->data);
+
+/* -------------------------------------------------------------------- */
+/* Setup layer wide drawing state. */
+/* -------------------------------------------------------------------- */
+ gv_shapes_layer_get_draw_info( view, layer, &drawinfo );
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ //this enables anti-aliasing for lines, points and polygons
+ pszAntialiased = gv_properties_get( &(GV_DATA(layer)->properties),
+ "_gl_antialias");
+
+ //the property can be NULL or 0 to turn it off, otherwise it is on
+ if (pszAntialiased == NULL )
+ {
+ bAntialiased = FALSE;
+ }
+ else if (strcmp(pszAntialiased, "0") == 0)
+ {
+ bAntialiased = FALSE;
+ }
+ else
+ {
+ bAntialiased = TRUE;
+ }
+
+ if (bAntialiased)
+ glEnable( GL_LINE_SMOOTH );
+
+/* -------------------------------------------------------------------- */
+/* Draw all shapes that are not scale dependent, potentially */
+/* using a display list. */
+/* -------------------------------------------------------------------- */
+ if( glIsList( layer->display_list ) )
+ {
+ glCallList( layer->display_list );
+ }
+ else if( bDisplayListsEnabled )
+ {
+ layer->display_list = glGenLists( 1 );
+ glNewList( layer->display_list, GL_COMPILE_AND_EXECUTE );
+
+ for (i=0; i < shape_count; ++i)
+ {
+ GvShape *shape_obj;
+ guint part_index;
+
+ if (selected[i] && !presentation)
+ continue;
+
+ shape_obj = gv_shapes_get_shape(layer->data,i);
+ if( shape_obj == NULL )
+ continue;
+
+ /*
+ * We need to ensure the parts are initialized as this sets the
+ * scale dependent flag we need to test.
+ */
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i );
+ if( part_index == GVP_UNINITIALIZED_PART )
+ {
+ gv_shape_layer_update_renderinfo( GV_SHAPE_LAYER(layer), i );
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i);
+ g_assert( part_index != GVP_UNINITIALIZED_PART );
+ }
+
+ /* Cross hairs are scale dependent drawing. */
+ if( part_index == GVP_LAST_PART
+ && gv_shape_type(shape_obj) == GVSHAPE_POINT )
+ gv_shape_layer_set_scale_dep( GV_SHAPE_LAYER(layer),
+ i, TRUE );
+
+ /*
+ * Only draw this shape as part of the display list if it is
+ * not scale dependent.
+ */
+ if( !gv_shape_layer_get_scale_dep( GV_SHAPE_LAYER(layer), i ) )
+ {
+ in_list_count++;
+ drawinfo.box_set = FALSE;
+ gv_shapes_layer_draw_shape( view, layer, part_index, shape_obj,
+ NORMAL, &drawinfo );
+ }
+ }
+
+ glEndList();
+ }
+
+/* -------------------------------------------------------------------- */
+/* Draw all scale dependent shapes. */
+/* -------------------------------------------------------------------- */
+ for (i=0; i < shape_count; ++i)
+ {
+ GvShape *shape_obj;
+ guint part_index;
+
+ if (selected[i] && !presentation)
+ continue;
+
+ shape_obj = gv_shapes_get_shape(layer->data,i);
+ if( shape_obj == NULL )
+ continue;
+
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i );
+
+ if( part_index == GVP_UNINITIALIZED_PART )
+ {
+ gv_shape_layer_update_renderinfo( GV_SHAPE_LAYER(layer), i );
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i);
+ g_assert( part_index != GVP_UNINITIALIZED_PART );
+ }
+
+ if( !bDisplayListsEnabled
+ || gv_shape_layer_get_scale_dep( GV_SHAPE_LAYER(layer), i ) )
+ {
+ out_list_count++;
+ drawinfo.box_set = FALSE;
+ gv_shapes_layer_draw_shape( view, layer, part_index, shape_obj,
+ NORMAL, &drawinfo );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Restore drawing state. */
+/* -------------------------------------------------------------------- */
+ glDisable(GL_BLEND);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (bAntialiased)
+ glDisable( GL_LINE_SMOOTH );
+
+
+ if( in_list_count > 0 )
+ {
+ CPLDebug( "OpenEV", "GvShapesLayer: %d in display list, %d not.",
+ in_list_count, out_list_count );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Do we need to draw selected shapes now? */
+/* -------------------------------------------------------------------- */
+ if( gv_shape_layer_selected( GV_SHAPE_LAYER(layer), GV_FIRST, &i )
+ && !GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ gv_shapes_layer_draw_selected(GV_SHAPE_LAYER(layer), view);
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_draw_selected() */
+/************************************************************************/
+
+void
+gv_shapes_layer_draw_selected(GvShapeLayer *r_layer, GvViewArea *view)
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER(r_layer);
+ gint i, shape_count;
+ gint *selected;
+ GvShapeDrawInfo drawinfo;
+
+ gv_shapes_layer_get_draw_info( view, layer, &drawinfo );
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+ shape_count = gv_shapes_num_shapes(layer->data);
+
+ /*
+ ideal box size for around point cross hairs.
+
+ bx = by = drawinfo.point_size + 2;
+ gv_view_area_correct_for_transform(view, bx, by, &bx, &by);
+ */
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ for (i=0; i < shape_count; ++i)
+ {
+ GvShape *shape_obj;
+ guint part_index;
+
+ /* skip unselected shapes */
+ if (!selected[i])
+ continue;
+
+ /* fetch the shape itself */
+ shape_obj = gv_shapes_get_shape(layer->data, i);
+ if( shape_obj == NULL )
+ continue;
+
+ /* get information on first part, ogrfs driven. */
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i );
+ if( part_index == GVP_UNINITIALIZED_PART )
+ {
+ gv_shape_layer_update_renderinfo( GV_SHAPE_LAYER(layer), i );
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i);
+ g_assert( part_index != GVP_UNINITIALIZED_PART );
+ }
+
+ /* draw the shape in selected mode. */
+ drawinfo.box_set = FALSE;
+ gv_shapes_layer_draw_shape( view, layer, part_index, shape_obj,
+ SELECTED, &drawinfo );
+ }
+ glDisable(GL_BLEND);
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_pick_shape() */
+/************************************************************************/
+static void
+gv_shapes_layer_pick_shape(GvShapeLayer *r_layer)
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER(r_layer);
+ gint i, shape_count;
+ GvShapeDrawInfo drawinfo;
+ GvViewArea *view;
+
+ view = GV_VIEW_AREA(GV_LAYER(r_layer)->view);
+ gv_shapes_layer_get_draw_info( view, layer, &drawinfo );
+
+ if (!gv_layer_is_visible(GV_LAYER(layer))) return;
+ shape_count = gv_shapes_num_shapes(layer->data);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ for (i=0; i < shape_count; ++i)
+ {
+ GvShape * shape_obj = gv_shapes_get_shape(layer->data, i);
+ guint part_index;
+
+ if( shape_obj == NULL )
+ continue;
+
+ /* get information on first part, ogrfs driven. */
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i );
+ if( part_index == GVP_UNINITIALIZED_PART )
+ {
+ gv_shape_layer_update_renderinfo( GV_SHAPE_LAYER(layer), i );
+ part_index =
+ gv_shape_layer_get_first_part_index( GV_SHAPE_LAYER(layer), i);
+ g_assert( part_index != GVP_UNINITIALIZED_PART );
+ }
+
+ /* Load the "ID" of the shape being drawn. */
+ glLoadName(i);
+
+ /* Draw it in PICKING mode */
+ drawinfo.box_set = FALSE;
+ gv_shapes_layer_draw_shape( view, layer, part_index, shape_obj,
+ PICKING, &drawinfo );
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_pick_node() */
+/************************************************************************/
+static void
+gv_shapes_layer_pick_node(GvShapeLayer *rlayer)
+{
+ GvShape *shape;
+ gint sel, i, r;
+ GvShapeDrawInfo drawinfo;
+ double dx, dy, dsize;
+
+ if (!gv_layer_is_visible(GV_LAYER(rlayer))) return;
+
+ if (!gv_shape_layer_selected(rlayer, GV_FIRST, &sel))
+ return;
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(rlayer)->data, sel);
+ if( shape == NULL )
+ return;
+
+ /* How big should node be drawn? We want this to match the size
+ they are normally drawn visibly */
+
+ gv_shapes_layer_get_draw_info( GV_LAYER(rlayer)->view,
+ GV_SHAPES_LAYER(rlayer), &drawinfo );
+
+ dsize = drawinfo.dunit;
+ dx = dsize * (drawinfo.point_size+2);
+ dy = dsize * (drawinfo.point_size+2);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ /* Nodes first */
+ glLoadName(0);
+ glPushName(-1);
+ glPointSize(2.0);
+ for (r=0; r < gv_shape_get_rings(shape); ++r)
+ {
+ int num_nodes = gv_shape_get_nodes(shape,r);
+
+ glLoadName(r);
+ glPushName(-1);
+
+ for (i=0; i < num_nodes; ++i)
+ {
+ double x, y, z;
+
+ x = gv_shape_get_x(shape,r,i);
+ y = gv_shape_get_y(shape,r,i);
+ z = gv_shape_get_z(shape,r,i);
+
+ glLoadName(i);
+
+ glBegin(GL_POLYGON);
+ glVertex3(x-dx, y-dy, z);
+ glVertex3(x+dy, y-dx, z);
+ glVertex3(x+dx, y+dy, z);
+ glVertex3(x-dy, y+dx, z);
+ glVertex3(x-dx, y-dy, z);
+ glEnd();
+
+ }
+ glPopName(); /* node id */
+ }
+ glPopName(); /* ring id */
+
+ /* Segments next */
+ glLoadName(1);
+ glPushName(-1);
+ for (r=0; r < gv_shape_get_rings(shape); ++r)
+ {
+ int num_nodes = gv_shape_get_nodes(shape,r);
+
+ glLoadName(r);
+
+ /* First segment connects last vertex to first vertex:
+ "before" vertex zero as long as the line wouldn't be degenerate. */
+
+ /* April, 2004 bug fix: the last vertex-first vertex segment
+ * should not be drawn for line shapes, as this can cause problems
+ * with editing if another segment of the line is contained within
+ * the segment, eg:
+ * N6----------N7
+ * | |
+ * N1 N5--N4 N8
+ * | |
+ * N2-------N3
+ * clicking to create a new node on the N4-N5 segment would
+ * actually result in a node being inserted before N1.
+ */
+ glPushName(0);
+ if( (gv_shape_type(shape) != GVSHAPE_LINE) &&
+ (gv_shape_get_x(shape,r,num_nodes-1) != gv_shape_get_x(shape,r,0)
+ || gv_shape_get_y(shape,r,num_nodes-1) != gv_shape_get_y(shape,r,0)))
+ {
+ glBegin(GL_LINES);
+ glVertex3( gv_shape_get_x(shape,r,num_nodes-1),
+ gv_shape_get_y(shape,r,num_nodes-1),
+ gv_shape_get_z(shape,r,num_nodes-1));
+ glVertex3( gv_shape_get_x(shape,r,0),
+ gv_shape_get_y(shape,r,0),
+ gv_shape_get_z(shape,r,0));
+ glEnd();
+ }
+
+ for (i=1; i < num_nodes; ++i)
+ {
+ glLoadName(i);
+ glBegin(GL_LINES);
+ glVertex3( gv_shape_get_x(shape,r,i),
+ gv_shape_get_y(shape,r,i),
+ gv_shape_get_z(shape,r,i));
+ glVertex3( gv_shape_get_x(shape,r,i-1),
+ gv_shape_get_y(shape,r,i-1),
+ gv_shape_get_z(shape,r,i-1));
+ glEnd();
+ }
+ glPopName(); /* node id */
+ }
+ glPopName(); /* ring id */
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_get_node() */
+/************************************************************************/
+static void
+gv_shapes_layer_get_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ GvShape *shape;
+
+ shape = gv_shapes_get_shape( GV_SHAPES_LAYER(layer)->data,
+ info->shape_id );
+ if( shape == NULL )
+ return;
+
+ if( gv_shape_type(shape) == GVSHAPE_POINT )
+ info->vertex = (GvVertex *) &((GvPointShape *) shape)->x;
+ else if( gv_shape_type(shape) == GVSHAPE_LINE )
+ {
+ GvLineShape *line = (GvLineShape *) shape;
+
+ info->vertex = (GvVertex *) (line->xyz_nodes + 3*info->node_id);
+ }
+
+ else if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ GvAreaShape *area = (GvAreaShape *) shape;
+ gvgeocoord *ring = area->xyz_ring_nodes[info->ring_id];
+
+ info->vertex = (GvVertex *) (ring + 3*info->node_id);
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_move_node() */
+/************************************************************************/
+static void
+gv_shapes_layer_move_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ GvShape *shape;
+
+ shape = gv_shapes_get_shape( GV_SHAPES_LAYER(layer)->data,
+ info->shape_id );
+ if( shape == NULL )
+ return;
+
+ shape = gv_shape_copy( shape );
+
+ gv_shape_set_xyz( shape, info->ring_id, info->node_id,
+ info->vertex->x,
+ info->vertex->y,
+ 0.0 );
+
+ gv_shapes_replace_shapes( GV_SHAPES_LAYER(layer)->data,
+ 1, &(info->shape_id),
+ &shape, FALSE );
+}
+
+/************************************************************************/
+/* gv_shapes_layer_insert_node() */
+/************************************************************************/
+static void
+gv_shapes_layer_insert_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ GvShape *shape;
+
+ shape = gv_shapes_get_shape( GV_SHAPES_LAYER(layer)->data,
+ info->shape_id );
+ if( shape == NULL )
+ return;
+
+ shape = gv_shape_copy( shape );
+
+ gv_shape_insert_node( shape, info->ring_id, info->node_id,
+ info->vertex->x, info->vertex->y, 0.0 );
+
+ gv_shapes_replace_shapes( GV_SHAPES_LAYER(layer)->data,
+ 1, &(info->shape_id),
+ &shape, FALSE );
+}
+
+/************************************************************************/
+/* gv_shapes_layer_delete_node() */
+/************************************************************************/
+static void
+gv_shapes_layer_delete_node(GvShapeLayer *layer, GvNodeInfo *info)
+{
+ GvShape *shape;
+
+ shape = gv_shapes_get_shape( GV_SHAPES_LAYER(layer)->data,
+ info->shape_id );
+ if( shape == NULL )
+ return;
+
+ shape = gv_shape_copy( shape );
+
+ gv_shape_delete_node( shape, info->ring_id, info->node_id );
+
+ /* delete the ring, if it is now empty */
+ if( gv_shape_get_nodes( shape, info->ring_id ) == 0 )
+ gv_shape_delete_ring( shape, info->ring_id );
+
+ /* Delete the shape if it is now empty */
+ if( gv_shape_get_rings( shape ) == 0 )
+ {
+ gv_shape_layer_clear_selection( layer );
+ gv_shapes_delete_shapes( GV_SHAPES_LAYER(layer)->data,
+ 1, &(info->shape_id) );
+ gv_shape_delete( shape );
+ }
+ else
+ {
+ gv_shapes_replace_shapes( GV_SHAPES_LAYER(layer)->data,
+ 1, &(info->shape_id),
+ &shape, FALSE );
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_node_motion() */
+/************************************************************************/
+static void
+gv_shapes_layer_node_motion(GvShapeLayer *layer, gint area_id)
+{
+ GvShape *shape;
+
+ shape = gv_shapes_get_shape( GV_SHAPES_LAYER(layer)->data, area_id );
+ if( shape == NULL )
+ return;
+
+ if( gv_shape_type(shape) == GVSHAPE_AREA )
+ {
+ ((GvAreaShape *) shape)->fill_objects = -2;
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_delete_selected() */
+/************************************************************************/
+static void
+gv_shapes_layer_delete_selected(GvShapeLayer *layer)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ gv_shapes_delete_shapes(GV_SHAPES_LAYER(layer)->data,
+ sel->len, (gint*)sel->data);
+ gv_shape_layer_clear_selection(layer);
+ }
+ g_array_free(sel, TRUE);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_translate_selected() */
+/************************************************************************/
+static void
+gv_shapes_layer_translate_selected(GvShapeLayer *layer, GvVertex *delta)
+{
+ GArray *sel;
+
+ sel = g_array_new(FALSE, FALSE, sizeof(gint));
+ if (gv_shape_layer_selected(GV_SHAPE_LAYER(layer), GV_ALL, sel))
+ {
+ /* This will force a selection clear */
+ gv_shapes_translate_shapes(GV_SHAPES_LAYER(layer)->data,
+ sel->len, (gint*)sel->data,
+ delta->x, delta->y);
+ }
+ g_array_free(sel, TRUE);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_extents() */
+/************************************************************************/
+static void
+gv_shapes_layer_extents(GvLayer *layer, GvRect *rect)
+{
+ gv_shapes_get_extents(GV_SHAPES_LAYER(layer)->data, rect);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_data_change() */
+/************************************************************************/
+static void
+gv_shapes_layer_data_change(GvData *data, gpointer change_info)
+{
+ GvShapesLayer *layer = GV_SHAPES_LAYER(data);
+
+ gv_shape_layer_clear_all_renderinfo( GV_SHAPE_LAYER(data) );
+
+ /* Reset the selected array to reflect the data length */
+ gv_shape_layer_set_num_shapes(GV_SHAPE_LAYER(layer),
+ gv_shapes_num_shapes(layer->data));
+
+ /* clear the display list if the data changes, this will cause a new
+ list to be created the next time it is drawn */
+ if (glIsList(layer->display_list))
+ {
+ glDeleteLists( layer->display_list, 1 );
+ layer->display_list = 0;
+ }
+
+}
+
+/************************************************************************/
+/* gv_shapes_layer_selection_change() */
+/************************************************************************/
+static void gv_shapes_layer_selection_change(GvLayer *data,
+ gpointer change_info )
+
+{
+ /* If the selection changes, we need to clear the display list. */
+
+ if (glIsList(GV_SHAPES_LAYER(data)->display_list))
+ {
+ glDeleteLists( GV_SHAPES_LAYER(data)->display_list, 1 );
+ GV_SHAPES_LAYER(data)->display_list = 0;
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_display_change() */
+/************************************************************************/
+static void
+gv_shapes_layer_display_change(GvLayer *data, gpointer change_info)
+
+{
+ gv_shape_layer_clear_all_renderinfo( GV_SHAPE_LAYER(data) );
+
+ /* clear the display list if the data changes, this will cause a new
+ list to be created the next time it is drawn */
+ if (glIsList(GV_SHAPES_LAYER(data)->display_list))
+ {
+ glDeleteLists( GV_SHAPES_LAYER(data)->display_list, 1 );
+ GV_SHAPES_LAYER(data)->display_list = 0;
+ }
+}
+
+/************************************************************************/
+/* gv_shapes_layer_destroy() */
+/************************************************************************/
+
+static void gv_shapes_layer_destroy( GtkObject *gtk_object )
+
+{
+ GvShapeLayerClass *parent_class;
+ GvShapesLayer *slayer = GV_SHAPES_LAYER(gtk_object);
+
+ CPLDebug( "OpenEV", "gv_shapes_layer_destroy(%s)",
+ gv_data_get_name(GV_DATA(slayer)) );
+
+ if( slayer->symbol_manager != NULL )
+ {
+ gtk_object_unref( GTK_OBJECT(slayer->symbol_manager) );
+ slayer->symbol_manager = NULL;
+ }
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_shape_layer_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(gtk_object);
+}
+
+/************************************************************************/
+/* gv_shapes_layer_finalize() */
+/************************************************************************/
+static void
+gv_shapes_layer_finalize(GtkObject *object)
+
+{
+ GvShapeLayerClass *parent_class;
+ GvShapesLayer *layer = GV_SHAPES_LAYER(object);
+
+ CPLDebug( "OpenEV", "gv_shapes_layer_finalize(%s)",
+ gv_data_get_name( GV_DATA(object) ) );
+
+ /* delete the display list if it is valid */
+ if (glIsList(layer->display_list))
+ glDeleteLists( layer->display_list, 1 );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_shape_layer_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
Added: packages/openev/branches/upstream/current/gvshapeslayer.h
===================================================================
--- packages/openev/branches/upstream/current/gvshapeslayer.h (rev 0)
+++ packages/openev/branches/upstream/current/gvshapeslayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,161 @@
+/******************************************************************************
+ * $Id: gvshapeslayer.h,v 1.18 2003/09/12 17:35:43 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Display layer for vector shapes.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvshapeslayer.h,v $
+ * Revision 1.18 2003/09/12 17:35:43 warmerda
+ * Added logic to aggregate selection boxes in the drawinfo.selection_box
+ * rectangle when draw_mode == NORMAL_GET_BOX. This is intended to allow
+ * us to draw a selection box around a complex shapes consisting of multiple
+ * parts offset from the reference point. In the past we only drew the
+ * selection around the first part in such cases. This seems to work though
+ * the testing isn't ... extensive.
+ *
+ * Revision 1.17 2003/09/02 17:22:27 warmerda
+ * added per-layer symbol manager support
+ *
+ * Revision 1.16 2003/08/27 20:03:05 warmerda
+ * Added geo2screen_works to drawinfo structure. It is set to false for text
+ * drawn within symbols since symbol rescaling via glScale() will mess up
+ * the bmfont_draw() logic for ensuring text is drawn "on screen". True
+ * otherwise. It is passed on to gv_view_area_bmfont_draw().
+ *
+ * Revision 1.15 2003/05/16 21:31:26 warmerda
+ * added support for passing default color down to components of a symbol
+ *
+ * Revision 1.14 2003/05/16 17:42:40 warmerda
+ * fix up pixel offsets for sub-symbols
+ *
+ * Revision 1.13 2003/02/28 16:49:42 warmerda
+ * preliminary support for symbols rendered from GvShapes
+ *
+ * Revision 1.12 2003/02/27 04:08:57 warmerda
+ * added view to gv_shapes_layer_get_draw_info
+ *
+ * Revision 1.11 2003/02/14 22:55:57 pgs
+ * added support for _line_width and _area_edge_width
+ *
+ * Revision 1.10 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.9 2002/09/27 18:16:21 pgs
+ * added display list support and antialiasing support for line layers
+ *
+ * Revision 1.8 2001/04/09 18:22:22 warmerda
+ * use renderinfo for ogrfs, added text selection box
+ *
+ * Revision 1.7 2001/03/21 22:40:18 warmerda
+ * allow setting _gv_ogrfs on layer, and add support for text from fields
+ *
+ * Revision 1.6 2000/08/14 15:08:08 warmerda
+ * make gv_shapes_layer_override_color public
+ *
+ * Revision 1.5 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_SHAPES_LAYER_H__
+#define __GV_SHAPES_LAYER_H__
+
+#include "gvshapelayer.h"
+#include "gvshapes.h"
+
+#define GV_TYPE_SHAPES_LAYER (gv_shapes_layer_get_type ())
+#define GV_SHAPES_LAYER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_SHAPES_LAYER, GvShapesLayer))
+#define GV_SHAPES_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_SHAPES_LAYER, GvShapesLayerClass))
+#define GV_IS_SHAPES_LAYER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_SHAPES_LAYER))
+#define GV_IS_SHAPES_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_SHAPES_LAYER))
+
+typedef struct _GvShapesLayer GvShapesLayer;
+typedef struct _GvShapesLayerClass GvShapesLayerClass;
+
+struct _GvShapesLayer
+{
+ GvShapeLayer shape_layer;
+
+ GvShapes *data;
+ gint edit_ring;
+ gint display_list;
+
+ GtkObject *symbol_manager;
+};
+
+struct _GvShapesLayerClass
+{
+ GvShapeLayerClass parent_class;
+};
+
+typedef struct
+{
+ GvColor color;
+ GvColor point_color;
+ GvColor line_color;
+ float line_width;
+ GvColor area_fill_color;
+ GvColor area_edge_color;
+ float area_edge_width;
+ gvgeocoord point_size;
+ gvgeocoord dx, dy, dunit, dpixel;
+ int geo2screen_works; /* this doesn't work if extra GL scalings
+ are in effect for sub-symbols */
+
+ char ogrfs[2048];
+
+ /* used to aggregate and return selection box extents. */
+ int box_set;
+ GvRect selection_box;
+} GvShapeDrawInfo;
+
+typedef enum
+{
+ NORMAL,
+ SELECTED,
+ PICKING,
+ NORMAL_GET_BOX
+} gv_draw_mode;
+
+void gv_draw_info_aggregate_select_region( GvShapeDrawInfo *,
+ double x, double y );
+
+GtkType gv_shapes_layer_get_type(void);
+GtkObject* gv_shapes_layer_new(GvShapes *data);
+gint gv_shapes_layer_select_new_shape( GvShapesLayer *, GvShape * );
+void gv_shapes_layer_set_data( GvShapesLayer *, GvShapes * );
+void gv_shapes_layer_draw_selected(GvShapeLayer *layer, GvViewArea *view);
+void gv_shapes_layer_draw(GvLayer *layer, GvViewArea *view);
+void gv_shapes_layer_get_draw_info(GvViewArea *view, GvShapesLayer *,
+ GvShapeDrawInfo * );
+void gv_shapes_layer_override_color( GvShape *, GvColor, const char * );
+
+void gv_shapes_layer_update_renderinfo( GvShapesLayer *, int shape_id );
+GtkObject *gv_shapes_layer_get_symbol_manager( GvShapesLayer *layer,
+ int ok_to_create );
+
+void gv_shapes_layer_draw_shape( GvViewArea *view, GvShapesLayer *layer,
+ int part_index, GvShape *shape_obj,
+ gv_draw_mode draw_mode,
+ GvShapeDrawInfo *drawinfo );
+#endif /* __GV_SHAPES_LAYER_H__ */
Added: packages/openev/branches/upstream/current/gvskirt.c
===================================================================
--- packages/openev/branches/upstream/current/gvskirt.c (rev 0)
+++ packages/openev/branches/upstream/current/gvskirt.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,367 @@
+/******************************************************************************
+ * $Id: gvskirt.c,v 1.6 2002/10/07 06:08:07 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Code to generate 3D skirts around a raster layer. The skirts
+ * are generated as GvShapesLayer. This feature is initially
+ * implemented for use in CIETmap.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, DM Solutions Group (www.dmsolutions.ca)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvskirt.c,v $
+ * Revision 1.6 2002/10/07 06:08:07 warmerda
+ * Avoid unused variable warning.
+ *
+ * Revision 1.5 2002/09/27 18:17:18 pgs
+ * modified skirt building to remove white lines.
+ *
+ * Revision 1.4 2002/09/12 15:34:41 warmerda
+ * use odd modulus for facet counter
+ *
+ * Revision 1.3 2002/09/11 19:15:37 warmerda
+ * changed way of deciding on white facets to avoid angular dependencies
+ *
+ * Revision 1.2 2001/07/13 22:14:18 warmerda
+ * completed implementation
+ *
+ * Revision 1.1 2001/07/09 20:22:04 warmerda
+ * New
+ *
+ */
+
+#include "gvshapes.h"
+#include "gvrasterlayer.h"
+#include "cpl_error.h"
+#include "gvshapeslayer.h"
+
+static void add_edge( GvShapes *shapes, GvRasterLayer *dem_layer,
+ double base_z,
+ double x1, double y1, double z1,
+ double x2, double y2, double z2 )
+
+{
+ GvRaster *dem = dem_layer->prototype_data;
+ GvShape *facet;
+ GvColor color;
+ GvProperties *prop;
+ char color_prop[128];
+ float z1_mesh = 0, z2_mesh = 0;
+ int success, i;
+ double x_geo, y_geo;
+ //static int facet_counter = 0;
+ float alpha = 0.8;
+
+ facet = gv_shape_new( GVSHAPE_AREA );
+
+/* -------------------------------------------------------------------- */
+/* Get sample value from the mesh. */
+/* -------------------------------------------------------------------- */
+ x_geo = x1;
+ y_geo = y1;
+ gv_raster_pixel_to_georef( dem, &x_geo, &y_geo, NULL );
+
+ z1_mesh = gv_mesh_get_height( dem_layer->mesh, x_geo, y_geo, &success );
+ if( !success )
+ z1_mesh = z1;
+
+ x_geo = x2;
+ y_geo = y2;
+ gv_raster_pixel_to_georef( dem, &x_geo, &y_geo, NULL );
+
+ z2_mesh = gv_mesh_get_height( dem_layer->mesh, x_geo, y_geo, &success );
+ if( !success )
+ z2_mesh = z2;
+
+/* -------------------------------------------------------------------- */
+/* Setup the color of the facet. We set some to white to */
+/* provide a stripped effect. The rest are set to the color of */
+/* the raster at that point. */
+/* -------------------------------------------------------------------- */
+/* if( ((int) (x1+y1)) % 20 >= 0 && ((int) (x1+y1)) % 20 <= 2 ) */
+
+ //use a transparent skirt instead
+ /*
+ if( facet_counter++ > 18 ) //facet_counter == 19 ) //facet_counter == 18 || facet_counter == 19)
+ {
+ if (facet_counter == 19)
+ facet_counter = 0;
+ color[0] = 1.0;
+ color[1] = 1.0;
+ color[2] = 1.0;
+ color[3] = alpha;
+ }
+ else
+ */
+ {
+ GvRasterSource *src = dem_layer->source_list + 0;
+ int r_class;
+
+ r_class = (((((z1+z2)/2.0) - src->min)/ (src->max-src->min))*255);
+ r_class = MAX(0,MIN(255,r_class));
+
+ if( src->lut )
+ r_class = src->lut[r_class];
+
+ if( dem_layer->pc_lut != NULL )
+ {
+ color[0] = dem_layer->pc_lut[r_class * 4 ] / 255.0;
+ color[1] = dem_layer->pc_lut[r_class * 4 + 1] / 255.0;
+ color[2] = dem_layer->pc_lut[r_class * 4 + 2] / 255.0;
+ //color[3] = dem_layer->pc_lut[r_class * 4 + 3] / 255.0;
+ color[3] = alpha;
+ }
+ else
+ {
+ color[0] = color[1] = color[2] = r_class / 255.0;
+ color[3] = alpha;
+ }
+ }
+
+ for (i=0;i<3;i++)
+ color[i] = color[i] + (1.0 - color[3]) * (1.0 - color[i]);
+ color[3] = 1.0;
+
+ prop = gv_shape_get_properties( facet );
+
+ sprintf( color_prop, "%.3f %.3f %.3f %.3f", color[0], color[1],
+ color[2], color[3] );
+ gv_properties_set( prop, "_gv_fill_color", color_prop );
+ //disable edges to speed up drawing
+ gv_properties_set( prop, "_gv_color", "0.0 0.0 0.0 0.0" );
+
+/* -------------------------------------------------------------------- */
+/* Create a polygon for the facet. */
+/* -------------------------------------------------------------------- */
+ gv_raster_pixel_to_georef( dem, &x1, &y1, NULL );
+ gv_raster_pixel_to_georef( dem, &x2, &y2, NULL );
+
+ gv_shape_add_node( facet, 0, x1, y1, z1_mesh );
+ gv_shape_add_node( facet, 0, x1, y1, base_z );
+ gv_shape_add_node( facet, 0, x2, y2, base_z );
+ gv_shape_add_node( facet, 0, x2, y2, z2_mesh );
+ gv_shape_add_node( facet, 0, x1, y1, z1_mesh );
+
+/* -------------------------------------------------------------------- */
+/* Add the shape to the shapes container. */
+/* -------------------------------------------------------------------- */
+ gv_shapes_add_shape( shapes, facet );
+}
+
+
+/************************************************************************/
+/* gv_build_skirt() */
+/************************************************************************/
+GvLayer *gv_build_skirt( GvRasterLayer *dem_layer, double base_z )
+
+{
+ GvShapes *shapes;
+ int x, y;
+ GvRaster *dem = dem_layer->prototype_data;
+ double no_data = 1000000;
+ float *this_line, *next_line;
+
+ this_line = g_new(float,dem->width+2);
+ next_line = g_new(float,dem->width+2);
+
+ if( dem_layer->source_list[0].nodata_active )
+ no_data = dem_layer->source_list[0].nodata_real;
+
+ for( x = 0; x < dem->width+2; x++)
+ next_line[x] = no_data;
+
+ shapes = GV_SHAPES(gv_shapes_new());
+
+ for( y = -1; y < dem->height; y++ )
+ {
+ memcpy( this_line, next_line, sizeof(float) * (dem->width+2) );
+
+ if( y+1 < dem->height )
+ {
+ GDALRasterIO( dem->gdal_band, GF_Read,
+ 0, y+1, dem->width, 1,
+ next_line + 1, dem->width, 1, GDT_Float32, 0, 0 );
+ }
+ else
+ {
+ for( x = 0; x < dem->width+2; x++)
+ next_line[x] = no_data;
+ }
+
+ for( x = -1; x < dem->width; x++ )
+ {
+ double pix_00, pix_10, pix_01, pix_11;
+ int nd_00, nd_10, nd_01, nd_11;
+
+ /*
+ ** Fetch the four local pixels.
+ */
+
+ pix_00 = this_line[x+1];
+ pix_10 = this_line[x+2];
+ pix_01 = next_line[x+1];
+ pix_11 = next_line[x+2];
+
+ nd_00 = (pix_00 == no_data);
+ nd_01 = (pix_01 == no_data);
+ nd_10 = (pix_10 == no_data);
+ nd_11 = (pix_11 == no_data);
+
+ if( (nd_00 == nd_01) && (nd_00 == nd_10) && (nd_00 == nd_11) )
+ continue;
+#ifndef notdef
+ if( !nd_00 && nd_01 )
+ {
+ add_edge( shapes, dem_layer, base_z,
+ x, y+1, pix_00,
+ x+1, y+1, pix_00);
+ }
+ if( nd_00 && !nd_01 )
+ {
+ add_edge( shapes, dem_layer, base_z,
+ x+1, y+1, pix_01,
+ x, y+1, pix_01);
+ }
+ if( !nd_00 && nd_10 )
+ {
+ add_edge( shapes, dem_layer, base_z,
+ x+1, y+1, pix_00,
+ x+1, y, pix_00);
+ }
+ if( nd_00 && !nd_10 )
+ {
+ add_edge( shapes, dem_layer, base_z,
+ x+1, y, pix_10,
+ x+1, y+1, pix_10);
+ }
+#endif
+#ifdef notdef
+ if( nd_00 && nd_01 && !nd_10 && !nd_11 )
+ {
+ /* vertical edge. */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y, pix_10,
+ x+0.5, y+1, pix_11 );
+ }
+ else if( !nd_00 && !nd_01 && nd_10 && nd_11 )
+ {
+ /* vertical edge, reversed. */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y+1, pix_00,
+ x+0.5, y, pix_01 );
+ }
+ else if( nd_00 && nd_10 && !nd_01 && !nd_11 )
+ {
+ /* horizontal edge. */
+
+ add_edge( shapes, dem_layer, base_z,
+ x, y+0.5, pix_01,
+ x+1.0, y+0.5, pix_11 );
+ }
+ else if( !nd_00 && !nd_10 && nd_01 && nd_11 )
+ {
+ /* horizontal edge, reversed. */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+1.0, y+0.5, pix_00,
+ x, y+0.5, pix_10 );
+ }
+ else if( nd_00 && !nd_10 && !nd_01 && !nd_11 )
+ {
+ /* diag, top left missing, reversed */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y, pix_10,
+ x, y+0.5, pix_01 );
+ }
+ else if( !nd_00 && nd_10 && nd_01 && nd_11 )
+ {
+ /* diag, top left present */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y, pix_00,
+ x, y+0.5, pix_00 );
+ }
+ else if( !nd_00 && !nd_10 && nd_01 && !nd_11 )
+ {
+ /* diag, bottom left missing */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y+1, pix_11,
+ x, y+0.5, pix_00 );
+ }
+ else if( nd_00 && nd_10 && !nd_01 && nd_11 )
+ {
+ /* diag, bottom left present */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y+1, pix_01,
+ x, y+0.5, pix_01 );
+ }
+ else if( !nd_00 && nd_10 && !nd_01 && !nd_11 )
+ {
+ /* diag, top right missing */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y, pix_00,
+ x+1, y+0.5, pix_11 );
+ }
+ else if( nd_00 && !nd_10 && nd_01 && nd_11 )
+ {
+ /* diag, top right present */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+0.5, y, pix_10,
+ x+1, y+0.5, pix_10 );
+ }
+ else if( !nd_10 && !nd_10 && !nd_01 && nd_11 )
+ {
+ /* diag, bottom right missing */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+1, y+0.5, pix_10,
+ x+0.5, y+1, pix_01 );
+ }
+ else if( nd_00 && nd_10 && nd_01 && !nd_11 )
+ {
+ /* diag, bottom right present */
+
+ add_edge( shapes, dem_layer, base_z,
+ x+1, y+0.5, pix_11,
+ x+0.5, y+1, pix_11 );
+ }
+ else
+ {
+ printf( "%d,%d,%d,%d\n", nd_00, nd_10, nd_01, nd_11 );
+ }
+#endif
+ }
+ }
+
+ g_free( this_line );
+ g_free( next_line );
+
+/* -------------------------------------------------------------------- */
+/* Turn this into a layer. */
+/* -------------------------------------------------------------------- */
+ return GV_LAYER(gv_shapes_layer_new(shapes));
+}
Added: packages/openev/branches/upstream/current/gvsymbolmanager.c
===================================================================
--- packages/openev/branches/upstream/current/gvsymbolmanager.c (rev 0)
+++ packages/openev/branches/upstream/current/gvsymbolmanager.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,706 @@
+/******************************************************************************
+ * $Id: gvsymbolmanager.c,v 1.12 2004/02/16 17:08:12 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: manage file-based symbols
+ * Author: Paul Spencer (pgs at magma.ca)
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Paul Spencer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvsymbolmanager.c,v $
+ * Revision 1.12 2004/02/16 17:08:12 warmerda
+ * support OPENEVHOME as well as OPENEV_HOME
+ *
+ * Revision 1.11 2003/11/07 18:27:08 warmerda
+ * use dummy sumbol when load fails
+ *
+ * Revision 1.10 2003/09/02 17:25:08 warmerda
+ * Added _has_symbol(), and _get_names() methods. Use outside GvShape
+ * serialize/deserialize code. Don't store symbols with absolute paths in
+ * the hash.
+ *
+ * Revision 1.9 2003/08/29 20:52:58 warmerda
+ * use gv_shape_from_xml_tree
+ *
+ * Revision 1.8 2003/05/16 17:50:34 warmerda
+ * moved debug statement to avoid output everytime a loaded symbol is drawn
+ *
+ * Revision 1.7 2003/04/09 21:32:48 andrey_kiselev
+ * Couple of memory leaks fixed.
+ *
+ * Revision 1.6 2003/04/09 13:14:24 andrey_kiselev
+ * Memory leak fixed.
+ *
+ * Revision 1.5 2003/04/08 11:56:32 andrey_kiselev
+ * Implemented gv_symbol_manager_save_vector_symbol() function.
+ *
+ * Revision 1.4 2003/04/07 20:09:04 andrey_kiselev
+ * Path to simbols directory now could be configured with "symbols_dir"
+ * GvManager property.
+ *
+ * Revision 1.3 2003/04/07 15:52:49 andrey_kiselev
+ * gv_symbol_manager_get_symbol() now able to load and inject vector symbols.
+ *
+ * Revision 1.2 2003/02/28 16:46:45 warmerda
+ * added partial support for vector symbols
+ *
+ * Revision 1.1 2002/11/14 20:10:41 warmerda
+ * New
+ */
+
+#include "gvsymbolmanager.h"
+#include "gvmanager.h"
+#include "gdal.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_minixml.h"
+#include <gtk/gtksignal.h>
+#include <stdio.h>
+
+/* signals (none for now?) */
+enum { LAST_SIGNAL };
+
+GByte * gdal_to_rgba( GDALDatasetH hDS );
+gboolean finalize_symbol(gpointer key, gpointer value, gpointer user_data);
+
+static void gv_symbol_manager_init( GvSymbolManager *manager );
+static void gv_symbol_manager_class_init( GvSymbolManagerClass *klass );
+static void gv_symbol_manager_finalize( GtkObject *manager );
+
+/* static void gv_symbol_manager_signals[LAST_SIGNAL] = { 0 }; */
+
+/************************************************************************/
+/* gv_symbol_manager_class_init() */
+/************************************************************************/
+GtkType
+gv_symbol_manager_get_type(void)
+{
+ static GtkType symbol_manager_type = 0;
+
+ if (!symbol_manager_type)
+ {
+ static const GtkTypeInfo symbol_manager_info =
+ {
+ "GvSymbolManager",
+ sizeof(GvSymbolManager),
+ sizeof(GvSymbolManagerClass),
+ (GtkClassInitFunc) gv_symbol_manager_class_init,
+ (GtkObjectInitFunc) gv_symbol_manager_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+ symbol_manager_type = gtk_type_unique( gtk_object_get_type(),
+ &symbol_manager_info );
+ }
+ return symbol_manager_type;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_class_init() */
+/************************************************************************/
+static void
+gv_symbol_manager_class_init( GvSymbolManagerClass *klass )
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ ((GtkObjectClass *) klass)->finalize = gv_symbol_manager_finalize;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_init() */
+/************************************************************************/
+static void
+gv_symbol_manager_init( GvSymbolManager *manager )
+{
+ manager->symbol_cache = g_hash_table_new( g_str_hash, g_str_equal );
+
+ //GDALAllRegister();
+}
+
+/************************************************************************/
+/* gv_symbol_manager_new() */
+/* */
+/* construct a new instance of the symbol manager. This */
+/* function is private. Call gv_get_symbol_manager() */
+/************************************************************************/
+GvSymbolManager *gv_symbol_manager_new()
+{
+ return GV_SYMBOL_MANAGER(gtk_type_new(GV_TYPE_SYMBOL_MANAGER));
+}
+
+/************************************************************************/
+/* gv_get_symbol_manager() */
+/* */
+/* return a reference to the symbol manager object. This */
+/* implements the singleton pattern so that only one symbol */
+/* manager is created. */
+/************************************************************************/
+GvSymbolManager *
+gv_get_symbol_manager()
+{
+ static GvSymbolManager *main_symbol_manager = NULL;
+
+ if ( main_symbol_manager == NULL )
+ {
+ main_symbol_manager = gv_symbol_manager_new();
+ }
+
+ return main_symbol_manager;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_has_symbol() */
+/************************************************************************/
+
+int gv_symbol_manager_has_symbol( GvSymbolManager *manager,
+ const char *name )
+
+{
+ g_return_val_if_fail( manager != NULL, 0 );
+
+ return g_hash_table_lookup( manager->symbol_cache, name ) != NULL;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_get_symbol() */
+/* */
+/* manager - a gvsymbolmanager instance (use gv_get_symbol_manager)*/
+/* pszFilename - the name of the symbol to read in */
+/* */
+/* This returns a texture 'name' that can be used with */
+/* glBindTexture if the symbol is successfully loaded and */
+/* converted to a texture or 0 on failure. Symbols are cached */
+/* using the absolute path to the symbol file so that only one */
+/* copy of the symbol should ever be loaded. This could be */
+/* circumvented by having symlinks or .. in the path but in */
+/* most real cases this won't happen. */
+/* */
+/* The maximum cache size is set in the xxxxxxx property. When */
+/* the symbol cache is full, textures are released on a Least */
+/* Recently Used basis. The texture can still be accessed */
+/* because the symbol name will persist in the cache. */
+/************************************************************************/
+GvSymbolObj *
+gv_symbol_manager_get_symbol(GvSymbolManager *manager, const char *symbol_name)
+{
+ gchar *pszOpenEVHome = NULL;
+ gchar *pszSymbolsDir = NULL;
+ gchar *pszAbsolutePath = NULL;
+ gchar *pszPathSeparator = NULL;
+ GDALDatasetH hDataset;
+ GvSymbolObj *poSymbol;
+ CPLXMLNode *xml_shape = NULL;
+ GByte *rgba_buffer;
+
+/* -------------------------------------------------------------------- */
+/* Lookup the symbol in the hash table, and return it if found. */
+/* -------------------------------------------------------------------- */
+ poSymbol = g_hash_table_lookup( manager->symbol_cache, symbol_name );
+ if( poSymbol != NULL )
+ return poSymbol;
+
+/* -------------------------------------------------------------------- */
+/* We didn't already have it, so try to find a file to load it */
+/* from. */
+/* -------------------------------------------------------------------- */
+#ifndef WIN32
+ pszPathSeparator = "/";
+#else
+ pszPathSeparator = "\\";
+#endif /* WIN32 */
+
+ /* validate inputs */
+ g_return_val_if_fail( manager != NULL, 0 );
+ g_return_val_if_fail( symbol_name != NULL, 0 );
+
+ /* get an absolute path */
+ if ( !g_path_is_absolute( symbol_name ) )
+ {
+ /* check configuration option first */
+ pszSymbolsDir = g_strdup( gv_manager_get_preference( gv_get_manager(),
+ "symbols_dir" ) );
+
+ /* if not configured check $OPENEV_HOME */
+ if ( !pszSymbolsDir )
+ {
+ pszOpenEVHome = g_getenv( "OPENEV_HOME" );
+ if( pszOpenEVHome == NULL )
+ pszOpenEVHome = g_getenv( "OPENEVHOME" );
+ if ( pszOpenEVHome )
+ pszSymbolsDir = g_strjoin( pszPathSeparator, pszOpenEVHome,
+ "symbols", NULL );
+ }
+
+ /* get current directory as last resort */
+ if ( !pszSymbolsDir )
+ pszSymbolsDir = g_get_current_dir();
+
+ pszAbsolutePath = g_strjoin( pszPathSeparator, pszSymbolsDir,
+ symbol_name, NULL );
+ g_free( pszSymbolsDir );
+ }
+ else
+ pszAbsolutePath = g_strdup( symbol_name );
+
+/* -------------------------------------------------------------------- */
+/* pszAbsolutePath contains a newly allocated string that is */
+/* suitable for using as a key in the hash table. If a texture */
+/* is found in the hash table then this string needs to be */
+/* freed. If one isn't found then the string is used in the */
+/* hash table and should be freed when the associated hash */
+/* table entry is released */
+/* -------------------------------------------------------------------- */
+ CPLDebug( "OpenEV",
+ "gv_symbol_manager_get_symbol(%s) ... need to load.",
+ pszAbsolutePath );
+
+ /*
+ * validate path by opening with GDAL and looking for an error
+ * Disable CPL error handler to supress error reporting
+ */
+
+ CPLErrorReset();
+ CPLPushErrorHandler( CPLQuietErrorHandler );
+ hDataset = GDALOpen( pszAbsolutePath, GA_ReadOnly );
+ CPLPopErrorHandler();
+
+ if ( hDataset )
+ {
+ rgba_buffer = gdal_to_rgba( hDataset );
+
+ if ( rgba_buffer )
+ {
+ gv_symbol_manager_inject_raster_symbol(
+ manager, symbol_name,
+ GDALGetRasterXSize( hDataset ),
+ GDALGetRasterYSize( hDataset ),
+ rgba_buffer );
+ CPLFree( rgba_buffer );
+ }
+
+ GDALClose( hDataset );
+ }
+ /* probably we have vector symbol? */
+ else if ( ( xml_shape = CPLParseXMLFile( pszAbsolutePath ) ) )
+ {
+ GvShape *shape;
+ shape = gv_shape_from_xml_tree( xml_shape );
+
+ CPLDestroyXMLNode( xml_shape );
+
+ if( shape != NULL )
+ gv_symbol_manager_inject_vector_symbol( manager, symbol_name,
+ shape );
+ else
+ {
+ CPLDebug( "OpenEV",
+ "Failed to instantiate GvSahpe from file %s, using simple point.",
+ pszAbsolutePath );
+
+ shape = gv_shape_new( GVSHAPE_POINT );
+ gv_symbol_manager_inject_vector_symbol( manager, symbol_name,
+ shape );
+ }
+ }
+ else
+ {
+ GvShape *shape;
+
+ CPLDebug( "OpenEV", "Failed to open file %s, using simple point.",
+ pszAbsolutePath );
+
+ shape = gv_shape_new( GVSHAPE_POINT );
+ gv_symbol_manager_inject_vector_symbol( manager, symbol_name,
+ shape );
+ }
+
+ /* look up in the hash table again */
+ poSymbol = g_hash_table_lookup(manager->symbol_cache, symbol_name );
+
+ g_free( pszAbsolutePath );
+
+ return poSymbol;
+}
+
+/************************************************************************/
+/* finalize_symbol() */
+/* */
+/* finalize a symbol object's hash table entry by freeing */
+/* allocated memory. It is (relatively) safe to free the key */
+/* since we are sure we allocated the memory for it when */
+/* inserting into the hashtable. */
+/************************************************************************/
+
+gboolean
+finalize_symbol( gpointer key, gpointer value, gpointer user_data )
+{
+ GvSymbolObj *poSymbol = (GvSymbolObj *) value;
+
+ g_free( key );
+
+ if (poSymbol->type == GV_SYMBOL_RASTER)
+ g_free( poSymbol->buffer );
+ else if( poSymbol->type == GV_SYMBOL_VECTOR )
+ gv_shape_unref( (GvShape *) poSymbol->buffer );
+
+ g_free( poSymbol );
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_finalize() */
+/* */
+/* clean up the symbol manager storage and free associated memory. */
+/************************************************************************/
+static void
+gv_symbol_manager_finalize( GtkObject *object)
+{
+ GvSymbolManagerClass *parent_class;
+ GvSymbolManager *manager = GV_SYMBOL_MANAGER(object);
+
+ CPLDebug( "OpenEV", "gv_symbol_manager_finalize(%p)", object );
+
+ g_hash_table_foreach_remove(manager->symbol_cache, finalize_symbol, NULL);
+
+ g_hash_table_destroy( manager->symbol_cache );
+
+ /* parent class destructor */
+ parent_class = gtk_type_class( gtk_object_get_type() );
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+/************************************************************************/
+/* gv_symbol_manager_eject_symbol() */
+/* */
+/* Remove and deallocate one (named) symbol from the symbol */
+/* manager cache. */
+/************************************************************************/
+
+int gv_symbol_manager_eject_symbol( GvSymbolManager *manager,
+ const char *symbol_name )
+
+{
+ CPLDebug( "OpenEV",
+ "gv_symbol_manager_eject_symbol() not yet impelemented." );
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_inject_raster_symbol() */
+/* */
+/* Create a GvSymbolObject corresponding to the pass size and */
+/* raster info, and inject it into the symbol manager with the */
+/* indicated name. */
+/************************************************************************/
+
+void gv_symbol_manager_inject_raster_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ int width, int height,
+ void *rgba_buffer )
+
+{
+ GvSymbolObj *symbol;
+
+ /* allocate a new symbol object */
+ symbol = g_new0( GvSymbolObj, 1 );
+
+ symbol->type = GV_SYMBOL_RASTER;
+
+ symbol->width = width;
+ symbol->height = height;
+
+ /* initialize the foreground and background colors */
+ symbol->foreground[0] = 0.0;
+ symbol->foreground[1] = 0.0;
+ symbol->foreground[2] = 0.0;
+ symbol->foreground[3] = 1.0;
+ symbol->background[0] = 1.0;
+ symbol->background[1] = 1.0;
+ symbol->background[2] = 1.0;
+ symbol->background[3] = 0.0;
+
+ /* copy the raster buffer. */
+ symbol->buffer = (GByte *) CPLMalloc(width*height*4);
+ memcpy( symbol->buffer, rgba_buffer, width*height*4 );
+
+ /* insert new symbol into symbol manager */
+ g_hash_table_insert( manager->symbol_cache, g_strdup(symbol_name), symbol);
+
+ CPLDebug("OpenEV", "inject_raster_symbol(%s, %dx%d)",
+ symbol_name, width, height );
+}
+
+/************************************************************************/
+/* gv_symbol_manager_inject_vector_symbol() */
+/* */
+/* Create a GvSymbolObject corresponding to the passed */
+/* GvShape. An internal copy of the shape is made. */
+/************************************************************************/
+
+void gv_symbol_manager_inject_vector_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ GvShape *shape )
+
+{
+ GvSymbolObj *symbol;
+
+ /* allocate a new symbol object */
+ symbol = g_new0( GvSymbolObj, 1 );
+
+ symbol->type = GV_SYMBOL_VECTOR;
+
+ /* take a reference to the shape */
+ symbol->buffer = shape;
+ gv_shape_ref( shape );
+
+ /* insert new symbol into symbol manager */
+ g_hash_table_insert( manager->symbol_cache, g_strdup(symbol_name), symbol );
+
+ CPLDebug("OpenEV", "inject_vector_symbol(%s)", symbol_name );
+}
+
+/************************************************************************/
+/* gv_symbol_manager_save_vector_symbol() */
+/* */
+/* Save an existing and loaded vector simbol under new name. */
+/************************************************************************/
+
+int gv_symbol_manager_save_vector_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ const char *new_name )
+
+{
+ GvSymbolObj *symbol;
+
+ /* allocate a new symbol object */
+ symbol = g_hash_table_lookup( manager->symbol_cache, symbol_name );
+
+ CPLDebug("OpenEV", "save_vector_symbol(%s->%s)", symbol_name, new_name );
+
+ if ( symbol && symbol->type == GV_SYMBOL_VECTOR )
+ {
+ GvShape *shape;
+ CPLXMLNode *xml_shape;
+
+ shape = (GvShape *)symbol->buffer;
+ xml_shape = gv_shape_to_xml_tree( shape );
+
+ if ( CPLSerializeXMLTreeToFile( xml_shape, new_name ) )
+ {
+ CPLDestroyXMLNode( xml_shape );
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+}
+
+/************************************************************************/
+/* gdal_to_rgba() */
+/* */
+/* convert a GDAL dataset into an RGBA buffer. Provided by */
+/* Frank Warmerdam :) */
+/************************************************************************/
+GByte *
+gdal_to_rgba( GDALDatasetH hDS )
+{
+ int nXSize, nYSize;
+ GByte *pabyRGBABuf = NULL;
+
+ /* validation of input parameters */
+ g_return_val_if_fail( hDS != NULL, NULL );
+
+/* -------------------------------------------------------------------- */
+/* Allocate RGBA Raster buffer. */
+/* -------------------------------------------------------------------- */
+
+ nXSize = GDALGetRasterXSize( hDS );
+ nYSize = GDALGetRasterYSize( hDS );
+ CPLDebug( "OpenEV", "creating buffer of (%d,%d)", nXSize, nYSize );
+ pabyRGBABuf = (GByte *) CPLMalloc( nXSize * nYSize * 4 );
+
+/* -------------------------------------------------------------------- */
+/* Handle case where source is already presumed to be RGBA. */
+/* -------------------------------------------------------------------- */
+ if( GDALGetRasterCount(hDS) == 4 )
+ {
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+0, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 2 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+1, nXSize, nYSize, GDT_Byte, 4,
+ nXSize * 4 );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 3 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+2, nXSize, nYSize, GDT_Byte, 4,
+ nXSize * 4 );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 4 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+3, nXSize, nYSize, GDT_Byte, 4,
+ nXSize * 4 );
+ }
+/* -------------------------------------------------------------------- */
+/* Source is RGB. Set Alpha to 255. */
+/* -------------------------------------------------------------------- */
+ else if( GDALGetRasterCount(hDS) == 3 )
+ {
+ memset( pabyRGBABuf, 255, 4 * nXSize * nYSize );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+0, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 2 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+1, nXSize, nYSize, GDT_Byte, 4,
+ nXSize * 4 );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 3 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+2, nXSize, nYSize, GDT_Byte, 4,
+ nXSize * 4 );
+ }
+/* -------------------------------------------------------------------- */
+/* Source is pseudocolored. Load and then convert to RGBA. */
+/* -------------------------------------------------------------------- */
+ else if( GDALGetRasterCount(hDS) == 1
+ && GDALGetRasterColorTable( GDALGetRasterBand( hDS, 1 )) != NULL )
+ {
+ int i;
+ GDALColorTableH hTable;
+ GByte abyPCT[1024];
+
+ /* Load color table, and produce 256 entry table to RGBA. */
+ hTable = GDALGetRasterColorTable( GDALGetRasterBand( hDS, 1 ) );
+
+ for( i = 0; i < MIN(256,GDALGetColorEntryCount( hTable )); i++ )
+ {
+ GDALColorEntry sEntry;
+
+ GDALGetColorEntryAsRGB( hTable, i, &sEntry );
+ abyPCT[i*4+0] = sEntry.c1;
+ abyPCT[i*4+1] = sEntry.c2;
+ abyPCT[i*4+2] = sEntry.c3;
+ abyPCT[i*4+3] = sEntry.c4;
+ }
+
+ /* Fill in any missing colors with greyscale. */
+ for( i = GDALGetColorEntryCount( hTable ); i < 256; i++ )
+ {
+ abyPCT[i*4+0] = i;
+ abyPCT[i*4+1] = i;
+ abyPCT[i*4+2] = i;
+ abyPCT[i*4+3] = 255;
+ }
+
+ /* Read indexed raster */
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+0, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+
+ /* Convert to RGBA using palette. */
+ for( i = nXSize * nYSize - 1; i >= 0; i-- )
+ {
+ memcpy( pabyRGBABuf + i*4,
+ abyPCT + pabyRGBABuf[i*4]*4,
+ 4 );
+ }
+ }
+/* -------------------------------------------------------------------- */
+/* Source band is greyscale. Load it into Red, Green and Blue. */
+/* -------------------------------------------------------------------- */
+ else if( GDALGetRasterCount(hDS) == 1 )
+ {
+ memset( pabyRGBABuf, 255, 4 * nXSize * nYSize );
+
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+0, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+1, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+ GDALRasterIO( GDALGetRasterBand( hDS, 1 ), GF_Read,
+ 0, 0, nXSize, nYSize,
+ pabyRGBABuf+2, nXSize, nYSize, GDT_Byte,
+ 4, nXSize * 4 );
+ }
+
+ return pabyRGBABuf;
+}
+
+/************************************************************************/
+/* gv_sm_name_collector() */
+/* */
+/* Callback function used by gv_symbol_manager_get_names(). */
+/************************************************************************/
+
+typedef struct {
+ char **name_list;
+ int count_so_far;
+ int count_max;
+} name_collector_info;
+
+static void gv_sm_name_collector( gpointer key, gpointer value,
+ gpointer user_data )
+
+{
+ name_collector_info *nci = (name_collector_info *) user_data;
+
+ nci->name_list[nci->count_so_far++] = (char*) key;
+}
+
+/************************************************************************/
+/* gv_symbol_manager_get_names() */
+/* */
+/* Fetch a list of all symbol names on this symbol manager. */
+/* The list should be freed with g_free() when no longer */
+/* needed. The strings it contains are internal. */
+/************************************************************************/
+
+char **gv_symbol_manager_get_names( GvSymbolManager *manager )
+
+{
+ name_collector_info nci;
+
+ nci.count_so_far = 0;
+ nci.count_max = g_hash_table_size( manager->symbol_cache );
+ nci.name_list = g_new( char *, nci.count_max+1 );
+ nci.name_list[nci.count_max] = NULL;
+
+ g_hash_table_foreach( manager->symbol_cache, gv_sm_name_collector,
+ &nci );
+
+ return nci.name_list;
+}
+
Added: packages/openev/branches/upstream/current/gvsymbolmanager.h
===================================================================
--- packages/openev/branches/upstream/current/gvsymbolmanager.h (rev 0)
+++ packages/openev/branches/upstream/current/gvsymbolmanager.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * $Id: gvsymbolmanager.h,v 1.5 2003/09/02 17:25:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: manage file-based symbols
+ * Author: Paul Spencer (pgs at magma.ca)
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Paul Spencer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvsymbolmanager.h,v $
+ * Revision 1.5 2003/09/02 17:25:08 warmerda
+ * Added _has_symbol(), and _get_names() methods. Use outside GvShape
+ * serialize/deserialize code. Don't store symbols with absolute paths in
+ * the hash.
+ *
+ * Revision 1.4 2003/04/08 11:56:32 andrey_kiselev
+ * Implemented gv_symbol_manager_save_vector_symbol() function.
+ *
+ * Revision 1.3 2003/02/28 16:46:46 warmerda
+ * added partial support for vector symbols
+ *
+ * Revision 1.2 2003/01/08 03:25:40 warmerda
+ * fiddle with include files for win build
+ *
+ * Revision 1.1 2002/11/14 20:10:41 warmerda
+ * New
+ *
+ *
+ */
+
+#ifndef __GV_SYMBOL_H__
+#define __GV_SYMBOL_H__
+
+#include <gtkgl/gdkgl.h>
+#include <GL/gl.h>
+#include <gtk/gtkobject.h>
+#include "gvtypes.h"
+#include "gvshapes.h"
+
+
+#define GV_TYPE_SYMBOL_MANAGER (gv_symbol_manager_get_type ())
+#define GV_SYMBOL_MANAGER(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_SYMBOL_MANAGER, GvSymbolManager))
+#define GV_SYMBOL_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_SYMBOL_MANAGER, GvSymbolManagerClass))
+#define GV_IS_SYMBOL_MANAGER(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_SYMBOL_MANAGER))
+#define GV_IS_SYMBOL_MANAGER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_SYMBOL_TYPE_MANAGER))
+
+enum { GV_SYMBOL_RASTER = 0, GV_SYMBOL_VECTOR = 1 };
+
+typedef struct _GvSymbolManager GvSymbolManager;
+typedef struct _GvSymbolManagerClass GvSymbolManagerClass;
+
+typedef struct _GvSymbolObj
+{
+ guint type; /* GV_SYMBOL_RASTER or GV_SYMBOL_VECTOR */
+
+ /* for rasters */
+ GvColor foreground; /* foreground color */
+ GvColor background; /* background color */
+ guint width; /* width of the symbol */
+ guint height; /* height of the symbol */
+
+ /* type specific storage (RGBA image or GvShape *) */
+ void * buffer;
+} GvSymbolObj;
+
+struct _GvSymbolManager
+{
+ GtkObject object;
+ GHashTable *symbol_cache;
+};
+
+struct _GvSymbolManagerClass
+{
+ GtkObjectClass parent_class;
+};
+
+GtkType gv_symbol_manager_get_type ( void );
+GvSymbolManager* gv_symbol_manager_new ( void );
+GvSymbolManager* gv_get_symbol_manager ( void );
+
+int gv_symbol_manager_has_symbol( GvSymbolManager *manager,
+ const char *name );
+
+GvSymbolObj* gv_symbol_manager_get_symbol( GvSymbolManager *manager,
+ const char *pszFilename );
+
+void gv_symbol_manager_inject_raster_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ int width, int height,
+ void *rgba_buffer );
+void gv_symbol_manager_inject_vector_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ GvShape *shape );
+int gv_symbol_manager_eject_symbol( GvSymbolManager *manager,
+ const char *symbol_name );
+int gv_symbol_manager_save_vector_symbol( GvSymbolManager *manager,
+ const char *symbol_name,
+ const char *new_name );
+
+char **gv_symbol_manager_get_names( GvSymbolManager *manager );
+
+
+#endif /* __GV_SYMBOL_H__ */
Added: packages/openev/branches/upstream/current/gvtess.c
===================================================================
--- packages/openev/branches/upstream/current/gvtess.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtess.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,272 @@
+/******************************************************************************
+ * $Id: gvtess.c,v 1.12 2002/12/10 02:57:33 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Tesselation for GvAreas (will be discarded with GvAreas)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtess.c,v $
+ * Revision 1.12 2002/12/10 02:57:33 sduclos
+ * update tess callback cast for WIN_CALLBACK
+ *
+ * Revision 1.11 2002/11/05 18:56:25 sduclos
+ * fix gcc warning
+ *
+ * Revision 1.10 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.9 2001/05/01 21:48:01 warmerda
+ * fixed Mesa3.3 compatibility fixes
+ *
+ * Revision 1.8 2001/04/24 16:22:12 warmerda
+ * fixed mesa3.3 incompatibility
+ *
+ * Revision 1.7 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvtess.h"
+
+/* gtkgl.h is to satisfy some Windows definition requirements */
+#include <gtkgl/gdkgl.h>
+
+#include <GL/glu.h>
+
+/* Backward compatibility with glu ver. 1.1 */
+#if !defined(GLU_VERSION_1_2)
+
+#if !defined(GLU_TESS_BEGIN)
+#define GLU_TESS_BEGIN GLU_BEGIN
+#define GLU_TESS_END GLU_END
+#define GLU_TESS_VERTEX GLU_VERTEX
+#define GLU_TESS_ERROR GLU_ERROR
+#endif
+
+#define gluTessBeginPolygon(tess,data) gluBeginPolygon(tess)
+#define gluTessBeginContour(tess) gluNextContour(tess, GLU_UNKNOWN)
+#define gluTessEndContour(tess)
+#define gluTessEndPolygon(tess) gluEndPolygon(tess)
+
+typedef GLUtriangulatorObj GLUtesselator;
+#endif /* GLU_VERSION_1_2 */
+
+enum { GV_CCW, GV_CW };
+
+static GvArea *area;
+
+#ifdef WIN32
+# define WIN_CALLBACK FAR PASCAL
+#else
+# define WIN_CALLBACK
+#endif
+
+static void WIN_CALLBACK tess_begin(GLenum type);
+static void WIN_CALLBACK tess_end(void);
+static void WIN_CALLBACK tess_vertex(void *data);
+static void WIN_CALLBACK tess_error(GLenum err);
+static gint check_ring_lengths(void);
+static void check_winding(void);
+static gint find_winding(GArray *array);
+static void reverse_array(GArray *array);
+
+gint
+gv_area_tessellate(GvArea *in_area)
+{
+ typedef void (*f);
+ static GLUtesselator *tess = NULL;
+ GArray *ring;
+ GvVertex *v;
+ int i, j;
+ GLdouble coords[3];
+
+
+ if (!tess)
+ {
+ tess = gluNewTess();
+ g_return_val_if_fail(tess, FALSE);
+
+ gluTessCallback(tess, GLU_TESS_BEGIN, (f) tess_begin);
+ gluTessCallback(tess, GLU_TESS_END, (f) tess_end);
+ gluTessCallback(tess, GLU_TESS_VERTEX,(f) tess_vertex);
+ gluTessCallback(tess, GLU_TESS_ERROR, (f) tess_error);
+ }
+
+ /* Global is available to all tess callbacks */
+ area = in_area;
+
+ /* Check for short ring lengths */
+ if (!check_ring_lengths()) return FALSE;
+
+ /* Fix ring winding before tesselation */
+ check_winding();
+
+ area->fill_objects = 0;
+ if (area->fill)
+ {
+ g_array_set_size(area->fill, 0);
+ g_array_set_size(area->mode_offset, 0);
+ }
+ else
+ {
+ area->fill = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ area->mode_offset =
+ g_array_new(FALSE, FALSE, sizeof(gint));
+ }
+
+ coords[2] = 0.0;
+
+ gluTessBeginPolygon(tess, NULL);
+ for (i=0; i < area->rings->len; ++i)
+ {
+ ring = gv_areas_get_ring(area, i);
+
+ gluTessBeginContour(tess);
+ for (j=0; j < ring->len; ++j)
+ {
+ v = &g_array_index(ring, GvVertex, j);
+ coords[0] = (GLdouble)v->x;
+ coords[1] = (GLdouble)v->y;
+
+ gluTessVertex(tess, coords, v);
+ }
+ gluTessEndContour(tess);
+ }
+ gluTessEndPolygon(tess);
+
+ return (area->fill_objects > 0
+ && g_array_index(area->mode_offset,gint,0) != GV_TESS_NONE);
+}
+
+static void WIN_CALLBACK
+tess_begin(GLenum type)
+{
+ area->fill_objects++;
+ g_array_append_val(area->mode_offset, type );
+ g_array_append_val(area->mode_offset, area->fill->len );
+}
+
+static void WIN_CALLBACK
+tess_end(void)
+{
+}
+
+static void WIN_CALLBACK
+tess_vertex(void *data)
+{
+ /* for some unknown reason, we somes get called with a NULL
+ if the object doesn't tesselate properly (with libMesa). */
+
+ if( data != NULL )
+ g_array_append_vals(area->fill, data, 1);
+ else
+ tess_error( 0 );
+}
+
+static void WIN_CALLBACK
+tess_error(GLenum err)
+{
+ GLenum bad_fill_mode = GV_TESS_NONE;
+ gint offset = 0;
+
+ g_array_set_size(area->fill, 0);
+ g_array_set_size(area->mode_offset, 0);
+
+ area->fill_objects = 1;
+ g_array_append_val(area->mode_offset, bad_fill_mode );
+ g_array_append_val(area->mode_offset, offset );
+}
+
+static gint
+check_ring_lengths(void)
+{
+ int r, rings;
+
+ rings = gv_areas_num_rings(area);
+
+ for (r=0; r < rings; ++r)
+ {
+ if (gv_areas_get_ring(area, r)->len < 3) return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+check_winding(void)
+{
+ int r, rings, winding;
+ GArray *ring;
+
+ rings = gv_areas_num_rings(area);
+
+ for (r=0; r < rings; ++r)
+ {
+ ring = gv_areas_get_ring(area, r);
+ winding = find_winding(ring);
+ if ((r == 0 && winding == GV_CW) || (r > 0 && winding == GV_CCW))
+ {
+ reverse_array(ring);
+ }
+ }
+}
+
+/* According to the comp.graphics.algorthms FAQ, item 2.07, the
+ * orientation (winding) of a simple polygon can be determined by
+ * looking at the sign of the following series:
+ * sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1})
+ * A positive result means a counter clockwise winding.
+ */
+static gint
+find_winding(GArray *array)
+{
+ GvVertex *a, *b;
+ gvgeocoord sum;
+ int i;
+
+ sum = 0.0;
+ a = &g_array_index(array, GvVertex, 0);
+ b = a+1;
+ for (i=1; i < array->len; ++i, ++a, ++b)
+ {
+ sum += a->x * b->y - a->y * b->x;
+ }
+ b = &g_array_index(array, GvVertex, 0);
+ sum += a->x * b->y - a->y * b->x;
+
+ return (sum < 0.0 ? GV_CW : GV_CCW);
+}
+
+static void
+reverse_array(GArray *array)
+{
+ GvVertex temp;
+ int i;
+
+ for (i=0; i < array->len/2; ++i)
+ {
+ temp = g_array_index(array, GvVertex, i);
+ g_array_index(array, GvVertex, i) = g_array_index(array, GvVertex,
+ array->len - i - 1);
+ g_array_index(array, GvVertex, array->len - i - 1) = temp;
+ }
+}
+
Added: packages/openev/branches/upstream/current/gvtess.h
===================================================================
--- packages/openev/branches/upstream/current/gvtess.h (rev 0)
+++ packages/openev/branches/upstream/current/gvtess.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * $Id: gvtess.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Tesselation for GvAreas (will be discarded with GvAreas)
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtess.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_TESS_H__
+#define __GV_TESS_H__
+
+#include "gvareas.h"
+
+gint gv_area_tessellate(GvArea *area);
+
+#endif /* __GV_TESS_H__ */
Added: packages/openev/branches/upstream/current/gvtessshape.c
===================================================================
--- packages/openev/branches/upstream/current/gvtessshape.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtessshape.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,288 @@
+/******************************************************************************
+ * $Id: gvtessshape.c,v 1.11 2003/02/25 19:41:23 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Tesselation for GvAreaShape.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtessshape.c,v $
+ * Revision 1.11 2003/02/25 19:41:23 warmerda
+ * avoid warning
+ *
+ * Revision 1.10 2002/12/10 02:57:34 sduclos
+ * update tess callback cast for WIN_CALLBACK
+ *
+ * Revision 1.9 2002/11/05 18:56:26 sduclos
+ * fix gcc warning
+ *
+ * Revision 1.8 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.7 2001/05/01 21:48:01 warmerda
+ * fixed Mesa3.3 compatibility fixes
+ *
+ * Revision 1.6 2001/04/24 16:22:12 warmerda
+ * fixed mesa3.3 incompatibility
+ *
+ * Revision 1.5 2000/07/13 22:25:43 warmerda
+ * detect tesselations w/1 fill_object and no vertices, and reset to 0 objects
+ *
+ * Revision 1.4 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvshapes.h"
+
+/* gtkgl.h is to satisfy some Windows definition requirements */
+#include <gtkgl/gdkgl.h>
+#include <GL/glu.h>
+#include <string.h>
+
+/* Backward compatibility with glu ver. 1.1 */
+#if !defined(GLU_VERSION_1_2)
+
+#if !defined(GLU_TESS_BEGIN)
+#define GLU_TESS_BEGIN GLU_BEGIN
+#define GLU_TESS_END GLU_END
+#define GLU_TESS_VERTEX GLU_VERTEX
+#define GLU_TESS_ERROR GLU_ERROR
+#endif
+
+#define gluTessBeginPolygon(tess,data) gluBeginPolygon(tess)
+#define gluTessBeginContour(tess) gluNextContour(tess, GLU_UNKNOWN)
+#define gluTessEndContour(tess)
+#define gluTessEndPolygon(tess) gluEndPolygon(tess)
+
+typedef GLUtriangulatorObj GLUtesselator;
+#endif /* GLU_VERSION_1_2 */
+
+enum { GV_CCW, GV_CW };
+
+static GvAreaShape *area;
+
+#ifdef WIN32
+# define WIN_CALLBACK FAR PASCAL
+#else
+# define WIN_CALLBACK
+#endif
+
+static void WIN_CALLBACK tess_begin(GLenum type);
+static void WIN_CALLBACK tess_end(void);
+static void WIN_CALLBACK tess_vertex(void *data);
+static void WIN_CALLBACK tess_error(GLenum err);
+static gint check_ring_lengths(void);
+static void check_winding(void);
+static gint find_winding(gvgeocoord *, int);
+static void reverse_array(gvgeocoord *, int);
+
+gint
+gv_area_shape_tessellate(GvAreaShape *in_area)
+{
+ typedef void (*f);
+ static GLUtesselator *tess = NULL;
+ int i, j;
+ GLdouble coords[3];
+
+ /* A fill_objects value of -2 is a special flag meaning don't tesselate
+ or fill because we are in the midst of editing. */
+ if( in_area->fill_objects == -2 )
+ return FALSE;
+
+ if (!tess)
+ {
+ tess = gluNewTess();
+ g_return_val_if_fail(tess, FALSE);
+
+ gluTessCallback(tess, GLU_TESS_BEGIN, (f) tess_begin);
+ gluTessCallback(tess, GLU_TESS_END, (f) tess_end);
+ gluTessCallback(tess, GLU_TESS_VERTEX,(f) tess_vertex);
+ gluTessCallback(tess, GLU_TESS_ERROR, (f) tess_error);
+ }
+
+ /* Global is available to all tess callbacks */
+ area = in_area;
+
+ /* Check for short ring lengths, or unclosed rings */
+ if (!check_ring_lengths()) return FALSE;
+
+ /* Fix ring winding before tesselation */
+ check_winding();
+
+ area->fill_objects = 0;
+ if (area->fill)
+ {
+ g_array_set_size(area->fill, 0);
+ g_array_set_size(area->mode_offset, 0);
+ }
+ else
+ {
+ area->fill = g_array_new(FALSE, FALSE, sizeof(GvVertex3d));
+ area->mode_offset =
+ g_array_new(FALSE, FALSE, sizeof(gint));
+ }
+
+ gluTessBeginPolygon(tess, NULL);
+ for (i=0; i < gv_shape_get_rings((GvShape *) area); ++i)
+ {
+ int node_count;
+ gvgeocoord *xyz_nodes;
+
+ node_count = area->num_ring_nodes[i];
+ xyz_nodes = area->xyz_ring_nodes[i];
+
+ gluTessBeginContour(tess);
+ for (j=0; j < node_count; ++j)
+ {
+ coords[0] = xyz_nodes[j*3+0];
+ coords[1] = xyz_nodes[j*3+1];
+ coords[2] = xyz_nodes[j*3+2];
+
+ gluTessVertex(tess, coords, xyz_nodes + j*3);
+ }
+ gluTessEndContour(tess);
+ }
+ gluTessEndPolygon(tess);
+
+ if( area->fill->len == 0 )
+ area->fill_objects = 0;
+
+ return (area->fill_objects > 0
+ && g_array_index(area->mode_offset,gint,0) != GV_TESS_NONE);
+}
+
+static void WIN_CALLBACK
+tess_begin(GLenum type)
+{
+ area->fill_objects++;
+ g_array_append_val(area->mode_offset, type );
+ g_array_append_val(area->mode_offset, area->fill->len );
+}
+
+static void WIN_CALLBACK
+tess_end(void)
+{
+}
+
+static void WIN_CALLBACK
+tess_vertex(void *data)
+{
+ /* for some unknown reason, we somes get called with a NULL
+ if the object doesn't tesselate properly (with libMesa). */
+
+ if( data != NULL )
+ g_array_append_vals(area->fill, data, 1);
+ else
+ tess_error( 0 );
+}
+
+static void WIN_CALLBACK
+tess_error(GLenum err)
+{
+ GLenum bad_fill_mode = GV_TESS_NONE;
+ gint offset = 0;
+
+ g_array_set_size(area->fill, 0);
+ g_array_set_size(area->mode_offset, 0);
+
+ area->fill_objects = 1;
+ g_array_append_val(area->mode_offset, bad_fill_mode );
+ g_array_append_val(area->mode_offset, offset );
+}
+
+static gint
+check_ring_lengths(void)
+{
+ int r;
+
+ for (r=0; r < area->num_rings; ++r)
+ {
+ int nodes = area->num_ring_nodes[r];
+
+ if ( nodes < 3)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+check_winding(void)
+{
+ int r, winding;
+
+ for (r=0; r < area->num_rings; ++r)
+ {
+ winding = find_winding(area->xyz_ring_nodes[r],
+ area->num_ring_nodes[r]);
+
+ if ((r == 0 && winding == GV_CW) || (r > 0 && winding == GV_CCW))
+ {
+ reverse_array(area->xyz_ring_nodes[r],
+ area->num_ring_nodes[r]);
+ }
+ }
+}
+
+/* According to the comp.graphics.algorthms FAQ, item 2.07, the
+ * orientation (winding) of a simple polygon can be determined by
+ * looking at the sign of the following series:
+ * sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1})
+ * A positive result means a counter clockwise winding.
+ */
+static gint
+find_winding(gvgeocoord *xyz_nodes, int node_count)
+{
+ gvgeocoord *a, *b;
+ gvgeocoord sum;
+ int i;
+
+ sum = 0.0;
+ a = xyz_nodes + 0;
+ b = xyz_nodes + 3;
+ for (i=1; i < node_count; ++i, a += 3, b += 3)
+ {
+ sum += a[0] * b[1] - a[1] * b[0];
+ }
+ b = xyz_nodes;
+ sum += a[0] * b[1] - a[1] * b[0];
+
+ return (sum < 0.0 ? GV_CW : GV_CCW);
+}
+
+static void
+reverse_array(gvgeocoord *xyz_nodes, int node_count)
+{
+ int i;
+ gvgeocoord xyz_temp[3];
+
+ for (i=0; i < node_count/2; ++i)
+ {
+ memcpy( xyz_temp, xyz_nodes+i*3,
+ sizeof(gvgeocoord)*3 );
+ memcpy( xyz_nodes+i*3, xyz_nodes+(node_count-i-1)*3,
+ sizeof(gvgeocoord)*3);
+ memcpy( xyz_nodes+(node_count-i-1)*3, xyz_temp,
+ sizeof(gvgeocoord)*3);
+ }
+}
+
Added: packages/openev/branches/upstream/current/gvtexturecache.c
===================================================================
--- packages/openev/branches/upstream/current/gvtexturecache.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtexturecache.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,236 @@
+/******************************************************************************
+ * $Id: gvtexturecache.c,v 1.4 2001/12/13 03:29:17 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GvRasterLayer texture caching.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtexturecache.c,v $
+ * Revision 1.4 2001/12/13 03:29:17 warmerda
+ * avoid purging textures used in this render
+ *
+ * Revision 1.3 2000/07/18 14:52:06 warmerda
+ * added texture dump, touch reset textures
+ *
+ * Revision 1.2 2000/07/03 12:47:46 warmerda
+ * upped default to 16M again
+ *
+ * Revision 1.1 2000/06/27 21:25:53 warmerda
+ * New
+ *
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include "gvrasterlayer.h"
+
+static gint gv_cache_max = 16 * 1024 * 1024;
+static gint gv_cache_used = 0;
+
+static GvRasterLayerTexObj *lru_head = NULL;
+static GvRasterLayerTexObj *lru_tail = NULL;
+
+static int gv_purge_texture_lru();
+
+void gv_texture_cache_dump()
+
+{
+ GvRasterLayerTexObj *link;
+
+ printf( " -- texture lru dump -- (used=%d of %d)\n",
+ gv_cache_used, gv_cache_max );
+ for( link = lru_head; link != NULL; link = link->next )
+ {
+ if( link->next != NULL )
+ {
+ assert( link->next->prev == link );
+ }
+
+ printf( "%-20.20s tex_obj=%d tile=%d lod=%d, size=%d\n",
+ gv_data_get_name(GV_DATA(link->layer)),
+ link->tex_obj, link->texture, link->lod, link->size );
+ }
+}
+
+int gv_texture_cache_get_max()
+
+{
+ return gv_cache_max;
+}
+
+void gv_texture_cache_set_max( int new_max )
+
+{
+ gv_cache_max = new_max;
+
+ /* free space to ensure we stay below our limit */
+ while( gv_cache_used > gv_cache_max && gv_purge_texture_lru() ) {}
+}
+
+int gv_texture_cache_get_used()
+
+{
+ return gv_cache_used;
+}
+
+void gv_raster_layer_create_texture( GvRasterLayer *layer, int texture,
+ GLuint tex_obj, int lod, int size )
+
+{
+ GvRasterLayerTexObj *tex;
+
+ /* If it already exists, blow it away - this shouldn't happen */
+ if( layer->textures[texture] != NULL )
+ gv_raster_layer_purge_texture( layer, texture );
+
+ tex = g_new0( GvRasterLayerTexObj, 1 );
+ tex->lod = lod;
+ tex->size = size;
+ tex->tex_obj = tex_obj;
+ tex->layer = layer;
+ tex->texture = texture;
+
+ /* account for texture memory used */
+ gv_cache_used += tex->size;
+
+ /* free space to ensure we stay below our limit */
+ while( gv_cache_used > gv_cache_max && gv_purge_texture_lru() ) {}
+
+ /* attach to layer */
+ layer->textures[texture] = tex;
+
+ /* put into the LRU list */
+ gv_raster_layer_touch_texture( layer, texture );
+}
+
+void gv_raster_layer_reset_texture( GvRasterLayer *layer, int texture,
+ int lod, int size )
+
+{
+ gv_cache_used -= layer->textures[texture]->size;
+
+ layer->textures[texture]->size = size;
+ layer->textures[texture]->lod = lod;
+
+ gv_cache_used += layer->textures[texture]->size;
+ gv_raster_layer_touch_texture( layer, texture );
+
+ /* purge other textures so that will stay under the texture memory limit */
+ while(gv_cache_used > gv_cache_max && gv_purge_texture_lru()) {}
+}
+
+void gv_raster_layer_purge_texture( GvRasterLayer *layer, int texture )
+
+{
+ GvRasterLayerTexObj *tex = layer->textures[texture];
+
+ if( tex == NULL )
+ return;
+
+ gv_cache_used -= tex->size;
+ glDeleteTextures( 1, &(tex->tex_obj) );
+
+ if( tex->prev != NULL )
+ tex->prev->next = tex->next;
+
+ if( tex->next != NULL )
+ tex->next->prev = tex->prev;
+
+ if( lru_head == tex )
+ lru_head = tex->next;
+
+ if( lru_tail == tex )
+ lru_tail = tex->prev;
+
+ g_free( layer->textures[texture] );
+ layer->textures[texture] = NULL;
+}
+
+void gv_raster_layer_touch_texture( GvRasterLayer *layer, int texture )
+
+{
+ GvRasterLayerTexObj *tex = layer->textures[texture];
+
+ if( tex == NULL )
+ return;
+
+ /* Remove from current location in LRU list (if in it) */
+ if( tex->prev != NULL )
+ tex->prev->next = tex->next;
+
+ if( tex->next != NULL )
+ tex->next->prev = tex->prev;
+
+ if( lru_head == tex )
+ lru_head = tex->next;
+
+ if( lru_tail == tex )
+ lru_tail = tex->prev;
+
+ tex->prev = tex->next = NULL;
+
+ /* Add at tail of list */
+ if( lru_tail == NULL )
+ {
+ lru_tail = lru_head = tex;
+ }
+ else
+ {
+ assert( lru_head != NULL );
+ assert( lru_tail->next == NULL );
+
+ lru_tail->next = tex;
+ tex->prev = lru_tail;
+ lru_tail = tex;
+ }
+
+ /* mark it with the current render count */
+ tex->last_render = gv_get_render_counter();
+}
+
+/*
+ * Purge the least recently used texture (at the head of LRU list).
+ */
+static int gv_purge_texture_lru()
+
+{
+ if( lru_head == NULL )
+ return FALSE;
+
+ if( lru_head->last_render == gv_get_render_counter() )
+ {
+ static int bReported = FALSE;
+
+ if( !bReported )
+ {
+ CPLDebug( "gvrasterlayer", "short circuit purge within render" );
+ bReported = TRUE;
+ }
+
+ return FALSE;
+ }
+
+ gv_raster_layer_purge_texture( lru_head->layer,
+ lru_head->texture );
+
+ return TRUE;
+}
Added: packages/openev/branches/upstream/current/gvtool.c
===================================================================
--- packages/openev/branches/upstream/current/gvtool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,359 @@
+/******************************************************************************
+ * $Id: gvtool.c,v 1.11 2005/01/17 18:37:43 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for editing mode tools.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtool.c,v $
+ * Revision 1.11 2005/01/17 18:37:43 gmwalter
+ * Add ability to reset tool cursor type.
+ *
+ * Revision 1.10 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.9 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.8 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvtool.h"
+#include <gtk/gtksignal.h>
+
+enum
+{
+ ACTIVATE,
+ DEACTIVATE,
+ DRAW,
+ BUTTON_PRESS,
+ BUTTON_RELEASE,
+ MOTION_NOTIFY,
+ KEY_PRESS,
+ ENTER_NOTIFY,
+ LEAVE_NOTIFY,
+ LAST_SIGNAL
+};
+
+static void gv_tool_class_init(GvToolClass *klass);
+static void gv_tool_init(GvTool *tool);
+static void gv_tool_real_activate(GvTool *tool, GvViewArea *area);
+static void gv_tool_real_deactivate(GvTool *tool, GvViewArea *area);
+
+static guint tool_signals[LAST_SIGNAL] = { 0 };
+
+GtkType
+gv_tool_get_type(void)
+{
+ static GtkType tool_type = 0;
+
+ if (!tool_type)
+ {
+ static const GtkTypeInfo tool_info =
+ {
+ "GvTool",
+ sizeof(GvTool),
+ sizeof(GvToolClass),
+ (GtkClassInitFunc) gv_tool_class_init,
+ (GtkObjectInitFunc) gv_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ tool_type = gtk_type_unique(gtk_object_get_type(),
+ &tool_info);
+ }
+ return tool_type;
+}
+
+static void
+gv_tool_class_init(GvToolClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ tool_signals[ACTIVATE] =
+ gtk_signal_new ("activate",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, activate),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[DEACTIVATE] =
+ gtk_signal_new ("deactivate",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, deactivate),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[DRAW] =
+ gtk_signal_new ("draw",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, draw),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ tool_signals[BUTTON_PRESS] =
+ gtk_signal_new ("button-press",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, button_press),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[BUTTON_RELEASE] =
+ gtk_signal_new ("button-release",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, button_release),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[MOTION_NOTIFY] =
+ gtk_signal_new ("motion-notify",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, motion_notify),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[KEY_PRESS] =
+ gtk_signal_new ("key-press",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, key_press),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[ENTER_NOTIFY] =
+ gtk_signal_new ("enter-notify",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, enter_notify),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ tool_signals[LEAVE_NOTIFY] =
+ gtk_signal_new ("leave-notify",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvToolClass, leave_notify),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ gtk_object_class_add_signals(object_class, tool_signals, LAST_SIGNAL);
+
+ klass->activate = gv_tool_real_activate;
+ klass->deactivate = gv_tool_real_deactivate;
+ klass->draw = NULL;
+ klass->button_press = NULL;
+ klass->button_release = NULL;
+ klass->motion_notify = NULL;
+ klass->key_press = NULL;
+ klass->enter_notify = NULL;
+ klass->leave_notify = NULL;
+}
+
+static void
+gv_tool_init(GvTool *tool)
+{
+ tool->view = NULL;
+ tool->cursor = NULL;
+ tool->bounded = 0;
+}
+
+void
+gv_tool_activate(GvTool *tool, GvViewArea *view)
+{
+ gtk_signal_emit(GTK_OBJECT(tool), tool_signals[ACTIVATE], view);
+}
+
+void
+gv_tool_deactivate(GvTool *tool, GvViewArea *view)
+{
+ gtk_signal_emit(GTK_OBJECT(tool), tool_signals[DEACTIVATE], view);
+}
+
+/**************************************************************/
+
+static void
+gv_tool_real_activate(GvTool *tool, GvViewArea *view)
+{
+ GvToolClass *klass;
+
+ if (tool->view)
+ {
+ g_warning("gv_tool_activate(): tool %s is already active on a view",
+ gtk_type_name(GTK_OBJECT_TYPE(tool)));
+ return;
+ }
+
+ tool->view = view;
+ gtk_object_ref(GTK_OBJECT(view));
+ klass = (GvToolClass*)gtk_type_class(GTK_OBJECT_TYPE(tool));
+
+ /* This could be done through an indirect function call which
+ emits a tool signal. Probably better but more overhead... */
+
+ if (klass->draw)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "gldraw",
+ GTK_SIGNAL_FUNC(klass->draw),
+ GTK_OBJECT(tool));
+ }
+ if (klass->button_press)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "button-press-event",
+ GTK_SIGNAL_FUNC(klass->button_press),
+ GTK_OBJECT(tool));
+ }
+ if (klass->button_release)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "button-release-event",
+ GTK_SIGNAL_FUNC(klass->button_release),
+ GTK_OBJECT(tool));
+ }
+ if (klass->motion_notify)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "motion-notify-event",
+ GTK_SIGNAL_FUNC(klass->motion_notify),
+ GTK_OBJECT(tool));
+ }
+ if (klass->key_press)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "key-press-event",
+ GTK_SIGNAL_FUNC(klass->key_press),
+ GTK_OBJECT(tool));
+ }
+ if (klass->enter_notify)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "enter-notify-event",
+ GTK_SIGNAL_FUNC(klass->enter_notify),
+ GTK_OBJECT(tool));
+ }
+ if (klass->leave_notify)
+ {
+ gtk_signal_connect_object(GTK_OBJECT(view), "leave-notify-event",
+ GTK_SIGNAL_FUNC(klass->leave_notify),
+ GTK_OBJECT(tool));
+ }
+
+ /* Install cursor for this tool */
+ if (GTK_WIDGET_REALIZED(GTK_WIDGET(view)))
+ {
+ gdk_window_set_cursor(GTK_WIDGET(view)->window, tool->cursor);
+ }
+}
+
+static void
+gv_tool_real_deactivate(GvTool *tool, GvViewArea *view)
+{
+ g_return_if_fail(tool->view == view);
+
+ gtk_signal_disconnect_by_data(GTK_OBJECT(tool->view), (gpointer)tool);
+ tool->view = NULL;
+ gtk_object_unref(GTK_OBJECT(view));
+}
+
+GvViewArea *gv_tool_get_view(GvTool *tool)
+
+{
+ return tool->view;
+}
+
+gint
+gv_tool_set_boundary(GvTool *tool, GvRect *rect)
+{
+ if( rect == NULL )
+ {
+ tool->bounded = FALSE;
+ return TRUE;
+ }
+
+ /* check rect is valid */
+ if (rect->width <= 0 || rect->height <= 0)
+ {
+ return FALSE;
+ }
+
+ tool->bounded = TRUE;
+ tool->boundary = *rect;
+
+ return TRUE;
+}
+
+void gv_tool_clamp_to_bounds( GvTool *tool, gvgeocoord *x, gvgeocoord *y )
+
+{
+ if( tool->bounded )
+ {
+ *x = MAX(MIN(*x,tool->boundary.x+tool->boundary.width),
+ tool->boundary.x);
+ *y = MAX(MIN(*y,tool->boundary.y+tool->boundary.height),
+ tool->boundary.y);
+ }
+}
+
+gint gv_tool_check_bounds( GvTool *tool, gvgeocoord x, gvgeocoord y )
+
+{
+ if( !tool->bounded )
+ return TRUE;
+
+ if( x < tool->boundary.x || x > tool->boundary.x + tool->boundary.width )
+ return FALSE;
+
+ if( y < tool->boundary.y || y > tool->boundary.y + tool->boundary.height )
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+gv_tool_set_cursor(GvTool *tool, gint cursor_type)
+{
+ if (tool->cursor != NULL)
+ gdk_cursor_destroy(tool->cursor);
+
+ tool->cursor = gdk_cursor_new(cursor_type);
+
+ if ((tool->view != NULL) && (GTK_WIDGET_REALIZED(GTK_WIDGET(tool->view))))
+ {
+ gdk_window_set_cursor(GTK_WIDGET(tool->view)->window, tool->cursor);
+ }
+
+}
Added: packages/openev/branches/upstream/current/gvtool.h
===================================================================
--- packages/openev/branches/upstream/current/gvtool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvtool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * $Id: gvtool.h,v 1.8 2005/01/17 18:37:43 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Base class for editing mode tools.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtool.h,v $
+ * Revision 1.8 2005/01/17 18:37:43 gmwalter
+ * Add ability to reset tool cursor type.
+ *
+ * Revision 1.7 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.6 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.5 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_TOOL_H__
+#define __GV_TOOL_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkobject.h>
+#include "gvviewarea.h"
+#include "gvtypes.h"
+
+#define GV_TYPE_TOOL (gv_tool_get_type ())
+#define GV_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_TOOL, GvTool))
+#define GV_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_TOOL, GvToolClass))
+#define GV_IS_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_TOOL))
+#define GV_IS_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_TOOL))
+
+/* Shortcuts to parent class functions */
+#define GV_TOOL_ACTIVATE(t,v) (*((GvToolClass*)gtk_type_class(GV_TYPE_TOOL))->activate)(GV_TOOL(t),v)
+#define GV_TOOL_DEACTIVATE(t,v) (*((GvToolClass*)gtk_type_class(GV_TYPE_TOOL))->deactivate)(GV_TOOL(t),v)
+
+typedef struct _GvTool GvTool;
+typedef struct _GvToolClass GvToolClass;
+
+struct _GvTool
+{
+ GtkObject object;
+
+ GvViewArea *view;
+ GdkCursor *cursor;
+
+ GvRect boundary; /* Constraints of where ROI can be dragged out */
+ gint bounded : 1; /* Boolean, have boundary constraints on ROI be set*/
+};
+
+struct _GvToolClass
+{
+ GtkObjectClass parent_class;
+
+ void (* activate) (GvTool *tool, GvViewArea *view);
+ void (* deactivate) (GvTool *tool, GvViewArea *view);
+ void (* draw) (GvTool *tool);
+ void (* button_press) (GvTool *tool, GdkEventButton *event);
+ void (* button_release) (GvTool *tool, GdkEventButton *event);
+ void (* motion_notify) (GvTool *tool, GdkEventMotion *event);
+ void (* key_press) (GvTool *tool, GdkEventKey *event);
+ void (* enter_notify) (GvTool *tool, GdkEventCrossing *event);
+ void (* leave_notify) (GvTool *tool, GdkEventCrossing *event);
+};
+
+GtkType gv_tool_get_type(void);
+
+void gv_tool_activate(GvTool *tool, GvViewArea *view);
+void gv_tool_deactivate(GvTool *tool, GvViewArea *view);
+GvViewArea *gv_tool_get_view(GvTool *tool);
+gint gv_tool_set_boundary(GvTool *tool, GvRect *rect);
+void gv_tool_clamp_to_bounds( GvTool *tool, gvgeocoord *x, gvgeocoord *y );
+gint gv_tool_check_bounds( GvTool *tool, gvgeocoord x, gvgeocoord y );
+void gv_tool_set_cursor(GvTool *tool, gint cursor_type);
+
+#endif /* __GV_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvtoolbox.c
===================================================================
--- packages/openev/branches/upstream/current/gvtoolbox.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtoolbox.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,280 @@
+/******************************************************************************
+ * $Id: gvtoolbox.c,v 1.8 2000/08/03 18:39:49 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Container for available editing tools, manages which is active.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtoolbox.c,v $
+ * Revision 1.8 2000/08/03 18:39:49 warmerda
+ * activate a tool on key-press, or button-press but not focus-enter
+ *
+ * Revision 1.7 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvtoolbox.h"
+#include <gtk/gtksignal.h>
+
+static void gv_toolbox_class_init(GvToolboxClass *klass);
+static void gv_toolbox_init(GvToolbox *toolbox);
+static void gv_toolbox_activate(GvTool *toolbox, GvViewArea *view);
+static void gv_toolbox_deactivate(GvTool *toolbox, GvViewArea *view);
+static void gv_toolbox_view_event(GvViewArea *view, GdkEvent *event, GvToolbox *toolbox);
+static void gv_toolbox_switch_to_view(GvToolbox *toolbox, GvViewArea *view);
+static void gv_toolbox_destroy(GtkObject *object);
+static void gv_toolbox_finalize(GtkObject *object);
+
+GtkType
+gv_toolbox_get_type(void)
+{
+ static GtkType toolbox_type = 0;
+
+ if (!toolbox_type)
+ {
+ static const GtkTypeInfo toolbox_info =
+ {
+ "GvToolbox",
+ sizeof(GvToolbox),
+ sizeof(GvToolboxClass),
+ (GtkClassInitFunc) gv_toolbox_class_init,
+ (GtkObjectInitFunc) gv_toolbox_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ toolbox_type = gtk_type_unique(gv_tool_get_type(),
+ &toolbox_info);
+ }
+ return toolbox_type;
+}
+
+static void
+gv_toolbox_class_init(GvToolboxClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvToolClass *tool_class;
+
+ object_class = (GtkObjectClass*)klass;
+ tool_class = (GvToolClass*)klass;
+
+ object_class->destroy = gv_toolbox_destroy;
+ object_class->finalize = gv_toolbox_finalize;
+
+ tool_class->activate = gv_toolbox_activate;
+ tool_class->deactivate = gv_toolbox_deactivate;
+}
+
+static void
+gv_toolbox_init(GvToolbox *toolbox)
+{
+ toolbox->tools = g_hash_table_new(g_str_hash, g_str_equal);
+ toolbox->active_tool = NULL;
+ toolbox->views = NULL;
+}
+
+GvTool *
+gv_toolbox_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_TOOLBOX));
+}
+
+void
+gv_toolbox_add_tool(GvToolbox *toolbox, gchar *name, GvTool *tool)
+{
+ if (g_hash_table_lookup(toolbox->tools, name))
+ {
+ g_warning("gv_toolbox_add_tool(): tool %s already exists", name);
+ return;
+ }
+
+ gtk_object_ref(GTK_OBJECT(tool));
+ gtk_object_sink(GTK_OBJECT(tool));
+ g_hash_table_insert(toolbox->tools, g_strdup(name), (gpointer)tool);
+
+ if( GV_TOOL(toolbox)->bounded )
+ gv_tool_set_boundary( tool, &(GV_TOOL(toolbox)->boundary) );
+}
+
+void
+gv_toolbox_activate_tool(GvToolbox *toolbox, gchar *tool_name)
+{
+ GvTool *tool;
+
+ if (tool_name)
+ {
+ tool = (GvTool*)g_hash_table_lookup(toolbox->tools, tool_name);
+ if (!tool)
+ {
+ g_warning("gv_toolbox_activate_tool(): no tool %s in toolbox",
+ tool_name);
+ return;
+ }
+ }
+ else
+ {
+ tool = NULL;
+ }
+
+ /* Check if tool is already active */
+ if (tool == toolbox->active_tool) return;
+
+ /* Deactivate currently active tool */
+ if (toolbox->active_tool && GV_TOOL(toolbox)->view)
+ {
+ gv_tool_deactivate(toolbox->active_tool, GV_TOOL(toolbox)->view);
+ }
+
+ /* Activate new tool */
+ toolbox->active_tool = tool;
+ if (toolbox->active_tool && GV_TOOL(toolbox)->view)
+ {
+ gv_tool_activate(toolbox->active_tool, GV_TOOL(toolbox)->view);
+ }
+}
+
+/*******************************************************/
+
+static void
+gv_toolbox_activate(GvTool *tool, GvViewArea *view)
+{
+ GvToolbox *toolbox = GV_TOOLBOX( tool );
+
+ if (!g_list_find(toolbox->views, view))
+ {
+ gtk_object_ref(GTK_OBJECT(view));
+ toolbox->views = g_list_append(toolbox->views, (gpointer)view);
+
+ gtk_signal_connect(GTK_OBJECT(view), "button-press-event",
+ GTK_SIGNAL_FUNC(gv_toolbox_view_event),
+ (gpointer)toolbox);
+ gtk_signal_connect(GTK_OBJECT(view), "key-press-event",
+ GTK_SIGNAL_FUNC(gv_toolbox_view_event),
+ (gpointer)toolbox);
+ }
+
+ gv_toolbox_switch_to_view( toolbox, view );
+}
+
+static void
+gv_toolbox_deactivate(GvTool *tool, GvViewArea *view)
+{
+ GvToolbox *toolbox = GV_TOOLBOX( tool );
+
+ if (!g_list_find(toolbox->views, view))
+ {
+ g_warning("gv_toolbox_activate(): view not active");
+ return;
+ }
+
+ if (view == GV_TOOL(toolbox)->view)
+ {
+ if (toolbox->active_tool)
+ {
+ gv_tool_deactivate(toolbox->active_tool, view);
+ }
+ GV_TOOL(toolbox)->view = NULL;
+ }
+
+ gtk_signal_disconnect_by_data(GTK_OBJECT(view), (gpointer)toolbox);
+ toolbox->views = g_list_remove(toolbox->views, view);
+ gtk_object_unref(GTK_OBJECT(view));
+}
+
+static void
+gv_toolbox_view_event(GvViewArea *view, GdkEvent *event, GvToolbox *toolbox)
+{
+ /* Check whether this view is the active view */
+ if (view != GV_TOOL(toolbox)->view)
+ {
+ gv_tool_activate( GV_TOOL(toolbox), view );
+ }
+}
+
+static void
+gv_toolbox_switch_to_view(GvToolbox *toolbox, GvViewArea *view)
+{
+ /* Deactivate the active tool */
+ if (toolbox->active_tool && GV_TOOL(toolbox)->view)
+ {
+ gv_tool_deactivate(toolbox->active_tool, GV_TOOL(toolbox)->view);
+ }
+
+ /* Switch views */
+ GV_TOOL(toolbox)->view = view;
+
+ /* Reactivate the active tool */
+ if (toolbox->active_tool && view)
+ {
+ gv_tool_activate(toolbox->active_tool, view);
+ }
+}
+
+static gboolean
+unref_object_foreach(gpointer key, gpointer value, gpointer data)
+{
+ gtk_object_unref((GtkObject*)value);
+ return TRUE;
+}
+
+static void
+gv_toolbox_destroy(GtkObject *object)
+{
+ GvToolClass *parent_class;
+ GvToolbox *toolbox;
+
+ toolbox = GV_TOOLBOX(object);
+
+ /* Remove all views */
+ while (toolbox->views)
+ {
+ GvViewArea *view = (GvViewArea*)toolbox->views->data;
+ gv_tool_deactivate(GV_TOOL(toolbox), view);
+ }
+
+ /* Remove all tools */
+ g_hash_table_foreach_remove(toolbox->tools, unref_object_foreach, NULL);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_tool_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(object);
+}
+
+static void
+gv_toolbox_finalize(GtkObject *object)
+{
+ GvToolClass *parent_class;
+ GvToolbox *toolbox;
+
+ toolbox = GV_TOOLBOX(object);
+
+ g_hash_table_destroy(toolbox->tools);
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_tool_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
Added: packages/openev/branches/upstream/current/gvtoolbox.h
===================================================================
--- packages/openev/branches/upstream/current/gvtoolbox.h (rev 0)
+++ packages/openev/branches/upstream/current/gvtoolbox.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+/******************************************************************************
+ * $Id: gvtoolbox.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Container for available editing tools, manages which is active.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtoolbox.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_TOOLBOX_H__
+#define __GV_TOOLBOX_H__
+
+#include "gvtool.h"
+
+#define GV_TYPE_TOOLBOX (gv_toolbox_get_type ())
+#define GV_TOOLBOX(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_TOOLBOX, GvToolbox))
+#define GV_TOOLBOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_TOOLBOX, GvToolboxClass))
+#define GV_IS_TOOLBOX(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_TOOLBOX))
+#define GV_IS_TOOLBOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_TOOLBOX))
+
+typedef struct _GvToolbox GvToolbox;
+typedef struct _GvToolboxClass GvToolboxClass;
+
+struct _GvToolbox
+{
+ GvTool tool;
+
+ GHashTable *tools;
+ GvTool *active_tool;
+ GList *views;
+};
+
+struct _GvToolboxClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_toolbox_get_type(void);
+GvTool* gv_toolbox_new(void);
+
+void gv_toolbox_add_tool(GvToolbox *toolbox, gchar *name, GvTool *tool);
+void gv_toolbox_activate_tool(GvToolbox *toolbox, gchar *tool_name);
+
+#endif /* __GV_TOOLBOX_H__ */
Added: packages/openev/branches/upstream/current/gvtracktool.c
===================================================================
--- packages/openev/branches/upstream/current/gvtracktool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvtracktool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,147 @@
+/******************************************************************************
+ * $Id: gvtracktool.c,v 1.8 2002/11/04 21:42:07 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Tracking display of raster values and position of cursor.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtracktool.c,v $
+ * Revision 1.8 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.7 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvtracktool.h"
+#include "gvrasterlayer.h"
+#include "gvutils.h"
+#include "gvmanager.h"
+
+#include <gtk/gtklabel.h>
+
+static void gv_track_tool_class_init(GvTrackToolClass *klass);
+static void gv_track_tool_init(GvTrackTool *tool);
+static void gv_track_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_track_tool_leave_notify(GvTool *tool, GdkEventCrossing *event);
+static void gv_track_tool_destroy(GtkObject *object);
+
+GtkType
+gv_track_tool_get_type(void)
+{
+ static GtkType track_tool_type = 0;
+
+ if (!track_tool_type)
+ {
+ static const GtkTypeInfo track_tool_info =
+ {
+ "GvTrackTool",
+ sizeof(GvTrackTool),
+ sizeof(GvTrackToolClass),
+ (GtkClassInitFunc) gv_track_tool_class_init,
+ (GtkObjectInitFunc) gv_track_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ track_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &track_tool_info);
+ }
+ return track_tool_type;
+}
+
+static void
+gv_track_tool_class_init(GvTrackToolClass *klass)
+{
+ GtkObjectClass *object_class;
+ GvToolClass *tool_class;
+
+ object_class = (GtkObjectClass*)klass;
+ tool_class = (GvToolClass*)klass;
+
+ object_class->destroy = gv_track_tool_destroy;
+
+ tool_class->motion_notify = gv_track_tool_motion_notify;
+ tool_class->leave_notify = gv_track_tool_leave_notify;
+}
+
+static void
+gv_track_tool_init(GvTrackTool *tool)
+{
+ tool->label = NULL;
+}
+
+GvTool *
+gv_track_tool_new(GtkObject *label)
+{
+ GvTrackTool *tool;
+
+ g_return_val_if_fail(GTK_IS_LABEL(label), NULL);
+
+ tool = GV_TRACK_TOOL(gtk_type_new(GV_TYPE_TRACK_TOOL));
+ tool->label = label;
+ gtk_object_ref(label);
+
+ return GV_TOOL(tool);
+}
+
+/********************************************************/
+
+static void
+gv_track_tool_motion_notify(GvTool *tool_in, GdkEventMotion *event)
+{
+ GvTrackTool *tool = GV_TRACK_TOOL(tool_in);
+ gvgeocoord geo_x, geo_y;
+ const char *text;
+ GvProperties *properties = gv_manager_get_preferences( gv_get_manager() );
+
+ gv_view_area_map_pointer(GV_TOOL(tool)->view, event->x, event->y,
+ &geo_x, &geo_y);
+
+ text = gv_format_point_query( GV_TOOL(tool)->view,
+ properties, geo_x, geo_y );
+ gtk_label_set_text(GTK_LABEL(tool->label), text);
+}
+
+static void
+gv_track_tool_leave_notify(GvTool *tool, GdkEventCrossing *event)
+{
+ gtk_label_set_text(GTK_LABEL(GV_TRACK_TOOL(tool)->label), "");
+}
+
+static void
+gv_track_tool_destroy(GtkObject *object)
+{
+ GvToolClass *parent_class;
+ GvTrackTool *tool;
+
+ tool = GV_TRACK_TOOL(object);
+
+ gtk_object_unref(tool->label);
+ tool->label = NULL;
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gv_tool_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(object);
+}
Added: packages/openev/branches/upstream/current/gvtracktool.h
===================================================================
--- packages/openev/branches/upstream/current/gvtracktool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvtracktool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * $Id: gvtracktool.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Tracking display of raster values and position of cursor.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtracktool.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_TRACK_TOOL_H__
+#define __GV_TRACK_TOOL_H__
+
+#include "gvtool.h"
+
+#define GV_TYPE_TRACK_TOOL (gv_track_tool_get_type ())
+#define GV_TRACK_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_TRACK_TOOL, GvTrackTool))
+#define GV_TRACK_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_TRACK_TOOL, GvTrackToolClass))
+#define GV_IS_TRACK_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_TRACK_TOOL))
+#define GV_IS_TRACK_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_TRACK_TOOL))
+
+typedef struct _GvTrackTool GvTrackTool;
+typedef struct _GvTrackToolClass GvTrackToolClass;
+
+struct _GvTrackTool
+{
+ GvTool tool;
+
+ GtkObject *label;
+};
+
+struct _GvTrackToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_track_tool_get_type(void);
+GvTool* gv_track_tool_new(GtkObject *label);
+
+#endif /* __GV_TRACK_TOOL_H__ */
Added: packages/openev/branches/upstream/current/gvtypes.h
===================================================================
--- packages/openev/branches/upstream/current/gvtypes.h (rev 0)
+++ packages/openev/branches/upstream/current/gvtypes.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,155 @@
+/******************************************************************************
+ * $Id: gvtypes.h,v 1.15 2004/03/05 23:40:12 sduclos Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Assortment of OpenEV types.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvtypes.h,v $
+ * Revision 1.15 2004/03/05 23:40:12 sduclos
+ * remove commentd define GV_USE_DOUBLE.. , remove TAB
+ *
+ * Revision 1.14 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.13 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_TYPES_H__
+#define __GV_TYPES_H__
+
+#include <glib.h>
+#include "gv_config.h"
+
+#define GV_NONE 0x000
+#define GV_ALWAYS 0x001
+#define GV_LATER 0x002
+#define GV_NOW 0x003
+#define GV_FIRST 0x004
+#define GV_ALL 0x005
+
+/* GvShapeLayer.flags */
+#define GV_DELAY_SELECTED 0x0001
+#define GV_SUPPRESS_SELCHANGED 0x0002
+
+#define GV_TESS_NONE 0
+#define GV_TESS_LOCK -1
+
+#define GV_CHANGE_ADD 0x001
+#define GV_CHANGE_REPLACE 0x002
+#define GV_CHANGE_DELETE 0x003
+
+#define GV_MINFLOAT G_MINFLOAT
+#define GV_MAXFLOAT G_MAXFLOAT
+
+
+#ifdef GV_USE_DOUBLE_PRECISION_COORD
+#
+# define glVertex2 glVertex2d
+# define glVertex2v glVertex2dv
+# define glVertex3 glVertex3d
+# define glScale glScaled
+# define glRotate glRotated
+# define glTranslate glTranslated
+#
+# define GL_GEOCOORD GL_DOUBLE
+# define GLgeocoord GLdouble
+#
+#else
+#
+# define glVertex2 glVertex2f
+# define glVertex2v glVertex2fv
+# define glVertex3 glVertex3f
+# define glScale glScalef
+# define glRotate glRotatef
+# define glTranslate glTranslatef
+#
+# define GL_GEOCOORD GL_FLOAT
+# define GLgeocoord GLfloat
+#
+#endif
+
+// SD Note: sizeof(GLgeocoord) == sizeof(gvgeocoord)
+#ifdef GV_USE_DOUBLE_PRECISION_COORD
+typedef double gvgeocoord;
+#else
+typedef float gvgeocoord;
+#endif
+
+typedef float gvfloat;
+
+typedef float GvColor[4]; /* RGBA, range [0-1] */
+
+typedef struct _GvRect GvRect;
+typedef struct _GvVertex GvVertex;
+typedef struct _GvVertex3d GvVertex3d;
+typedef struct _GvNodeInfo GvNodeInfo;
+typedef struct _GvShapeChangeInfo GvShapeChangeInfo;
+
+struct _GvRect
+{
+ gvgeocoord x, y, width, height;
+};
+
+struct _GvVertex
+{
+ gvgeocoord x, y;
+};
+
+struct _GvVertex3d
+{
+ gvgeocoord x, y, z;
+};
+
+struct _GvNodeInfo
+{
+ gint shape_id;
+ gint ring_id;
+ gint node_id;
+ GvVertex *vertex;
+};
+
+struct _GvShapeChangeInfo
+{
+ gint change_type;
+ gint num_shapes;
+ gint *shape_id;
+};
+
+typedef struct _GvRasterChangeInfo
+{
+ gint change_type;
+ gint x_off;
+ gint y_off;
+ gint width;
+ gint height;
+} GvRasterChangeInfo;
+
+/* FIXME: Where is a good place for this? */
+#define gv_color_copy(d,s) {d[0]=s[0];d[1]=s[1];d[2]=s[2];d[3]=s[3];}
+
+#endif /* __GV_TYPES_H__ */
+
+
+
Added: packages/openev/branches/upstream/current/gvundo.c
===================================================================
--- packages/openev/branches/upstream/current/gvundo.c (rev 0)
+++ packages/openev/branches/upstream/current/gvundo.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,248 @@
+/******************************************************************************
+ * $Id: gvundo.c,v 1.6 2002/09/30 20:50:32 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Generic undo management.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvundo.c,v $
+ * Revision 1.6 2002/09/30 20:50:32 warmerda
+ * fixed serious bug in gv_undo_end_group
+ *
+ * Revision 1.5 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvundo.h"
+#include "gextra.h"
+#include <gtk/gtksignal.h>
+
+#define DEFAULT_STACK_MAX 64
+
+typedef struct _GvUndo GvUndo;
+
+struct _GvUndo
+{
+ GList *undo_stack;
+ gint undo_stack_count;
+ gint stack_max;
+ gint undo_enabled : 1;
+ gint undo_open : 1;
+ gint group_locked : 1;
+ gint next_group;
+};
+
+static void gv_undo_data_changing(GvData *data, gpointer change_info);
+static void gv_undo_data_destroy(GvData *data);
+
+static GvUndo *undo = NULL;
+
+static void
+gv_undo_init(void)
+{
+ undo = g_new(GvUndo, 1);
+ undo->undo_stack = NULL;
+ undo->undo_stack_count = 0;
+ undo->stack_max = DEFAULT_STACK_MAX;
+ undo->undo_enabled = TRUE;
+ undo->undo_open = TRUE;
+ undo->next_group = 1;
+ undo->group_locked = FALSE;
+}
+
+void
+gv_undo_register_data(GvData *data)
+{
+ if (!undo) gv_undo_init();
+
+ gtk_signal_connect(GTK_OBJECT(data), "changing",
+ GTK_SIGNAL_FUNC(gv_undo_data_changing), NULL);
+
+ gtk_signal_connect(GTK_OBJECT(data), "destroy",
+ GTK_SIGNAL_FUNC(gv_undo_data_destroy), NULL);
+}
+
+void
+gv_undo_open(void)
+{
+ if (!undo) gv_undo_init();
+ undo->undo_open = TRUE;
+}
+
+void
+gv_undo_close(void)
+{
+ if (!undo) gv_undo_init();
+ undo->undo_open = FALSE;
+}
+
+void
+gv_undo_push(GvDataMemento *memento)
+{
+ if (!undo) gv_undo_init();
+
+ /* set group id */
+ memento->group = undo->next_group;
+ if( !undo->group_locked )
+ undo->next_group++;
+
+ /* push on undo stack */
+ undo->undo_stack = g_list_push(undo->undo_stack, memento);
+
+ /* discard oldest undo step if we are at the limit */
+ if (++undo->undo_stack_count > undo->stack_max)
+ {
+ GList *remove;
+ GvDataMemento *memento;
+
+ remove = g_list_last(undo->undo_stack);
+ memento = (GvDataMemento*)remove->data;
+ undo->undo_stack = g_list_remove_link(undo->undo_stack, remove);
+ undo->undo_stack_count--;
+
+ gv_data_del_memento(memento->data, memento);
+ }
+}
+
+void
+gv_undo_pop(void)
+{
+ GvDataMemento *memento;
+ gint open;
+ gint pop_group;
+
+ if (!undo) gv_undo_init();
+ if (!undo->undo_enabled || undo->undo_stack_count == 0) return;
+
+ if( undo->group_locked )
+ gv_undo_end_group( undo->next_group );
+
+ /* pop all the undo's of a group */
+ pop_group = ((GvDataMemento *) undo->undo_stack->data)->group;
+ while( undo->undo_stack_count > 0
+ && ((GvDataMemento *) undo->undo_stack->data)->group == pop_group )
+ {
+ memento = (GvDataMemento*)undo->undo_stack->data;
+ undo->undo_stack = g_list_pop(undo->undo_stack);
+ undo->undo_stack_count--;
+
+ /* Close the undo object temporarily while undoing */
+ open = undo->undo_open;
+ undo->undo_open = FALSE;
+ gv_data_set_memento(memento->data, memento);
+ undo->undo_open = open;
+ }
+}
+
+void
+gv_undo_clear(void)
+{
+ GvDataMemento *memento;
+
+ if (!undo) gv_undo_init();
+ while (undo->undo_stack_count)
+ {
+ memento = (GvDataMemento*)undo->undo_stack->data;
+ undo->undo_stack = g_list_pop(undo->undo_stack);
+ undo->undo_stack_count--;
+
+ gv_data_del_memento(memento->data, memento);
+ }
+
+ undo->group_locked = FALSE;
+}
+
+void
+gv_undo_enable()
+{
+ if (!undo) gv_undo_init();
+ undo->undo_enabled = TRUE;
+}
+
+void
+gv_undo_disable()
+{
+ if (!undo) gv_undo_init();
+ undo->undo_enabled = FALSE;
+}
+
+gint
+gv_undo_can_undo(void)
+{
+ if (!undo) gv_undo_init();
+ return (undo->undo_enabled && undo->undo_stack_count > 0);
+}
+
+gint gv_undo_start_group(void)
+
+{
+ if (!undo) gv_undo_init();
+
+ if( undo->group_locked )
+ {
+ /* failure */
+ return 0;
+ }
+
+ undo->group_locked = TRUE;
+ return undo->next_group;
+}
+
+void
+gv_undo_end_group(gint group)
+
+{
+ if (!undo) gv_undo_init();
+
+ if( !undo->group_locked || undo->next_group != group)
+ {
+ /* failure */
+ return;
+ }
+
+ undo->group_locked = FALSE;
+ undo->next_group++;
+}
+
+
+static void
+gv_undo_data_changing(GvData *data, gpointer change_info)
+{
+ GvDataMemento *memento;
+
+ if (!undo->undo_open) return;
+
+ memento = gv_data_get_memento(data, change_info);
+ if (memento)
+ {
+ gv_undo_push(memento);
+ }
+}
+
+static void
+gv_undo_data_destroy(GvData *data)
+{
+ /* FIXME: remove mementos corresponding to data from stack */
+ /* For now just clear the stack */
+ gv_undo_clear();
+}
Added: packages/openev/branches/upstream/current/gvundo.h
===================================================================
--- packages/openev/branches/upstream/current/gvundo.h (rev 0)
+++ packages/openev/branches/upstream/current/gvundo.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * $Id: gvundo.h,v 1.3 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Generic undo management.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvundo.h,v $
+ * Revision 1.3 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_UNDO_H__
+#define __GV_UNDO_H__
+
+#include "gvdata.h"
+
+void gv_undo_register_data(GvData *data);
+void gv_undo_open(void);
+void gv_undo_close(void);
+void gv_undo_push(GvDataMemento *memento);
+void gv_undo_pop(void);
+void gv_undo_clear(void);
+void gv_undo_enable();
+void gv_undo_disable();
+gint gv_undo_can_undo(void);
+gint gv_undo_start_group(void);
+void gv_undo_end_group(gint);
+
+#endif /*__GV_UNDO_H__*/
Added: packages/openev/branches/upstream/current/gvutils.c
===================================================================
--- packages/openev/branches/upstream/current/gvutils.c (rev 0)
+++ packages/openev/branches/upstream/current/gvutils.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,590 @@
+/******************************************************************************
+ * $Id: gvutils.c,v 1.22 2004/06/23 14:35:05 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Various utility functions.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvutils.c,v $
+ * Revision 1.22 2004/06/23 14:35:05 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.21 2004/04/21 15:13:58 andrey_kiselev
+ * Fix comparisons with NODATA value.
+ *
+ * Revision 1.20 2004/04/02 17:01:02 gmwalter
+ * Updated nodata support for complex and
+ * rgb data.
+ *
+ * Revision 1.19 2004/01/22 20:03:22 andrey_kiselev
+ * gv_format_point_query() returns "[NODATA]" label if value marked as NODATA.
+ *
+ * Revision 1.18 2001/08/08 17:43:22 warmerda
+ * avoid warning
+ *
+ * Revision 1.17 2001/04/22 17:32:25 pgs
+ * added get_short_path_name
+ *
+ * Revision 1.16 2000/10/10 17:38:41 srawlin
+ * changed lat/long decimal format to report position to 7 decimal digits
+ *
+ * Revision 1.15 2000/09/26 16:55:35 srawlin
+ * changed lat/long decimal format to report N/S and E/W instead of +/-
+ *
+ * Revision 1.14 2000/09/26 16:32:41 srawlin
+ * added degree_mode to set Lat/Long display to be either in the form dd:mm:ss (dms) or dd.dd (decimal)
+ *
+ * Revision 1.13 2000/08/25 20:08:44 warmerda
+ * added phase/magnitude reporting
+ *
+ * Revision 1.12 2000/08/24 19:49:27 warmerda
+ * don't operate o null strings
+ *
+ * Revision 1.11 2000/08/24 03:37:52 warmerda
+ * added PIXEL as a coordinate system
+ *
+ * Revision 1.10 2000/08/24 03:26:01 warmerda
+ * fixed +- sign for complex raster values
+ *
+ * Revision 1.9 2000/06/26 15:12:17 warmerda
+ * don't crash if gvraster is null
+ *
+ * Revision 1.8 2000/06/23 12:56:52 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.7 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <stdio.h>
+#include "gvutils.h"
+#include "gvrasterlayer.h"
+#include "ogr_srs_api.h"
+#include "cpl_conv.h"
+
+void gv_set_color_from_string( GvColor color, const char * string,
+ float def_red, float def_green,
+ float def_blue, float def_alpha )
+
+{
+ if( string != NULL )
+ {
+ def_alpha = 1.0;
+ sscanf( string, "%f %f %f %f",
+ &def_red, &def_green, &def_blue, &def_alpha );
+ }
+
+ if( def_red > 1.0 || def_green > 1.0 || def_blue > 1.0 || def_alpha > 1.0 )
+ {
+ def_red /= 255.0;
+ def_green /= 255.0;
+ def_blue /= 255.0;
+ def_alpha /= 255.0;
+ }
+ color[0] = def_red;
+ color[1] = def_green;
+ color[2] = def_blue;
+ color[3] = def_alpha;
+}
+
+void gv_complex_to_phase_mag( float real, float imaginary,
+ float *phase, float *magnitude )
+
+{
+ *magnitude = sqrt(real*real+imaginary*imaginary);
+ *phase = atan2(imaginary, real);
+}
+
+const char *gv_format_point_query( GvViewArea *view,
+ GvProperties *properties,
+ double geo_x, double geo_y )
+
+{
+ static gchar buf[256];
+ double raster_x=0.0, raster_y=0.0, pix_real, pix_imaginary;
+ GvLayer *layer;
+ GvRaster *raster = NULL;
+ GvRasterLayer *raster_layer = NULL;
+ GList *layer_list, *node;
+ const char *coord_mode, *pixel_mode, *degree_mode;
+ const char *coord_sys = gv_view_area_get_projection(view);
+ char *latlong_srs = NULL;
+ char east_west, north_south;
+
+ /* Check the properties to see what options are in effect */
+ coord_mode = gv_properties_get( properties, "_coordinate_mode" );
+ if( coord_mode == NULL )
+ coord_mode = "georef";
+
+ pixel_mode = gv_properties_get( properties, "_pixel_mode" );
+ if( pixel_mode == NULL )
+ pixel_mode = "on";
+
+ degree_mode = gv_properties_get( properties, "_degree_mode" );
+ if( degree_mode == NULL )
+ degree_mode = "dms";
+
+ /* This code should be factored out into gvviewarea at some point. */
+ layer_list = gv_view_area_list_layers( view );
+
+ for( node = layer_list; node != NULL; node = node->next )
+ {
+ layer = GV_LAYER(node->data);
+ if( gv_layer_is_visible(layer) && GV_IS_RASTER_LAYER( layer ) )
+ {
+ raster = GV_RASTER_LAYER(layer)->prototype_data;
+ raster_layer = GV_RASTER_LAYER(layer);
+
+ raster_x = geo_x;
+ raster_y = geo_y;
+
+ if( !gv_raster_layer_view_to_pixel( raster_layer,
+ &raster_x, &raster_y, NULL )
+ ||raster_x < 0 || raster_x >= raster->width
+ || raster_y < 0 || raster_y >= raster->height )
+ {
+ raster = NULL;
+ raster_layer = NULL;
+ }
+ }
+ }
+
+ /* Do we want to transform coordinate into a real `geo' space? */
+ if( raster != NULL
+ && (gv_view_area_get_projection(view) == NULL
+ || EQUAL(gv_view_area_get_projection(view),"PIXEL"))
+ && raster_layer->mesh_is_raw )
+ {
+ double geo_x_dbl, geo_y_dbl;
+
+ geo_x_dbl = raster_x;
+ geo_y_dbl = raster_y;
+ gv_raster_pixel_to_georef( raster,
+ &geo_x_dbl, &geo_y_dbl, NULL );
+ coord_sys = gv_data_get_projection( GV_DATA(raster) );
+ geo_x = geo_x_dbl;
+ geo_y = geo_y_dbl;
+ }
+
+ if( g_strcasecmp(coord_mode,"latlong") == 0
+ && (coord_sys != NULL && !EQUAL(coord_sys,"PIXEL")) )
+ {
+ latlong_srs = gv_make_latlong_srs( coord_sys );
+
+ if( latlong_srs != NULL )
+ {
+ double x, y, z;
+
+ x = geo_x;
+ y = geo_y;
+ z = 0.0;
+
+ if( gv_reproject_points( coord_sys, latlong_srs,
+ 1, &x, &y, &z ) )
+ {
+ geo_x = x;
+ geo_y = y;
+ coord_sys = latlong_srs;
+ }
+ }
+ }
+
+ buf[0] = '\0';
+ if( g_strcasecmp(coord_mode,"off") == 0 )
+ {
+ /* do nothing */
+ }
+ else if( g_strcasecmp(coord_mode,"raster") == 0 )
+ {
+ if( raster != NULL )
+ g_snprintf(buf, 64, "(%.2fP, %.2fL)", raster_x, raster_y );
+ }
+ else
+ {
+ if( coord_sys != NULL
+ && strstr(coord_sys,"PROJCS") == NULL
+ && strstr(coord_sys,"GEOGCS") != NULL )
+ {
+ /* Display in Degree Minute Second format */
+ if ( g_strcasecmp(degree_mode, "dms") == 0 )
+ {
+ strcat( buf, "(");
+ strcat( buf, GDALDecToDMS( geo_x, "Long", 2 ));
+ strcat( buf, "," );
+ strcat( buf, GDALDecToDMS( geo_y, "Lat", 2 ));
+ strcat( buf, ")" );
+ } else {
+ /* Display in decimal format */
+ if (geo_x < 0)
+ east_west = 'W';
+ else
+ east_west = 'E';
+
+ if (geo_y < 0)
+ north_south = 'S';
+ else
+ north_south = 'N';
+
+ g_snprintf(buf, 64, "(%.7f%c, %.7f%c)",
+ fabs(geo_x), east_west, fabs(geo_y), north_south );
+ }
+ }
+ else if( coord_sys != NULL
+ && g_strcasecmp(coord_sys,"PIXEL") == 0 )
+ {
+ g_snprintf(buf, 64, "(%.2fP, %.2fL)", geo_x, geo_y );
+ }
+ else
+ {
+ g_snprintf(buf, 64, "(%.2fE, %.2fN)", geo_x, geo_y );
+ }
+ }
+
+ if( latlong_srs != NULL )
+ g_free( latlong_srs );
+
+ /* Try to get a raster value */
+ if( raster_layer != NULL
+ && g_strcasecmp(pixel_mode, "on") == 0 )
+ {
+ const char *nodata_mode;
+ GvRaster *rsrc;
+
+ nodata_mode = gv_properties_get( properties, "_nodata_mode" );
+ if( nodata_mode == NULL )
+ nodata_mode = "on";
+
+ if( buf[0] != '\0' )
+ strcat( buf, ": " );
+
+ if( raster_layer->mode == GV_RLM_COMPLEX )
+ {
+ rsrc = gv_raster_layer_get_data(raster_layer,0);
+ if( rsrc != NULL
+ && gv_raster_get_sample( rsrc, raster_x, raster_y,
+ &pix_real, &pix_imaginary ) )
+ {
+ float phase, magnitude;
+
+ if( pix_imaginary < 0.0 )
+ g_snprintf(buf+strlen(buf), 64, "%g%gi",
+ pix_real, pix_imaginary );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%g+%gi",
+ pix_real, pix_imaginary );
+
+ gv_complex_to_phase_mag( pix_real, pix_imaginary,
+ &phase, &magnitude );
+ g_snprintf(buf+strlen(buf), 64, ", phase:%g, magnitude:%g",
+ phase, magnitude );
+
+ if ( g_strcasecmp( nodata_mode, "on") == 0 )
+ {
+ double nodata_real, nodata_imaginary;
+
+ if( gv_raster_layer_nodata_get( raster_layer, 0,
+ &nodata_real,
+ &nodata_imaginary )
+ && ABS(pix_real - nodata_real) < 0.0000000001
+ && ABS(pix_imaginary - nodata_imaginary) < 0.0000000001 )
+ {
+ g_snprintf(buf+strlen(buf), 64, " [NODATA]" );
+ }
+ }
+ }
+ }
+ else if( raster_layer->mode == GV_RLM_RGBA )
+ {
+ int isource;
+ double rgba[4];
+ double rgba_imag[4];
+
+ for( isource = 0; isource < 4; isource++ )
+ {
+
+ rsrc = gv_raster_layer_get_data(raster_layer,isource);
+ if( rsrc == NULL
+ || !gv_raster_get_sample( rsrc, raster_x, raster_y,
+ rgba + isource,
+ rgba_imag + isource) )
+ {
+ rgba[isource] =
+ gv_raster_layer_get_const_value(raster_layer,isource);
+ }
+ }
+
+ if( gv_raster_layer_get_data(raster_layer,3) == NULL )
+ {
+ if ((rgba_imag[0] != 0.0) || (rgba_imag[1] != 0.0) ||
+ (rgba_imag[2] != 0.0))
+ {
+ if (rgba_imag[0] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.5g%.5gi r ",
+ rgba[0], rgba_imag[0] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.5g+%.5gi r ",
+ rgba[0], rgba_imag[0] );
+
+ if (rgba_imag[1] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.5g%.5gi g ",
+ rgba[1], rgba_imag[1] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.5g+%.5gi g ",
+ rgba[1], rgba_imag[1] );
+
+ if (rgba_imag[2] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.5g%.5gi b ",
+ rgba[2], rgba_imag[2] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.5g+%.5gi b ",
+ rgba[2], rgba_imag[2] );
+ }
+ else
+ g_snprintf(buf+strlen(buf), 64, "%gr %gg %gb ",
+ rgba[0], rgba[1], rgba[2] );
+ }
+ else
+ {
+ if ((rgba_imag[0] != 0) || (rgba_imag[1] != 0) ||
+ (rgba_imag[2] != 0) || (rgba_imag[3] != 0))
+ {
+ if (rgba_imag[0] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.4g%.4gi r ",
+ rgba[0], rgba_imag[0] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.4g+%.4gi r ",
+ rgba[0], rgba_imag[0] );
+
+ if (rgba_imag[1] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.4g%.4gi g ",
+ rgba[1], rgba_imag[1] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.4g+%.4gi g ",
+ rgba[1], rgba_imag[1] );
+
+ if (rgba_imag[2] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.4g%.4gi b ",
+ rgba[2], rgba_imag[2] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.4g+%.4gi b ",
+ rgba[2], rgba_imag[2] );
+
+ if (rgba_imag[3] < 0.0)
+ g_snprintf(buf+strlen(buf), 64, "%.4g%.4gi a ",
+ rgba[3], rgba_imag[3] );
+ else
+ g_snprintf(buf+strlen(buf), 64, "%.4g+%.4gi a ",
+ rgba[3], rgba_imag[3] );
+ }
+ else
+ g_snprintf(buf+strlen(buf), 64, "%gr %gg %gb %ga",
+ rgba[0], rgba[1], rgba[2], rgba[3] );
+ }
+
+ if ( g_strcasecmp( nodata_mode, "on") == 0 )
+ {
+ double nodata[3];
+
+ if( (gv_raster_layer_nodata_get(raster_layer, 0, nodata, NULL)
+ && ABS(rgba[0] - nodata[0]) < 0.0000000001) ||
+ (gv_raster_layer_nodata_get(raster_layer, 1, nodata+1, NULL)
+ && ABS(rgba[1] - nodata[1]) < 0.0000000001) ||
+ (gv_raster_layer_nodata_get(raster_layer, 2, nodata+2, NULL)
+ && ABS(rgba[2] - nodata[2]) < 0.0000000001) )
+ {
+ g_snprintf(buf+strlen(buf), 64, " [NODATA]" );
+ }
+ }
+ }
+ else
+ {
+ rsrc = gv_raster_layer_get_data(raster_layer,0);
+ if( rsrc != NULL &&
+ gv_raster_get_sample( rsrc, raster_x, raster_y,
+ &pix_real, &pix_imaginary ) )
+ {
+ g_snprintf(buf+strlen(buf), 64, "%g", pix_real);
+ }
+
+ if ( g_strcasecmp( nodata_mode, "on") == 0 )
+ {
+ double nodata;
+
+ if( gv_raster_layer_nodata_get( raster_layer, 0, &nodata, NULL )
+ && ABS(pix_real - nodata) < 0.0000000001 )
+ {
+ g_snprintf(buf+strlen(buf), 64, " [NODATA]" );
+ }
+ }
+ }
+ }
+
+ return buf;
+}
+
+char *gv_make_latlong_srs( const char * projected_srs )
+
+{
+ OGRSpatialReferenceH hSRSProjected, hSRSLatLong;
+ char *osr_wkt, *glib_wkt;
+
+ if( projected_srs == NULL )
+ return NULL;
+
+ hSRSProjected = OSRNewSpatialReference( projected_srs );
+ if( hSRSProjected == NULL )
+ return FALSE;
+
+ if( OSRIsGeographic( hSRSProjected ) )
+ {
+ OSRDestroySpatialReference( hSRSProjected );
+ return g_strdup( projected_srs );
+ }
+
+ hSRSLatLong = OSRCloneGeogCS( hSRSProjected );
+ OSRDestroySpatialReference( hSRSProjected );
+ if( hSRSLatLong == NULL )
+ return NULL;
+
+ osr_wkt = NULL;
+ glib_wkt = NULL;
+ OSRExportToWkt( hSRSLatLong, &osr_wkt );
+ if( osr_wkt != NULL )
+ {
+ glib_wkt = g_strdup( osr_wkt );
+ CPLFree( osr_wkt );
+ }
+
+ if( hSRSLatLong != NULL )
+ OSRDestroySpatialReference( hSRSLatLong );
+
+ return glib_wkt;
+}
+
+int gv_reproject_points( const char *source_srs,
+ const char *destination_srs,
+ int count, double *x, double *y, double *z )
+
+{
+ int success = TRUE;
+ OGRSpatialReferenceH hSRSNew = NULL, hSRSOld = NULL;
+ OGRCoordinateTransformationH hTransform = NULL;
+
+ if( source_srs == NULL || destination_srs == NULL )
+ return FALSE;
+
+ /*
+ * Try and establish if we can, or need to do reprojection.
+ */
+ hSRSNew = OSRNewSpatialReference( destination_srs );
+ if( hSRSNew == NULL )
+ return FALSE;
+
+ hSRSOld = OSRNewSpatialReference(source_srs);
+ if( hSRSOld == NULL )
+ {
+ OSRDestroySpatialReference( hSRSNew );
+ return FALSE;
+ }
+
+ if( OSRIsSame( hSRSOld, hSRSNew ) )
+ {
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ return TRUE;
+ }
+
+ /*
+ * Establish transformation.
+ */
+
+ hTransform = OCTNewCoordinateTransformation( hSRSOld, hSRSNew );
+ if( hTransform == NULL )
+ {
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ return FALSE;
+ }
+
+ /*
+ * Transform all the mesh points.
+ */
+
+ success = OCTTransform( hTransform, count, x, y, z );
+
+ OCTDestroyCoordinateTransformation( hTransform );
+ OSRDestroySpatialReference( hSRSOld );
+ OSRDestroySpatialReference( hSRSNew );
+
+ return success;
+}
+
+#ifndef WIN32
+int gv_launch_url( const char * url )
+
+{
+ return 0;
+}
+
+char * gv_short_path_name( const char * lpszLongPath)
+{
+ return (char *) lpszLongPath;
+}
+
+#else
+#include "windows.h"
+int gv_launch_url( const char * url )
+
+{
+ HINSTANCE hInstance;
+
+ hInstance = ShellExecute( NULL, "open", url, "", "", SW_SHOWNORMAL );
+
+ return ((int) hInstance) > 32;
+}
+
+char * gv_short_path_name( const char * lpszLongPath)
+{
+ int ret;
+ char * lpszShortPath;
+
+ lpszShortPath = (char *) malloc(MAX_PATH * sizeof(char));
+ lpszShortPath[0] = 0;
+
+ ret = GetShortPathName(lpszLongPath, lpszShortPath, MAX_PATH);
+
+ #ifdef DEBUG
+ printf("gv_short_path_name: returned %d for (%s)\n", ret, lpszShortPath);
+ #endif
+
+ if (ret > 0)
+ return lpszShortPath;
+ else
+ {
+ free(lpszShortPath);
+ return "";
+ }
+}
+#endif
Added: packages/openev/branches/upstream/current/gvutils.h
===================================================================
--- packages/openev/branches/upstream/current/gvutils.h (rev 0)
+++ packages/openev/branches/upstream/current/gvutils.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,66 @@
+/******************************************************************************
+ * $Id: gvutils.h,v 1.5 2001/04/22 17:32:25 pgs Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Various utility functions.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvutils.h,v $
+ * Revision 1.5 2001/04/22 17:32:25 pgs
+ * added get_short_path_name
+ *
+ * Revision 1.4 2000/08/25 20:08:44 warmerda
+ * added phase/magnitude reporting
+ *
+ * Revision 1.3 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_UTILS_H__
+#define __GV_UTILS_H__
+
+#include "gvtypes.h"
+#include "gvproperties.h"
+#include "gvviewarea.h"
+
+void gv_set_color_from_string( GvColor, const char *,
+ float, float, float, float );
+
+const char *gv_format_point_query( GvViewArea *view,
+ GvProperties *properties,
+ double geo_x, double geo_y );
+
+int gv_reproject_points( const char *source_srs,
+ const char *destination_srs,
+ int count, double *x, double *y, double *z );
+char *gv_make_latlong_srs( const char * );
+
+void gv_complex_to_phase_mag( float real, float imaginary,
+ float *phase, float *magnitude );
+
+int gv_launch_url( const char * );
+
+char *gv_short_path_name( const char * );
+
+#endif /* __GV_UTILS_H__ */
+
Added: packages/openev/branches/upstream/current/gvviewarea.c
===================================================================
--- packages/openev/branches/upstream/current/gvviewarea.c (rev 0)
+++ packages/openev/branches/upstream/current/gvviewarea.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,3644 @@
+/******************************************************************************
+ * $Id: gvviewarea.c,v 1.125 2005/01/14 15:27:26 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GTK/OpenGL View Canvas
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvviewarea.c,v $
+ * Revision 1.125 2005/01/14 15:27:26 warmerda
+ * added flip flag access
+ *
+ * Revision 1.124 2004/08/20 18:01:14 warmerda
+ * Ensure that adding a first layer results in the flip_y flag being reset
+ * to 1.0 even if some previous raw image had resulted it in being set to
+ * -1.0.
+ *
+ * Revision 1.123 2004/04/28 01:27:08 sduclos
+ * GDK_GL_STENCIL_SIZE moved into S52 viewer glcontext
+ *
+ * Revision 1.122 2004/01/20 16:11:09 warmerda
+ * Default GDK_GL_STENCIL_SIZE to 1 for S52 viewer
+ *
+ * Revision 1.121 2003/08/27 19:58:43 warmerda
+ * added force_simple flag for gv_view_area_bmfont_draw
+ *
+ * Revision 1.120 2003/05/08 19:51:13 pgs
+ * modified adjustment logic forpage size
+ *
+ * Revision 1.119 2003/03/07 22:18:26 warmerda
+ * const correctness fix for get_layer_by_name
+ *
+ * Revision 1.118 2003/02/20 19:27:18 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.117 2002/12/12 03:42:14 warmerda
+ * verified Gillians change, and cleaned old cruft
+ *
+ * Revision 1.116 2002/12/12 01:04:26 gmwalter
+ * Fix to deal with upside-down symbol bug, symbol migration in non-georeferenced mode.
+ *
+ * Revision 1.115 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.114 2002/09/29 18:40:28 warmerda
+ * ensure new_x and new_y in gv_view_area_get_volume are float not int
+ * as per bug report from Sylvain Duclos.
+ *
+ * Revision 1.113 2002/09/16 17:20:02 warmerda
+ * ensure depth buffer cleared in 3d render_to_func
+ *
+ * Revision 1.112 2002/09/12 20:26:51 warmerda
+ * changed near clipping plane calc to improve depth resolution
+ *
+ * Revision 1.111 2002/09/11 18:58:33 warmerda
+ * dmsg bug 475: disable depth testing in 2D mode
+ *
+ * Revision 1.110 2002/09/10 13:26:43 warmerda
+ * added get_height_scale method
+ *
+ * Revision 1.109 2002/07/19 14:06:38 warmerda
+ * Fixed bug reported by Gillian with switching between raw and georeferenced
+ * mode for images with GCPs that effectively do x or y flips of the image
+ * (such as some esrin ceos scenes). Changes all in gv_view_area_set_raw().
+ *
+ * Revision 1.108 2002/07/16 14:17:05 warmerda
+ * added support for getting background color
+ *
+ * Revision 1.107 2002/07/08 19:44:39 warmerda
+ * added properties on GvViewArea
+ *
+ * Revision 1.106 2002/05/02 19:16:26 gmwalter
+ * Updated key press function to allow smaller height and zoom increments in 3d
+ * (original step sizes now require that shift be pressed as well).
+ *
+ * Revision 1.105 2002/03/20 19:19:14 warmerda
+ * added exact_render flag
+ *
+ * Revision 1.104 2002/01/30 17:25:19 warmerda
+ * added set_state and get_primary_raster functions
+ *
+ * Revision 1.103 2001/12/13 03:29:17 warmerda
+ * avoid purging textures used in this render
+ *
+ * Revision 1.102 2001/12/12 15:32:39 warmerda
+ * ensure volume is computed for fit_all_layers
+ *
+ * Revision 1.101 2001/10/23 02:29:07 warmerda
+ * call gv_view_area_state_changed() in _add_layer()
+ *
+ * Revision 1.100 2001/10/19 13:26:47 warmerda
+ * fixed up checkf or mesa windows
+ *
+ * Revision 1.99 2001/10/12 17:44:18 warmerda
+ * avoid extra redraws when many raster layers displayed
+ *
+ * Revision 1.98 2001/10/12 02:11:45 warmerda
+ * Always render on non-win32, swapbuffer doesnt do what we want on X/OpenGL
+ *
+ * Revision 1.97 2001/10/12 01:58:19 warmerda
+ * avoid re-rendering if backing store OK
+ *
+ * Revision 1.96 2001/07/18 03:34:44 warmerda
+ * fixed flipping problem
+ *
+ * Revision 1.95 2001/07/09 20:21:28 warmerda
+ * fixed raw mesh info
+ *
+ * Revision 1.94 2001/07/03 14:26:05 warmerda
+ * added set/get raw ability
+ *
+ * Revision 1.93 2001/06/15 00:01:53 warmerda
+ * added GDK_GLX_RED/GREEN/BLUE_SIZE attribs for visual
+ *
+ * Revision 1.92 2001/05/07 19:14:02 warmerda
+ * removed a bunch of debugging cruft
+ *
+ * Revision 1.91 2001/05/07 19:08:03 warmerda
+ * draw text with origin off viewport properly
+ *
+ * Revision 1.90 2001/04/26 18:36:40 warmerda
+ * added glFinish() before swapbuffers
+ *
+ * Revision 1.89 2001/04/09 18:20:14 warmerda
+ * added ability to query list of available fonts
+ *
+ * Revision 1.88 2001/03/28 15:03:02 warmerda
+ * Added direct_render flag within gv_view_area_render_to_func(). This flag
+ * kicks in for 1:1 prints, and prevents any attempt to reapply the view
+ * transformation since the naive code loses rotations, and 3D perspectives.
+ * This relates to CIETMap bug 89, and OpenEV bug 212486.
+ *
+ * Revision 1.87 2001/03/27 18:38:05 warmerda
+ * fixed return value
+ *
+ * Revision 1.86 2001/03/26 19:18:35 warmerda
+ * restructure bmfont handling to preserve GdkFont handle
+ *
+ * Revision 1.85 2001/03/22 22:34:24 warmerda
+ * fixed bug in gv_view_load_bmfont() with reporting load errors
+ *
+ * Revision 1.84 2001/02/15 16:35:32 warmerda
+ * turned g_warning into CPLDebug call
+ *
+ * Revision 1.83 2001/02/03 22:21:08 warmerda
+ * added gv_view_area_get_mode() and python covers
+ *
+ * Revision 1.82 2001/01/30 19:33:58 warmerda
+ * removed printf
+ *
+ * Revision 1.81 2001/01/26 13:56:15 warmerda
+ * ensure fit_all_layers(), Home, and fit_extents all produce compatible results.
+ * Route all view setting through gv_viewarea_set_3d_view().
+ * Fix up default view.
+ * Remove view setting in get_volume() function.
+ *
+ * Revision 1.80 2001/01/19 15:19:49 warmerda
+ * improve near range calculation when over scene
+ *
+ * Revision 1.79 2000/10/06 16:48:56 warmerda
+ * added GvViewArea background color
+ *
+ * Revision 1.78 2000/09/29 16:09:17 srawlin
+ * added Goto function requring fuction to map lat/long to view coordinates
+ *
+ * Revision 1.77 2000/09/21 02:57:20 warmerda
+ * reorganized bitmap font support to allow any gdk supported font at runtime
+ *
+ * Revision 1.76 2000/09/13 15:58:55 srawlin
+ * added python bindings for gv_view_area_get_zoom
+ *
+ * Revision 1.75 2000/09/07 21:02:26 warmerda
+ * ensure projection string is cleared when last layer removed
+ *
+ * Revision 1.74 2000/08/25 19:58:00 warmerda
+ * Fixed problems with setting slider adjustments out of bounds. This sometimes
+ * caused a feedback loop as the slider itself tried to keep things legal.
+ *
+ * Revision 1.73 2000/08/24 17:05:01 srawlin
+ * fixed 3D eye_pos passed to vec_near_far_range() (near/far clipping plane
+ * calculation) to account for image flipping
+ *
+ * Revision 1.72 2000/08/24 15:44:30 srawlin
+ * fixed flip about y axis in 3D mode
+ *
+ * Revision 1.71 2000/08/24 02:22:46 warmerda
+ * fixed scrollbar step and page increments
+ *
+ * Revision 1.70 2000/08/23 15:45:45 warmerda
+ * updated adjustments after user scrolls
+ *
+ * Revision 1.69 2000/08/17 16:50:51 warmerda
+ * fixed leak of lock_adjustment flag
+ *
+ * Revision 1.68 2000/08/17 16:45:00 warmerda
+ * get_world_extents works without layers now
+ *
+ * Revision 1.67 2000/08/16 22:14:36 warmerda
+ * fixed scrolling for raw and projected views
+ *
+ * Revision 1.66 2000/08/16 14:07:47 warmerda
+ * added prototype scrollbar support
+ *
+ * Revision 1.65 2000/08/02 17:47:01 warmerda
+ * don't allow further processing of arrows or we will lose focus
+ *
+ * Revision 1.64 2000/07/25 17:51:48 warmerda
+ * added finalize, and debug statements
+ *
+ * Revision 1.63 2000/07/24 14:26:30 warmerda
+ * use up to char 126 in gdk_gl_use_gdk_font
+ *
+ * Revision 1.62 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.61 2000/07/17 19:10:00 warmerda
+ * added tentative support for scaling wait between redraws to actual redraw time
+ *
+ * Revision 1.60 2000/07/13 18:04:33 srawlin
+ * removed use of view.state.eye_az and .eye_el, contained same information as view.state.eye_dir
+ *
+ * Revision 1.59 2000/07/11 20:56:23 srawlin
+ * added methods to get and set viewing direction relative to z-plane in 3D
+ *
+ * Revision 1.58 2000/07/10 22:13:39 srawlin
+ * Added motion scaling based on distance to z-plane
+ *
+ * Revision 1.57 2000/07/10 20:45:00 srawlin
+ * Added 3D Translate controls
+ *
+ * Revision 1.56 2000/07/10 16:20:33 srawlin
+ * fixed bug when zooming in 3D and panning, also removed debug printfs
+ *
+ * Revision 1.55 2000/07/10 13:36:55 srawlin
+ * updated 3D controls to be more like 2D
+ *
+ * Revision 1.54 2000/07/07 17:53:32 warmerda
+ * ifdef out debug statement
+ *
+ * Revision 1.53 2000/07/05 11:26:26 srawlin
+ * 3D - changed initial view, some mouse movement directions, set angle boundaries
+ *
+ * Revision 1.52 2000/07/04 15:47:18 warmerda
+ * removed debug lines in 3d mode
+ *
+ * Revision 1.51 2000/07/03 20:58:31 warmerda
+ * eye_pos in georef coordinates now
+ *
+ * Revision 1.50 2000/06/29 16:14:58 warmerda
+ * added one more set_busy call
+ *
+ * Revision 1.49 2000/06/29 14:38:37 warmerda
+ * use GvManager for idle tasks
+ *
+ * Revision 1.48 2000/06/23 12:56:52 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.47 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvviewarea.h"
+#include "gvlayer.h"
+#include "gvrasterlayer.h"
+#include "gvundo.h"
+#include "gvmanager.h"
+#include "gvutils.h"
+#include <gtk/gtksignal.h>
+#include <gtkgl/gdkgl.h>
+#include <gdk/gdkkeysyms.h>
+#include "gextra.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <math.h>
+
+#define DEG2RAD 0.01745329252
+#define LOG2(x) (log(x) / 0.69314718056)
+#define DEAD_ZONE 8.0
+#define DRAG_THRESHOLD 10
+#define WHEEL_ZOOM_INC 0.1
+
+/* 3D motion Stuff */
+#define MOVE_SPEED 0.04
+#define AZ_SCALE 0.15
+#define EL_SCALE 0.15
+#define HEIGHT_SCALE 0.1
+#define CONTIN_3DMOVE_INC 20.0
+
+/* 2D Zooming */
+#define CONTIN_ZOOM_INC 1.5
+#define ZOOM_STEP 1
+
+/* useful 3D vector copy function */
+#define vec_copy(s,d) {d[0]=s[0];d[1]=s[1];d[2]=s[2];}
+#define vec_add(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define vec_scale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
+
+#define VIEW_EVENT_MASK (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | \
+ GDK_POINTER_MOTION_MASK | \
+ GDK_POINTER_MOTION_HINT_MASK | \
+ GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | \
+ GDK_LEAVE_NOTIFY_MASK)
+
+enum
+{
+ GLDRAW,
+ GLCURSOR,
+ ACTIVE_CHANGED,
+ VIEW_STATE_CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ ARG_0,
+ ARG_HADJUSTMENT,
+ ARG_VADJUSTMENT,
+};
+
+static void gv_view_area_class_init(GvViewAreaClass *klass);
+static void gv_view_area_init(GvViewArea *view);
+
+static void gv_view_area_update_adjustments( GvViewArea *view );
+static gint gv_view_area_configure(GtkWidget *view, GdkEventConfigure *event);
+static gint gv_view_area_reset_projection(GvViewArea *view, gvgeocoord width, gvgeocoord height);
+static void gv_view_area_realize(GtkWidget *view);
+static void gv_view_area_unrealize(GtkWidget *view);
+static void gv_view_area_motion_handle_hint(GtkWidget *view, GdkEventMotion *event);
+static gint gv_view_area_motion_notify(GtkWidget *view, GdkEventMotion *event);
+static gint gv_view_area_button_press(GtkWidget *view, GdkEventButton *event);
+static gint gv_view_area_button_release(GtkWidget*view, GdkEventButton *event);
+static gint gv_view_area_key_press(GtkWidget *view, GdkEventKey *event);
+static void gv_view_area_change_notify(GvViewArea *view, gpointer info);
+static void gv_view_area_state_changed(GvViewArea *view);
+static void gv_view_area_fit_layer(GvViewArea *view, GvLayer *layer);
+static void gv_view_area_destroy(GtkObject *object);
+static void gv_view_area_fit_extents_3D(GvViewArea *view,
+ gvgeocoord llx, gvgeocoord lly, gvgeocoord minz,
+ gvgeocoord width, gvgeocoord height, gvgeocoord deltaz );
+static gint gv_view_area_zoompan_handler(gpointer data );
+static void gv_view_area_finalize( GtkObject *object );
+
+static guint view_area_signals[LAST_SIGNAL] = { 0 };
+
+static void gv_view_area_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gv_view_area_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+static struct { char *gvname, *gdkname; } bmfontmap[] =
+{
+ { "Fixed", "-*-fixed-*-*-*-*-*-*-*-*-*-*-iso8859-*" },
+ { "Times, 20pt", "-*-times-*-*-*-*-20-*-*-*-*-*-iso8859-*" },
+ { "Times, 14pt", "-*-times-*-*-*-*-14-*-*-*-*-*-iso8859-*" },
+ { NULL, NULL } /* Sentinel */
+};
+
+/* Incremented each render */
+static int render_counter = 0;
+
+void
+vec_point(vec3_t point, gvgeocoord az, gvgeocoord el)
+{
+ gvgeocoord c = cos(el * DEG2RAD);
+
+ point[0] = c * cos(az * DEG2RAD);
+ point[1] = c * sin(az * DEG2RAD);
+ point[2] = sin(el * DEG2RAD);
+}
+
+/* Inverse of vec_point, given direction vector find az and el, az in [-180, 180] */
+int
+inv_vec_point(vec3_t point, gvgeocoord *az, gvgeocoord *el)
+{
+ gvgeocoord c, az1, az2;
+
+ *el = asin(point[2]) / DEG2RAD;
+ c = cos( *el * DEG2RAD);
+ if ((c < 0.000001) && (c > -0.000001))
+ c = 0.00001;
+ az1 = (asin(point[1]/c)) / DEG2RAD;
+ az2 = (acos(point[0]/c)) / DEG2RAD;
+
+ if ((point[0] >= 0.0) && (point[1] >= 0.0))
+ *az = az1;
+ else if ((point[0] >= 0.0) && (point[1] <= 0.0))
+ *az = az1;
+ else if ((point[0] <= 0.0) && (point[1] >= 0.0))
+ *az = az2;
+ else if ((point[0] <= 0.0) && (point[1] <= 0.0))
+ *az = -az2;
+ else
+ {
+ printf("ERROR! in gvviewarea.c, inv_vec_point. Should never reach here.\n");
+ /* printf("point[0] %f, point[1] %f, c %f, az1 %f, az2 %f\n", point[0], point[1], c, az1, az2); */
+ return 0;
+ }
+
+ return 1;
+
+}
+
+
+static void
+vec_near_far_range( vec3_t point, double *volume, double *min, double *max )
+
+{
+ vec3_t nearest, furthest;
+
+ /* Find nearest X in volume */
+ if( point[0] < volume[0] )
+ nearest[0] = volume[0];
+ else if( point[0] > volume[1] )
+ nearest[0] = volume[1];
+ else
+ nearest[0] = point[0];
+
+ /* Find nearest Y in volume */
+ if( point[1] < volume[2] )
+ nearest[1] = volume[2];
+ else if( point[1] > volume[3] )
+ nearest[1] = volume[3];
+ else
+ nearest[1] = point[1];
+
+ /* Find nearest Z in volume */
+ if( point[2] < volume[4] )
+ nearest[1] = volume[4];
+ else if( point[2] > volume[5] )
+ nearest[2] = volume[5];
+ else
+ nearest[2] = point[2];
+
+ /* Find furthest X in volume */
+ if( ABS(point[0] - volume[0]) > ABS(point[0] - volume[1]) )
+ furthest[0] = volume[0];
+ else
+ furthest[0] = volume[1];
+
+ /* Find furthest Y in volume */
+ if( ABS(point[1] - volume[2]) > ABS(point[1] - volume[3]) )
+ furthest[1] = volume[2];
+ else
+ furthest[1] = volume[3];
+
+ /* Find furthest Z in volume */
+ if( ABS(point[2] - volume[4]) > ABS(point[2] - volume[5]) )
+ furthest[2] = volume[4];
+ else
+ furthest[2] = volume[5];
+
+ /* find distances */
+
+ *min = sqrt( (nearest[0] - point[0]) * (nearest[0] - point[0])
+ + (nearest[1] - point[1]) * (nearest[1] - point[1])
+ + (nearest[2] - point[2]) * (nearest[2] - point[2]) );
+
+ *max = sqrt( (furthest[0] - point[0]) * (furthest[0] - point[0])
+ + (furthest[1] - point[1]) * (furthest[1] - point[1])
+ + (furthest[2] - point[2]) * (furthest[2] - point[2]) );
+
+}
+
+GtkType
+gv_view_area_get_type(void)
+{
+ static GtkType view_area_type = 0;
+
+ if (!view_area_type)
+ {
+ static const GtkTypeInfo view_area_info =
+ {
+ "GvViewArea",
+ sizeof(GvViewArea),
+ sizeof(GvViewAreaClass),
+ (GtkClassInitFunc) gv_view_area_class_init,
+ (GtkObjectInitFunc) gv_view_area_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ view_area_type = gtk_type_unique( gtk_gl_area_get_type(),
+ &view_area_info );
+ }
+ return view_area_type;
+}
+
+static void
+gv_view_area_class_init(GvViewAreaClass *klass)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = GTK_OBJECT_CLASS(klass);
+ widget_class = GTK_WIDGET_CLASS(klass);
+
+ view_area_signals[GLDRAW] =
+ gtk_signal_new ("gldraw",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvViewAreaClass, gldraw),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ view_area_signals[GLCURSOR] =
+ gtk_signal_new ("glcursor",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvViewAreaClass, glcursor),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ view_area_signals[ACTIVE_CHANGED] =
+ gtk_signal_new ("active-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvViewAreaClass, active_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ view_area_signals[VIEW_STATE_CHANGED] =
+ gtk_signal_new ("view-state-changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvViewAreaClass,
+ view_state_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals(object_class, view_area_signals, LAST_SIGNAL);
+
+ object_class->destroy = gv_view_area_destroy;
+ object_class->finalize = gv_view_area_finalize;
+ object_class->set_arg = gv_view_area_set_arg;
+ object_class->get_arg = gv_view_area_get_arg;
+
+ widget_class->realize = gv_view_area_realize;
+ widget_class->unrealize = gv_view_area_unrealize;
+ widget_class->configure_event = gv_view_area_configure;
+ widget_class->expose_event = gv_view_area_expose;
+ widget_class->button_press_event = gv_view_area_button_press;
+ widget_class->button_release_event = gv_view_area_button_release;
+ widget_class->motion_notify_event = gv_view_area_motion_notify;
+ widget_class->key_press_event = gv_view_area_key_press;
+
+ widget_class->set_scroll_adjustments_signal =
+ gtk_signal_new ("set_scroll_adjustments",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GvViewAreaClass,
+ set_scroll_adjustments),
+ gtk_marshal_NONE__POINTER_POINTER,
+ GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
+ klass->set_scroll_adjustments = gv_view_area_set_adjustments;
+ klass->gldraw = NULL;
+ klass->active_changed = NULL;
+ klass->view_state_changed = NULL;
+}
+
+static void
+gv_view_area_init(GvViewArea *view)
+{
+ view->state.tx = view->state.ty = view->state.rot = 0.0;
+ view->state.zoom = 0.0;
+ view->state.linear_zoom = 1.0;
+ view->state.flip_x = view->state.flip_y = 1.0;
+ view->state.shape_x = view->state.shape_y = 0.0;
+ view->volume_current = FALSE;
+ view->linear_measure = 1000.0;
+
+ /* 3D Specific stuff */
+ view->state.eye_pos[0] = 0.0;
+ view->state.eye_pos[1] = 0.0;
+ view->state.eye_pos[2] = 500.0;
+ vec_point(view->state.eye_dir, 90.0, -45.0); /* rotation = 90, tilt 45 deg down */
+ view->state.z_scale = 1.0;
+
+ view->exact_render = FALSE;
+
+ view->flag_3d = 0; /* 0=2D, 1=3D, default 2D */
+
+ view->bmfonts = g_array_new(FALSE,TRUE,sizeof(GvBMFontInfo));
+
+ view->background[0] = view->background[1] = view->background[2] = 0.0;
+ view->background[3] = 1.0;
+
+ view->layers = NULL;
+ view->projection = NULL;
+
+ view->last_button = 0;
+ view->dragging_mode = FALSE;
+ view->display_dirty = TRUE;
+
+ /* ghost cursor stuff */
+ view->next_valid = FALSE;
+ view->last_valid = FALSE;
+ view->next_x = 0.0;
+ view->next_y = 0.0;
+ view->last_x = 0.0;
+ view->last_y = 0.0;
+ /* end of ghost cursor stuff */
+
+ view->last_draw_time = 0.0;
+ view->redraw_timer = NULL;
+
+ view->vadj = NULL;
+ view->hadj = NULL;
+ view->lock_adjustments = FALSE;
+
+ view->properties = NULL;
+
+ GTK_WIDGET_SET_FLAGS(GTK_WIDGET(view), GTK_CAN_FOCUS);
+
+ gtk_widget_set_events(GTK_WIDGET(view),
+ gtk_widget_get_events(GTK_WIDGET(view)) |
+ VIEW_EVENT_MASK);
+
+ /* Need to handle motion hints BEFORE other handlers */
+ gtk_signal_connect(GTK_OBJECT(view), "motion-notify-event",
+ GTK_SIGNAL_FUNC(gv_view_area_motion_handle_hint), NULL);
+}
+
+GtkWidget *
+gv_view_area_new(void)
+{
+ GdkGLContext *glcontext;
+ GvViewArea *view;
+ int attrlist[] = {
+ GDK_GL_RGBA,
+ GDK_GL_DOUBLEBUFFER,
+ GDK_GL_DEPTH_SIZE, 4,
+ GDK_GL_RED_SIZE, 3,
+ GDK_GL_GREEN_SIZE, 3,
+ GDK_GL_BLUE_SIZE, 3,
+ GDK_GL_NONE};
+
+#ifdef WIN32
+ /* figure out how to actually share context later */
+ glcontext = gdk_gl_context_attrlist_share_new(attrlist, NULL, TRUE);
+ if (glcontext == NULL)
+ return NULL;
+
+ view = gtk_type_new(gv_view_area_get_type());
+ GTK_GL_AREA(view)->glcontext = glcontext;
+
+ return GTK_WIDGET(view);
+#else
+ /* Largely copied from gtkglarea.c - should be in the constructor(?) */
+ GdkVisual *visual;
+
+ // SD check that geometric data type are in sync with OpenGL
+ g_assert(sizeof(gvgeocoord) == sizeof(GLgeocoord));
+
+ visual = gdk_gl_choose_visual(attrlist);
+ if (visual == NULL) return NULL;
+
+ glcontext = gdk_gl_context_share_new(visual, NULL , TRUE);
+ if (glcontext == NULL) return NULL;
+
+ /* use colormap and visual suitable for OpenGL rendering */
+ gtk_widget_push_colormap(gdk_colormap_new(visual, TRUE));
+ gtk_widget_push_visual(visual);
+
+ view = gtk_type_new(gv_view_area_get_type());
+ GTK_GL_AREA(view)->glcontext = glcontext;
+
+ /* pop back defaults */
+ gtk_widget_pop_visual();
+ gtk_widget_pop_colormap();
+
+ return GTK_WIDGET(view);
+#endif
+}
+
+gint
+gv_view_area_set_projection( GvViewArea *view, const char *projection )
+
+{
+ if( view->projection != NULL )
+ g_free( view->projection );
+
+ view->projection = g_strdup( projection );
+
+ return TRUE;
+}
+
+const char *
+gv_view_area_get_projection( GvViewArea *view )
+
+{
+ return view->projection;
+}
+
+
+/* Set mode to 2D or 3D */
+void
+gv_view_area_set_mode(GvViewArea *view, int flag_3d)
+{
+ view->flag_3d= flag_3d; /* 0=2D, 1=3D, */
+
+ /* Reset OpenGL Projection Method */
+ if( GTK_WIDGET_REALIZED(GTK_WIDGET(view)) )
+ gv_view_area_reset_projection(view,
+ view->state.shape_x,
+ view->state.shape_y);
+
+ gv_view_area_state_changed(view);
+}
+
+int gv_view_area_get_mode(GvViewArea *view)
+
+{
+ return view->flag_3d;
+}
+
+/* Change 3D Scaling factor - has no effect unless in 3D mode */
+void
+gv_view_area_height_scale(GvViewArea *view, gvgeocoord scale)
+{
+ view->state.z_scale = scale;
+ gv_view_area_state_changed(view);
+}
+
+gvgeocoord
+gv_view_area_get_height_scale( GvViewArea *view )
+
+{
+ return view->state.z_scale;
+}
+
+
+/* Change 3D view position and direction */
+void gv_view_area_set_3d_view( GvViewArea *view,
+ vec3_t eye_pos, vec3_t eye_dir )
+
+{
+ int changed = FALSE;
+
+ if( eye_pos != NULL
+ && (eye_pos[0] != view->state.eye_pos[0]
+ || eye_pos[1] != view->state.eye_pos[1]
+ || eye_pos[2] != view->state.eye_pos[2]) )
+ {
+ vec_copy( eye_pos, view->state.eye_pos );
+ changed = TRUE;
+ }
+
+ if( eye_dir != NULL
+ && (eye_dir[0] != view->state.eye_dir[0]
+ || eye_dir[1] != view->state.eye_dir[1]
+ || eye_dir[2] != view->state.eye_dir[2]) )
+ {
+ gvgeocoord mag = sqrt(eye_dir[0] * eye_dir[0]
+ + eye_dir[1] * eye_dir[1]
+ + eye_dir[2] * eye_dir[2] );
+
+ if( mag != 0.0 )
+ {
+ vec_scale( eye_dir, 1.0 / mag, view->state.eye_dir );
+ changed = TRUE;
+ }
+ }
+
+ if( changed )
+ gv_view_area_state_changed(view);
+}
+
+/* Change 3D view position and direction to given location on z-plane */
+void gv_view_area_set_3d_view_look_at( GvViewArea *view,
+ vec3_t eye_pos, gvgeocoord *eye_look_at )
+{
+ if( eye_look_at != NULL )
+ {
+ vec3_t eye_dir;
+ gvgeocoord mag;
+
+ eye_dir[0] = eye_look_at[0] - eye_pos[0];
+ eye_dir[1] = eye_look_at[1] - eye_pos[1];
+ eye_dir[2] = -eye_pos[2];
+
+ mag = sqrt(eye_dir[0] * eye_dir[0]
+ + eye_dir[1] * eye_dir[1]
+ + eye_dir[2] * eye_dir[2] );
+
+ if( mag != 0.0 )
+ {
+ vec_scale( eye_dir, 1.0 / mag, view->state.eye_dir );
+ gv_view_area_set_3d_view( view, eye_pos, eye_dir );
+ }
+ }
+ else
+ {
+ gv_view_area_set_3d_view( view, eye_pos, view->state.eye_dir );
+ }
+}
+
+
+/* Get point in z-plane that looking at, false if not meaningful */
+gint
+gv_view_area_get_look_at_pos( GvViewArea *view,
+ gvgeocoord *x, gvgeocoord *y)
+{
+ /* Check if looking up above z-plane */
+ if (view->state.eye_dir[2] >= 0.0)
+ {
+ return FALSE;
+ } else {
+
+ *x = view->state.eye_pos[0] - view->state.eye_dir[0]
+ * (view->state.eye_pos[2]/ view->state.eye_dir[2]);
+
+ *y = view->state.eye_pos[1] - view->state.eye_dir[1]
+ * (view->state.eye_pos[2]/ view->state.eye_dir[2]);
+ }
+
+ return TRUE;
+}
+
+void
+gv_view_area_queue_draw(GvViewArea *view)
+{
+ gv_manager_set_busy( gv_get_manager(), TRUE );
+
+ view->display_dirty = TRUE;
+
+ gtk_widget_queue_draw(GTK_WIDGET(view));
+}
+void
+gv_view_area_queue_cursor_draw(GvViewArea *view, int next_valid, gvgeocoord x, gvgeocoord y)
+{
+ gv_manager_set_busy( gv_get_manager(), TRUE );
+ view->next_valid = next_valid;
+ view->next_x = x;
+ view->next_y = y;
+ gtk_widget_queue_draw(GTK_WIDGET(view));
+}
+
+void
+gv_view_area_zoom(GvViewArea *view, gvgeocoord zoom)
+{
+ view->state.zoom += zoom;
+ view->state.linear_zoom = pow(2.0, view->state.zoom);
+
+ gv_view_area_state_changed(view);
+}
+
+gvgeocoord
+gv_view_area_get_zoom(GvViewArea *view)
+{
+ return view->state.zoom;
+}
+
+void
+gv_view_area_rotate(GvViewArea *view, gvgeocoord angle)
+{
+ view->state.rot += angle;
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_translate(GvViewArea *view, gvgeocoord dx, gvgeocoord dy)
+{
+ gvgeocoord cr, sr;
+
+ dx /= view->state.linear_zoom;
+ dy /= view->state.linear_zoom;
+ cr = cos(-view->state.rot * DEG2RAD);
+ sr = sin(-view->state.rot * DEG2RAD);
+ view->state.tx += (dx * cr - dy * sr) * view->state.flip_x;
+ view->state.ty += (dx * sr + dy * cr) * view->state.flip_y;
+
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_set_translation(GvViewArea *view, gvgeocoord x, gvgeocoord y)
+{
+ view->state.tx = x;
+ view->state.ty = y;
+
+ gv_view_area_state_changed(view);
+}
+
+int
+gv_view_area_get_flip_x( GvViewArea *view )
+{
+ return view->state.flip_x;
+}
+
+int
+gv_view_area_get_flip_y( GvViewArea *view )
+{
+ return view->state.flip_y;
+}
+
+void gv_view_area_set_flip_xy( GvViewArea *view, int flip_x, int flip_y )
+{
+ if( flip_x == view->state.flip_x && flip_y == view->state.flip_y )
+ return;
+
+ view->state.flip_x = flip_x;
+ view->state.flip_y = flip_y;
+
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_copy_state(GvViewArea *view, GvViewArea *copy)
+{
+ gv_view_area_set_state( view, &(copy->state) );
+}
+
+void
+gv_view_area_set_state(GvViewArea *view, GvViewAreaState *state)
+{
+ /* consider preserving mouse position, and re-deriving zoom or log_zoom */
+
+ view->state = *state;
+
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_map_location(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *geo_x, gvgeocoord *geo_y)
+{
+ const char *coord_sys = gv_view_area_get_projection(view);
+ char *latlong_srs = NULL;
+
+ *geo_x = x;
+ *geo_y = y;
+
+ /* Don't need to do anything in the case of a view with
+ raw PIXEL projection */
+ if (coord_sys != NULL && !EQUAL(coord_sys,"PIXEL"))
+ {
+ latlong_srs = gv_make_latlong_srs( coord_sys );
+
+ if( latlong_srs != NULL )
+ {
+ double temp_x, temp_y, temp_z;
+
+ temp_x = x;
+ temp_y = y;
+ temp_z = 0.0;
+
+ if( gv_reproject_points( latlong_srs, coord_sys,
+ 1, &temp_x, &temp_y, &temp_z ) )
+ {
+ *geo_x = temp_x;
+ *geo_y = temp_y;
+
+ /* printf(" (x,y)=(%f,%f), (geo_x, geo_y)=(%f,%f)\n", x,y,temp_x,temp_y); */
+ }
+ }
+ }
+
+ /* geo_x, geo_y contains the original x,y pair or the reprojected values
+ if view is lat/long */
+}
+
+void
+gv_view_area_map_pointer(GvViewArea *view, gvgeocoord px, gvgeocoord py,
+ gvgeocoord *x, gvgeocoord *y)
+{
+ gvgeocoord fx, fy, cr, sr;
+
+ cr = cos(-view->state.rot * DEG2RAD);
+ sr = sin(-view->state.rot * DEG2RAD);
+ fx = px - view->state.shape_x / 2.0;
+ fy = view->state.shape_y / 2.0 - py;
+ fx /= view->state.linear_zoom;
+ fy /= view->state.linear_zoom;
+ *x = (fx * cr - fy * sr) * view->state.flip_x - view->state.tx;
+ *y = (fx * sr + fy * cr) * view->state.flip_y - view->state.ty;
+}
+
+void
+
+gv_view_area_inverse_map_pointer(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *px, gvgeocoord *py)
+{
+ gvgeocoord fx, fy, cr, sr;
+
+ cr = cos(view->state.rot * DEG2RAD);
+ sr = sin(view->state.rot * DEG2RAD);
+
+ x += view->state.tx;
+ y += view->state.ty;
+
+ fx = (x * cr * view->state.flip_x - y * sr * view->state.flip_y)
+ * view->state.linear_zoom;
+ fy = (x * sr * view->state.flip_x + y * cr * view->state.flip_y)
+ * view->state.linear_zoom;
+
+ *px = fx + view->state.shape_x / 2.0;
+ *py = view->state.shape_y / 2.0 - fy;
+}
+
+void
+gv_view_area_correct_for_transform(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *cx, gvgeocoord *cy)
+{
+ /* Correct a vector for rotation and zoom: used for sprites */
+ gvgeocoord cr, sr;
+
+ cr = cos(-view->state.rot * DEG2RAD);
+ sr = sin(-view->state.rot * DEG2RAD);
+
+ *cx = (x * cr - y * sr) * view->state.flip_x / view->state.linear_zoom;
+ *cy = (x * sr + y * cr) * view->state.flip_y / view->state.linear_zoom;
+}
+
+void
+gv_view_area_add_layer(GvViewArea *view, GtkObject *layer_obj)
+{
+ GvLayer *layer;
+
+ g_return_if_fail(GV_IS_LAYER(layer_obj));
+ layer = GV_LAYER(layer_obj);
+
+ if (GTK_WIDGET_REALIZED(GTK_WIDGET(view)))
+ {
+ /* Call the one time setup function for the layer */
+ /* If the view area is not yet realized, this is deferred to
+ gv_view_area_realize() */
+ if (gtk_gl_area_make_current(GTK_GL_AREA(view)))
+ {
+ gv_layer_setup(layer, view);
+ }
+
+ /* If this is the first layer, set initial view area
+ transformation based on layer extents. Also ensure
+ we are reset back to unflipped even if we previously got
+ flipped for a raw image. */
+ if (view->layers == NULL)
+ {
+ view->state.flip_y = 1.0;
+ gv_view_area_fit_layer(view, layer);
+ }
+ }
+
+ /* Maintain reference to layer */
+ gtk_object_ref(GTK_OBJECT(layer));
+ gtk_object_sink(GTK_OBJECT(layer));
+
+ g_assert( layer->view == NULL );
+
+ view->volume_current = FALSE;
+ view->layers = g_list_append(view->layers, layer);
+
+ layer->view = view;
+
+ gtk_signal_connect_object(GTK_OBJECT(layer), "changed",
+ GTK_SIGNAL_FUNC(gv_view_area_change_notify),
+ GTK_OBJECT(view));
+ gtk_signal_connect_object(GTK_OBJECT(layer), "display-change",
+ GTK_SIGNAL_FUNC(gv_view_area_change_notify),
+ GTK_OBJECT(view));
+
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[ACTIVE_CHANGED]);
+
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_remove_layer(GvViewArea *view, GtkObject *layer_obj)
+{
+ GvLayer *layer;
+ GList *link;
+
+ g_return_if_fail(GV_IS_LAYER(layer_obj));
+ layer = GV_LAYER(layer_obj);
+
+ if (GTK_WIDGET_REALIZED(GTK_WIDGET(view)))
+ {
+ /* Allow layer to destroy gl handles if necessary */
+ if (gtk_gl_area_make_current(GTK_GL_AREA(view)))
+ {
+ gv_layer_teardown(layer, view);
+ }
+ }
+
+ if (layer_obj == view->active_layer)
+ {
+ gv_view_area_set_active_layer(view, NULL);
+ }
+
+ g_assert( layer->view == view );
+ layer->view = NULL;
+
+ link = g_list_find(view->layers, layer);
+ if (link == NULL)
+ {
+ CPLDebug( "OpenEV",
+ "gv_view_area_remove_link(): layer %s is not in view",
+ gtk_type_name(GTK_OBJECT_TYPE(layer)));
+ return;
+ }
+
+ view->layers = g_list_remove_link(view->layers, link);
+ view->volume_current = FALSE;
+
+
+
+ /* clear projection if no layers are left. */
+ if( view->layers == NULL )
+ {
+ if( view->projection != NULL )
+ {
+ g_free( view->projection );
+ view->projection = NULL;
+ }
+ }
+
+ gtk_signal_disconnect_by_data(layer_obj, GTK_OBJECT(view));
+ gtk_object_unref(layer_obj);
+
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[ACTIVE_CHANGED]);
+
+ gv_view_area_queue_draw(view);
+}
+
+GtkObject *
+gv_view_area_active_layer(GvViewArea *view)
+{
+ return view->active_layer;
+}
+
+void
+gv_view_area_set_active_layer(GvViewArea *view, GtkObject *layer)
+{
+ g_return_if_fail(layer == NULL || GV_IS_LAYER(layer));
+
+ /* Ignore if this is already the active layer */
+ if (layer == view->active_layer) return;
+
+ if (layer)
+ {
+ /* Make sure this layer is in the list */
+ if (g_list_find(view->layers, (gpointer)layer) == NULL)
+ {
+ CPLDebug( "OpenEV",
+ "gv_view_area_set_active_layer(): layer %s not in view",
+ gtk_type_name(GTK_OBJECT_TYPE(layer)));
+ return;
+ }
+ }
+
+ view->active_layer = layer;
+
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[ACTIVE_CHANGED]);
+}
+
+GtkObject *
+gv_view_area_get_layer_of_type(GvViewArea *view, GtkType layer_type,
+ gint read_only_ok )
+{
+ GList *list;
+
+ /* First check the active layer */
+ if(view->active_layer &&
+ gtk_type_is_a(GTK_OBJECT_TYPE(view->active_layer), layer_type)
+ && (read_only_ok || !gv_data_is_read_only(GV_DATA(view->active_layer))))
+ {
+ return view->active_layer;
+ }
+
+ /* Next move through the list in order */
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ if( gtk_type_is_a(GTK_OBJECT_TYPE(layer), layer_type)
+ && (read_only_ok || !gv_data_is_read_only(GV_DATA(layer))) )
+ {
+ return GTK_OBJECT(layer);
+ }
+ list = g_list_next(list);
+ }
+ return NULL;
+}
+
+GtkObject *
+gv_view_area_get_named_layer(GvViewArea *view, const char *name)
+{
+ GList *list;
+
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ if (GV_DATA(layer)->name && strcmp(GV_DATA(layer)->name, name) == 0)
+ {
+ return GTK_OBJECT(layer);
+ }
+ list = g_list_next(list);
+ }
+ return NULL;
+}
+
+GList *
+gv_view_area_list_layers(GvViewArea *view)
+{
+ return g_list_copy(view->layers);
+}
+
+void
+gv_view_area_swap_layers(GvViewArea *view, gint index_a, gint index_b)
+{
+ gpointer *layer_a, *layer_b;
+
+ g_return_if_fail(index_a != index_b);
+
+ /* Put indicies in ascending order */
+ if (index_a > index_b)
+ {
+ gint tmp = index_b;
+ index_b = index_a;
+ index_a = tmp;
+ }
+
+ layer_a = g_list_nth_data(view->layers, index_a);
+ layer_b = g_list_nth_data(view->layers, index_b);
+ g_return_if_fail(layer_a && layer_b);
+
+ /* Perform swap */
+ view->layers = g_list_remove(view->layers, layer_a);
+ view->layers = g_list_remove(view->layers, layer_b);
+ view->layers = g_list_insert(view->layers, layer_b, index_a);
+ view->layers = g_list_insert(view->layers, layer_a, index_b);
+
+ gv_view_area_queue_draw(view);
+}
+
+GdkPixmap *
+gv_view_area_create_thumbnail(GvViewArea *view, GtkObject *layerobj,
+ gint width, gint height)
+{
+#ifdef WIN32
+ return NULL;
+#else
+ GvLayer *layer;
+ GdkPixmap *pixmap;
+ GdkVisual *visual;
+ GdkGLContext *glcontext;
+ GdkGLPixmap *glpixmap;
+ GvRect extents;
+ gvgeocoord aspect;
+ gint visible;
+
+ if( !GTK_WIDGET_REALIZED(view) )
+ return NULL;
+
+ g_return_val_if_fail(GV_IS_LAYER(layerobj), NULL);
+
+ layer = GV_LAYER(layerobj);
+
+ visual = gtk_widget_get_visual(GTK_WIDGET(view));
+ pixmap = gdk_pixmap_new(NULL, width, height, visual->depth);
+ glcontext = GTK_GL_AREA(view)->glcontext;
+ glpixmap = gdk_gl_pixmap_new(visual, pixmap);
+
+ if (!gdk_gl_pixmap_make_current(glpixmap, glcontext))
+ {
+ CPLDebug( "OpenEV",
+ "gv_view_area_create_thumbnail(): offscreen render failed.");
+ gdk_gl_pixmap_unref(glpixmap);
+ gdk_pixmap_unref(pixmap);
+ return NULL;
+ }
+
+ /* Add 5% to extents in each direction to get a nice border */
+ gv_layer_extents(layer, &extents);
+ extents.x -= extents.width * 0.05;
+ extents.y -= extents.height * 0.05;
+ extents.width *= 1.1;
+ extents.height *= 1.1;
+
+ /* Fix aspect ratio */
+ aspect = (gvgeocoord)width / (gvgeocoord)height;
+ if( (extents.width / extents.height) > aspect )
+ {
+ gvgeocoord newheight = extents.width / aspect;
+ extents.y -= (newheight - extents.height) / 2.0;
+ extents.height = newheight;
+ }
+ else
+ {
+ gvgeocoord newwidth = extents.height * aspect;
+ extents.x -= (newwidth - extents.width) / 2.0;
+ extents.width = newwidth;
+ }
+
+ /* glpixmap is in the front left buffer */
+ glDrawBuffer(GL_FRONT_LEFT);
+ glViewport(0, 0, width, height);
+
+ /* Set background to black */
+ glClearColor(view->background[0], view->background[1], view->background[2],
+ view->background[3] );
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Make sure there is something to draw */
+ if (extents.width > 0 || extents.height > 0)
+ {
+ /* Temporarily make visible, and turn on presentation mode */
+ visible = gv_layer_set_visible_temp(layer, TRUE);
+ gv_layer_set_presentation(layer, TRUE);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ if( view->state.flip_y < 0 )
+ {
+ gluOrtho2D(extents.x, extents.x + extents.width,
+ extents.y + extents.height, extents.y );
+ }
+ else
+ {
+ gluOrtho2D(extents.x, extents.x + extents.width,
+ extents.y, extents.y + extents.height);
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ gv_layer_draw(layer, view);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ /* Turn off presentation mode and restore visibility */
+ gv_layer_set_visible_temp(layer, visible);
+ gv_layer_set_presentation(layer, FALSE);
+ }
+ glFinish();
+
+ /* Restore the view as the current context before destroying
+ the glpixmap */
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view)))
+ {
+ g_warning("gv_view_area_create_thumbnail(): view context restore failed.");
+ }
+ glViewport(0, 0, view->state.shape_x, view->state.shape_y);
+ glDrawBuffer(GL_BACK);
+
+ gdk_gl_pixmap_unref(glpixmap);
+ return pixmap;
+#endif
+}
+
+gint
+gv_view_area_render_to_func(GvViewArea *view,
+ gint width, gint height,
+ gint (*scanline_handler)( void *, void * ),
+ void *cb_data )
+{
+ GvRect extents;
+ gvgeocoord aspect;
+ guint8 *scanline;
+ gvgeocoord xmin, xmax, ymin, ymax;
+ gint line, errcode = 0;
+ gint x_chunk, x_chunk_size, y_chunk, y_chunk_size;
+ GList *list;
+ guint8 *row_of_chunks;
+ int direct_render, save_exact;
+
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view))) return -1;
+
+ direct_render = (width == view->state.shape_x)
+ && (height == view->state.shape_y);
+
+ save_exact = view->exact_render;
+ view->exact_render = TRUE;
+
+ x_chunk_size = view->state.shape_x;
+ y_chunk_size = view->state.shape_y;
+
+ gv_view_area_get_extents(view, &xmin, &ymin, &xmax, &ymax );
+ extents.x = xmin;
+ extents.width = xmax - xmin;
+ extents.y = ymin;
+ extents.height = ymax - ymin;
+
+ /* Fix aspect ratio */
+ aspect = (gvgeocoord)width / (gvgeocoord)height;
+ if ( (extents.width / extents.height) > aspect )
+ {
+ gvgeocoord newheight = extents.width / aspect;
+ extents.y -= (newheight - extents.height) / 2.0;
+ extents.height = newheight;
+ }
+ else
+ {
+ gvgeocoord newwidth = extents.height * aspect;
+ extents.x -= (newwidth - extents.width) / 2.0;
+ extents.width = newwidth;
+ }
+
+ /* allocate a buffer large enough to hold one RGB row of chunks */
+ row_of_chunks = g_malloc(width * y_chunk_size * 3);
+ if( row_of_chunks == NULL )
+ {
+ g_warning( "out of memory in gv_view_area_render_to_func" );
+ view->exact_render = save_exact;
+ return -1;
+ }
+ memset( row_of_chunks, 0, width*y_chunk_size*3 );
+
+ /* glpixmap is in the front left buffer */
+ glDrawBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
+
+ /* Make sure there is something to draw */
+ if (extents.width == 0 || extents.height == 0)
+ {
+ view->exact_render = save_exact;
+ return -1;
+ }
+
+ for( y_chunk=0; y_chunk < height && errcode == 0; y_chunk += y_chunk_size)
+ {
+ GvRect chunk_extents;
+
+ chunk_extents.height =
+ extents.height * (y_chunk_size / (double) height);
+ if( view->state.flip_y < 0 )
+ {
+ chunk_extents.y = extents.y
+ + extents.height * (y_chunk / (double) height);
+ }
+ else
+ {
+ chunk_extents.y = extents.y + extents.height
+ - extents.height * ((y_chunk+y_chunk_size) / (double) height);
+ }
+
+ for( x_chunk = 0;
+ x_chunk < width && errcode == 0;
+ x_chunk += x_chunk_size )
+ {
+ chunk_extents.width =
+ extents.width * (x_chunk_size / (double) width);
+ chunk_extents.x = extents.x
+ + extents.width * (x_chunk / (double) width);
+
+ /* Set background to black */
+ glClearColor(view->background[0], view->background[1],
+ view->background[2], view->background[3] );
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ render_counter++;
+
+ if( !direct_render )
+ {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ if( view->state.flip_y < 0 )
+ {
+ gluOrtho2D(chunk_extents.x,
+ chunk_extents.x + chunk_extents.width,
+ chunk_extents.y + chunk_extents.height,
+ chunk_extents.y );
+ }
+ else
+ {
+ gluOrtho2D(chunk_extents.x,
+ chunk_extents.x + chunk_extents.width,
+ chunk_extents.y,
+ chunk_extents.y + chunk_extents.height);
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ }
+
+ for( list = view->layers; list != NULL; list = g_list_next(list) )
+ {
+ GvLayer *layer = GV_LAYER( list->data );
+
+ gv_layer_set_presentation(layer, TRUE);
+ gv_layer_draw(layer, view);
+ gv_layer_set_presentation(layer, FALSE);
+ }
+
+ if( !direct_render )
+ {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ }
+
+ glFinish();
+
+ for( line = 0;
+ line < y_chunk_size && errcode == 0
+ && (line + y_chunk) < height;
+ line++ )
+ {
+ scanline = row_of_chunks +
+ x_chunk * 3
+ + line * width * 3;
+
+ scanline[0] = 253;
+ scanline[1] = 101;
+ glReadPixels( 0, y_chunk_size - line - 1,
+ MIN(x_chunk_size,width-x_chunk), 1,
+ GL_RGB, GL_UNSIGNED_BYTE, scanline );
+
+ if( scanline[0] == 253 && scanline[1] == 101 )
+ {
+ CPLDebug( "OpenEV",
+ "glReadPixels() appears to have failed." );
+ errcode = 1;
+ }
+ }
+ }
+
+ for( line = 0;
+ line < y_chunk_size && errcode == 0
+ && (line + y_chunk) < height;
+ line++ )
+ {
+ scanline = row_of_chunks + line * width * 3;
+ errcode = scanline_handler( cb_data, scanline );
+ }
+ }
+
+ g_free( row_of_chunks );
+
+ view->exact_render = save_exact;
+
+ return errcode;
+}
+
+GPtrArray *gv_view_area_get_fontnames( GvViewArea *view )
+
+{
+ GPtrArray *ret_list;
+ int font;
+
+ ret_list = g_ptr_array_new();
+
+ for( font = 0; bmfontmap[font].gvname != NULL; font++ )
+ g_ptr_array_add( ret_list, bmfontmap[font].gvname );
+
+ return ret_list;
+}
+
+gint
+gv_view_area_bmfont_load(GvViewArea *view, gchar *name)
+{
+ gint font;
+ GvBMFontInfo new_finfo;
+
+ /* translate aliases */
+ for (font=0; bmfontmap[font].gvname != NULL; font++)
+ {
+ if (strcmp(name, bmfontmap[font].gvname) == 0)
+ {
+ name = bmfontmap[font].gdkname;
+ break;
+ }
+ }
+
+ /* Do we already have this font loaded? */
+ for (font=0; font < view->bmfonts->len; font++ )
+ {
+ GvBMFontInfo *finfo;
+
+ finfo = &(g_array_index( view->bmfonts, GvBMFontInfo, font ));
+ if (strcmp(name, finfo->name) == 0)
+ return font;
+ }
+
+ /* Try to load the font */
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view)))
+ {
+ g_warning("gv_view_area_bmfont_load(): can't make view area current");
+ return -1;
+ }
+
+ new_finfo.listbase = glGenLists(96);
+ if (new_finfo.listbase == 0)
+ {
+ g_warning("gv_view_area_bmfont_load(): font allocation failed");
+ return -1;
+ }
+
+ new_finfo.gdkfont = gdk_font_load(name);
+ if (!new_finfo.gdkfont)
+ {
+ g_warning("gv_view_area_bmfont_load(): gdk font load failed: %s",
+ name );
+ return -1;
+ }
+
+ gdk_gl_use_gdk_font(new_finfo.gdkfont, 0, 127, new_finfo.listbase);
+
+
+ new_finfo.name = g_strdup(name);
+ g_array_append_val( view->bmfonts, new_finfo);
+
+ return view->bmfonts->len-1;
+}
+
+GvBMFontInfo *
+gv_view_area_bmfont_get_info(GvViewArea *view, gint font)
+{
+ GvBMFontInfo *finfo;
+
+ if (font < 0 || font >= view->bmfonts->len )
+ return NULL;
+
+ finfo = &(g_array_index( view->bmfonts, GvBMFontInfo, font ));
+ return finfo;
+}
+
+void
+gv_view_area_bmfont_draw(GvViewArea *view, gint font, gvgeocoord x, gvgeocoord y,
+ gchar *text, int force_simple )
+{
+ GvBMFontInfo *finfo;
+
+ if (font < 0 || font >= view->bmfonts->len )
+ return;
+
+ finfo = &(g_array_index( view->bmfonts, GvBMFontInfo, font ));
+
+ /*
+ * In 3D it would be too hard to determine whats in/out of view, so
+ * we just do the simple thing. This will result in strings with an
+ * origin out of the view frustrum not being drawn, but that's life.
+ */
+ if( view->flag_3d || force_simple )
+ {
+ glRasterPos2f(x, y);
+ }
+ /*
+ * Ensure we initially position the raster position within the
+ * view frustrum, then offset to our desired location.
+ */
+ else
+ {
+ gvgeocoord vx, vy, vx_screen, vy_screen, tx_screen, ty_screen;
+
+ vx_screen = view->state.shape_x/2;
+ vy_screen = view->state.shape_y/2;
+
+ gv_view_area_map_pointer( view, vx_screen, vy_screen,
+ &vx, &vy );
+ gv_view_area_inverse_map_pointer( view, x, y, &tx_screen, &ty_screen );
+
+ /* position in frustrum */
+ glRasterPos2f(vx, vy);
+
+ /* shift to desired location. */
+ glBitmap( 0, 0, 0, 0,
+ (int) -(vx_screen - floor(tx_screen)),
+ (int) (vy_screen - ceil(ty_screen)),
+ NULL );
+ }
+
+ glPushAttrib(GL_LIST_BASE);
+ glListBase(finfo->listbase);
+ glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte*)text);
+ glPopAttrib();
+}
+
+void gv_view_area_set_background_color( GvViewArea *view, GvColor new_color )
+
+{
+ if( new_color[0] != view->background[0]
+ || new_color[1] != view->background[1]
+ || new_color[2] != view->background[2]
+ || new_color[3] != view->background[3] )
+ {
+ gv_color_copy( view->background, new_color );
+ gv_view_area_state_changed(view);
+ }
+}
+
+void gv_view_area_get_background_color( GvViewArea *view, GvColor color )
+
+{
+ color[0] = view->background[0];
+ color[1] = view->background[1];
+ color[2] = view->background[2];
+ color[3] = view->background[3];
+}
+
+/*****************************************************************/
+
+static gint
+gv_view_area_reset_projection(GvViewArea *view, gvgeocoord width, gvgeocoord height)
+{
+ if( !gtk_gl_area_make_current(GTK_GL_AREA(view)) )
+ return 1;
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ if (! view->flag_3d)
+ {
+ /* Assumes clipping plane of [-1.0, 1.0]
+ gluOrtho2D(-width/2.0, width/2.0, -height/2.0, height/2.0); */
+ glOrtho(-width/2.0, width/2.0, -height/2.0, height/2.0, -1000.0f, 1000.0f);
+ } else {
+ gluPerspective(90.0f,(GLgeocoord)width/(GLgeocoord)height,10.0f,3000000.0f);
+ }
+ glMatrixMode(GL_MODELVIEW);
+
+ return 0;
+
+}
+static gint
+gv_view_area_configure(GtkWidget *widget, GdkEventConfigure *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+ int w, h;
+
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view))) return 0;
+
+ CPLDebug( "OpenEV", "VENDOR = %s", glGetString( GL_VENDOR ) );
+ CPLDebug( "OpenEV", "RENDERER = %s", glGetString( GL_RENDERER ) );
+ CPLDebug( "OpenEV", "VERSION = %s", glGetString( GL_VERSION ) );
+ CPLDebug( "OpenEV", "EXTENSIONS = %s", glGetString( GL_EXTENSIONS ) );
+
+ w = event->width;
+ h = event->height;
+
+ gv_view_area_reset_projection(view, (gvgeocoord)w, (gvgeocoord)h);
+
+ view->state.shape_x = (gvgeocoord)w;
+ view->state.shape_y = (gvgeocoord)h;
+
+ gv_view_area_state_changed( view );
+
+ return 0;
+}
+
+gint
+gv_view_area_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+ GList *list;
+ GvLayer *layer;
+ GTimer *timer;
+
+
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view))) return 0;
+
+ /*
+ ** If the display state hasn't changed in any way, then just refresh from
+ ** our display buffer. Otherwise we will actually need to rerender with
+ ** OpenGL. We avoid rerendering for interactivity on software rendered
+ ** systems.
+ */
+
+ if( (!view->display_dirty)
+ && ((strstr(glGetString(GL_RENDERER), "Mesa Windows") != NULL) ||
+ (strstr(glGetString(GL_RENDERER),"Mesa X11") != NULL) ||
+ (strstr(glGetString(GL_RENDERER), "Mesa GLX Indirect") != NULL)))
+ {
+
+ gtk_gl_area_swap_buffers(GTK_GL_AREA(view));
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[GLCURSOR]);
+ return 0;
+ }
+
+ view->display_dirty = FALSE;
+
+ render_counter++;
+
+ gv_manager_set_busy( gv_get_manager(), TRUE );
+
+ timer = g_timer_new();
+ g_timer_start( timer );
+
+ glDisable(GL_DITHER);
+ glShadeModel(GL_FLAT);
+ glClearColor(view->background[0], view->background[1],
+ view->background[2], view->background[3] );
+
+ /* Do we need these??? */
+ if (view->flag_3d)
+ {
+#ifdef notdef
+ glEnable(GL_CULL_FACE);
+#endif
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ }
+ else
+ {
+ glDisable(GL_NORMALIZE);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+
+ if (view->flag_3d)
+ {
+ double min_range, max_range;
+ vec3_t eye_pos, eye_dir, flip_eye_pos;
+ int debug3d = 0;
+
+ if( gv_manager_get_preference(gv_get_manager(),"DEBUG3D") != NULL )
+ debug3d =
+ atoi(gv_manager_get_preference(gv_get_manager(),"DEBUG3D"));
+
+ eye_pos[0] = view->state.eye_pos[0];
+ eye_pos[1] = view->state.eye_pos[1];
+ eye_pos[2] = view->state.eye_pos[2];
+
+ eye_dir[0] = view->state.eye_dir[0];
+ eye_dir[1] = view->state.eye_dir[1];
+ eye_dir[2] = view->state.eye_dir[2];
+
+
+ /* Compute the near and far clipping planes - taking into account any image flips */
+ gv_view_area_get_volume( view, NULL );
+
+ flip_eye_pos[0] = view->state.flip_x * eye_pos[0];
+ flip_eye_pos[1] = view->state.flip_y * eye_pos[1];
+ flip_eye_pos[2] = eye_pos[2];
+
+ vec_near_far_range( flip_eye_pos, view->view_volume,
+ &min_range, &max_range);
+
+ if( min_range < max_range / 500.0 || min_range >= max_range )
+ min_range = max_range / 500.0;
+
+ max_range = max_range * 1.2;
+ min_range = min_range * 0.5;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(90.0f,
+ (gvgeocoord)view->state.shape_x/(gvgeocoord)view->state.shape_y,
+ min_range*0.5, max_range );
+ glMatrixMode(GL_MODELVIEW);
+
+ if( debug3d )
+ {
+ printf( "================ Redraw Start ===================\n" );
+ printf( "Clipping planes: near=%g, far=%g\n",
+ min_range, max_range );
+ }
+
+ /* Set view orientation */
+ gluLookAt(eye_pos[0], eye_pos[1], eye_pos[2],
+ eye_pos[0] + eye_dir[0],
+ eye_pos[1] + eye_dir[1],
+ eye_pos[2] + eye_dir[2],
+ 0.0, 0.0, 1.0);
+
+ glScale(1.0 * view->state.flip_x, 1.0 * view->state.flip_y, view->state.z_scale);
+
+ if( debug3d )
+ {
+ printf( "eye=(%g,%g,%g) eye_dir=(%g,%g,%g)\n",
+ eye_pos[0], eye_pos[1], eye_pos[2],
+ eye_dir[0], eye_dir[1], eye_dir[2] );
+ }
+
+ } else {
+ glRotate(view->state.rot, 0.0, 0.0, 1.0);
+
+ glScale(view->state.linear_zoom * view->state.flip_x,
+ view->state.linear_zoom * view->state.flip_y, 1.0);
+
+ glTranslate(view->state.tx, view->state.ty, 0.0);
+ }
+
+ list = view->layers;
+ while (list)
+ {
+ layer = (GvLayer*)list->data;
+ gv_layer_draw(layer, view);
+ list = g_list_next(list);
+ }
+
+ /* Give other interested objects a chance to add to the drawing */
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[GLDRAW]);
+
+ /* draw banded zoom area */
+ if (view->dragging_mode)
+ {
+ gvgeocoord x[4], y[4];
+
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->state.mpos_y,
+ x+0, y+0 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->state.mpos_y,
+ x+1, y+1 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->last_mpos_y,
+ x+2, y+2 );
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->last_mpos_y,
+ x+3, y+3 );
+
+ glColor3f(1.0, 0.5, 0.0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x[0], y[0]);
+ glVertex2(x[1], y[1]);
+ glVertex2(x[2], y[2]);
+ glVertex2(x[3], y[3]);
+ glEnd();
+ }
+
+ gtk_gl_area_swap_buffers(GTK_GL_AREA(view));
+ /* Don't XOR last ghost cursor position, since view has been redrawn */
+ /* (only has effect in logical cursor mode) */
+ view->last_valid=FALSE;
+ gtk_signal_emit(GTK_OBJECT(view),view_area_signals[GLCURSOR]);
+
+ glFinish();
+
+ /*
+ * Capture time this draw took.
+ */
+ view->last_draw_time = g_timer_elapsed(timer,NULL);
+ g_timer_stop( timer );
+ g_timer_destroy( timer );
+
+ /*
+ * Setup timer so we know when we should do the next redraw, even if
+ * all the idle work isn't done yet.
+ */
+ if( view->redraw_timer != NULL )
+ g_timer_destroy( view->redraw_timer );
+
+ view->redraw_timer = g_timer_new();
+ g_timer_start( view->redraw_timer );
+
+ return 0;
+}
+
+static void
+gv_view_area_realize(GtkWidget *widget)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+ GtkGLAreaClass *parent_class;
+ GList *list;
+ GvLayer *layer;
+ const char *auto_fit_flag;
+
+ /* Call parent class function first */
+ parent_class = gtk_type_class(gtk_gl_area_get_type());
+ GTK_WIDGET_CLASS(parent_class)->realize(GTK_WIDGET(view));
+
+ g_return_if_fail(GTK_WIDGET_REALIZED(GTK_WIDGET(view)));
+
+ /* Make gl area current so layers can create gl handles */
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view))) return;
+
+ /* Call the one time setup function for all layers */
+ list = view->layers;
+ while (list)
+ {
+ layer = (GvLayer*)list->data;
+ gv_layer_setup(layer, view);
+ list = g_list_next(list);
+ }
+
+ /* Set up the inital view transformation using the first layer */
+ auto_fit_flag = gv_properties_get(&(view->properties),
+ "_supress_realize_auto_fit");
+ if (view->layers && (auto_fit_flag == NULL || EQUAL(auto_fit_flag,"off")))
+ {
+ layer = (GvLayer*)view->layers->data;
+ gv_view_area_fit_layer(view, layer);
+ }
+}
+
+static void
+gv_view_area_unrealize(GtkWidget *widget)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+ GtkGLAreaClass *parent_class;
+ GList *list;
+ gint font;
+
+ /* Make gl area current so layers can clean up gl handles */
+ if (!gtk_gl_area_make_current(GTK_GL_AREA(view)))
+ {
+ g_warning("gv_view_area_unrealize(): can't make view area current");
+ return;
+ }
+
+ /* Teardown all layers */
+ view->active_layer = NULL;
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ gv_layer_teardown(layer, view);
+ list = g_list_next(list);
+ }
+
+ /* Destroy bmfont listbase array */
+ for( font=0; font < view->bmfonts->len; font++ )
+ {
+ GvBMFontInfo *finfo;
+
+ finfo = &(g_array_index( view->bmfonts, GvBMFontInfo, font ));
+
+ if( finfo->gdkfont != NULL )
+ gdk_font_unref(finfo->gdkfont);
+
+ g_free( finfo->name );
+ glDeleteLists(finfo->listbase, 96);
+ }
+ g_array_free( view->bmfonts, TRUE );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gtk_gl_area_get_type());
+ GTK_WIDGET_CLASS(parent_class)->unrealize(GTK_WIDGET(view));
+}
+
+static void
+gv_view_area_fit_layer(GvViewArea *view, GvLayer *layer)
+{
+ GvRect rect;
+
+ /* Set the view transformation to show the full extents of the layer */
+
+ /* Make sure the view area is realized so the state.shape has been
+ set (a configure event has been recieved) */
+ if (!GTK_WIDGET_REALIZED(GTK_WIDGET(view))) return;
+
+ /*
+ * Set the view projection.
+ */
+ if( view->projection != NULL )
+ {
+ g_free( view->projection );
+ view->projection = NULL;
+ }
+
+ if( gv_data_get_projection(GV_DATA(layer)) != NULL )
+ {
+ view->projection = g_strdup(gv_data_get_projection(GV_DATA(layer)));
+ }
+
+ /*
+ * Get the layer extents.
+ */
+ gv_layer_extents(layer, &rect);
+
+ /*
+ * If this is an image, we want to try and orient the image with
+ * pixel (0,0) in the top left if possible.
+ */
+ if( GV_IS_RASTER_LAYER(layer) )
+ {
+ GvRaster *raster;
+
+ raster = GV_RASTER_LAYER(layer)->prototype_data;
+
+ if( GV_RASTER_LAYER(layer)->mesh_is_raw
+ || (raster->gcp_count == 0
+ && raster->geotransform[2] == 0.0
+ && raster->geotransform[4] == 0.0
+ && raster->geotransform[5] > 0.0) )
+ {
+ rect.y = rect.y + rect.height;
+ rect.height *= -1;
+ }
+ }
+
+ gv_view_area_fit_extents(view, rect.x, rect.y, rect.width, rect.height );
+
+ /* Setup 3D specific extent information */
+ gv_view_area_fit_extents_3D(view,
+ rect.x, rect.y, 0.0,
+ rect.width, rect.height,
+ (rect.width+rect.height)*0.5 );
+}
+
+void
+gv_view_area_fit_all_layers(GvViewArea *view)
+
+{
+ GvRect rect;
+ double volume[6];
+
+ /*
+ * Set 2D view.
+ */
+ gv_view_area_get_world_extents( view, &rect );
+ gv_view_area_fit_extents(view, rect.x, rect.y, rect.width, rect.height );
+
+ /*
+ * Also do a default 3D view.
+ */
+ gv_view_area_get_volume( view, volume );
+ gv_view_area_fit_extents_3D( view,
+ volume[0],
+ volume[2],
+ volume[4],
+ volume[1] - volume[0],
+ volume[3] - volume[2],
+ volume[5] - volume[4] );
+}
+
+void
+gv_view_area_get_world_extents(GvViewArea *view, GvRect *extents )
+
+{
+ GvRect rect;
+ int flip_y = FALSE, first = TRUE, first_raster = TRUE;
+ GList *list;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = 0;
+ rect.height = 0;
+
+ /* Make sure the view area is realized so the state.shape has been
+ set (a configure event has been recieved) */
+ if (!GTK_WIDGET_REALIZED(GTK_WIDGET(view)))
+ {
+ *extents = rect;
+ return;
+ }
+
+ /*
+ * Get the layers extents.
+ */
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ GvRect layer_rect;
+
+ gv_layer_extents(layer, &layer_rect);
+
+ if( layer_rect.width == 0 && layer_rect.height == 0 )
+ /* do nothing */;
+
+ else if( first )
+ {
+ rect = layer_rect;
+ first = FALSE;
+
+ if( first_raster && GV_IS_RASTER_LAYER(layer) )
+ {
+ GvRasterLayer *rlayer = GV_RASTER_LAYER(layer);
+ GvRaster *raster = rlayer->prototype_data;
+
+ if( rlayer->mesh_is_raw )
+ {
+ flip_y = TRUE;
+ }
+ else if( raster->gcp_count == 0
+ && raster->geotransform[2] == 0.0
+ && raster->geotransform[4] == 0.0 )
+ {
+ if( raster->geotransform[5] > 0.0 )
+ {
+ flip_y = TRUE;
+ }
+ }
+
+ first_raster = FALSE;
+ }
+ }
+ else
+ {
+ gvgeocoord new_x, new_y;
+
+ new_x = MIN(rect.x,layer_rect.x);
+ rect.width = MAX(rect.x+rect.width,
+ layer_rect.x+layer_rect.width) - new_x;
+ new_y = MIN(rect.y,layer_rect.y);
+ rect.height = MAX(rect.y+rect.height,
+ layer_rect.y+layer_rect.height) - new_y;
+ rect.x = new_x;
+ rect.y = new_y;
+ }
+
+ list = g_list_next(list);
+ }
+
+ /*
+ * If we found a "raw" raster layer, flip the coordinate system.
+ */
+ if( flip_y )
+ {
+ rect.y = rect.y + rect.height;
+ rect.height *= -1;
+ }
+
+ *extents = rect;
+}
+
+void
+gv_view_area_fit_extents(GvViewArea *view,
+ gvgeocoord llx, gvgeocoord lly,
+ gvgeocoord width, gvgeocoord height )
+{
+ /* Make sure the view area is realized so the state.shape has been
+ set (a configure event has been recieved) */
+ if (!GTK_WIDGET_REALIZED(GTK_WIDGET(view))) return;
+
+ if (width == 0.0 || height == 0.0)
+ {
+ view->state.linear_zoom = 1.0;
+ }
+ else
+ {
+ gvgeocoord zoomx, zoomy;
+
+ zoomx = view->state.shape_x / width;
+ zoomy = view->state.shape_y / ABS(height);
+
+ view->state.linear_zoom = MIN(zoomx, zoomy);
+ }
+
+ view->state.rot = 0.0;
+ view->state.tx = -(width/2.0 + llx);
+ view->state.ty = -(height/2.0 + lly);
+ view->state.zoom = LOG2(view->state.linear_zoom);
+
+ if( height < 0.0 )
+ {
+ view->state.flip_y = -1.0;
+ }
+
+ gv_view_area_state_changed(view);
+}
+
+void
+gv_view_area_fit_extents_3D(GvViewArea *view,
+ gvgeocoord llx, gvgeocoord lly, gvgeocoord minz,
+ gvgeocoord width, gvgeocoord height, gvgeocoord delta_z )
+
+{
+ vec3_t new_eye_pos, new_eye_dir;
+ double eye_az, eye_el, linear_measure;
+
+ /* Make sure the view area is realized so the state.shape has been
+ set (a configure event has been recieved) */
+ if (!GTK_WIDGET_REALIZED(GTK_WIDGET(view))) return;
+
+ if (width == 0.0 || height == 0.0) return;
+
+ linear_measure = MAX(MAX(width,height),delta_z);
+
+ new_eye_pos[0] = llx + width * 0.5;
+ new_eye_pos[1] = lly - linear_measure * 0.5;
+ new_eye_pos[2] = minz + linear_measure * 0.5;
+
+ eye_az = 90.0; /* rotation ? */
+ eye_el = -45.0; /* tilt 0 --> extreem -90 --> none*/
+ vec_point(new_eye_dir, eye_az, eye_el);
+
+ gv_view_area_set_3d_view( view, new_eye_pos, new_eye_dir );
+}
+
+void
+gv_view_area_get_extents(GvViewArea *view,
+ gvgeocoord *xmin, gvgeocoord *ymin,
+ gvgeocoord *xmax, gvgeocoord *ymax )
+
+{
+ gvgeocoord x[4], y[4];
+
+ gv_view_area_map_pointer( view, 0, 0,
+ x+0, y+0 );
+ gv_view_area_map_pointer( view, 0, view->state.shape_y,
+ x+1, y+1 );
+ gv_view_area_map_pointer( view, view->state.shape_x, 0,
+ x+2, y+2 );
+ gv_view_area_map_pointer( view, view->state.shape_x, view->state.shape_y,
+ x+3, y+3 );
+
+ *xmin = MIN(MIN(x[0],x[1]),MIN(x[2],x[3]));
+ *ymin = MIN(MIN(y[0],y[1]),MIN(y[2],y[3]));
+ *xmax = MAX(MAX(x[0],x[1]),MAX(x[2],x[3]));
+ *ymax = MAX(MAX(y[0],y[1]),MAX(y[2],y[3]));
+}
+
+void
+gv_view_area_get_volume( GvViewArea *view, double *volume )
+
+{
+ GvRect rect;
+ int first = TRUE;
+ GList *list;
+
+ if( view->volume_current )
+ {
+ if( volume != NULL )
+ memcpy( volume, view->view_volume, sizeof(double) * 6 );
+ return;
+ }
+
+ view->view_volume[0] = 0.0;
+ view->view_volume[1] = 1000.0;
+ view->view_volume[2] = 0.0;
+ view->view_volume[3] = 1000.0;
+ view->view_volume[4] = 0.0;
+ view->view_volume[5] = 1000.0;
+ view->linear_measure = 1000.0;
+
+ /* Make sure the view area is realized so the state.shape has been
+ set (a configure event has been recieved) */
+ if (!GTK_WIDGET_REALIZED(GTK_WIDGET(view))) return;
+
+ /*
+ * Get the layers extents.
+ */
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ GvRect layer_rect;
+
+ gv_layer_extents(layer, &layer_rect);
+
+ if( layer_rect.width == 0 && layer_rect.height == 0 )
+ {
+ /* do nothing */;
+ }
+
+ else if( first )
+ {
+ rect = layer_rect;
+ first = FALSE;
+ }
+ else
+ {
+ gvgeocoord new_x, new_y;
+ new_x = MIN(rect.x,layer_rect.x);
+ rect.width = MAX(rect.x+rect.width,
+ layer_rect.x+layer_rect.width) - new_x;
+ new_y = MIN(rect.y,layer_rect.y);
+ rect.height = MAX(rect.y+rect.height,
+ layer_rect.y+layer_rect.height) - new_y;
+ rect.x = new_x;
+ rect.y = new_y;
+ }
+
+ list = g_list_next(list);
+ }
+
+ if( !first )
+ {
+ view->view_volume[0] = rect.x;
+ view->view_volume[1] = rect.x + rect.width;
+ view->view_volume[2] = rect.y;
+ view->view_volume[3] = rect.y + rect.height;
+ view->view_volume[4] = 0.0;
+ view->view_volume[5] = (rect.width + rect.height) * 0.5;
+ view->volume_current = TRUE;
+
+ view->linear_measure = MAX(rect.width,rect.height);
+ }
+
+ if( volume != NULL )
+ memcpy( volume, view->view_volume, sizeof(double) * 6 );
+
+#ifdef notdef
+ printf( "gv_view_area_get_volume(): %g, %g, %g, %g, %g, %g\n",
+ view->view_volume[0],
+ view->view_volume[1],
+ view->view_volume[2],
+ view->view_volume[3],
+ view->view_volume[4],
+ view->view_volume[5] );
+#endif
+}
+
+static void
+gv_view_area_motion_handle_hint(GtkWidget *view, GdkEventMotion *event)
+{
+ /* If this is a hint place the event mouse position */
+ /* with the real value (round trip query) */
+
+ if (event->is_hint)
+ {
+ int x, y;
+ gtk_widget_get_pointer(view, &x, &y);
+ event->x = (gdouble)x;
+ event->y = (gdouble)y;
+ }
+}
+
+void
+motion(GvViewArea *view, gvgeocoord move, gvgeocoord strafe, gvgeocoord vert)
+{
+ vec3_t delta;
+ vec3_t new_eye_pos, new_eye_dir;
+
+ /* scaling factor for all motion, always > 0 */
+ gvgeocoord scaling_factor = MOVE_SPEED * view->state.eye_pos[2] + (0.0001 * view->linear_measure);
+
+ vec_copy( view->state.eye_dir, new_eye_dir);
+ vec_copy( view->state.eye_pos, new_eye_pos);
+
+ if (move != 0.0)
+ {
+ vec_copy(new_eye_dir, delta);
+ /* Scale movement based on height above z plane, previously scaled
+ by view->linear_measure */
+ vec_scale(delta, move * scaling_factor, delta);
+ vec_add(new_eye_pos, delta, new_eye_pos);
+ }
+
+ if (strafe != 0.0)
+ {
+ gvgeocoord norm = sqrt(new_eye_dir[0]*new_eye_dir[0]
+ + new_eye_dir[1]*new_eye_dir[1]);
+ if (norm > 0.0)
+ {
+ delta[0] = new_eye_dir[1] / norm;
+ delta[1] = -new_eye_dir[0] / norm;
+ delta[2] = 0.0;
+ vec_scale(delta, strafe * scaling_factor ,delta);
+ vec_add(new_eye_pos, delta, new_eye_pos);
+ }
+ }
+
+ if (vert != 0.0)
+ {
+ vec3_t perp;
+ gvgeocoord perp_norm;
+ gvgeocoord norm = sqrt(new_eye_dir[0]*new_eye_dir[0]
+ + new_eye_dir[1]*new_eye_dir[1]
+ + new_eye_dir[2]*new_eye_dir[2]);
+
+ /* Get a vector perpendicular to eye_dir */
+ perp[0] = - new_eye_dir[0];
+ perp[1] = - new_eye_dir[1];
+ perp[2] = (norm/ new_eye_dir[2]) - new_eye_dir[2];
+
+ perp_norm = 1 / sqrt(perp[0]*perp[0]
+ + perp[1]*perp[1]
+ + perp[2]*perp[2]);
+
+ vec_scale(perp, perp_norm * vert * scaling_factor, perp);
+ vec_add(new_eye_pos, perp, new_eye_pos);
+ }
+
+ gv_view_area_set_3d_view( view, new_eye_pos, new_eye_dir );
+}
+
+static gint
+gv_view_area_motion_notify(GtkWidget *widget, GdkEventMotion *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+
+ if (event->state & GDK_BUTTON1_MASK && view->dragging_mode)
+ {
+ gv_view_area_queue_draw( view );
+ }
+
+ else if( view->last_button != 0
+ && (ABS(view->last_mpos_x - event->x) > DRAG_THRESHOLD
+ || ABS(view->last_mpos_y - event->y) > DRAG_THRESHOLD )
+ && (g_get_current_time_as_double() - view->last_zoom_time) > 0.0
+ && !view->flag_3d)
+ {
+ view->dragging_mode = TRUE;
+ view->last_button = 0;
+
+ gv_view_area_queue_draw(view);
+ return FALSE;
+ }
+
+ /* zoom */
+ else if (event->state & GDK_BUTTON2_MASK
+ && event->state & GDK_SHIFT_MASK )
+ {
+ gvgeocoord ax, ay, bx, by, dz;
+
+ /* Translate origin to the center of the view */
+ ax = view->state.mpos_x - view->state.shape_x / 2.0;
+ ay = view->state.shape_y / 2.0 - view->state.mpos_y;
+ bx = event->x - view->state.shape_x / 2.0;
+ by = view->state.shape_y / 2.0 - event->y;
+
+ /* Put an insensitive area about the origin */
+ if (!(fabs(bx) < DEAD_ZONE && fabs(by) < DEAD_ZONE) &&
+ !(fabs(ax) < DEAD_ZONE && fabs(ay) < DEAD_ZONE))
+ {
+ /* The "delta" zoom (multiplicative) is the projection of
+ b (new pos) on a (old pos) divided by the length of a.
+ That is: (a.b)/|a|^2 */
+ if (ax*ax+ay*ay != 0.0)
+ {
+ dz = (ax*bx+ay*by) / (ax*ax+ay*ay);
+
+ /* Sanity check on dz */
+ dz = MAX(dz, 1.0e-2);
+ dz = MIN(dz, 1.0e2);
+
+ /* gv_view_area_zoom() expects a log (base 2)
+ zoom factor */
+ gv_view_area_zoom(view, LOG2(dz));
+ }
+ }
+ }
+ /* rotate */
+ else if (event->state & GDK_SHIFT_MASK
+ && event->state & GDK_BUTTON1_MASK )
+
+ {
+ gvgeocoord ax, ay, bx, by, dr;
+
+ /* Translate origin to the center of the view */
+ ax = view->state.mpos_x - view->state.shape_x / 2.0;
+ ay = view->state.shape_y / 2.0 - view->state.mpos_y;
+ bx = event->x - view->state.shape_x / 2.0;
+ by = view->state.shape_y / 2.0 - event->y;
+
+ /* Put an insensitive area about the origin */
+ if (!(fabs(bx) < DEAD_ZONE && fabs(by) < DEAD_ZONE))
+ {
+ /* The "delta" rotation is found by taking arc sin of the
+ the normalized length of the cross product of b (new pos)
+ and a (old pos). That is: arcsin(|axb|/(|a||b|)) */
+ dr = asin((ax*by-ay*bx) /
+ (sqrt(ax*ax+ay*ay) * sqrt(bx*bx+by*by)));
+
+ /* gv_view_area_rotate() expects an angle in degrees */
+ gv_view_area_rotate(view, dr / DEG2RAD);
+ }
+ }
+
+ /* translate */
+ else if (event->state & GDK_CONTROL_MASK
+ && event->state & GDK_BUTTON2_MASK )
+ {
+ gv_view_area_translate(view, event->x - view->state.mpos_x,
+ view->state.mpos_y - event->y);
+ }
+
+ /* Auto-scroll as we drag outside of window */
+ if (event->state & GDK_BUTTON1_MASK)
+ {
+ if (event->x < 0.0 || event->x > view->state.shape_x ||
+ event->y < 0.0 || event->y > view->state.shape_y)
+ {
+ /* Scroll to mouse pos */
+ gvgeocoord dx = 0, dy = 0;
+ if (event->x < 0.0)
+ dx = -event->x;
+ if (event->x > view->state.shape_x)
+ dx = view->state.shape_x - event->x;
+ if (event->y < 0.0)
+ dy = event->y;
+ if (event->y > view->state.shape_y)
+ dy = event->y - view->state.shape_y;
+ gv_view_area_translate(view, dx, dy);
+
+ /* Need to put this event back on the queue
+ so it keeps scrolling -- see gtktext.c for example */
+ }
+ }
+
+ /* Change 3D view direction */
+ if (view->flag_3d
+ && !(event->state & GDK_CONTROL_MASK)
+ && ((event->state & GDK_BUTTON1_MASK)
+ || (event->state & GDK_BUTTON2_MASK)
+ || (event->state & GDK_BUTTON3_MASK)))
+ {
+ gvgeocoord eye_az, eye_el;
+ int return_value;
+
+ return_value = inv_vec_point(view->state.eye_dir, &eye_az, &eye_el);
+
+ eye_az += (event->x - view->state.mpos_x) * AZ_SCALE;
+ eye_el += (event->y - view->state.mpos_y) * EL_SCALE;
+
+ if (eye_el < -89.9) eye_el = -89.9;
+ if (eye_el > 45.1) eye_el = 45.1;
+
+ vec_point(view->state.eye_dir, eye_az, eye_el);
+
+ gv_view_area_state_changed(view);
+
+ /* For case when trying to zoom and pan - force zoom update */
+ gv_view_area_zoompan_handler((gpointer)view);
+ }
+
+ /* Change 3D position (translate on when CTRL) */
+ if (view->flag_3d
+ && (event->state & GDK_CONTROL_MASK)
+ && ((event->state & GDK_BUTTON1_MASK) ||
+ (event->state & GDK_BUTTON2_MASK) ||
+ (event->state & GDK_BUTTON3_MASK)))
+ {
+ motion(view, 0.0, -(event->x - view->state.mpos_x) * 0.10, -(event->y - view->state.mpos_y)* 0.10);
+ }
+ view->state.mpos_x = event->x;
+ view->state.mpos_y = event->y;
+
+ return 0;
+}
+
+
+static gint
+gv_view_area_zoompan_handler(gpointer data )
+
+{
+ GvViewArea *view = (GvViewArea *) data;
+ double time_elapsed, cur_time;
+ gvgeocoord zoom = 0.0;
+
+ if( view->last_button == 0 )
+ return( FALSE );
+
+ cur_time = g_get_current_time_as_double();
+ time_elapsed = cur_time - view->last_zoom_time;
+ view->last_zoom_time = MAX(cur_time,view->last_zoom_time);
+ if( time_elapsed < 0 )
+ {
+ time_elapsed = 0;
+ }
+ else if( time_elapsed > 1.0 )
+ time_elapsed = 1.0;
+ else if( !view->flag_3d
+ && (ABS(view->last_mpos_x - view->state.mpos_x) > DRAG_THRESHOLD
+ || ABS(view->last_mpos_y - view->state.mpos_y) > DRAG_THRESHOLD ))
+ {
+ view->dragging_mode = TRUE;
+ view->last_button = 0;
+
+ gv_view_area_queue_draw(view);
+ return FALSE;
+ }
+
+ if( view->last_button == 1 )
+ zoom = CONTIN_ZOOM_INC * time_elapsed;
+ else if( view->last_button == 3 )
+ zoom = -(CONTIN_ZOOM_INC * time_elapsed);
+
+ if( zoom != 0.0 )
+ {
+ gv_view_area_translate(view,
+ view->state.shape_x/2 - view->state.mpos_x,
+ view->state.mpos_y - view->state.shape_y/2 );
+ gv_view_area_zoom(view, zoom );
+ gv_view_area_translate(view,
+ view->state.mpos_x - view->state.shape_x/2,
+ view->state.shape_y/2 - view->state.mpos_y );
+ }
+
+ return TRUE;
+}
+
+static gint
+gv_view_area_3d_motion_handler(gpointer data )
+
+{
+ GvViewArea *view = (GvViewArea *) data;
+ double time_elapsed, cur_time;
+ gvgeocoord move = 0.0;
+
+ if( view->last_button == 0 )
+ return( FALSE );
+
+ cur_time = g_get_current_time_as_double();
+ time_elapsed = cur_time - view->last_zoom_time;
+ view->last_zoom_time = MAX(cur_time,view->last_zoom_time);
+ if( time_elapsed < 0 )
+ {
+ time_elapsed = 0;
+ }
+ else if( time_elapsed > 1.0 )
+ {
+ time_elapsed = 1.0;
+ }
+
+ if( view->last_button == 1 )
+ move = CONTIN_3DMOVE_INC * time_elapsed;
+ else if( view->last_button == 3 )
+ move = -(CONTIN_3DMOVE_INC * time_elapsed);
+
+ /* Move Forward or backwards */
+ if( move != 0.0 )
+ motion(view, move, 0.0, 0.0);
+
+ return TRUE;
+}
+
+void
+gv_view_area_zoompan_event(GvViewArea *view, GdkEventButton *event)
+
+{
+ /* note: we want this function to work properly for "zoom mode"
+ with no control, and the modeless "cntl-button" method. */
+
+ if( event->type == GDK_2BUTTON_PRESS )
+ {
+ view->dragging_mode = FALSE;
+ gv_view_area_translate(view,
+ view->state.shape_x/2 - event->x,
+ event->y - view->state.shape_y/2 );
+
+ view->last_button = 0;
+
+ if( event->button == 1 )
+ gv_view_area_zoom( view, ZOOM_STEP );
+ else if( event->button == 3 )
+ gv_view_area_zoom( view, -ZOOM_STEP );
+
+ }
+ else if( event->type == GDK_BUTTON_PRESS
+ && (event->button == 1 || event->button == 3) )
+ {
+ view->last_button = event->button;
+ view->last_button_time = g_get_current_time_as_double();
+ view->last_zoom_time = view->last_button_time + 0.25;
+ view->last_mpos_x = view->state.mpos_x;
+ view->last_mpos_y = view->state.mpos_y;
+
+ gv_manager_queue_task( gv_get_manager(), "zoompan-handler", 2,
+ gv_view_area_zoompan_handler, view );
+ }
+ else if( event->type == GDK_BUTTON_PRESS
+ || event->type == GDK_BUTTON_RELEASE )
+ {
+ view->last_button = 0;
+ }
+}
+
+void
+gv_view_area_3d_move_event(GvViewArea *view, GdkEventButton *event)
+
+{
+ /* note: we want this function to work properly for "zoom mode"
+ with no control, and the modeless "cntl-button" method. */
+
+ /* Double Click */
+ if( event->type == GDK_2BUTTON_PRESS )
+ {
+ view->last_button = 0;
+
+ if( event->button == 1 )
+ motion(view, 10.0, 0.0, 0.0);
+ else if( event->button == 3 )
+ motion(view, -10.0, 0.0, 0.0);
+
+ }
+ /* Click and hold */
+ else if( event->type == GDK_BUTTON_PRESS
+ && (event->button == 1 || event->button == 3) )
+ {
+ view->last_button = event->button;
+ view->last_button_time = g_get_current_time_as_double();
+ view->last_zoom_time = view->last_button_time + 0.25;
+ view->last_mpos_x = view->state.mpos_x;
+ view->last_mpos_y = view->state.mpos_y;
+
+ gv_manager_queue_task( gv_get_manager(), "3d-motion-handler", 2,
+ gv_view_area_3d_motion_handler, view );
+ }
+ /* Click and release */
+ else if( event->type == GDK_BUTTON_PRESS
+ || event->type == GDK_BUTTON_RELEASE )
+ {
+ view->last_button = 0;
+ }
+}
+
+static gint
+gv_view_area_button_press(GtkWidget *widget, GdkEventButton *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+
+ if (event->button == 4)
+ {
+ gv_view_area_zoom(view, -WHEEL_ZOOM_INC);
+ }
+ else if (event->button == 5)
+ {
+ gv_view_area_zoom(view, WHEEL_ZOOM_INC);
+ }
+
+ /* new zoom logic stuff */
+ if( (event->button == 1 || event->button == 3)
+ && (event->state & GDK_CONTROL_MASK) )
+ {
+ if ( view->flag_3d )
+ {
+ gv_view_area_3d_move_event( view, event);
+ } else {
+ gv_view_area_zoompan_event( view, event );
+ }
+ }
+ else if (view->flag_3d && (event->button == 1 || event->button == 2 || event->button == 3))
+ {
+ gv_view_area_3d_move_event( view, event);
+ }
+ else if( event->state & GDK_CONTROL_MASK )
+ {
+ if ( view->flag_3d )
+ {
+ /* Nothing? */
+ } else {
+ gv_view_area_zoompan_event( view, event );
+ }
+ }
+
+
+ view->state.mpos_x = event->x;
+ view->state.mpos_y = event->y;
+
+ return 0;
+}
+
+static gint
+gv_view_area_button_release(GtkWidget *widget, GdkEventButton *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+
+ view->state.mpos_x = event->x;
+ view->state.mpos_y = event->y;
+
+ if( view->dragging_mode )
+ {
+ gvgeocoord x[4], y[4], min_x, max_x, min_y, max_y;
+
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->state.mpos_y,
+ x+0, y+0 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->state.mpos_y,
+ x+1, y+1 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->last_mpos_y,
+ x+2, y+2 );
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->last_mpos_y,
+ x+3, y+3 );
+
+ min_x = MIN(MIN(x[0],x[1]),MIN(x[2],x[3]));
+ min_y = MIN(MIN(y[0],y[1]),MIN(y[2],y[3]));
+ max_x = MAX(MAX(x[0],x[1]),MAX(x[2],x[3]));
+ max_y = MAX(MAX(y[0],y[1]),MAX(y[2],y[3]));
+
+ gv_view_area_fit_extents( view, min_x, min_y,
+ max_x - min_x, max_y - min_y );
+
+ view->dragging_mode = FALSE;
+ }
+
+ /* new zoom logic stuff */
+ if( (event->button == 1 || event->button == 3) )
+ {
+ if ( view->flag_3d )
+ {
+ gv_view_area_3d_move_event(view, event);
+ } else {
+ gv_view_area_zoompan_event( view, event );
+ }
+ }
+
+ return 0;
+}
+
+static gint
+gv_view_area_key_press(GtkWidget *widget, GdkEventKey *event)
+{
+ GvViewArea *view = GV_VIEW_AREA(widget);
+
+ gvgeocoord move = 0.0;
+ gvgeocoord strafe = 0.0;
+ gvgeocoord vert = 0.0;
+
+ int big_step_x, big_step_y;
+
+ big_step_x = (int) (view->state.shape_x / 1.3);
+ big_step_y = (int) (view->state.shape_x / 1.3);
+
+ switch (event->keyval)
+ {
+ case GDK_z:
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ gv_undo_pop();
+ }
+ break;
+
+ case GDK_Escape:
+ if( view->dragging_mode )
+ {
+ view->dragging_mode = FALSE;
+ gv_view_area_queue_draw( view );
+ }
+ break;
+
+ case '-':
+ if (view->flag_3d)
+ {
+ view->state.z_scale -= HEIGHT_SCALE*0.1;
+ gv_view_area_state_changed(view);
+ }
+ break;
+
+ case '_':
+ if (view->flag_3d)
+ {
+ view->state.z_scale -= HEIGHT_SCALE;
+ gv_view_area_state_changed(view);
+ }
+ break;
+
+ case '=':
+ if (view->flag_3d)
+ {
+ view->state.z_scale += HEIGHT_SCALE*0.1;
+ gv_view_area_state_changed(view);
+ }
+ break;
+
+ case '+':
+ if (view->flag_3d)
+ {
+ view->state.z_scale += HEIGHT_SCALE;
+ gv_view_area_state_changed(view);
+ }
+ break;
+
+ case GDK_F1:
+ if( event->state & GDK_CONTROL_MASK )
+ {
+ view->state.flip_x *= -1;
+ gv_view_area_state_changed(view);
+ }
+ break;
+
+ case GDK_F2:
+ /* Flip along y */
+ if( event->state & GDK_CONTROL_MASK )
+ {
+ view->state.flip_y *= -1;
+ gv_view_area_state_changed(view);
+
+ } else {
+
+ /* Switch between 2D and 3D Modes on-the-fly */
+ if ( view->flag_3d )
+ {
+ gv_view_area_set_mode(view, 0);
+ gv_view_area_state_changed(view);
+ } else {
+ gv_view_area_set_mode(view, 1);
+ gv_view_area_state_changed(view);
+ }
+ }
+ break;
+
+ case GDK_Page_Up:
+ if (view->flag_3d)
+ {
+ move = 0.1;
+ if (event->state & GDK_SHIFT_MASK)
+ move = 1.0; /* Use bigger inc. if shifted */
+
+ motion(view, move, strafe, vert);
+ } else {
+ gv_view_area_zoom( view, ZOOM_STEP );
+ }
+ break;
+
+ case GDK_Page_Down:
+ if (view->flag_3d)
+ {
+ move = -0.1;
+ if (event->state & GDK_SHIFT_MASK)
+ move = -1.0; /* Use bigger inc. if shifted */
+
+ motion(view, move, strafe, vert);
+ } else {
+ gv_view_area_zoom( view, -ZOOM_STEP );
+ }
+ break;
+
+ case GDK_Right:
+ if (view->flag_3d)
+ {
+ strafe = 1.0;
+ motion(view, move, strafe, vert);
+ } else {
+
+ if (event->state & GDK_CONTROL_MASK)
+ gv_view_area_translate( view, -big_step_x, 0 );
+ else if (event->state & GDK_SHIFT_MASK)
+ gv_view_area_translate( view, -big_step_x/2, 0 );
+ else
+ gv_view_area_translate( view, -10, 0 );
+ }
+ return TRUE; /* Don't let focus change */
+ break;
+
+ case GDK_Left:
+ if (view->flag_3d)
+ {
+ strafe = -1.0;
+ motion(view, move, strafe, vert);
+ } else {
+ if (event->state & GDK_CONTROL_MASK)
+ gv_view_area_translate( view, big_step_x, 0 );
+ else if (event->state & GDK_SHIFT_MASK)
+ gv_view_area_translate( view, big_step_x/2, 0 );
+ else
+ gv_view_area_translate( view, 10, 0 );
+ }
+ return TRUE; /* Don't let focus change */
+ break;
+
+ case GDK_Up:
+ if (view->flag_3d)
+ {
+ vert = 1.0;
+ motion(view, move, strafe, vert);
+ } else {
+ if (event->state & GDK_CONTROL_MASK)
+ gv_view_area_translate( view, 0, -big_step_y );
+ else if (event->state & GDK_SHIFT_MASK)
+ gv_view_area_translate( view, 0, -big_step_y/2 );
+ else
+ gv_view_area_translate( view, 0, -10 );
+ }
+ return TRUE; /* Don't let focus change */
+ break;
+
+ case GDK_Down:
+ if (view->flag_3d)
+ {
+ vert = -1.0;
+ motion(view, move, strafe, vert);
+ } else {
+ if (event->state & GDK_CONTROL_MASK)
+ gv_view_area_translate( view, 0, big_step_y );
+ else if (event->state & GDK_SHIFT_MASK)
+ gv_view_area_translate( view, 0, big_step_y/2 );
+ else
+ gv_view_area_translate( view, 0, 10 );
+ }
+ return TRUE; /* Don't let focus change */
+ break;
+
+ case GDK_Home:
+ gv_view_area_fit_all_layers( view );
+ break;
+ }
+ /* FIXME: add flipping controls, etc. */
+
+ return 0;
+}
+
+static void
+gv_view_area_change_notify(GvViewArea *view, gpointer info)
+{
+ gv_view_area_queue_draw(view);
+}
+
+static void
+gv_view_area_state_changed(GvViewArea *view)
+{
+ gtk_signal_emit(GTK_OBJECT(view), view_area_signals[VIEW_STATE_CHANGED]);
+ gv_view_area_queue_draw(view);
+ gv_view_area_update_adjustments( view );
+}
+
+static void
+gv_view_area_destroy(GtkObject *object)
+{
+ GtkGLAreaClass *parent_class;
+ GvViewArea *view;
+
+ view = GV_VIEW_AREA(object);
+
+ CPLDebug( "OpenEV", "gv_view_area_destroy" );
+
+ /* Remove all layers */
+ view->active_layer = NULL;
+ while (view->layers != NULL)
+ {
+ GvLayer *layer = (GvLayer*)view->layers->data;
+ gv_view_area_remove_layer(view, GTK_OBJECT(layer));
+ }
+
+ gv_view_area_set_adjustments( view, NULL, NULL );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gtk_gl_area_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(object);
+}
+
+static void
+gv_view_area_finalize(GtkObject *object)
+{
+ GvLayerClass *parent_class;
+
+ CPLDebug( "OpenEV", "gv_view_area_finalize" );
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gtk_gl_area_get_type());
+ GTK_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+static void
+gv_view_area_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GvViewArea *view;
+
+ view = GV_VIEW_AREA (object);
+
+ switch (arg_id)
+ {
+ case ARG_HADJUSTMENT:
+ gv_view_area_set_adjustments (view,
+ GTK_VALUE_POINTER (*arg),
+ view->vadj);
+ break;
+ case ARG_VADJUSTMENT:
+ gv_view_area_set_adjustments (view,
+ view->hadj,
+ GTK_VALUE_POINTER (*arg));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gv_view_area_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GvViewArea *view;
+
+ view = GV_VIEW_AREA (object);
+
+ switch (arg_id)
+ {
+ case ARG_HADJUSTMENT:
+ GTK_VALUE_POINTER (*arg) = view->hadj;
+ break;
+ case ARG_VADJUSTMENT:
+ GTK_VALUE_POINTER (*arg) = view->vadj;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gv_view_area_update_adjustments( GvViewArea *view )
+
+{
+ GvRect world_extents;
+ GvRect view_extents;
+
+ if( !GTK_WIDGET_REALIZED(GTK_WIDGET(view)) )
+ return;
+
+ if( view->hadj == NULL && view->vadj == NULL )
+ return;
+
+ if( view->lock_adjustments )
+ return;
+
+ gv_view_area_get_world_extents( view, &world_extents );
+ if( world_extents.width == 0 || world_extents.height == 0 )
+ return;
+
+ if( world_extents.height < 0.0 )
+ {
+ world_extents.y += world_extents.height;
+ world_extents.height *= -1;
+ }
+
+ gv_view_area_get_extents( view, &view_extents.x, &view_extents.y,
+ &view_extents.width, &view_extents.height);
+ view_extents.width = ABS(view_extents.x-view_extents.width);
+ view_extents.height = ABS(view_extents.y-view_extents.height);
+
+ view->lock_adjustments = TRUE;
+
+ if( view->hadj != NULL )
+ {
+ if( view->state.flip_x < 0 )
+ {
+ view->hadj->upper = -world_extents.x;
+ view->hadj->lower = -(world_extents.x + world_extents.width);
+ view->hadj->value = -(view_extents.x+view_extents.width);
+ view->hadj->page_size = ABS(view_extents.width);
+ }
+ else
+ {
+ view->hadj->lower = world_extents.x;
+ view->hadj->upper = world_extents.x + world_extents.width;
+ view->hadj->value = view_extents.x;
+ view->hadj->page_size = view_extents.width;
+ }
+
+ if( view->hadj->page_size > view->hadj->upper - view->hadj->lower )
+ view->hadj->page_size = view->hadj->upper - view->hadj->lower;
+ if( view->hadj->value < view->hadj->lower )
+ view->hadj->value = view->hadj->lower;
+ if( view->hadj->value+view->hadj->page_size > view->hadj->upper )
+ view->hadj->value = view->hadj->upper - view->hadj->page_size;
+
+ view->hadj->page_increment = view->hadj->page_size;
+ view->hadj->step_increment = view->hadj->page_increment / 4;
+
+ gtk_adjustment_changed( view->hadj );
+ }
+
+ if( view->vadj != NULL )
+ {
+ if( view->state.flip_y > 0 )
+ {
+ view->vadj->upper = -world_extents.y;
+ view->vadj->lower = -(world_extents.y + world_extents.height);
+ view->vadj->value = -(view_extents.y+view_extents.height);
+ view->vadj->page_size = ABS(view_extents.height);
+ }
+ else
+ {
+ view->vadj->lower = world_extents.y;
+ view->vadj->upper = world_extents.y + world_extents.height;
+ view->vadj->value = view_extents.y;
+ view->vadj->page_size = view_extents.height;
+ }
+
+ if( view->vadj->page_size > view->vadj->upper - view->vadj->lower )
+ view->vadj->page_size = view->vadj->upper - view->vadj->lower;
+ if( view->vadj->value < view->vadj->lower )
+ view->vadj->value = view->vadj->lower;
+ if( view->vadj->value+view->vadj->page_size > view->vadj->upper )
+ view->vadj->value = view->vadj->upper - view->vadj->page_size;
+
+ view->vadj->page_increment = view->vadj->page_size;
+ view->vadj->step_increment = view->vadj->page_increment / 4;
+
+ gtk_adjustment_changed( view->vadj );
+ }
+
+ view->lock_adjustments = FALSE;
+}
+
+static void
+gv_view_area_adjustment (GtkAdjustment *adjustment,
+ GvViewArea *view)
+{
+ gvgeocoord xmin, ymin, width, height;
+ static int local_lock = FALSE;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (GV_IS_VIEW_AREA (view));
+
+ if( !GTK_WIDGET_REALIZED(GTK_WIDGET(view)) )
+ return;
+
+ if( view->lock_adjustments || local_lock )
+ return;
+
+ if( view->vadj == NULL || view->hadj == NULL )
+ return;
+
+ xmin = view->hadj->value * view->state.flip_x;
+ width = view->hadj->page_size * view->state.flip_x;
+
+ if( view->state.flip_y > 0 )
+ {
+ ymin = (-1 * view->vadj->value) - view->vadj->page_size;
+ height = view->vadj->page_size;
+ }
+ else
+ {
+ ymin = view->vadj->value;
+ height = view->vadj->page_size;
+ }
+
+ view->lock_adjustments = TRUE;
+ gv_view_area_fit_extents( view, xmin, ymin, width, height );
+ view->lock_adjustments = FALSE;
+
+ local_lock = TRUE;
+ gv_view_area_update_adjustments( view );
+ local_lock = FALSE;
+}
+
+static void
+gv_view_area_disconnect (GtkAdjustment *adjustment,
+ GvViewArea *view)
+{
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (GV_IS_VIEW_AREA (view));
+
+ if (adjustment == view->hadj)
+ gv_view_area_set_adjustments (view, NULL, view->vadj);
+ if (adjustment == view->vadj)
+ gv_view_area_set_adjustments (view, view->hadj, NULL);
+}
+
+void
+gv_view_area_set_adjustments (GvViewArea *view,
+ GtkAdjustment *hadj,
+ GtkAdjustment *vadj)
+{
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (GV_VIEW_AREA (view));
+
+ if (hadj)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+
+ if (vadj)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+
+ if (view->hadj && (view->hadj != hadj))
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (view->hadj), view);
+ gtk_object_unref (GTK_OBJECT (view->hadj));
+ }
+
+ if (view->vadj && (view->vadj != vadj))
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (view->vadj), view);
+ gtk_object_unref (GTK_OBJECT (view->vadj));
+ }
+
+ if( hadj == NULL )
+ view->hadj = NULL;
+ else if (view->hadj != hadj)
+ {
+ view->hadj = hadj;
+ gtk_object_ref (GTK_OBJECT (view->hadj));
+ gtk_object_sink (GTK_OBJECT (view->hadj));
+
+ gtk_signal_connect (GTK_OBJECT (view->hadj), "changed",
+ (GtkSignalFunc) gv_view_area_adjustment,
+ view);
+ gtk_signal_connect (GTK_OBJECT (view->hadj), "value_changed",
+ (GtkSignalFunc) gv_view_area_adjustment,
+ view);
+ gtk_signal_connect (GTK_OBJECT (view->hadj), "disconnect",
+ (GtkSignalFunc) gv_view_area_disconnect,
+ view);
+
+ gv_view_area_adjustment (hadj, view);
+ }
+
+ if( vadj == NULL )
+ view->vadj = NULL;
+ else if (view->vadj != vadj)
+ {
+ view->vadj = vadj;
+ gtk_object_ref (GTK_OBJECT (view->vadj));
+ gtk_object_sink (GTK_OBJECT (view->vadj));
+
+ gtk_signal_connect (GTK_OBJECT (view->vadj), "changed",
+ (GtkSignalFunc) gv_view_area_adjustment,
+ view);
+ gtk_signal_connect (GTK_OBJECT (view->vadj), "value_changed",
+ (GtkSignalFunc) gv_view_area_adjustment,
+ view);
+ gtk_signal_connect (GTK_OBJECT (view->vadj), "disconnect",
+ (GtkSignalFunc) gv_view_area_disconnect,
+ view);
+ gv_view_area_adjustment (vadj, view);
+ }
+
+ gv_view_area_update_adjustments( view );
+}
+
+/************************************************************************/
+/* gv_view_area_set_raw() */
+/* */
+/* Try to reset whether this layer is in georeferenced or raw */
+/* mode relative to the indicated raster layer. */
+/************************************************************************/
+
+int gv_view_area_set_raw( GvViewArea *view, GtkObject *ref_layer,
+ int raw_enable )
+
+{
+ GvRasterLayer *rlayer = NULL;
+ gvgeocoord xmin, ymin, xmax, ymax;
+ double pl_xmin, pl_ymin, pl_xmax, pl_ymax;
+
+ if( ref_layer != NULL && GV_IS_RASTER_LAYER(ref_layer) )
+ rlayer = GV_RASTER_LAYER(ref_layer);
+ else
+ rlayer = GV_RASTER_LAYER(gv_view_area_get_primary_raster(view));
+
+ if( !raw_enable == !gv_view_area_get_raw(view, ref_layer) )
+ return TRUE;
+
+ /* For now we need a raster layer. */
+ if( rlayer == NULL )
+ return FALSE;
+
+ /* Get the current view extents, and transform to raster PL coordinates.*/
+ gv_view_area_get_extents( view, &xmin, &ymin, &xmax, &ymax );
+
+ pl_xmin = xmin;
+ pl_ymin = ymin;
+ pl_xmax = xmax;
+ pl_ymax = ymax;
+
+ if( !gv_raster_layer_view_to_pixel( rlayer, &pl_xmin, &pl_ymin, NULL )
+ || !gv_raster_layer_view_to_pixel( rlayer, &pl_xmax, &pl_ymax, NULL ) )
+ return FALSE;
+
+ /* Now force the raster layer to change it's mesh coordinate system. */
+ if( !gv_raster_layer_set_raw( rlayer, raw_enable ) )
+ return FALSE;
+
+ /* Clear or set projection on view. */
+ if( raw_enable || gv_data_get_projection(GV_DATA(rlayer)) == NULL )
+ gv_view_area_set_projection( view, "PIXEL" );
+ else
+ gv_view_area_set_projection( view,
+ gv_data_get_projection(GV_DATA(rlayer)) );
+
+ /* Reset the view */
+ if( !gv_raster_layer_pixel_to_view( rlayer, &pl_xmin, &pl_ymin, NULL )
+ || !gv_raster_layer_pixel_to_view( rlayer, &pl_xmax, &pl_ymax, NULL ) )
+ return FALSE;
+
+ /*
+ * A bunch of hacky stuff to ensure the correct orientation of the
+ * new extents even if this requires some flipping. We must always
+ * keep an upper-right origin in pixel/line space (raw) and a lower left
+ * origin in georeferenced space.
+ */
+ if( !raw_enable && pl_ymax < pl_ymin )
+ {
+ double temp;
+
+ temp = pl_ymax;
+ pl_ymax = pl_ymin;
+ pl_ymin = temp;
+ }
+ else if( raw_enable && pl_ymax > pl_ymin )
+ {
+ double temp;
+
+ temp = pl_ymax;
+ pl_ymax = pl_ymin;
+ pl_ymin = temp;
+ }
+ if( pl_xmax < pl_xmin )
+ {
+ double temp;
+
+ temp = pl_xmax;
+ pl_xmax = pl_xmin;
+ pl_xmin = temp;
+
+ }
+
+ if( !raw_enable )
+ view->state.flip_y = 1.0;
+
+ gv_view_area_fit_extents( view,
+ pl_xmin, pl_ymin,
+ pl_xmax - pl_xmin, pl_ymax - pl_ymin );
+
+ return TRUE;
+}
+
+/************************************************************************/
+/* gv_view_area_get_raw() */
+/* */
+/* Determine whether this view is in "raw" mode relative to the */
+/* given layer. TRUE is returned for raw mode. */
+/************************************************************************/
+
+int gv_view_area_get_raw( GvViewArea *view, GtkObject *ref_layer )
+
+{
+ GvRasterLayer *rlayer = NULL;
+
+ if( ref_layer != NULL && GV_IS_RASTER_LAYER(ref_layer) )
+ rlayer = GV_RASTER_LAYER(ref_layer);
+ else
+ rlayer = GV_RASTER_LAYER(gv_view_area_get_primary_raster(view));
+
+ if( rlayer )
+ return rlayer->mesh_is_raw;
+ else
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_view_area_redraw_timeout() */
+/* */
+/* Returns TRUE if "quite a while" has elapsed since the last */
+/* view redraw. This is used by the various layers to decide */
+/* if they should stop doing idle work. */
+/************************************************************************/
+
+int gv_view_area_redraw_timeout( GvViewArea *view )
+
+{
+ float max_work_time;
+
+ if( view->redraw_timer == NULL )
+ return TRUE;
+
+ max_work_time = MAX(0.25,MIN(2.0,view->last_draw_time*3));
+
+ if( g_timer_elapsed(view->redraw_timer,NULL) > max_work_time )
+ {
+ g_timer_destroy( view->redraw_timer );
+ view->redraw_timer = NULL;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_view_area_pending_idle_work() */
+/* */
+/* Returns TRUE if any of the layers displayed on this view */
+/* report they still have idle work pending, else it returns */
+/* FALSE. */
+/************************************************************************/
+
+int gv_view_area_pending_idle_work( GvViewArea *view )
+
+{
+ GList *list;
+
+
+ list = view->layers;
+ while (list)
+ {
+ GvLayer *layer = (GvLayer*)list->data;
+ if( layer->pending_idle )
+ return TRUE;
+ list = g_list_next(list);
+ }
+
+ return FALSE;
+}
+
+/************************************************************************/
+/* gv_get_render_counter() */
+/************************************************************************/
+
+int gv_get_render_counter()
+
+{
+ return render_counter;
+}
+
+/************************************************************************/
+/* gv_view_area_get_primary_raster() */
+/************************************************************************/
+
+GtkObject *gv_view_area_get_primary_raster( GvViewArea *view )
+
+{
+ GList *layer_list, *node;
+
+ layer_list = gv_view_area_list_layers( view );
+
+ for( node = layer_list; node != NULL; node = node->next )
+ {
+ GvLayer *layer;
+
+ layer = GV_LAYER(node->data);
+ if( gv_layer_is_visible(layer) && GV_IS_RASTER_LAYER( layer ) )
+ return GTK_OBJECT(layer);
+ }
+
+ return NULL;
+}
+
+const char *
+gv_view_area_get_property(GvViewArea *data, const char *name)
+{
+ return gv_properties_get( &(data->properties), name );
+}
+
+void
+gv_view_area_set_property(GvViewArea *data, const char *name, const char *value)
+{
+ gv_properties_set( &(data->properties), name, value );
+}
+
+GvProperties *
+gv_view_area_get_properties(GvViewArea *data)
+{
+ return &(data->properties);
+}
+
Added: packages/openev/branches/upstream/current/gvviewarea.h
===================================================================
--- packages/openev/branches/upstream/current/gvviewarea.h (rev 0)
+++ packages/openev/branches/upstream/current/gvviewarea.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,354 @@
+/******************************************************************************
+ * $Id: gvviewarea.h,v 1.60 2005/01/14 15:27:28 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: GTK/OpenGL View Canvas
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvviewarea.h,v $
+ * Revision 1.60 2005/01/14 15:27:28 warmerda
+ * added flip flag access
+ *
+ * Revision 1.59 2003/08/27 19:58:43 warmerda
+ * added force_simple flag for gv_view_area_bmfont_draw
+ *
+ * Revision 1.58 2003/03/07 22:18:25 warmerda
+ * const correctness fix for get_layer_by_name
+ *
+ * Revision 1.57 2003/02/20 19:27:18 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.56 2002/11/05 04:14:54 warmerda
+ * fixed prototype
+ *
+ * Revision 1.55 2002/11/05 04:14:11 warmerda
+ * added prototype
+ *
+ * Revision 1.54 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.53 2002/09/10 13:26:43 warmerda
+ * added get_height_scale method
+ *
+ * Revision 1.52 2002/07/16 14:17:06 warmerda
+ * added support for getting background color
+ *
+ * Revision 1.51 2002/07/08 19:44:39 warmerda
+ * added properties on GvViewArea
+ *
+ * Revision 1.50 2002/03/20 19:19:14 warmerda
+ * added exact_render flag
+ *
+ * Revision 1.49 2002/01/30 17:25:19 warmerda
+ * added set_state and get_primary_raster functions
+ *
+ * Revision 1.48 2001/12/13 03:29:17 warmerda
+ * avoid purging textures used in this render
+ *
+ * Revision 1.47 2001/10/12 17:44:18 warmerda
+ * avoid extra redraws when many raster layers displayed
+ *
+ * Revision 1.46 2001/10/12 01:58:19 warmerda
+ * avoid re-rendering if backing store OK
+ *
+ * Revision 1.45 2001/07/03 14:26:05 warmerda
+ * added set/get raw ability
+ *
+ * Revision 1.44 2001/04/09 18:20:14 warmerda
+ * added ability to query list of available fonts
+ *
+ * Revision 1.43 2001/03/26 19:18:35 warmerda
+ * restructure bmfont handling to preserve GdkFont handle
+ *
+ * Revision 1.42 2001/02/03 22:21:08 warmerda
+ * added gv_view_area_get_mode() and python covers
+ *
+ * Revision 1.41 2000/10/06 16:48:56 warmerda
+ * added GvViewArea background color
+ *
+ * Revision 1.40 2000/09/29 16:09:17 srawlin
+ * added Goto function requring fuction to map lat/long to view coordinates
+ *
+ * Revision 1.39 2000/09/27 19:16:33 warmerda
+ * *** empty log message ***
+ *
+ * Revision 1.38 2000/09/21 02:57:20 warmerda
+ * reorganized bitmap font support to allow any gdk supported font at runtime
+ *
+ * Revision 1.37 2000/09/13 15:58:55 srawlin
+ * added python bindings for gv_view_area_get_zoom
+ *
+ * Revision 1.36 2000/08/16 14:07:47 warmerda
+ * added prototype scrollbar support
+ *
+ * Revision 1.35 2000/08/07 17:18:13 warmerda
+ * added windows printing support
+ *
+ * Revision 1.34 2000/08/03 18:20:41 warmerda
+ * implemented print scaling and paper sizes properly
+ *
+ * Revision 1.33 2000/07/21 01:31:11 warmerda
+ * added read_only flag for GvData, and utilize for vector layers
+ *
+ * Revision 1.32 2000/07/20 03:21:26 warmerda
+ * added is_rgb for print_to_file()
+ *
+ * Revision 1.31 2000/07/17 19:10:00 warmerda
+ * added tentative support for scaling wait between redraws to actual redraw time
+ *
+ * Revision 1.30 2000/07/13 18:05:22 srawlin
+ * removed use of view.state.eye_az and .eye_el, contained same information
+ * as view.state.eye_dir
+ *
+ * Revision 1.29 2000/07/11 20:56:23 srawlin
+ * added methods to get and set viewing direction relative to z-plane in 3D
+ *
+ * Revision 1.28 2000/07/10 16:20:50 srawlin
+ * removed unused function def
+ *
+ * Revision 1.27 2000/07/10 13:36:58 srawlin
+ * updated 3D controls to be more like 2D
+ *
+ * Revision 1.26 2000/07/03 20:58:31 warmerda
+ * eye_pos in georef coordinates now
+ *
+ * Revision 1.25 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_VIEW_AREA_H__
+#define __GV_VIEW_AREA_H__
+
+#include <gtkgl/gtkglarea.h>
+#include "gvtypes.h"
+#include "gvproperties.h"
+
+#define GV_TYPE_VIEW_AREA (gv_view_area_get_type ())
+#define GV_VIEW_AREA(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_VIEW_AREA, GvViewArea))
+#define GV_VIEW_AREA_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_VIEW_AREA, GvViewAreaClass))
+#define GV_IS_VIEW_AREA(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_VIEW_AREA))
+#define GV_IS_VIEW_AREA_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_VIEW_AREA))
+
+typedef struct _GvViewArea GvViewArea;
+typedef struct _GvViewAreaClass GvViewAreaClass;
+typedef struct _GvViewAreaState GvViewAreaState;
+
+typedef gvgeocoord vec3_t[3]; /* xyz */
+
+struct _GvViewAreaState
+{
+ gvgeocoord tx, ty; /* translation of center (georef) */
+ gvgeocoord rot; /* xy-plane rotation in degrees */
+ gvgeocoord zoom; /* log 2 based zoom, 0 is 1:1 */
+ gvgeocoord linear_zoom; /* xy plane zoom */
+ gvgeocoord flip_x, flip_y;
+ gvgeocoord shape_x, shape_y; /* width/height of window in pixels */
+ gvgeocoord mpos_x, mpos_y; /* mouse position (pixel/line)*/
+
+ vec3_t eye_pos, eye_dir; /* 3D only, eye location and view
+ direction */
+ gvgeocoord z_scale;
+};
+
+typedef struct
+{
+ char *name;
+ gint listbase;
+
+ GdkFont *gdkfont;
+} GvBMFontInfo;
+
+struct _GvViewArea
+{
+ GtkGLArea glarea;
+
+ GvViewAreaState state;
+
+ GList *layers;
+ GtkObject *active_layer;
+
+ GArray *bmfonts;
+
+ char *projection; /* projection of view is in, eg UTM */
+
+ GvColor background; /* background color used in clears */
+
+ int exact_render; /* normally set for prints */
+
+ int flag_3d; /* 2D or 3D mode flag */
+
+ double linear_measure; /* Diaganonal of view extents for
+ scaling linear step sizes */
+ int volume_current;
+ double view_volume[6]; /* xmin/xmax/ymin/ymax/zmin/zmax */
+
+ gint last_button; /* zero mean no current button */
+ double last_button_time;
+ double last_zoom_time;
+
+ gvgeocoord last_mpos_x, last_mpos_y;
+ gint dragging_mode;
+
+ GtkAdjustment *hadj;
+ GtkAdjustment *vadj;
+ int lock_adjustments;
+
+ int display_dirty; /*does the display need rerendering?*/
+
+ /* ghost cursor stuff */
+ gvgeocoord next_x, next_y;
+ gvgeocoord last_x, last_y;
+ int next_valid; /* flag to indicate if ghost cursor should draw next_x, next_y */
+ int last_valid; /* flag to indicate if last cursor should be erased (logical cursor) */
+ /* end of ghost cursor stuff */
+
+ float last_draw_time;
+ GTimer *redraw_timer;
+
+ GvProperties properties;
+};
+
+struct _GvViewAreaClass
+{
+ GtkGLAreaClass parent_class;
+
+ void (* gldraw) (GvViewArea *view);
+ void (* glcursor) (GvViewArea *view);
+ void (* active_changed) (GvViewArea *view);
+ void (* view_state_changed) (GvViewArea *view);
+ void (*set_scroll_adjustments) (GvViewArea *view,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+};
+
+GtkType gv_view_area_get_type (void);
+GtkWidget* gv_view_area_new (void);
+
+void gv_view_area_set_mode(GvViewArea *view, int flag_3d);
+int gv_view_area_get_mode(GvViewArea *view);
+void gv_view_area_height_scale(GvViewArea *view, gvgeocoord scale);
+gvgeocoord gv_view_area_get_height_scale(GvViewArea *view);
+void gv_view_area_set_3d_view( GvViewArea *view, vec3_t eye_pos,
+ vec3_t eye_dir );
+void gv_view_area_set_3d_view_look_at( GvViewArea *view, vec3_t eye_pos,
+ gvgeocoord *eye_look_at );
+gint gv_view_area_get_look_at_pos( GvViewArea *view,
+ gvgeocoord *x, gvgeocoord *y);
+
+gint gv_view_area_set_raw( GvViewArea *view, GtkObject *ref_layer,
+ int raw_enable );
+gint gv_view_area_get_raw( GvViewArea *view, GtkObject *ref_layer );
+
+void gv_view_area_queue_draw(GvViewArea *view);
+void gv_view_area_zoom(GvViewArea *view, gvgeocoord zoom);
+gvgeocoord gv_view_area_get_zoom(GvViewArea *view);
+void gv_view_area_rotate(GvViewArea *view, gvgeocoord angle);
+void gv_view_area_translate(GvViewArea *view, gvgeocoord dx, gvgeocoord dy);
+void gv_view_area_set_translation(GvViewArea *view, gvgeocoord x, gvgeocoord y);
+int gv_view_area_get_flip_x(GvViewArea *view);
+int gv_view_area_get_flip_y(GvViewArea *view);
+void gv_view_area_set_flip_xy(GvViewArea *view, int flip_x, int flip_y );
+void gv_view_area_fit_all_layers(GvViewArea *view);
+void gv_view_area_fit_extents(GvViewArea *view,
+ gvgeocoord llx, gvgeocoord lly, gvgeocoord width, gvgeocoord height );
+gint gv_view_area_expose(GtkWidget *view, GdkEventExpose *event);
+void gv_view_area_get_extents(GvViewArea *view,
+ gvgeocoord *xmin, gvgeocoord *ymin,
+ gvgeocoord *xmax, gvgeocoord *ymax );
+void gv_view_area_get_world_extents(GvViewArea *view, GvRect *extents );
+void gv_view_area_get_volume( GvViewArea *view, double *volume );
+
+void gv_view_area_map_location(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *geo_x, gvgeocoord *geo_y);
+void gv_view_area_copy_state(GvViewArea *view, GvViewArea *copy);
+void gv_view_area_set_state(GvViewArea *view, GvViewAreaState *state);
+void gv_view_area_map_pointer(GvViewArea *view, gvgeocoord px, gvgeocoord py,
+ gvgeocoord *x, gvgeocoord *y);
+void gv_view_area_inverse_map_pointer(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *px, gvgeocoord *py);
+void gv_view_area_correct_for_transform(GvViewArea *view, gvgeocoord x, gvgeocoord y,
+ gvgeocoord *cx, gvgeocoord *cy);
+
+void gv_view_area_add_layer(GvViewArea *view, GtkObject *layer);
+void gv_view_area_remove_layer(GvViewArea *view, GtkObject *layer);
+GtkObject* gv_view_area_active_layer(GvViewArea *view);
+void gv_view_area_set_active_layer(GvViewArea *view, GtkObject *layer);
+GtkObject* gv_view_area_get_layer_of_type(GvViewArea *view, GtkType layer_type,
+ gint read_only_ok );
+GtkObject* gv_view_area_get_named_layer(GvViewArea *view, const char *name);
+GList* gv_view_area_list_layers(GvViewArea *view);
+GtkObject *gv_view_area_get_primary_raster( GvViewArea *view );
+void gv_view_area_swap_layers(GvViewArea *view, gint layer_a, gint layer_b);
+GdkPixmap* gv_view_area_create_thumbnail(GvViewArea *view, GtkObject *layer, gint width, gint height);
+
+GPtrArray *gv_view_area_get_fontnames(GvViewArea *view);
+gint gv_view_area_bmfont_load(GvViewArea *view, gchar *name);
+GvBMFontInfo *gv_view_area_bmfont_get_info(GvViewArea *view, gint font);
+void gv_view_area_bmfont_draw(GvViewArea *view, gint font, gvgeocoord x, gvgeocoord y, gchar *text, int force_simple );
+void gv_view_area_set_background_color(GvViewArea *view, GvColor color);
+void gv_view_area_get_background_color(GvViewArea *view, GvColor color);
+
+void
+gv_view_area_set_adjustments (GvViewArea *view, GtkAdjustment *hadj,
+ GtkAdjustment *vadj);
+
+gint gv_view_area_set_projection(GvViewArea *view, const char *projection);
+const char *gv_view_area_get_projection(GvViewArea *view);
+gint gv_view_area_print_to_file(GvViewArea *, int, int, const char *,
+ const char *, int );
+gint gv_view_area_print_postscript_to_file(
+ GvViewArea *, int, int, float, float, float, float, int, const char * );
+gint gv_view_area_render_postscript(GvViewArea *, int, int,
+ float, float, float, float, int,
+ gint (*)(void *, const char *),
+ void * );
+gint gv_view_area_render_to_func(GvViewArea *, int, int,
+ gint (*)(void*, void*), void * );
+void gv_view_area_page_setup();
+gint gv_view_area_print_to_windriver(GvViewArea *, int, int,
+ float, float, float, float,
+ int );
+void gv_view_area_zoompan_event(GvViewArea *, GdkEventButton *);
+#define gv_view_area_get_width(view) (view)->state.shape_x
+#define gv_view_area_get_height(view) (view)->state.shape_y
+
+int gv_view_area_redraw_timeout(GvViewArea *view);
+int gv_view_area_pending_idle_work(GvViewArea *view);
+
+int gv_get_render_counter();
+
+void gv_view_area_set_property(GvViewArea *data, const char *name,
+ const char *value);
+const char *gv_view_area_get_property(GvViewArea *data, const char *name);
+GvProperties *gv_view_area_get_properties(GvViewArea *data);
+void gv_view_area_queue_cursor_draw(GvViewArea *view, int next_valid, gvgeocoord x, gvgeocoord y);
+
+#endif /* __GV_VIEW_AREA_H__ */
+
+
+
Added: packages/openev/branches/upstream/current/gvviewlink.c
===================================================================
--- packages/openev/branches/upstream/current/gvviewlink.c (rev 0)
+++ packages/openev/branches/upstream/current/gvviewlink.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,643 @@
+/******************************************************************************
+ * $Id: gvviewlink.c,v 1.12 2005/01/18 19:55:42 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Manage linked GvViewAreas.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvviewlink.c,v $
+ * Revision 1.12 2005/01/18 19:55:42 gmwalter
+ * Avoid georef->pixel->georef transformations
+ * when they are not necessary: second order
+ * warps don't invert exactly, and error
+ * accumulates.
+ *
+ * Revision 1.11 2003/03/31 22:27:56 gmwalter
+ * Alter copy state zoom level calculation so it doesn't change under rotation.
+ *
+ * Revision 1.10 2003/03/04 15:30:27 gmwalter
+ * Avoid artifacts when cursor mode switched.
+ *
+ * Revision 1.9 2003/02/21 22:35:30 gmwalter
+ * Removed unused variables.
+ *
+ * Revision 1.8 2003/02/20 19:27:19 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.7 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.6 2002/03/25 19:53:41 warmerda
+ * fix for NULL projection
+ *
+ * Revision 1.5 2002/01/30 17:26:11 warmerda
+ * make link state copying smarter
+ *
+ * Revision 1.4 2000/08/10 16:52:40 warmerda
+ * watch for destroy, not delete-event
+ *
+ * Revision 1.3 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvviewlink.h"
+#include <gtk/gtksignal.h>
+#include "gvrasterlayer.h"
+#include "gvutils.h"
+
+static void gv_view_link_class_init(GvViewLinkClass *klass);
+static void gv_view_link_init(GvViewLink *link);
+static void gv_view_link_view_state_changed(GvViewLink *link, GvViewArea *view);
+static void gv_view_link_destroy(GtkObject *object);
+
+/* Ghost cursor stuff */
+static void gv_view_link_cursor_draw(GvViewLink *link, GvViewArea *view);
+
+static void gv_view_link_cursor_motion_notify(GvViewLink *link,GdkEventMotion *event, GvViewArea *view);
+static void gv_view_link_cursor_leave_notify(GvViewLink *link, GdkEventCrossing *event, GvViewArea *view);
+static void gv_view_link_cursor_enter_notify(GvViewLink *link, GdkEventCrossing *event, GvViewArea *view);
+static void gv_view_link_cursor_set_x_y(GvViewLink *link, double x, double y, GvViewArea *view);
+static void gv_view_link_cursor_get_geo_x_y(double *event_x, double *event_y, GvViewArea *view);
+
+GtkType
+gv_view_link_get_type(void)
+{
+ static GtkType view_link_type = 0;
+
+ if (!view_link_type)
+ {
+ static const GtkTypeInfo view_link_info =
+ {
+ "GvViewLink",
+ sizeof(GvViewLink),
+ sizeof(GvViewLinkClass),
+ (GtkClassInitFunc) gv_view_link_class_init,
+ (GtkObjectInitFunc) gv_view_link_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ view_link_type = gtk_type_unique(gtk_object_get_type(),
+ &view_link_info);
+ }
+ return view_link_type;
+}
+
+static void
+gv_view_link_class_init(GvViewLinkClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ object_class->destroy = gv_view_link_destroy;
+}
+
+static void
+gv_view_link_init(GvViewLink *link)
+{
+ link->views = NULL;
+ link->enabled = FALSE;
+ link->blocked = FALSE;
+
+ /* Ghost cursor stuff */
+ link->cursor_mode = GV_LINK_CURSOR_OFF;
+ link->src_view=NULL;
+}
+
+GtkObject *
+gv_view_link_new(void)
+{
+ return GTK_OBJECT(gtk_type_new(GV_TYPE_VIEW_LINK));
+}
+
+void
+gv_view_link_register_view(GvViewLink *link, GvViewArea *view)
+{
+ /* Add a reference to this view */
+ gtk_object_ref(GTK_OBJECT(view));
+
+ /* Add view to registered views list */
+ link->views = g_list_prepend(link->views, view);
+
+ /* Connect to the view state changed event */
+ gtk_signal_connect_object(GTK_OBJECT(view), "view-state-changed",
+ GTK_SIGNAL_FUNC(gv_view_link_view_state_changed),
+ GTK_OBJECT(link));
+
+ /* Connect to view area delete event */
+ gtk_signal_connect_object(GTK_OBJECT(view), "destroy",
+ GTK_SIGNAL_FUNC(gv_view_link_remove_view),
+ GTK_OBJECT(link));
+
+ /* Next two connections are only needed for ghost cursor drawing */
+ /* Connect to view area glcursor signal */
+ gtk_signal_connect_object(GTK_OBJECT(view), "glcursor",
+ GTK_SIGNAL_FUNC(gv_view_link_cursor_draw),
+ GTK_OBJECT(link));
+
+ /* Connect to motion event */
+ gtk_signal_connect_object(GTK_OBJECT(view), "motion-notify-event",
+ GTK_SIGNAL_FUNC(gv_view_link_cursor_motion_notify),
+ GTK_OBJECT(link));
+
+ /* Connect to view area leave signal */
+ gtk_signal_connect_object(GTK_OBJECT(view), "leave-notify-event",
+ GTK_SIGNAL_FUNC(gv_view_link_cursor_leave_notify),
+ GTK_OBJECT(link));
+
+ /* Connect to view area enter signal */
+ gtk_signal_connect_object(GTK_OBJECT(view), "enter-notify-event",
+ GTK_SIGNAL_FUNC(gv_view_link_cursor_enter_notify),
+ GTK_OBJECT(link));
+
+}
+
+void
+gv_view_link_remove_view(GvViewLink *link, GvViewArea *view)
+{
+ GList *list;
+
+ list = g_list_find(link->views, view);
+ if (list == NULL)
+ {
+ g_warning("gv_view_link_remove_view(): view not linked.");
+ return;
+ }
+
+ link->views = g_list_remove_link(link->views, list);
+
+ gtk_signal_disconnect_by_data(GTK_OBJECT(view), GTK_OBJECT(link));
+ gtk_object_unref(GTK_OBJECT(view));
+}
+
+void
+gv_view_link_enable(GvViewLink *link)
+{
+ link->enabled = TRUE;
+}
+
+void
+gv_view_link_disable(GvViewLink *link)
+{
+ GList *list;
+
+ link->enabled = FALSE;
+ list = link->views;
+ while (list)
+ {
+ GvViewArea *view = (GvViewArea*)list->data;
+ gv_view_area_queue_cursor_draw(view,FALSE,0.0,0.0);
+ list = g_list_next(list);
+ }
+}
+
+/**************************************************************/
+
+static int
+gv_view_link_copy_state(GvViewLink *link,
+ GvViewArea *src_view,
+ GvViewArea *dst_view)
+
+{
+ GvViewAreaState state;
+ GvRasterLayer *src_raster, *dst_raster;
+ double x, y, xo, yo;
+ gvgeocoord f_xo, f_yo;
+
+ state = src_view->state;
+ x = -state.tx;
+ y = -state.ty;
+ gv_view_area_map_pointer( src_view, 0.0, 0.0, &f_xo, &f_yo );
+ xo = f_xo;
+ yo = f_yo;
+ if (gv_view_area_get_primary_raster(src_view) != NULL)
+ {
+ src_raster =
+ GV_RASTER_LAYER(gv_view_area_get_primary_raster(src_view));
+ if( gv_view_area_get_raw(src_view,NULL) )
+ {
+ /* If no cursor-link transformation has been set, these default to
+ * the usual gv_raster_pixel_to_georef.
+ */
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &x, &y, NULL );
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &xo, &yo, NULL);
+ }
+ else if ( src_raster->prototype_data->poly_orderCL > -1 )
+ {
+ /* Only need the georef->pixel->georefCL transformation if specific
+ * cursor-link transformations have been set.
+ */
+ gv_raster_georef_to_pixel( src_raster->prototype_data, &x, &y, NULL );
+ gv_raster_georef_to_pixel( src_raster->prototype_data, &xo, &yo, NULL);
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &x, &y, NULL );
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &xo, &yo, NULL);
+ }
+
+ }
+
+ if( gv_view_area_get_projection(src_view) != NULL
+ && gv_view_area_get_projection(dst_view) != NULL
+ && !EQUAL(gv_view_area_get_projection(src_view),
+ gv_view_area_get_projection(dst_view))
+ && !EQUAL(gv_view_area_get_projection(src_view),"PIXEL")
+ && !EQUAL(gv_view_area_get_projection(dst_view),"PIXEL") )
+ {
+ if( !gv_reproject_points( gv_view_area_get_projection(src_view),
+ gv_view_area_get_projection(dst_view),
+ 1, &x, &y, NULL ) )
+ {
+ CPLDebug( "GvViewLink", "gv_reproject_points(%s,%s) failed.",
+ gv_view_area_get_projection(src_view),
+ gv_view_area_get_projection(dst_view) );
+ return FALSE;
+ }
+ gv_reproject_points( gv_view_area_get_projection(src_view),
+ gv_view_area_get_projection(dst_view),
+ 1, &xo, &yo, NULL );
+ }
+
+ if (gv_view_area_get_primary_raster(dst_view) != NULL)
+ {
+ dst_raster =
+ GV_RASTER_LAYER(gv_view_area_get_primary_raster(dst_view));
+ if( gv_view_area_get_raw(dst_view,NULL) )
+ {
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &x, &y, NULL );
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &xo, &yo, NULL);
+ }
+ else if ( dst_raster->prototype_data->poly_orderCL > -1 )
+ {
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &x, &y, NULL );
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &xo, &yo, NULL);
+ gv_raster_pixel_to_georef( dst_raster->prototype_data, &x, &y, NULL );
+ gv_raster_pixel_to_georef( dst_raster->prototype_data, &xo, &yo, NULL);
+
+ }
+
+ }
+
+ state.tx = -x;
+ state.ty = -y;
+
+/* -------------------------------------------------------------------- */
+/* Try to set the zoom level so that the same region from the */
+/* source view will be seen in the destination view, even if it */
+/* is a different size. Try to account for rotation. */
+/* -------------------------------------------------------------------- */
+
+ state.linear_zoom = 0.5*sqrt((dst_view->state.shape_y*dst_view->state.shape_y +
+ dst_view->state.shape_x*dst_view->state.shape_x)/
+ ((yo-y)*(yo-y) + (xo-x)*(xo-x)));
+
+ state.zoom = log(state.linear_zoom) / log(2.0);
+
+/* -------------------------------------------------------------------- */
+/* The shape is view specific, and should not be updated. The */
+/* flip value is less obvious, but if one view is */
+/* georeferenced, and the other is "raw" we don't want the flip */
+/* values propagating and screwing stuff up. This may require */
+/* future review. */
+/* -------------------------------------------------------------------- */
+ state.shape_x = dst_view->state.shape_x;
+ state.shape_y = dst_view->state.shape_y;
+
+ state.flip_x = dst_view->state.flip_x;
+ state.flip_y = dst_view->state.flip_y;
+
+ /* we could try to derive a rough rotation from the change in the
+ direction of the (x,y) to (xd,yd) vector */
+ gv_view_area_set_state( dst_view, &state );
+ return TRUE;
+}
+
+/**************************************************************/
+
+static void
+gv_view_link_view_state_changed(GvViewLink *link, GvViewArea *view)
+{
+ GList *list;
+ int x, y;
+ double geo_xd,geo_yd;
+
+ if (! link->enabled) return;
+ if (link->blocked) return;
+
+ /* Copy the view state to the other views in the list */
+ list = link->views;
+ link->blocked = TRUE;
+
+ /* ghost cursor needs to be reset because motion notify not always done! */
+ gtk_widget_get_pointer(GTK_WIDGET(view), &x, &y);
+ geo_xd = (double)x;
+ geo_yd = (double)y;
+ gv_view_link_cursor_get_geo_x_y(&geo_xd, &geo_yd, view);
+
+ while (list)
+ {
+ GvViewArea *other_view = (GvViewArea*)list->data;
+ if (other_view != view)
+ {
+ gv_view_link_copy_state(link, view, other_view);
+ other_view->next_valid = 1;
+ other_view->next_x = geo_xd;
+ other_view->next_y = geo_yd;
+ }
+ list = g_list_next(list);
+ }
+
+ link->blocked = FALSE;
+}
+
+/* Ghost cursor-related functions */
+static void
+gv_view_link_cursor_motion_notify(GvViewLink *link,GdkEventMotion *event, GvViewArea *view)
+{
+
+ if (link->blocked) return; /* don't think this is necessary, cause of interrupt processing */
+ if (link->cursor_mode == GV_LINK_CURSOR_OFF) return;
+ gv_view_link_cursor_set_x_y(link,event->x,event->y,view);
+}
+
+static void gv_view_link_cursor_enter_notify(GvViewLink *link,GdkEventCrossing *event,GvViewArea *view)
+{
+
+ if (link->blocked) return; /* don't think this is necessary, cause of interrupt processing */
+ if (link->cursor_mode == GV_LINK_CURSOR_OFF) return;
+ gv_view_link_cursor_set_x_y(link,event->x,event->y,view);
+}
+
+static void gv_view_link_cursor_leave_notify(GvViewLink *link,GdkEventCrossing *event,GvViewArea *view)
+{
+ GList *list;
+
+ if (link->blocked) return; /* don't think this is necessary, cause of interrupt processing */
+ if (link->cursor_mode == GV_LINK_CURSOR_OFF) return;
+
+ list = link->views;
+ while (list)
+ {
+ GvViewArea *other_view = (GvViewArea*)list->data;
+ /* ALL views should be redrawn on leave event, to avoid artifacts in logical cursor case */
+ gv_view_area_queue_cursor_draw(other_view,FALSE,0.0,0.0);
+ list = g_list_next(list);
+ }
+}
+
+static void
+gv_view_link_cursor_get_geo_x_y(double *event_x, double *event_y, GvViewArea *view)
+{
+ GvRasterLayer *src_raster;
+ gvgeocoord geo_x, geo_y;
+ double geo_xd,geo_yd;
+
+ gv_view_area_map_pointer(view, *event_x, *event_y,
+ &geo_x, &geo_y);
+
+ /* hack to get around the fact that some things expect double, others gvgeocoord */
+ geo_xd=(double) geo_x;
+ geo_yd=(double) geo_y;
+ if (gv_view_area_get_primary_raster(view) != NULL)
+ {
+ src_raster = GV_RASTER_LAYER(gv_view_area_get_primary_raster(view));
+ if( gv_view_area_get_raw(view,NULL) )
+ {
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &geo_xd, &geo_yd, NULL );
+ }
+ else if ( src_raster->prototype_data->poly_orderCL > -1 )
+ {
+ /* convert from display georeferenced coordinates to pixel coordinates to */
+ /* link-cursor georeferenced coordinates */
+
+ gv_raster_georef_to_pixel( src_raster->prototype_data, &geo_xd, &geo_yd, NULL );
+ gv_raster_pixel_to_georefCL( src_raster->prototype_data, &geo_xd, &geo_yd, NULL );
+ }
+ }
+ *event_x = geo_xd;
+ *event_y = geo_yd;
+}
+
+static void
+gv_view_link_cursor_set_x_y(GvViewLink *link, double event_x, double event_y, GvViewArea *view)
+{
+ GList *list;
+ double geo_xd,geo_yd;
+
+
+ geo_xd = event_x;
+ geo_yd = event_y;
+ gv_view_link_cursor_get_geo_x_y(&geo_xd, &geo_yd, view);
+ link->src_view = view;
+
+ list = link->views;
+ while (list)
+ {
+ GvViewArea *other_view = (GvViewArea*)list->data;
+ if(other_view != view) {
+ gv_view_area_queue_cursor_draw(other_view,TRUE,geo_xd,geo_yd);
+ }
+ list = g_list_next(list);
+ }
+
+
+}
+
+
+static void
+gv_view_link_cursor_draw(GvViewLink *link, GvViewArea *view)
+{
+ gvgeocoord dx, dy, x, y;
+ GvRasterLayer *dst_raster;
+ double xdouble, ydouble;
+
+ /* Uncomment next line to get rid of cursor in non-linked case */
+ /*if (! link->enabled) return;*/
+ if (link->cursor_mode == GV_LINK_CURSOR_OFF) return;
+
+ /* Don't draw cursor if application has just started up (src_view */
+ /* is NULL) */
+ if (link->src_view == NULL) return;
+
+ dx = 6.0; /* Later should make this flexible */
+ dy = 0.0;
+
+ gv_view_area_correct_for_transform(view, dx, dy, &dx, &dy);
+
+ if(view->next_valid) {
+ xdouble = (double) view->next_x;
+ ydouble = (double) view->next_y;
+
+ if( gv_view_area_get_projection(link->src_view) != NULL
+ && gv_view_area_get_projection(view) != NULL
+ && !EQUAL(gv_view_area_get_projection(link->src_view),
+ gv_view_area_get_projection(view))
+ && !EQUAL(gv_view_area_get_projection(link->src_view),"PIXEL")
+ && !EQUAL(gv_view_area_get_projection(view),"PIXEL") )
+ {
+ if( !gv_reproject_points( gv_view_area_get_projection(link->src_view),
+ gv_view_area_get_projection(view),
+ 1, &xdouble, &ydouble, NULL ) )
+ {
+ CPLDebug( "GvViewLink", "gv_reproject_points(%s,%s) failed.",
+ gv_view_area_get_projection(link->src_view),
+ gv_view_area_get_projection(view) );
+ }
+ }
+ if (gv_view_area_get_primary_raster(view) != NULL)
+ {
+ dst_raster =
+ GV_RASTER_LAYER(gv_view_area_get_primary_raster(view));
+
+ if( gv_view_area_get_raw(view,NULL) )
+ {
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &xdouble, &ydouble, NULL );
+ }
+ else if ( dst_raster->prototype_data->poly_orderCL > -1 )
+ {
+ gv_raster_georef_to_pixelCL( dst_raster->prototype_data, &xdouble, &ydouble, NULL );
+ gv_raster_pixel_to_georef( dst_raster->prototype_data, &xdouble, &ydouble, NULL );
+ }
+ }
+ x = (gvgeocoord) xdouble;
+ y = (gvgeocoord) ydouble;
+ } else {
+ x = 0.0;
+ y = 0.0;
+ }
+
+ if (link->cursor_mode == GV_LINK_CURSOR_ON_LOGICAL)
+ {
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_XOR);
+ }
+ else
+ {
+ glDrawBuffer(GL_FRONT_LEFT);
+ }
+
+ /*glRenderMode(GL_RENDER);*/
+ if (link->cursor_mode == GV_LINK_CURSOR_ON_LOGICAL)
+ glColor3f(1.0,1.0,1.0);
+ else
+ glColor3f(0.0,1.0,0.0);
+
+ /* Draw crosshairs */
+ glBegin(GL_LINES);
+
+ if ((link->cursor_mode == GV_LINK_CURSOR_ON_LOGICAL) && (view->last_valid))
+ {
+ glVertex2f(view->last_x-dx, view->last_y-dy);
+ glVertex2f(view->last_x+dx, view->last_y+dy);
+ glVertex2f(view->last_x+dy, view->last_y-dx);
+ glVertex2f(view->last_x-dy, view->last_y+dx);
+ }
+
+ if (view->next_valid)
+ {
+ glVertex2f(x-dx, y-dy);
+ glVertex2f(x+dx, y+dy);
+ glVertex2f(x+dy, y-dx);
+ glVertex2f(x-dy, y+dx);
+ }
+ glEnd();
+
+ if (link->cursor_mode == GV_LINK_CURSOR_ON_LOGICAL)
+ {
+ glDisable(GL_COLOR_LOGIC_OP);
+ gtk_gl_area_swap_buffers(GTK_GL_AREA(view));
+ if (view->next_valid)
+ {
+ view->last_x = x;
+ view->last_y = y;
+ view->last_valid = TRUE;
+ }
+ else
+ view->last_valid = FALSE;
+ }
+ else
+ {
+ glFinish();
+ glDrawBuffer(GL_BACK);
+ /*gtk_gl_area_swap_buffers(GTK_GL_AREA(view));*/
+ }
+
+
+}
+
+void
+gv_view_link_set_cursor_mode(GvViewLink *link, int cursor_mode)
+{
+ GList *list;
+
+ if (link->cursor_mode != GV_LINK_CURSOR_OFF)
+ {
+ /* If cursor wasn't off, make sure no artifacts are left */
+ list = link->views;
+ while (list)
+ {
+ GvViewArea *other_view = (GvViewArea*)list->data;
+ /* ALL views should be redrawn on leave event, to avoid artifacts in logical cursor case */
+ gv_view_area_queue_cursor_draw(other_view,FALSE,0.0,0.0);
+ list = g_list_next(list);
+ }
+ }
+
+ if (cursor_mode == GV_LINK_CURSOR_OFF)
+ link->cursor_mode = GV_LINK_CURSOR_OFF;
+ else if (cursor_mode == GV_LINK_CURSOR_ON_DEFAULT)
+ link->cursor_mode = GV_LINK_CURSOR_ON_DEFAULT;
+ else if (cursor_mode == GV_LINK_CURSOR_ON_LOGICAL)
+ link->cursor_mode = GV_LINK_CURSOR_ON_LOGICAL;
+ else
+ g_warning("set_gv_view_link_cursor_mode(): invalid cursor mode");
+
+}
+
+/* End of ghost cursor-related functions */
+
+static void
+gv_view_link_destroy(GtkObject *object)
+{
+ GtkObjectClass *parent_class;
+ GvViewLink *link;
+
+ link = GV_VIEW_LINK(object);
+
+ /* Remove all views */
+ while (link->views)
+ {
+ GvViewArea *view = (GvViewArea*)link->views->data;
+ gv_view_link_remove_view(link, view);
+ }
+
+ /* Call parent class function */
+ parent_class = gtk_type_class(gtk_gl_area_get_type());
+ GTK_OBJECT_CLASS(parent_class)->destroy(object);
+}
+
Added: packages/openev/branches/upstream/current/gvviewlink.h
===================================================================
--- packages/openev/branches/upstream/current/gvviewlink.h (rev 0)
+++ packages/openev/branches/upstream/current/gvviewlink.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,96 @@
+/******************************************************************************
+ * $Id: gvviewlink.h,v 1.5 2003/02/21 22:35:31 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Manage linked GvViewAreas.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvviewlink.h,v $
+ * Revision 1.5 2003/02/21 22:35:31 gmwalter
+ * Removed unused variables.
+ *
+ * Revision 1.4 2003/02/20 19:27:19 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.3 2002/01/30 17:26:11 warmerda
+ * make link state copying smarter
+ *
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_VIEW_LINK_H__
+#define __GV_VIEW_LINK_H__
+
+#include <gtk/gtkobject.h>
+#include "gvviewarea.h"
+
+#define GV_TYPE_VIEW_LINK (gv_view_link_get_type ())
+#define GV_VIEW_LINK(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_VIEW_LINK, GvViewLink))
+#define GV_VIEW_LINK_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_VIEW_LINK, GvViewLinkClass))
+#define GV_IS_VIEW_LINK(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_VIEW_LINK))
+#define GV_IS_VIEW_LINK_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_VIEW_LINK))
+
+typedef struct _GvViewLink GvViewLink;
+typedef struct _GvViewLinkClass GvViewLinkClass;
+
+typedef enum {
+ GV_LINK_CURSOR_OFF = 0,
+ GV_LINK_CURSOR_ON_DEFAULT = 1,
+ GV_LINK_CURSOR_ON_LOGICAL = 2
+} GvLinkCursorMode;
+
+
+struct _GvViewLink
+{
+ GtkObject object;
+
+ GList *views;
+ gint enabled : 1;
+ gint blocked : 1;
+
+ /* Ghost cursor stuff */
+ GvLinkCursorMode cursor_mode;
+ GvViewArea *src_view;
+};
+
+struct _GvViewLinkClass
+{
+ GtkObjectClass parent_class;
+};
+
+GtkType gv_view_link_get_type(void);
+GtkObject* gv_view_link_new(void);
+void gv_view_link_register_view(GvViewLink *link, GvViewArea *view);
+void gv_view_link_remove_view(GvViewLink *link, GvViewArea *view);
+void gv_view_link_enable(GvViewLink *link);
+void gv_view_link_disable(GvViewLink *link);
+/* Ghost cursor function */
+void gv_view_link_set_cursor_mode(GvViewLink *link, int cursor_mode);
+
+#endif /*__GV_VIEW_LINK_H__ */
Added: packages/openev/branches/upstream/current/gvwinprint.c
===================================================================
--- packages/openev/branches/upstream/current/gvwinprint.c (rev 0)
+++ packages/openev/branches/upstream/current/gvwinprint.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,276 @@
+/******************************************************************************
+ * $Id: gvwinprint.c,v 1.4 2001/05/01 19:21:51 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: MS Windows Print Support
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvwinprint.c,v $
+ * Revision 1.4 2001/05/01 19:21:51 warmerda
+ * include cpl_error.h
+ *
+ * Revision 1.3 2001/05/01 19:20:19 warmerda
+ * reimplement using StretchDIBit(), avoid upsidedown DIB
+ *
+ * Revision 1.2 2001/04/27 20:50:49 warmerda
+ * interim update with everything in one big buffer
+ *
+ * Revision 1.1 2000/08/07 17:17:12 warmerda
+ * New
+ *
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include "gvviewarea.h"
+#include "cpl_error.h"
+
+static PRINTDLG prDlg;
+static PAGESETUPDLG psDlg;
+static HGLOBAL hDevMode = NULL;
+
+void gv_view_area_page_setup()
+
+{
+ printf( "gv_view_area_page_setup\n" );
+
+ psDlg.Flags = 0;
+ psDlg.hwndOwner = NULL;
+ psDlg.hDevNames = NULL;
+ psDlg.lStructSize = sizeof (PAGESETUPDLG);
+ psDlg.hDevMode = hDevMode;
+
+ if (!PageSetupDlg (&psDlg))
+ {
+ if (CommDlgExtendedError ())
+ g_message ("PageSetupDlg failed: %d",
+ CommDlgExtendedError ());
+ return;
+ }
+ psDlg.Flags |= PSD_MARGINS;
+
+ if( psDlg.hDevMode != NULL )
+ hDevMode = psDlg.hDevMode;
+}
+
+typedef struct {
+ int width;
+ int height;
+ int nextScanline;
+ unsigned char *bgrRow;
+ HDC hdcMem;
+ float devOffsetX;
+ float devOffsetY;
+ float devScaleX;
+ float devScaleY;
+} WinDriverOptions;
+
+static gint windriver_handler( void * cb_data, void * scanline_in )
+
+{
+ unsigned char *scanline = (unsigned char *) scanline_in;
+ WinDriverOptions *options = (WinDriverOptions *) cb_data;
+ int i, scan_off, line_len;
+
+ line_len = 4 * ((options->width * 3 + 3) / 4);
+ scan_off = line_len * (options->height - options->nextScanline - 1);
+ /* We need to convert into BGR format */
+ for( i = 0; i < options->width; i++ )
+ {
+ options->bgrRow[i*3+2+scan_off] = scanline[i*3+0];
+ options->bgrRow[i*3+1+scan_off] = scanline[i*3+1];
+ options->bgrRow[i*3+0+scan_off] = scanline[i*3+2];
+ }
+
+ options->nextScanline++;
+
+ return 0;
+}
+
+gint
+gv_view_area_print_to_windriver(GvViewArea *view, int width, int height,
+ float ulx, float uly, float lrx, float lry,
+ int is_rgb )
+
+{
+ DOCINFO docInfo;
+ double devResX, devResY;
+ double imgResX, imgResY;
+ HBITMAP hBitmap;
+ HANDLE oldBm;
+ BITMAPV4HEADER bmHeader;
+ HGLOBAL hDevNames;
+ WinDriverOptions options;
+ gint errcode;
+
+ prDlg.hwndOwner = NULL;
+ prDlg.hDevNames = NULL;
+ prDlg.Flags |=
+ PD_RETURNDC | PD_DISABLEPRINTTOFILE | PD_HIDEPRINTTOFILE
+ | PD_NOSELECTION;
+ prDlg.nMinPage = prDlg.nMaxPage = 0;
+ prDlg.nCopies = 1;
+ prDlg.lStructSize = sizeof (PRINTDLG);
+ prDlg.hDevMode = hDevMode;
+
+ if (!PrintDlg (&prDlg))
+ {
+ if (CommDlgExtendedError ())
+ g_message ("PrintDlg failed: %d",
+ CommDlgExtendedError ());
+ return 1;
+ }
+
+ if( hDevMode == NULL )
+ hDevMode = prDlg.hDevMode;
+
+ hDevNames = prDlg.hDevNames;
+
+ if( prDlg.hDevMode != NULL )
+ hDevMode = prDlg.hDevMode;
+
+ if (!(GetDeviceCaps(prDlg.hDC, RASTERCAPS) & RC_BITBLT))
+ {
+ g_message ("Printer doesn't support bitmaps");
+ return 1;
+ }
+
+ /* Start print job. */
+ docInfo.cbSize = sizeof (DOCINFO);
+ docInfo.lpszDocName = "OpenEV Print";
+ docInfo.lpszOutput = NULL;
+ docInfo.lpszDatatype = NULL;
+ docInfo.fwType = 0;
+
+ if (StartDoc (prDlg.hDC, &docInfo) == SP_ERROR)
+ return 1;
+
+ /* Prepare printer to accept a page. */
+ if (StartPage (prDlg.hDC) <= 0)
+ {
+ g_message ("StartPage failed");
+ AbortDoc (prDlg.hDC);
+ return 1;
+ }
+
+ options.hdcMem = CreateCompatibleDC (prDlg.hDC);
+
+ memset( &bmHeader, 0, sizeof(bmHeader) );
+ bmHeader.bV4Size = sizeof (BITMAPV4HEADER);
+ bmHeader.bV4Width = width;
+ bmHeader.bV4Height = height;
+ bmHeader.bV4Planes = 1;
+ bmHeader.bV4BitCount = 24;
+ bmHeader.bV4V4Compression = BI_RGB;
+ bmHeader.bV4SizeImage = 0;
+ bmHeader.bV4XPelsPerMeter = 0;
+ bmHeader.bV4YPelsPerMeter = 0;
+ bmHeader.bV4ClrUsed = 0;
+ bmHeader.bV4ClrImportant = 0;
+ bmHeader.bV4CSType = 0;
+
+ hBitmap = CreateDIBSection (options.hdcMem,
+ (BITMAPINFO *) &bmHeader,
+ DIB_RGB_COLORS,
+ (PVOID *) &(options.bgrRow),
+ NULL,
+ 0);
+ if (hBitmap == NULL)
+ {
+ g_message ("CreateDIBSection failed");
+ AbortDoc (prDlg.hDC);
+ return 1;
+ }
+
+ options.nextScanline = 0;
+ options.width = width;
+ options.height = height;
+
+ devResX = GetDeviceCaps(prDlg.hDC, LOGPIXELSX); /* in dpi */
+ devResY = GetDeviceCaps(prDlg.hDC, LOGPIXELSY); /* in dpi */
+
+ CPLDebug( "gvwinprint", "devResX = %f, devResY = %f\n",
+ devResX, devResY );
+
+ CPLDebug( "gvwinprint", "Size=%dmm x %dmm\n",
+ GetDeviceCaps( prDlg.hDC, HORZSIZE ),
+ GetDeviceCaps( prDlg.hDC, VERTSIZE ) );
+
+ CPLDebug( "gvwinprint", "Resolution=%dp x %dp\n",
+ GetDeviceCaps( prDlg.hDC, HORZRES ),
+ GetDeviceCaps( prDlg.hDC, VERTRES ) );
+
+ options.devOffsetX = 0;
+ options.devOffsetY = 0;
+
+ if( GetDeviceCaps( prDlg.hDC, HORZRES ) / (float) width
+ < GetDeviceCaps( prDlg.hDC, VERTRES ) / (float) height )
+ {
+ options.devScaleX =
+ GetDeviceCaps( prDlg.hDC, HORZRES ) / (float) width;
+ options.devScaleY =
+ GetDeviceCaps( prDlg.hDC, HORZRES ) / (float) width;
+ }
+ else
+ {
+ options.devScaleX =
+ GetDeviceCaps( prDlg.hDC, VERTRES ) / (float) height;
+ options.devScaleY =
+ GetDeviceCaps( prDlg.hDC, VERTRES ) / (float) height;
+ }
+
+ oldBm = SelectObject (options.hdcMem, hBitmap);
+
+ errcode = gv_view_area_render_to_func( view, width, height,
+ windriver_handler, &options );
+
+ if( StretchDIBits( prDlg.hDC,
+ (int) options.devOffsetX,
+ (int) options.devOffsetY,
+ (int) (width * options.devScaleX),
+ (int) (height * options.devScaleY),
+ 0, 0, width, height,
+ (PVOID *) options.bgrRow,
+ (BITMAPINFO *) &bmHeader,
+ DIB_RGB_COLORS,
+ SRCCOPY ) == 0 )
+ {
+ CPLDebug( "gvwinprint", "StretchDIBits() error.\n" );
+ errcode = 1;
+ }
+
+ SelectObject (options.hdcMem, oldBm);
+ DeleteObject (hBitmap);
+
+ if (EndPage (prDlg.hDC) <= 0)
+ {
+ g_message ("EndPage failed");
+ EndDoc (prDlg.hDC);
+ return 1;
+ }
+
+ EndDoc (prDlg.hDC);
+
+ DeleteDC( prDlg.hDC );
+
+ return errcode;
+}
Added: packages/openev/branches/upstream/current/gvzoompantool.c
===================================================================
--- packages/openev/branches/upstream/current/gvzoompantool.c (rev 0)
+++ packages/openev/branches/upstream/current/gvzoompantool.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,144 @@
+/******************************************************************************
+ * $Id: gvzoompantool.c,v 1.7 2000/07/10 13:37:05 srawlin Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Zoom/Pan editing mode (most zoompan code in gvviewarea.c)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvzoompantool.c,v $
+ * Revision 1.7 2000/07/10 13:37:05 srawlin
+ * updated 3D controls to be more like 2D
+ *
+ * Revision 1.6 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gvzoompantool.h"
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <GL/gl.h>
+
+static void gv_zoompan_tool_class_init(GvZoomPanToolClass *klass);
+static void gv_zoompan_tool_init(GvZoomPanTool *tool);
+static void gv_zoompan_tool_button_press(GvTool *tool, GdkEventButton *event);
+static void gv_zoompan_tool_button_release(GvTool *tool, GdkEventButton *event);
+static void gv_zoompan_tool_motion_notify(GvTool *tool, GdkEventMotion *event);
+static void gv_zoompan_tool_deactivate(GvTool *tool, GvViewArea *view);
+
+GtkType
+gv_zoompan_tool_get_type(void)
+{
+ static GtkType zoompan_tool_type = 0;
+
+ if (!zoompan_tool_type)
+ {
+ static const GtkTypeInfo zoompan_tool_info =
+ {
+ "GvZoomPanTool",
+ sizeof(GvZoomPanTool),
+ sizeof(GvZoomPanToolClass),
+ (GtkClassInitFunc) gv_zoompan_tool_class_init,
+ (GtkObjectInitFunc) gv_zoompan_tool_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ zoompan_tool_type = gtk_type_unique(gv_tool_get_type(),
+ &zoompan_tool_info);
+ }
+ return zoompan_tool_type;
+}
+
+static void
+gv_zoompan_tool_class_init(GvZoomPanToolClass *klass)
+{
+ GvToolClass *tool_class;
+
+ tool_class = (GvToolClass*)klass;
+ tool_class->deactivate = gv_zoompan_tool_deactivate;
+ tool_class->button_press = gv_zoompan_tool_button_press;
+ tool_class->button_release = gv_zoompan_tool_button_release;
+ tool_class->motion_notify = gv_zoompan_tool_motion_notify;
+}
+
+static void
+gv_zoompan_tool_init(GvZoomPanTool *tool)
+{
+}
+
+GvTool *
+gv_zoompan_tool_new(void)
+{
+ return GV_TOOL(gtk_type_new(GV_TYPE_ZOOMPAN_TOOL));
+}
+
+static void
+gv_zoompan_tool_button_press(GvTool *tool, GdkEventButton *event)
+{
+ if( (event->state & GDK_CONTROL_MASK)
+ || (event->state & GDK_SHIFT_MASK)
+ || tool->view->flag_3d)
+ return;
+
+ gv_view_area_zoompan_event(tool->view, event);
+}
+
+static void
+gv_zoompan_tool_button_release(GvTool *tool, GdkEventButton *event)
+{
+ gv_view_area_zoompan_event( tool->view, event );
+}
+
+static void
+gv_zoompan_tool_motion_notify(GvTool *tool, GdkEventMotion *event)
+{
+ GvViewArea *view = tool->view;
+
+ if( (event->state & GDK_BUTTON2_MASK)
+ && !(event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) )
+
+ {
+ gv_view_area_translate(view, event->x - view->state.mpos_x,
+ view->state.mpos_y - event->y);
+ }
+
+ /*
+ if (event->state & GDK_BUTTON3_MASK)
+ {
+ gv_view_area_3d_direction_event(tool->view, event);
+ }
+ */
+
+}
+
+static void
+gv_zoompan_tool_deactivate(GvTool *tool, GvViewArea *view)
+{
+ /* Call the parent class func */
+ GV_TOOL_DEACTIVATE(tool, view);
+
+ if( tool->view )
+ tool->view->last_button = 0;
+}
+
Added: packages/openev/branches/upstream/current/gvzoompantool.h
===================================================================
--- packages/openev/branches/upstream/current/gvzoompantool.h (rev 0)
+++ packages/openev/branches/upstream/current/gvzoompantool.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * $Id: gvzoompantool.h,v 1.2 2000/06/20 13:27:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Zoom/Pan editing mode (most zoompan code in gvviewarea.c)
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvzoompantool.h,v $
+ * Revision 1.2 2000/06/20 13:27:08 warmerda
+ * added standard headers
+ *
+ */
+
+#ifndef __GV_ZOOMPAN_TOOL_H__
+#define __GV_ZOOMPAN_TOOL_H__
+
+#include "gvtool.h"
+
+#define GV_TYPE_ZOOMPAN_TOOL (gv_zoompan_tool_get_type ())
+#define GV_ZOOMPAN_TOOL(obj) (GTK_CHECK_CAST ((obj), GV_TYPE_ZOOMPAN_TOOL, GvZoompanTool))
+#define GV_ZOOMPAN_TOOL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GV_TYPE_ZOOMPAN_TOOL, GvZoompanToolClass))
+#define GV_IS_ZOOMPAN_TOOL(obj) (GTK_CHECK_TYPE ((obj), GV_TYPE_ZOOMPAN_TOOL))
+#define GV_IS_ZOOMPAN_TOOL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GV_TYPE_ZOOMPAN_TOOL))
+
+typedef struct _GvZoomPanTool GvZoomPanTool;
+typedef struct _GvZoomPanToolClass GvZoomPanToolClass;
+
+struct _GvZoomPanTool
+{
+ GvTool tool;
+};
+
+struct _GvZoomPanToolClass
+{
+ GvToolClass parent_class;
+};
+
+GtkType gv_zoompan_tool_get_type(void);
+GvTool* gv_zoompan_tool_new(void);
+
+#endif /* __GV_ZOOMPAN_TOOL_H__ */
Added: packages/openev/branches/upstream/current/html/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/html/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/html/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,69 @@
+/Tool_Export.html/1.2/Fri Apr 11 18:03:30 2003//
+/busy.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/classify.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/customization.html/1.4/Tue May 18 13:29:48 2004//
+/edittools.gif/1.3/Wed Jun 25 17:47:46 2003/-kb/
+/edittools.html/1.3/Wed Jun 25 17:47:42 2003//
+/equalize.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/exporttool_advgui.gif/1.2/Fri Apr 11 18:03:30 2003/-kb/
+/exporttool_basicgui.gif/1.2/Fri Sep 3 17:43:18 2004/-kb/
+/files.html/1.1/Tue Aug 15 20:08:37 2000//
+/gvogrdlg.gif/1.1/Tue Jan 7 03:36:53 2003/-kb/
+/gvpquerypropdlg.html/1.1/Tue Jul 25 15:39:52 2000//
+/gvpquerypropdlg_drawstyle.gif/1.1/Tue Jul 25 15:39:52 2000/-kb/
+/gvpquerypropdlg_general.gif/1.1/Tue Jul 25 15:39:52 2000/-kb/
+/gvprint.gif/1.1/Mon Aug 7 21:26:35 2000/-kb/
+/gvprint.html/1.1/Mon Aug 7 21:26:47 2000//
+/gvrasterpropdlg.html/1.2/Tue Dec 11 20:14:34 2001//
+/gvrasterpropdlg_drawstyle.gif/1.2/Tue Dec 11 20:14:34 2001/-kb/
+/gvrasterpropdlg_general.gif/1.2/Tue Dec 11 20:14:34 2001/-kb/
+/gvrasterpropdlg_imageinfo.gif/1.1/Tue Dec 11 20:14:34 2001/-kb/
+/gvrasterpropdlg_lut.jpg/1.2/Tue Dec 11 20:14:34 2001/-kb/
+/gvrasterpropdlg_source.gif/1.2/Tue Dec 11 20:14:34 2001/-kb/
+/gvvectorpropdlg.html/1.1/Tue Jul 25 15:52:51 2000//
+/gvvectorpropdlg_drawstyle.gif/1.1/Tue Jul 25 15:52:51 2000/-kb/
+/gvvectorpropdlg_general.gif/1.1/Tue Jul 25 15:52:51 2000/-kb/
+/help.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/idle.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/layerdlg.gif/1.1/Tue Jul 11 16:11:34 2000/-kb/
+/layerdlg.html/1.1/Tue Jul 11 16:11:34 2000//
+/layerdlg_delete.gif/1.1/Tue Jul 11 16:11:34 2000/-kb/
+/layerdlg_lower.gif/1.1/Tue Jul 11 16:11:34 2000/-kb/
+/layerdlg_new.gif/1.1/Tue Jul 11 16:11:34 2000/-kb/
+/layerdlg_raise.gif/1.1/Tue Jul 11 16:11:34 2000/-kb/
+/legend.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/linear.gif/1.1/Wed Dec 12 15:16:20 2001/-kb/
+/log.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/logo.jpg/1.1/Thu Aug 17 14:09:24 2000/-kb/
+/mainwindow.gif/1.2/Wed Dec 12 15:11:54 2001/-kb/
+/mainwindow.html/1.5/Wed Dec 12 15:11:54 2001//
+/nonelut.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/onetoone.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/open3d.gif/1.3/Fri Sep 3 17:57:52 2004/-kb/
+/open3d.html/1.2/Fri May 3 21:01:39 2002//
+/openevmain.html/1.6/Thu May 13 20:29:16 2004//
+/openfile.gif/1.1/Thu Aug 10 19:45:14 2000/-kb/
+/performance.html/1.4/Wed Sep 27 19:33:41 2000//
+/pref_cache.gif/1.1/Mon Aug 14 20:21:20 2000/-kb/
+/pref_help.gif/1.1/Mon Aug 14 20:21:20 2000/-kb/
+/pref_raster.gif/1.3/Tue Dec 11 20:14:34 2001/-kb/
+/pref_tracking.gif/1.2/Fri Sep 29 19:17:40 2000/-kb/
+/preferences.html/1.4/Tue Dec 11 20:14:34 2001//
+/print.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/pyshell.html/1.4/Mon Jul 28 19:42:33 2003//
+/pyshell_default.gif/1.1/Mon Jul 28 19:42:33 2003/-kb/
+/refresh.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/rotatetool.gif/1.1/Wed Jun 25 17:47:35 2003/-kb/
+/seeall.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/tool_hist.gif/1.2/Fri Sep 3 18:00:31 2004/-kb/
+/tool_roigeneral.gif/1.1/Fri May 3 21:01:39 2002/-kb/
+/tools_openev.gif/1.2/Fri Sep 3 18:02:27 2004/-kb/
+/veclayerselect.html/1.1/Tue Jan 7 03:36:46 2003//
+/viewarea_keys.html/1.11/Fri Mar 12 21:01:00 2004//
+/windowed.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/worldg.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/worldrgb.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/zoom_control.gif/1.1/Wed Dec 12 15:14:52 2001/-kb/
+/zoomin.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+/zoomout.gif/1.1/Thu Aug 10 19:45:15 2000/-kb/
+D
Added: packages/openev/branches/upstream/current/html/CVS/Entries.Log
===================================================================
--- packages/openev/branches/upstream/current/html/CVS/Entries.Log (rev 0)
+++ packages/openev/branches/upstream/current/html/CVS/Entries.Log 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+A D/developer_info////
Added: packages/openev/branches/upstream/current/html/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/html/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/html/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/html
Added: packages/openev/branches/upstream/current/html/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/html/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/html/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/html/Tool_Export.html
===================================================================
--- packages/openev/branches/upstream/current/html/Tool_Export.html (rev 0)
+++ packages/openev/branches/upstream/current/html/Tool_Export.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,102 @@
+<html>
+<head>
+<title>Export Tool</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Export Tool</h1>
+
+The export tool can be used to convert raster files from one format to another.
+It has a basic mode for simple conversions, and an advanced mode that
+can interact with OpenEV to window and scale the data according to the current
+view settings (complex data and colour tables are not currently
+supported for the latter option). The exported file will be full
+resolution unless resolution reduction is requested.<p>
+
+<table border=0><tr>
+<td><img src="exporttool_basicgui.gif"></td>
+
+<td>
+<ul>
+<li>
+In the basic form of the gui, the user simply selects the input and output
+file, the output file format, and the resolution of the exported file relative
+to the input file (Full, 1/2, 1/4, or 1/8). <p>
+
+<li>
+Data Files: The files may be specified by typing in the complete path (directories
+must exist already) or selected through the file dialogs launched when the Set Input/
+Set Output buttons are clicked. When the export tool is launched, it will try to find
+the filename of the currently active layer and fill it into the input file field.
+<p>
+
+<li>
+Output Format: output file format (Geotiff, MFF2, etc.).
+<p>
+
+<li>
+To enable the advanced form of the gui, click the "Advanced Options" toggle.
+<p>
+
+<li>
+Click "Export" to perform the conversion, "Close" to close the tool.
+<p>
+
+</ul>
+
+</td>
+
+</table>
+
+<ul>
+
+
+
+<table border=0><tr>
+<td><img src="exporttool_advgui.gif"></td>
+
+<td>
+<ul>
+<li>
+In the advanced form of the gui, the user has the additional options of windowing and scaling the data to the
+current view settings.<p>
+
+<li>
+When "Window Input File" is toggled on, the Edit toolbar's "Draw ROI" mode is activated. Left-clicking and
+dragging out a region on the view will automatically update the input window information in the gui. The input
+window can also be entered manually. Clicking the "Draw ROI mode" button will re-activate the ROI selection mode
+(this is provided for convenience; launching the edit toolbar and pressing Draw ROI there will do the same thing).
+<p>
+
+<li>
+When "Scale to View Settings" is toggled on, the tool will search for the raster min/max settings of the current
+view, and will use these to scale the input file values from 0 to 255 for export.
+<p>
+
+<li>
+When "Active Layer->Input Filename" is pressed, the tool will update the Input File field with the filename of the
+currently active layer.
+<p>
+
+<li>
+The Geocoding Preference option can be used to specify the types of geocoding information to allow for storage in
+the output file. Selecting "Geotransform" will ensure that only geotransform-style geocoding information (if present)
+is transferred; "GCP" will ensure that only ground control point information is stored. This can be used to force the
+georeferencing information in MFF or MFF2 files to be stored as either ground control points or geotransforms when
+translating to GeoTiff, in cases where the corner and center coordinates can be expressed as a geotransform without
+loss of information (simple rotation/translation/scaling, but no warping).
+<p>
+
+</ul>
+
+</td>
+
+</table>
+
+<ul>
+
+<p>
+
+
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/busy.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/busy.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/classify.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/classify.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/customization.html
===================================================================
--- packages/openev/branches/upstream/current/html/customization.html (rev 0)
+++ packages/openev/branches/upstream/current/html/customization.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,581 @@
+<html>
+<head>
+<title>OpenEV Customization</title>
+</head>
+<body bgcolor="#ffffff">
+
+<h1><a name="contents">OpenEV Customization</a></h1>
+<ul>
+
+<li><a href="#section1">Introduction</a>
+<li><a href="#section1a">Tools (Plug-ins)</a>
+<li><a href="#section1b">Tutorial: Adding a new Plug-in</a>
+<li><a href="#section1c">XML File Configuration</a>
+
+</ul>
+
+<h1><a name="section1">Introduction</a></h1>
+
+Certain applications may require capabilities beyond those of
+the standard OpenEV viewer, or may wish to hide some of the existing
+functionality where it is not needed. While standard python inheritance
+is sometimes the best route, OpenEV does provides some mechanisms
+for customizing its appearance and functionality without rewriting the main
+application or view window code. <p>
+
+XML configuration files can be used to select which of the available menu
+and icon entries will be displayed in OpenEV view windows launched
+by the main application and in the OpenEV python shell, and whether
+or not the history area and progress bar will be shown in the OpenEV
+python shell. The names of the menu entries and icon files used can also
+be altered through the configuration files. The XML configuration
+files cannot be used to create new callbacks, they can only dictate
+how those callbacks that are present are referenced.<p>
+
+The functionality of OpenEV can be extended using the Tool_GViewApp class.
+In the most general case, this class contains only a reference to the
+current OpenEV (GViewApp) instance and a set of entries to add
+to the menu and icon bars of the view windows and python shell.
+Each menu or pymenu entry is defined by a default string
+describing the menu location (eg. 'Tools/ROI Analysis Tool'), an
+integer position relative to the existing items within the same menu
+(eg. 2 would place 'ROI Analysis Tool' after the second entry
+within the 'Tools' menu), and a callback. The reference to the main
+application allows the tool to interact with the current views,
+layers, and edit toolbar. Each icon entry is defined by
+an iconfile, hint text, default position, callback, help topic (not currently used),
+and text. All except the callbacks can be customized using XML, though
+the mechanism is slightly different than for the standard window items
+because the callback must be located through the information in the
+XML file since the tool's callback code isn't part of the gvviewwindow class.<p>
+
+<h2><a name="section1a">Tools (Plug-ins)</a></h2>
+
+OpenEV allows you to add hooks to your own callback functions through the
+main application using the Tool_GViewApp class stored in gviewapp.py.
+The base class is very simple- it simply stores a reference to the
+main application (the main application can also be found by importing
+gview, where it is stored as gview.app, but a reference is stored in
+each tool for convenience), and objects that store the
+view and pyshell menu and icon entries added by the tool.
+
+<pre>
+class Tool_GViewApp:
+ # Abstract base class to derive tools from
+ def __init__(self,app=None):
+ self.app = app
+ self.menu_entries = Tool_GViewAppMenuEntries()
+ self.icon_entries = Tool_GViewAppIconEntries()
+ self.pymenu_entries = Tool_GViewAppMenuEntries()
+ self.pyicon_entries = Tool_GViewAppIconEntries()
+</pre>
+
+Menu entry information is stored in a dictionary, with the
+entry path as the key and the position and callback as
+a tuple for the value.
+
+<pre>
+class Tool_GViewAppMenuEntries:
+ # Class to store entries to be added to openev's menu
+ def __init__(self):
+ self.entries = {}
+
+ def set_entry(self,item,position=0,callback=None,accelerator=None):
+ # item = a string describing menu location
+ # position = default location in the menu (integer): Ignored if an
+ # xml menu entry is specified for the tool. Note:
+ # when used, the position refers to position in the
+ # lowest level menu. Eg. if a menu entry is
+ # 'File/menu1/entryN', position refer's to entryN's
+ # position within menu1, not menu1's position in
+ # File. For more flexibility, use the xml form of
+ # configuration.
+ # callback = callback
+ # accelerator = shortcut key
+
+ if (type(item) == type('')):
+ if (type(position) == type(0)):
+ self.entries[item] = (position,callback, accelerator)
+ else:
+ raise AttributeError,"position should be an integer"
+ else:
+ raise AttributeError,"Menu entry item must be a string"
+
+</pre>
+
+Icon entry information is stored as a list, with each
+item in the list containing icon file, hint, position,
+callback, and help topic information. The icon files
+must be specified by a full path unless they are
+located in OpenEV's tools or pics directory, in which
+case the basename alone can be specified.
+
+<pre>
+class Tool_GViewAppIconEntries:
+ # Class to store entries to be added to openev's menu
+ def __init__(self):
+ self.entries = []
+
+ def set_entry(self,iconfile,hint_text,position=0,callback=None,help_topic=None,label=None,icontype='xpm'):
+ # iconfile=icon filename (xpm case), or some other string not yet defined
+ # (pixmap/widget case- not yet supported- may never be)
+ # hint_text=tooltip text to use
+ # position = default location in the icon bar (integer)
+ # callback = callback
+ # help topic = html help file (not yet used by anything)
+ # label = some gtk think- not sure what this does
+ # icontype = 'xpm' (later may allow 'pixmap' or 'widget', but not yet)
+
+ if (type(iconfile) == type('')):
+ import os
+ if os.path.isfile(iconfile):
+ fullfilename=iconfile
+ elif os.path.isfile(os.path.join(gview.home_dir,'tools',iconfile)):
+ fullfilename=os.path.join(gview.home_dir,'tools',iconfile)
+ elif os.path.isfile(os.path.join(gview.home_dir,'pics',iconfile)):
+ fullfilename=os.path.join(gview.home_dir,'pics',iconfile)
+ else:
+ txt = "Cannot find file "+iconfile+'. Either the full\n'
+ txt = txt+"path must be specified, or "+iconfile+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
+
+ # On nt, path separators need to be trapped and doubled to avoid
+ # being interpreted as an escape before special characters.
+ if os.name == 'nt':
+ import string
+ fullfilename=string.replace(fullfilename,"\\","\\\\")
+
+ if (type(position) == type(0)):
+ self.entries.append((fullfilename,label,hint_text,position,callback,help_topic,icontype))
+ else:
+ raise AttributeError,"position should be an integer"
+ else:
+ txt = "Cannot find file "+iconfile+'. Either the full\n'
+ txt = txt+"path must be specified, or "+iconfile+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
+
+</pre>
+
+
+<h3>An Example: The GeneralROITool</h3>
+In practice, the user defines a class which inherits from the
+Tool_GViewApp class (or at least has the same basic components
+defined), and adds menu entries and the callbacks associated with
+these entries.
+The GeneralROITool class in toolexample.py shows how this works.
+This is a demonstration tool that adds a 'Tools/ROI Analysis Tool' entry
+to the menu. When called, it activates the Edit toolbar's 'Draw ROI'
+method, and displays a dialog (see below). When the user selects
+a region, it updates the dialog to display the currently selected
+region. Pressing 'Analyze' will get it to print these values in the
+terminal window. <p>
+
+<img src="tool_roigeneral.gif"><p>
+<img src="tools_openev.gif"><p>
+
+In its initialization function, the GeneralROITool:
+<ul>
+<li> Calls gviewapp.Tool_GViewApp's __init__ function.
+This creates the reference to the main application
+(self.app) and an empty set of menu entries (self.menu_entries).
+<li> Creates a StoredROIPOI class instance to store the last selected
+region of interest (used to avoid tool failure if the 'Draw ROI' method
+has been deactivated in the Edit toolbar).
+<li> Calls its init_dialog function to create the dialog displayed when
+the 'Tools/ROI Analysis Tool' menu entry is selected. This dialog is
+hidden until the menu entry is called.
+<li> Calls its init_menu function to set up the menu entry. The
+associated callback shows the dialog created in the init_dialog step.
+<li> Calls init_connections to set up signal connections between the tool and
+its dialog (such as the 'analyze-pressed' signal emitted by the dialog), and
+between the tool and the main application (such as the 'roi-changed' signal
+emitted by the roi tool in the Edit toolbar).
+</ul>
+
+<h3>A More Advanced Example: The Histogram Tool</h3>
+The histogram tool inherits the dialog and connections of the GeneralROITool,
+but instead of just printing out the bounds of the currently selected region,
+it extracts the values contained in that region and forms a histogram
+from them. The tool's dialog has been extended to display this.
+This tool is available from SourceForge CVS (openev/tools/gvrastertools.py),
+but is not yet included in pre-built openev distributions, as it is still
+under development and not yet stable for all platforms and data types.
+<p>
+
+<img src="tool_hist.gif"><p>
+
+<h3>Registering A Tool</h3>
+Two mechanisms are provided for registering custom tools:<p>
+<ul>
+<li><b>Auto-Registration</b> OpenEV will automatically search through
+all the py-files in its 'tools' directory, and will load any tools
+listed in the global 'TOOL_LIST' variable for each module.
+<li><b>Command Line Argument</b> OpenEV allows you to specify a text
+file that lists modules to import and the tools to load from them at
+the command line. For instance, starting up openev with the command
+"openev -t (full or relative path)/tool_example.txt", where
+tool_example.txt contains:<p>
+<pre>
+MODULE_NAME = toolexample
+TOOL_NAME=GeneralROITool
+TOOL_NAME=GeneralPOITool
+</pre>
+will result in OpenEV loading the GeneralROITool and GeneralPOITool
+tools from toolexample.py. Note that the PYTHONPATH variable must
+include toolexample.py's directory for this to work.
+</ul>
+
+<h2><a name="section1b">Tutorial: Adding a new Plug-in</a></h2>
+
+To be able to write a comprehensive OpenEV GUI plug-in you should be familiar with
+GTK+ programming using Python (PyGTK).<p>
+
+OpenEV modules should be placed in the <i>tools/</i>
+subdirectory to be loaded automatically.<p>
+
+We will write a simple GUI module to automate the Fast Fourier Transform task. As a
+first attempt we make a menu item to perform an FFT.<p>
+
+<pre>
+# OpenEV module fft.py
+
+from gtk import *
+
+import gview
+import GtkExtra
+import gviewapp
+import gdalnumeric
+import FFT
+
+class FFTTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image processing/FFT",2,self.calculate_fft)
+
+ def calculate_fft(self,*args):
+ layer = gview.app.sel_manager.get_active_layer()
+ ds = layer.get_parent().get_dataset()
+ data = gdalnumeric.DatasetReadAsArray(ds)
+ data_tr = FFT.fft2d(data)
+ array_name = gdalnumeric.GetArrayFilename(data_tr)
+ gview.app.file_open_by_name(array_name)
+
+TOOL_LIST = ['FFTTool']
+</pre>
+
+This module adds a new top level menu "Image processing" with single item
+"FFT". Save this text into file, place it into <i>tools/</i> and restart
+OpenEV. Load an image, and click on the new menu item. The transformed image
+appears as a new layer (you may need click on the "Fit All Layers" button to see
+it).<p>
+
+Note, that you can easily extend the functionality of OpenEV with this
+approach. You can write scripts for your most often performed tasks (like
+calibration or NDVI calculation, described in the python shell section) and place them
+on the menu or taskbar.<p>
+
+Ok, our simplest script works, but now we will go further and make a dialog
+box to allow the user to select what type of transformation (forward or inverse) we
+should perform and where to place the results (in new layer of the same view or
+create a new view and place results there).<p>
+
+<pre>
+# OpenEV module fft2.py
+
+from gtk import *
+
+import gview
+import GtkExtra
+import gviewapp
+import gdalnumeric
+import FFT
+
+class FFT2Tool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = FFTDialog()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image processing/FFT2",2,self.launch_dialog)
+
+class FFTDialog(GtkWindow):
+
+ def __init__(self,app=None):
+ GtkWindow.__init__(self)
+ self.set_title('Fast Fourier Transform')
+ self.create_gui()
+ self.show()
+
+ def show(self):
+ GtkWindow.show_all(self)
+
+ def close(self, *args):
+ self.destroy()
+
+ def create_gui(self):
+ self.box1 = GtkVBox(spacing = 10)
+ self.box1.set_border_width(10)
+ self.add(self.box1)
+ self.box1.show()
+
+ self.switch_forward = GtkRadioButton(None, "Forward")
+ self.box1.pack_start(self.switch_forward)
+ self.switch_forward.show()
+ self.switch_inverse = GtkRadioButton(self.switch_forward, "Inverse")
+ self.box1.pack_start(self.switch_inverse)
+ self.switch_inverse.show()
+
+ self.separator = GtkHSeparator()
+ self.box1.pack_start(self.separator, expand=FALSE)
+
+ self.switch_new_view = GtkCheckButton("Create new view")
+ self.box1.pack_start(self.switch_new_view)
+ self.switch_new_view.show()
+
+ self.separator = GtkHSeparator()
+ self.box1.pack_start(self.separator, expand=FALSE)
+
+ self.box2 = GtkHBox(spacing=10)
+ self.box1.pack_start(self.box2, expand=FALSE)
+ self.box2.show()
+
+ self.execute_btn = GtkButton("Ok")
+ self.execute_btn.connect("clicked", self.execute_cb)
+ self.box2.pack_start(self.execute_btn)
+ self.execute_btn.set_flags(CAN_DEFAULT)
+ self.execute_btn.grab_default()
+
+ self.close_btn = GtkButton("Cancel")
+ self.close_btn.connect("clicked", self.close)
+ self.box2.pack_start(self.close_btn)
+
+ def execute_cb( self, *args ):
+ layer = gview.app.sel_manager.get_active_layer()
+ ds = layer.get_parent().get_dataset()
+ data = gdalnumeric.DatasetReadAsArray(ds)
+
+ if self.switch_forward.get_active():
+ data_tr = FFT.fft2d(data)
+ else:
+ data_tr = FFT.inverse_fft2d(data)
+ array_name = gdalnumeric.GetArrayFilename(data_tr)
+
+ if self.switch_new_view.get_active():
+ gview.app.new_view()
+ gview.app.file_open_by_name(array_name)
+ else:
+ gview.app.file_open_by_name(array_name)
+
+TOOL_LIST = ['FFT2Tool']
+</pre>
+
+As you can see, the most laborious part of the work is creating GUI
+controls.<p>
+
+<h2><a name="section1c">XML File Configuration</a></h2>
+XML configuration files are located in OpenEV's "xmlconfig" directory.
+Parts of a view menu XML file are shown below. The GViewAppMenu enclosing
+entry indicates that this is a configuration file for the menus in the main
+view window; this entry would be GViewAppIconBar for the main view window
+icon bar, or GViewAppPyshell for the python shell. <p>
+
+The <entry> items below are used to indicate the locations of standard
+view window entries- ie. those that have callbacks defined in gvviewwindow.py.
+The <path> part of the entry indicates how the entry will show up in the
+menu; <callback> indicates which gvviewwindow callback to use. The
+'File/rfl1' entry demonstrates how a simple argument (int or string) can
+be passed to the callback. <p>
+
+The <tools>, <simpletoolentry>, and <complextoolentry> items are used
+to define which tools' menu and icon entries will show up, and to
+customize their appearance. If no tool entries will be specified, all
+currently loaded tools will be shown.
+If a tool is indicated in the file but is not loaded, an error will occur.
+The <tools> entry, if present, must contain one of the strings All,
+None, or Some. If <tools> is All, all currently loaded tools will have
+entries in the view menu. If <tools> is None, no tool entries will be
+loaded in the view menu, and an error will occur if <simpletoolentry>
+or <complextoolentry> items occur later in the XML file. If <tools> is
+Some, only entries specified through <simpletoolentry> or <complextoolentry>
+items will show up. <p>
+
+The <simpletoolentry> item is used to put in tool entries using their
+Menu paths. The position of the menu entry will be determined by
+the entry's position in the XML file. For instance, GDALTool (the
+Export tool- Tool_Export.py) defines a menu entry "File/Export". In
+the case below, its entry would show up between "Import" and "Print"
+in the "File" menu. <p>
+
+The <complextoolentry> item is used to redefine the path names, and to
+select among entries to show in cases where a tool defines more than
+one menu entry. Each <complextoolentry> must define the tool,
+the old menu path (tool default) corresponding to the callback to be
+used, and a new menu path. The old menu path is used as a key to
+the tool's menu_entries dictionary to locate the desired callback.
+For instance, the <complextoolentry> item
+below indicates that the callback from RenderTestTool that corresponds
+to its "Render Test" entry under the "Tools" menu should appear in this view
+as a "Render Test" entry under the "File" menu, between the "Print"
+and separator items. If RenderTestTool specified other menu entries,
+they would have to appear as separate <complextoolentry> items in
+order to appear in the view menu. <p>
+
+<pre>
+<GViewAppMenu>
+ <Menu>
+ <tools>All</tools>
+ <entry>
+ <path>'File/Import'</path>
+ <callback>self.file_import_cb</callback>
+ </entry>
+ <simpletoolentry>
+ <name>GDALTool</name>
+ </simpletoolentry>
+ <entry>
+...
+ <path>'File/Print'</path>
+ <callback>self.print_cb</callback>
+ </entry>
+ <complextoolentry>
+ <name>RenderTestTool</name>
+ <oldpath>'Tools/Render Test'</oldpath>
+ <newpath>'File/Render Test'</newpath>
+ </complextoolentry>
+ <entry>
+ <path type="separator">'File/'</path>
+ </entry>
+ <entry>
+ <path>'File/rfl1'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>1</arg>
+ </arguments>
+ </entry>
+...
+ </Menu>
+</GViewAppMenu>
+</pre>
+
+In the icon bar XML file, the entry parameters defined are the file to use
+for the icon (<xpm>), the tooltip text (<hint>), and the
+callback. Position in the icon bar is determined by an entry's position
+in the file.<p>
+
+As in the menu bar XML file, the tool entries are specified using the <tool>,
+<simpletoolentry>, and <complextoolentry> items. Tool icon entries are stored
+internally as a list rather than a dictionary in case an application wishes to
+use the same icon file twice with different tooltip text to differentiate between
+callbacks, so an index is used to specify which of a tool's icon entries to use.
+The <complextoolentry> item can be used to override the icon file, hint, help (not
+currently used by OpenEV for icons) and position of an item.<p>
+
+An example of an XML icon file for view windows is given below (... indicates
+where sections have been removed for brevity):
+
+<pre>
+<GViewAppIconBar>
+ <Iconbar>
+ <icon>
+ <xpm>'openfile.xpm'</xpm>
+ <hint>'Open and Display Raster/Vector File'</hint>
+ <callback>self.file_open_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'print.xpm'</xpm>
+ <hint>'Print Current View'</hint>
+ <callback>self.print_cb</callback>
+ <help>'gvprint.html'</help>
+ </icon>
+ ...
+ <complextoolentry>
+ <name>ShapesGridTool</name>
+ <hint>Newhint</hint>
+ <index>0</index>
+ </complextoolentry>
+ ...
+ </Iconbar>
+</GViewAppIconBar>
+</pre>
+
+The python shell menu and icons entries are combined together
+in a single file that also indicates other options in the pyshell layout, such
+as whether a history area and progress bar are present. The menu and icon
+specifications are analogous to the view menu and icon specifications. The message
+area and prompt will always be present. An example of a python shell XML configuration
+file is given below: <p>
+
+<pre>
+<GViewAppPyshell>
+ <Menu>
+ <tools>All</tools>
+ <entry>
+ <path>'File/Preferences'</path>
+ <callback>self.preferences_cb</callback>
+ </entry>
+ <entry>
+ <path>'File/Quit'</path>
+ <callback>self.close_cb</callback>
+ <accelerator>control+D</accelerator>
+ </entry>
+ <entry>
+ <path>'Help/Help'</path>
+ <callback>self.launch_help_cb</callback>
+ </entry>
+ </Menu>
+ <Iconbar>
+ <tools>Some</tools>
+ <complextoolentry>
+ <name>MyTool</name>
+ <hint>MyToolHint</hint>
+ <index>0</index>
+ </complextoolentry>
+ </Iconbar>
+ <History>
+ </History>
+ <Progress>
+ </Progress>
+</GViewAppPyshell>
+</pre>
+In the case above, an empty entry (eg. <History> </History>)
+indicates that the entry should be present with the default settings.
+If an entry is not present (eg. the whole <Menu>...</Menu>
+entry was removed), that component will not be present. If the component is
+present, only the subentries
+specified will be used. The file above specifies a python shell with
+a menu with all tool menu entries, plus entries for the help callback
+(Help-> Help), a quit entry (File-> Quit), and an entry for specifying
+paths to search for python modules (File-> Preferences).
+The iconbar would contain only a single
+entry- the first icon entry specified in tool MyTool, with its hint text
+replaced by MyToolHint. The history bar and progress bar would be
+present with their default settings (currently there are no options
+to alter in these- they are either present or not present).
+The progress bar is not used automatically even if it is present, though
+functions that are going to take a long time can update it by
+importing gview and placing the following line inside the function
+wherever they want the progress bar to update:
+
+<pre>
+gview.app.shell.show_progress(i,msg)
+</pre>
+<p>
+where <i>i</i> is a number between 0 and 100 (the amount of progress
+to show in the bar), and msg is a string to display in the message
+section.
+<p>
+
+<a href="#contents">Top</a><p>
+<a href="openevmain.html>OpenEV Help</a><p>
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_big_picture.png
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/COURSE1_big_picture.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_gdal_datamodel.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/COURSE1_gdal_datamodel.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/COURSE1_gdal_datamodel.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,259 @@
+<html>
+<head>
+<title>GDAL Data Model</title>
+</head>
+
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<pre>
+
+ GDAL Data Model
+ ===============
+
+This document attempts to describe the GDAL data model. That is the
+types of information that a GDAL data store can contain, and their
+semantics.
+
+Dataset
+=======
+
+A dataset (represented by the GDALDataset class) is an assembly of
+related raster bands and some information common to them all. In particular
+the dataset has a concept of the raster size (in pixels and lines) that
+applies to all the bands. The dataset is also responsible for the
+georeferencing transform and coordinate system definition of all bands. The
+dataset itself can also have associated metadata, a list of name/value
+pairs in string form.
+
+Note that the GDAL dataset, and raster band data model is loosely
+based on the OpenGIS Grid Coverages specification.
+
+Coordinate System
+-----------------
+
+Dataset coordinate systems are represented as OpenGIS Well Known Text
+strings. This can contain:
+
+ o An overall coordinate system name.
+ o A geographic coordinate system name.
+ o A datum identifier.
+ o An ellipsoid name, semi-major axis, and inverse flattening.
+ o A prime meridian name and offset from Greenwich.
+ o A projection method type (ie. Transverse Mercator).
+ o A list of projection parameters (ie. central_meridian).
+ o A units name, and conversion factor to meters or radians.
+ o Names and ordering for the axes.
+ o Codes for most of the above in terms of predefined coordinate systems
+ from authorities such as EPSG.
+
+For more information on OpenGIS WKT coordinate system definitions, and
+mechanisms to manipulate them, refer to the osr_tutorial document and/or the
+OGRSpatialReference class documentation.
+
+The coordinate system returned by GDALDataset::GetProjectionRef()
+describes the georeferenced coordinates implied by the affine georeferencing
+transform returned by GDALDataset::GetGeoTransform(). The coordinate
+system returned by GDALDataset::GetGCPProjection() describes the
+georeferenced coordinates of the GCPs returned by GDALDataset::GetGCPs().
+
+Note that a returned coordinate system strings of "" indicates nothing
+is known about the georeferencing coordinate system.
+
+Affine GeoTransform
+-------------------
+
+GDAL datasets have two ways of describing the relationship between
+raster positions (in pixel/line coordinates) and georeferenced coordinates.
+The first, and most commonly used is the affine transform (the other is
+GCPs).
+
+The affine transform consists of six coefficients returned by
+GDALDataset::GetGeoTransform() which map pixel/line coordinates into
+georeferenced space using the following relationship:
+
+ Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
+ Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
+
+In case of north up images, the GT(2) and GT(4) coefficients are zero, and
+the GT(1) is pixel width, and GT(5) is pixel height. The (GT(0),GT(3))
+position is the top left corner of the top left pixel of the raster.
+
+
+GCPs
+----
+
+A dataset can have a set of control points relating one or more positions
+on the raster to georeferenced coordinates. All GCPs share a georeferencing
+coordinate system (returned by GDALDataset::GetGCPProjection()). Each GCP
+(represented as the GDAL_GCP class) contains the following:
+
+typedef struct
+{
+ char *pszId;
+ char *pszInfo;
+ double dfGCPPixel;
+ double dfGCPLine;
+ double dfGCPX;
+ double dfGCPY;
+ double dfGCPZ;
+} GDAL_GCP;
+
+The pszId string is intended to be a unique (and often, but not always
+numerical) identifier for the GCP within the set of GCPs on this dataset.
+The pszInfo is usually an empty string, but can contain any user defined
+text associated with the GCP. Potentially this can also contain machine
+parsable information on GCP status though that isn't done at this time.
+
+The (Pixel,Line) position is the GCP location on the raster. The (X,Y,Z)
+position is the associated georeferenced location with the Z often being
+zero.
+
+The GDAL data model does not imply a transformation mechanism that must
+be generated from the GCPs ... this is left to the application. However
+1st to 5th order polynomials are common.
+
+Normally a dataset will contain either an affine geotransform, GCPs or
+neither. It is uncommon to have both, and it is undefined which is
+authoritative.
+
+
+Metadata
+--------
+
+GDAL metadata is auxilary format and application specific textual data
+kept as a list of name/value pairs. The names are required to be well
+behaved tokens (no spaces, or odd characters). The values can be of
+any length, and contain anything except an embedded null (ASCII zero).
+
+The metadata handling system is well tuned to handling very large bodies
+of metadata. Handling of more than 100K of metadata for a dataset is likely
+to lead to performance degredation.
+
+Over time there will be some well known names defined with established
+semantics; however, that has not occured at this time.
+
+Some formats will support generic (user defined) metadata, while other
+format drivers will map specific format fields to metadata names. For
+instance the TIFF driver returns a few information tags as metadata
+including the date/time field which is returned as:
+
+TIFFTAG_DATETIME=1999:05:11 11:29:56
+
+Raster Band
+===========
+
+A raster band is represented in GDAL with the GDALRasterBand class. It
+represents a single raster band/channel/layer. It does not necessarily
+represent a whole image. For instance, a 24bit RGB image would normally
+be represented as a dataset with three bands, one for red, one for green
+and one for blue.
+
+A raster band has the following properties:
+
+ o A width and height in pixels and lines. This is the same as that
+ defined for the dataset, if this is a full resolution band.
+
+ o A datatype (GDALDataType). One of Byte, UInt16, Int16, UInt32, Int32,
+ Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and
+ CFloat64.
+
+ o A block size. This is a preferred (efficient) access chunk size. For
+ tiled images this will be one tile. For scanline oriented images this will
+ normally be one scanline.
+
+ o A list of name/value pair metadata in the same format as the dataset,
+ but of information that is potentially specific to this dataset.
+
+ o An optional description string.
+
+ o An optional list of category names (effectively class names in a
+ thematic image).
+
+ o An optional minimum and maximum value.
+
+ o An optional offset and scale for transforming raster values into
+ meaningful values (ie translate height to meters)
+
+ o An optional raster unit name. For instance, this might indicate linear
+ units for elevation data.
+
+ o A color interpretation for the band. This is one of:
+ - GCI_Undefined: the default, nothing is known.
+ - GCI_GrayIndex: this is an independent grayscale image
+ - GCI_PaletteIndex: this raster acts as an index into a color table
+ - GCI_RedBand: this raster is the red portion of an RGB or RGBA image
+ - GCI_GreenBand: this raster is the green portion of an RGB or RGBA image
+ - GCI_BlueBand: this raster is the blue portion of an RGB or RGBA image
+ - GCI_AlphaBand: this raster is the alpha portion of an RGBA image
+ - GCI_HueBand: this raster is the hue of an HLS image
+ - GCI_SaturationBand: this raster is the saturation of an HLS image
+ - GCI_LightnessBand: this raster is the hue of an HLS image
+ - GCI_CyanBand: this band is the cyan portion of a CMY or CMYK image
+ - GCI_MagentaBand: this band is the magenta portion of a CMY or CMYK image
+ - GCI_YellowBand: this band is the yellow portion of a CMY or CMYK image
+ - GCI_BlackBand: this band is the black portion of a CMYK image.
+
+ o A color table, described in more detail later.
+
+ o Knowledge of reduced resolution overviews (pyramids) if available.
+
+
+Color Table
+-----------
+
+A color table conists of zero or more color entries described in C by the
+following structure:
+
+typedef struct
+{
+ /- gray, red, cyan or hue -/
+ short c1;
+
+ /- green, magenta, or lightness -/
+ short c2;
+
+ /- blue, yellow, or saturation -/
+ short c3;
+
+ /- alpha or blackband -/
+ short c4;
+} GDALColorEntry;
+
+The color table also has a palette interpretation value (GDALPaletteInterp)
+which is one of the following values, and indicates how the c1/c2/c3/c4 values
+of a color entry should be interpreted.
+
+ o GPI_Gray: Use c1 as grayscale value.
+ o GPI_RGB: Use c1 as red, c2 as green, c3 as blue and c4 as alpha.
+ o GPI_CMYK: Use c1 as cyan, c2 as magenta, c3 as yellow and c4 as black.
+ o GPI_HLS: Use c1 as hue, c2 as lightness, and c3 as saturation.
+
+To associate a color with a raster pixel, the pixel value is used as a
+subscript into the color table. That means that the colors are always
+applied starting at zero and accending. There is no provision for indicating
+a prescaling mechanism before looking up in the color table.
+
+
+Overviews
+---------
+
+A band may have zero or more overviews. Each overview is represented as
+a "free standing" GDALRasterBand. The size (in pixels and lines) of the
+overview will be different than the underlying raster, but the geographic
+region covered by overviews is the same as the full resolution band.
+
+The overviews are used to display reduced resolution overviews more quickly
+than could be done by reading all the full resolution data and downsampling.
+
+Bands also have a HasArbitraryOverviews property which is TRUE if the
+raster can be read at any resolution efficiently but with no distinct
+overview levels. This applies to some FFT encoded images, or images pulled
+through gateways (like OGDI) where downsampling can be done efficiently
+at the remote point.
+
+</pre>
+<a href="COURSE1_oev_talk.html">Frank's Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a>
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_lib_inherit.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/COURSE1_lib_inherit.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_numpy.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/COURSE1_numpy.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/COURSE1_numpy.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,55 @@
+<html>
+<head>
+<title>Numerical Python</title>
+</head>
+
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<pre>
+
+ Numerical Python
+ ================
+
+Numerical Python adds a fast, compact, multidimensional array language
+facility to Python.
+
+ o Complete information is available at http://www.pfdubois.com/numpy/
+
+ o Data types for arrays include byte, integer, float, double and complex.
+
+ o Arrays support a variety of python style slicing operations to access
+ subregions of the array.
+
+ o Numpy includes interfaces to the LAPACK linear algebra library and the
+ FFTPACK Fourier transforms library.
+
+ o Convenient methods have been adding for translating GDAL images into
+ NumPy arrays, and for displaying NumPy arrays in OpenEV. However, the
+ NumPy representation loses georeferencing, metadata, and colortables.
+
+This example loads a band from a GDAL supported file (dist_file) into a
+NumPy array (distmap), converts it to floating point, does some manipulations,
+displays the result and then saves to another file.
+
+ from Numeric import *
+ from gdalnumeric import *
+
+ distmap = LoadFile( dist_file )
+ # hack: make sure no values are zero
+ distmap = distmap.astype(Float32) + 0.001
+ weightmap = sample[3] / power (distmap , exponent)
+ weightmap = weightmap.astype(Float32)
+ display( weightmap )
+ SaveArray( weightmap, weight_file, 'PAux' )
+
+(demo similar steps in OpenEV using the Interactive Shell)
+
+It would be good to have a more in depth review of NumPy another time.
+</pre>
+<a href="COURSE1_gdal_datamodel.html">Next</a><br>
+<a href="COURSE1_oev_talk.html">Frank's Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a>
+</body>
+</html>
+
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_oev_talk.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/COURSE1_oev_talk.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/COURSE1_oev_talk.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,34 @@
+<html>
+<head>
+<title>Frank Warmerdam's OpenEV Course</title>
+</head>
+
+<body BGCOLOR="#FFFFFF">
+
+<body>
+
+<h1><a name="Introduction">Introduction</a></h1>
+
+This document is based on notes from a course that Frank
+Warmerdam gave to new developers at Atlantis a few years
+ago. It provides an introduction to the major components of the
+development environment (Python, OpenGL, GTK, GDAL, PROJ.4,
+NumPy), the OpenEV system architecture,
+initial design objectives, and technical information about
+the data model, layer drawing, editing
+tools, user interface, and command-line interface.
+
+<p>
+<h1><a name="Contents">Contents</a></h1>
+<ul>
+<li> <a href="COURSE1_openev.html">OpenEV Architecture</a>
+<li> <a href="COURSE1_python.html">Python</a>
+<li> <a href="COURSE1_numpy.html">Numerical Python</a>
+<li> <a href="COURSE1_gdal_datamodel.html">GDAL Data Model</a>
+</ul>
+
+<a href="COURSE1_openev.html">Next</a><br>
+<a href="../openevmain.html">OpenEV Help</a>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_openev.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/COURSE1_openev.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/COURSE1_openev.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,293 @@
+<html>
+<head>
+<title>OpenEV Architecture</title>
+</head>
+
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<pre>
+ OpenEV Architecture
+ ===================
+
+</pre>
+
+See the <a href="http://openev.sourceforge.net/lib_design_doc/openev.html">library design document</a>
+for the detailed library design.
+
+<pre>
+The following figure shows an inheritance diagram of the main OpenEV
+classes, described below.
+</pre>
+<img src="COURSE1_lib_inherit.gif">
+<pre>
+
+GvViewArea
+----------
+
+ o Derived from GtkGLArea (a GTK widget for drawing with OpenGL).
+
+ o Maintains a of GvLayers (in drawing order), and a concept of which is
+ the "active" layer for the purposes of editing, and some other operations.
+
+ o Maintains a current view state (camera position and orientation in 3D,
+ zoom factor and center point in 2D),
+
+ o Provides some automatic event handling for zooming, and panning.
+
+ o Generates the "active-changed", "view-state-changed", and "gldraw" events.
+
+
+GvData
+------
+
+ o Derived from GtkData.
+
+ o Primarily it provides services to implement undo semantics for many
+ different types of objects. See Undo discussion below.
+
+ o Generates the "changing", "changed" and "meta-changed" events.
+
+ o Implements core services for managing undo "mementos".
+
+ o Also contains a properties list, a projection, a name, and a concept of
+ a parent.
+
+GvShapes
+--------
+
+ o Derived from GvData.
+
+ o Acts as a container for the vector objects (GvShape structures).
+
+ o Implements all sorts of create, update (ie. translate) and delete
+ operations.
+
+ o Implements meaningful undo for all updates, create and delete operations.
+
+ o Note that the GvShapes container has no concept of selection ... that is
+ a GvShapesLayer concept.
+
+GvShape
+-------
+
+ o Unlike essentially everything else described here, the GvShape is just
+ a simple structure, it isn't derived from GtkObject. This is intended to
+ keep it lightweight.
+
+ o It represents a single vector feature.
+
+ o The supported geometry types are point, line and area. Areas may have
+ multiple rings allowing them to have holes.
+
+ o Geometries are all 3D, though Z is usually 0.
+
+ o Each GvShape has a properties list (list of name/value pairs).
+
+ o GvShape's are reference counted.
+
+ o GvShape's do retain some rendering related information (tesselation of
+ areas).
+
+GvRaster
+--------
+
+ o Derived from GvData.
+
+ o Represents one band of raster data (real, or complex) - it corresponds
+ directly to a GDALRasterBand.
+
+ o It maintains a tile oriented cache of raster data (in addition to the
+ cache maintained by GDAL!). The cache of raster data is still at the
+ original data depth ... that is it hasn't been scaled yet.
+
+ o The GvRaster cache is also maintained in different levels of detail
+ (currently up to 8 levels of detail in powers of 2).
+
+ o The GvRaster implements a number of averaging methods when computing
+ low res overviews from high res data, but they basically devolve to
+ averaging or sampling.
+
+
+GvLayer
+-------
+
+ o Derived from GvData.
+
+ o Represents a layer of stuff that can be placed in a view (GvViewArea)
+
+ o Provides the "setup", "teardown", "draw", "get-extents" and "display-change"
+ methods.
+
+GvShapeLayer
+------------
+
+ o Derived from GvLayer.
+
+ o Abstract class for all the "shape editing" concepts. These are implemented
+ as events, the most significant of which from an outside point of view are
+ "selection-changed", and "subselection-changed".
+
+ o Eventually it is likely that GvShapeLayer will be merged into GvShapesLayer
+ when we are sure we don't want other types of layers with vector editing
+ semantics, and when the old GvPointLayer, GvLineLayer and GvAreaLayer are
+ gone.
+
+GvShapesLayer
+-------------
+
+ o Derived from GvShapeLayer
+
+ o Handles all the drawing and selection for vectors, including points, lines,
+ areas, text, symbols and so forth.
+
+ o Interacts with an underlying GvShapes which contains the shape (feature)
+ data.
+
+ o Rendering of features is based on a partial implementation of the OGR
+ Feature Style Specification.
+
+
+GvRasterLayer
+-------------
+
+ o Derived from GvLayer
+
+ o Is used to render raster layers.
+
+ o Supported modes are RGBA, Greyscale (+alpha), Pseudo-coloured, and
+ 2D (Complex) Pseudocolored.
+
+ o The GvRasterLayer has a pseudocolor table (used only in some modes).
+
+ o Depending on the mode 1-4 GvRasters may be used for source data. The
+ GvRasters are called "sources" in the GvRasterLayer API, and represented
+ as the GvRasterSource structure.
+
+ o Each source may be set to a constant value (instead of reading from a
+ GvRaster). Normally the "alpha" (transparency) source is set to the
+ constant 255 indicating there is no transparency.
+
+ o Each source has independent scaling information (min/max), an optional
+ "nodata value", and a greyscale (enhancement) lut.
+
+ o Note that source raster data is read from a GvRaster, put through the
+ indicated scaling to 256 levels, optionally passed through the LUT and then
+ utliized as part of forming a GvRasterLayer image which may include it's own
+ pseudocolor table.
+
+ o The GvRasterLayer maintains a cache of OpenGL textures for fully rendered
+ data. This "texture" cache normally resides in the memory of the OpenGL
+ compliant video card, allowing very fast refresh of raster data. The
+ textures are the size of the tiles from the GvRaster ... currently hardcoded
+ to be 256x256 (254x254 active area due to required texture overlap).
+
+ o The GvRasterLayer maintains a mesh for each texture. This mesh describes
+ how the texture should be warped into "view" coordinates. The view
+ coordinates are normally georeferenced space (ie. UTM meters, lat/long
+ decimal degrees, or raw scene pixel/line). The mesh includes a Z
+ coordinate which is normally zero for 2d scenes.
+
+ o Normally the mesh just consists of values at the four corners of the texture
+ but when doing 3D modelling the mesh is generally produced at a higher
+ resolution (perhaps 8x8). The resolution of the mesh will dictate how
+ detailed a terrain can be represented; however, the more refined the mesh
+ the slower the rendering by OpenGL. It is prohibitively expensive in
+ OpenGL terms to have a mesh the same size as the raster for even a medium
+ sized raster.
+
+ o The GvRasterLayer tries hard to avoid "blocking" the program for very
+ long while loading data. This is mainly accomplished by only loading
+ one or a few tiles before re-rendering and returning control to the main
+ event loop.
+
+
+Undo
+----
+
+ o Discuss mementos.
+
+
+Edit Tools
+----------
+
+ o Discuss
+
+
+Higher Level (Python) OpenEV Architecture
+=========================================
+
+The above really describes the core C services of OpenEV. It doesn't
+really address how much of the high level application is composed. A
+few services, and classes worthy of note include:
+
+GvManager
+---------
+
+ o Implemented in C, python interfaces in gview.py.
+
+ o Maintains application wide preferences (actually loaded by python
+ code in gview.py).
+
+ o Maintains a list of open GDALDatasets, and GvRasters which have been
+ created for the GDALRasterBands. Essentially a central "file" cache.
+
+ o Provides prioritized "idle task" services, for stuff like deferred
+ raster loading.
+
+ o Maintains the "busy" flag.
+
+GvViewWindow
+------------
+
+ o Derived from GtkWindow. Implemented in Python.
+
+ o Provides the standard OpenEV dialog, including a menu (optional),
+ iconbar (optional), tracker (optional) and scrollbars (optional).
+
+ o Provides implementation of many of the menu options.
+
+GViewApp
+--------
+
+ o Derived from Signaler ... no GUI component.
+
+ o One instance of the class must be instantiated
+ for an application and provides some services shared between all views.
+
+ o Maintains recently used file list.
+
+ o Manages layer dialog, and toolbar dialog.
+
+ o Creates new views (as generic GvViewWindows).
+
+ o Open a file on the current view.
+
+ o Launch preferences panel, toolbar, python shell, etc. Basically lots
+ of dialogs of which there should be once instance for the application.
+
+
+</pre>
+<img src="COURSE1_test.png">
+<pre>
+
+Toolbar
+-------
+
+Standard (OpenEV) editing toolbar.
+
+
+
+The following figure shows how OpenEV, GDAL, GTK, Python, etc. fit together.
+</pre>
+<img src="COURSE1_big_picture.png" height=1000 width=1000>
+
+<a href="COURSE1_python.html">Next</a><br>
+<a href="COURSE1_oev_talk.html">Frank's Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a>
+</body>
+</html>
+
+
+
+
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_python.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/COURSE1_python.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/COURSE1_python.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,130 @@
+<html>
+<head>
+<title>Python</title>
+</head>
+
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<h1><a name="section1">Python</a></h1>
+<pre>
+
+Python is an open source interpreted, object-oriented, high-level programming
+language with dynamic semantics. Its high-level built in data structures,
+combined with dynamic typing and dynamic binding, make it very attractive for
+Rapid Application Development, as well as for use as a scripting or glue
+language to connect existing components together.
+
+ o Relatively simple syntax, but a full fledged language.
+
+ o Extensive standard libraries include string manipulation, subprocesses,
+ file access, math, sockets, time.
+
+ o Fairly easy to make C code callable from Python, normally by writing
+ a layer of "glue" code. In some cases the glue code can be automatically
+ generated using mechanisms like SWIG (used for GDAL).
+
+ o Python has built in data types for things like lists, tuples, and
+ dictionaries.
+
+ o Python is the scripting language for OpenEV, and Peppers and a good
+ chunk of each is written directly in Python. Atlantis has also implemented
+ Python access to GDAL and the OGR projection services.
+
+ o Python has many rich extension packages, including NumPy (Numeric Python)
+ an interpreted array math environment vaguely like Matlab or IDL.
+
+ o Python is not very declarative, thus relatively few errors can be found
+ at compile time. It is much more easy to write code that compiles, but
+ fails at runtime than in more declarative languages like Java. Python
+ is a weakly typed language.
+
+ o Debugging environments do exist for Python; however, I haven't had much
+ success with them. On the plus side, the fact that python "crashes" are
+ normally just generates run-time exceptions which report a traceback can
+ make fixing errors fairly easy. I personally, have often sunk back to the
+ level of debugging by adding print statements in Python.
+
+ I think it would be useful for us to review python IDE environments like
+ IDLE to see if we should be using them. (talk to Paul about his experiences)
+
+ o Python is compiled on the fly, so generally instead of the
+ edit-compile-link-run cycle, you just have the edit-run cycle. However,
+ generally speaking you do have to restart the application which is often
+ the "heavy" part of the whole debugging cycle.
+
+ o It is possible to use a conventional debugger (ie. gdb) to debug problems
+ in C modules called from Python. However, you can't get any meaningful
+ traceback information from the Python side of stuff.
+
+</pre>
+
+<h1><a name="section2">Python Bindings</a></h1>
+<pre>
+
+Example of implementing a Gtk style binding for a C function to be
+accessable from Python. Gtk style bindings are used for the bulk of the
+OpenEV C entry points (and Peppers?).
+
+The declarations file (gv.defs) contains information on each class, and
+method along with the methods return type, and types passed to it.
+
+(define-object GvRasterLayer (GvLayer))
+
+(define-func gv_raster_layer_zoom_set
+ int
+ ((GvRasterLayer layer)
+ (int max_mode)
+ (int min_mode)))
+
+...
+
+Once processed C wrapper code is created that presents a function style
+interface to the method. To make it operate like a method on a class, the
+following Python wrapper code is added to the class (in gview.py in this case).
+Note the style of inline documentation which can be extracted and placed on
+the web.
+
+ class GvRasterLayer(GvLayer):
+ ...
+ def zoom_set(self,mag_mode,min_mode):
+ """Set interpolation method
+
+ I believe mag_mode sets the interpolation mode when zooming in past
+ 1:1 on a texture, and min_mode is the interpolation mode used for
+ downsampling from the texture, but I am not sure. Both default to
+ bilinear, and are normally changed together.
+
+ mag_mode -- One of gview.RL_FILTER_BILINEAR or gview.RL_FILTER_NEAREST.
+ min_mode -- One of gview.RL_FILTER_BILINEAR or gview.RL_FILTER_NEAREST.
+ """
+ return _gv.gv_raster_layer_zoom_set( self._o, mag_mode, min_mode )
+
+
+A significant portion of C functions/methods cannot be automatically wrapped
+like the above, so instead custom C code is written to wrap them. This is
+normally required in cases where pointers to basic data types are passed or
+where it is desired to translate things into more natural Python data types
+(like tuples or dictinoaries). The following is an example of a simple
+C binding to expose a function to Python. Note that a Python "method" style
+wrapper is still generally required, like the other method.
+
+static PyObject *
+_wrap_gv_layer_extents(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_layer_extents", &PyGtk_Type, &layer))
+ return NULL;
+ gv_layer_extents(GV_LAYER(PyGtk_Get(layer)), &rect);
+ return Py_BuildValue("(ffff)", rect.x, rect.y, rect.width, rect.height);
+}
+</pre>
+<a href="COURSE1_numpy.html">Next</a><br>
+<a href="COURSE1_oev_talk.html">Frank's Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a>
+</body>
+</html>
+
+
Added: packages/openev/branches/upstream/current/html/developer_info/COURSE1_test.png
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/COURSE1_test.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,61 @@
+/COURSE1_big_picture.png/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/COURSE1_gdal_datamodel.html/1.2/Thu May 13 20:29:16 2004//
+/COURSE1_lib_inherit.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/COURSE1_numpy.html/1.2/Thu May 13 20:29:16 2004//
+/COURSE1_oev_talk.html/1.2/Thu May 13 20:29:16 2004//
+/COURSE1_openev.html/1.2/Thu May 13 20:29:16 2004//
+/COURSE1_python.html/1.2/Thu May 13 20:29:16 2004//
+/COURSE1_test.png/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_building_maintenance.html/1.4/Thu Apr 7 21:11:23 2005//
+/DEVCOURSE_classify_example.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_colour_raster.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_colour_raster.tif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_components.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_gdal.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_greyscale_raster.tif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_label_ss1.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_label_ss2.gif/1.2/Thu Sep 23 15:34:03 2004/-kb/
+/DEVCOURSE_label_ss3.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_label_ss4.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_label_ss5.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_mini_raster.tif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_open3d_ss1.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_open3d_ss2.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_open3d_ss3.gif/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_openev_files.html/1.3/Thu Apr 7 21:11:23 2005//
+/DEVCOURSE_point_classes.dbf/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_point_classes.shp/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_point_classes.shx/1.1/Thu Sep 11 23:02:29 2003/-kb/
+/DEVCOURSE_print_ss1.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_example.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_ss1.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_ss2.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_ss3.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_ss4.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_pyshell_ss5.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_python_bindings.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_rasterfile_ss1.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_rasterfile_ss2.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_rasterfile_ss3.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_rasterfile_ss4.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_scripts.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_shape_example.dbf/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_shape_example.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_shape_example.shp/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_shape_example.shx/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_shapefile_ss1.gif/1.1/Thu Sep 11 23:02:30 2003/-kb/
+/DEVCOURSE_subpixel_interpolation.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/DEVCOURSE_tools_commands.html/1.2/Thu May 13 20:29:16 2004//
+/DEVCOURSE_tutorial1.html/1.3/Thu Sep 23 14:26:09 2004//
+/DEVCOURSE_tutorial2.html/1.4/Thu Sep 23 15:34:03 2004//
+/DEVCOURSE_tutorial3.html/1.3/Thu Sep 23 14:26:09 2004//
+/DEVCOURSE_vector_classes.dbf/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/DEVCOURSE_vector_classes.shp/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/DEVCOURSE_vector_classes.shx/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/DEVCOURSE_vector_classify.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/DEVCOURSE_vector_layerstyles.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/pyshell_example.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/pyshell_full.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+/pyshell_help.gif/1.1/Thu Sep 11 23:02:31 2003/-kb/
+D
Added: packages/openev/branches/upstream/current/html/developer_info/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/html/developer_info
Added: packages/openev/branches/upstream/current/html/developer_info/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,38 @@
+<html>
+<head>
+<title>OpenEV Developer Course</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<h1>Introduction</h1>
+
+This document was written for an internal
+OpenEV developer course at Atlantis. It covers
+OpenEV components, major files, some aspects of
+multi-platform building/troubleshooting, extending
+OpenEV, and scripting.
+
+<h1><a name="Contents">Contents</a></h1>
+<ul>
+<li>Overview: The
+<a href="../openevmain.html">OpenEV help files</a> provide
+a description of OpenEV's dialogs and capabilities. The
+<a href="DEVCOURSE_tutorial1.html">Tutorials</a> supply a demonstration
+of some of these.
+<li><a href="DEVCOURSE_components.html">Components: GTK, OpenGL, Proj, etc.</a>
+<li><a href="DEVCOURSE_gdal.html">Geospatial Data Abstraction Library (GDAL)</a>
+<li><a href="DEVCOURSE_python_bindings.html">Python Bindings</a>
+<li><a href="DEVCOURSE_openev_files.html">Important OpenEV Files</a>
+<li><a href="DEVCOURSE_tutorial1.html">Tutorial: General Overview</a>
+<li><a href="DEVCOURSE_tutorial2.html">Tutorial: Working with Vectors</a>
+<li><a href="DEVCOURSE_tutorial3.html">Tutorial: Working with Rasters</a>
+<li><a href="DEVCOURSE_tools_commands.html">Extending OpenEV- Tools and Commands</a>
+<li><a href="DEVCOURSE_scripts.html">Scripting with OpenEV/GDAL</a>
+<li><a href="DEVCOURSE_building_maintenance.html">Building and Maintenance</a>
+</ul>
+<p>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_building_maintenance.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_building_maintenance.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_building_maintenance.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <title>Building and Maintenance</title>
+</head>
+<body style="background-color: rgb(255, 255, 255);">
+<h1>Building and Maintenance</h1>
+<h2>Building OpenEV from scratch</h2>
+<h3>Linux/Unix</h3>
+<ol>
+ <li>First, download the source for Mesa, gtkglarea, python, pygtk,
+gtk/gdk/glib, gtk+extra, python-gtkextra, gnuplot, and proj (for
+gnuplot and proj, just the binary executables and
+library are fine). Note that OpenEV uses gtk 1.2.x and pygtk 0.6.x, not
+gtk 2.x and pygtk 1.99.x. </li>
+ <li>Optionally, create a new directory to install the libraries in.
+You could
+install directly to your system directories, but different versions of
+gtk/Mesa in particular might not mesh with other applications, so a new
+directory is safest. </li>
+ <li> Create a "build_setup.csh" setup file to set your paths
+to point to the new installation directory first. This is
+important for ensuring that the correct libraries are found for those
+packages that depend on others (eg. pygtk). The following example
+assumes that the newly-built libraries have been installed in
+/data/local_installations.:
+ <pre># setup for openev/gdal, other builds<br><br>setenv PATH "/data/local_installations/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/local/bin:/opt/bin:/usr/X11R6/bin:/usr/X11R6/bin"<br>setenv PYTHONHOME "/data/local_installations"<br>setenv LD_LIBRARY_PATH "/data/local_installations/lib"<br><br># environment variables needed by gdal/proj for some coordinate transformations<br># at run time (not technically needed for build). NOTES: Some additional gdal .csv<br># data files can be found in the source for libgeotiff. Also, if<br># you are going to be doing nad27-nad83 conversion, see proj/nad/README for information<br># on downloading additional (platform-dependent) data files for share/proj.<br><br>setenv GEOTIFF_CSV "/data/local_installations/share/gdal"<br>setenv GDAL_DATA "/data/local_installations/share/gdal"<br>setenv PROJ_LIB "/data/local_installations/share/proj"<br></pre>
+ </li>
+On solaris and irix, the standard directories will be different,
+and
+you may have to add other paths to your LD_LIBRARY_PATH (after
+the new directory path). Source this setup script before doing any
+building. <li> On irix, you may also have to set the environment
+variable CPP
+to be
+"gcc -E" if the default preprocessor is a Kernaghan & Ritchie one
+(this
+might be the case if configure complains about the presence of
+elif's in headers). </li>
+ <li> On solaris, if the build stops with messages about "Relocation
+errors",
+you might have to add "-fPIC" to the C and C++ compile options in the
+Makefile. </li>
+ <li> On irix or solaris, if you get messages about "Undefined
+symbols",
+make sure that all the necessary headers are in the include path in
+the Makefile, and that the most up-to-date header is the one being
+used by the Makefile (directories with the latest builds should be
+first
+in the include list). </li>
+ <li> You may also have to play with the CC, CXX/CPP, and LD_SHARED
+variables in the Makefile if OpenEV is to work with applications
+built with a specific version of C/C++ compilers. </li>
+ <li> Configure and build and install glib:
+ <pre>./configure --prefix=/data/local_installations<br>make<br>make install<br></pre>
+ </li>
+ <li> Configure and build and install gtk:
+ <pre>./configure --prefix=/data/local_installations --with-glib-prefix=/data/local_installations<br>make<br>make install<br></pre>
+ </li>
+ <li> Configure and build and install Mesa
+ <pre> ./configure --prefix=/data/local_installations<br>make<br>make install</pre>
+ </li>
+ <li>If 10 doesn't work, try:
+ <pre>cp Makefile.X11 Makefile<br>make linux-x86 (or whatever is appropriate- see the list at the top of the Makefile)<br>- copy all the .so's to your install library directory<br>- copy the include/GL to your install include directory<br></pre>
+ </li>
+ <li> Configure and build and install gtkglarea
+ <pre> ./configure --prefix=/data/local_installations --with-gtk-prefix=/data/local_installations --with-GL-prefix=/data/local_installations --with-lib-GL<br>make<br>make install<br></pre>
+ </li>
+ <li> Configure and build Python:
+ <pre> ./configure --prefix=/data/local_installations<br>make<br>make install<br></pre>
+ </li>
+ <li> Install the python extensions:
+ <pre>python setup.py install<br></pre>
+ </li>
+ <li> Download and install Numeric python.
+ <pre>python setup.py install<br></pre>
+ </li>
+ <li> Configure and make and install pygtk:
+ <pre> ./configure --prefix=/data/local_installations --with-gtk-prefix=/data/local_installations --with-gl-prefix=/data/local_installations --with-gtkgl-prefix=/data/local_installations --disable-imlibtest --disable-gdk-pixbuftest --disable-thread<br>make<br>make install<br></pre>
+ </li>
+ <li> Configure and make and install gtk+extra:
+ <pre> ./configure --prefix=/data/local_installations --with-gtk-prefix=/data/local_installations<br>make <br>make install<br></pre>
+ </li>
+ <li> Install python-gtkextra:
+ <pre>python setup.py install<br>cd /data/local_installations/lib/python?.?/site-packages<br>mv gtkextra pygtkextra<br></pre>
+The last move avoids namespace conflicts with pygtk's GtkExtra on
+Windows. </li>
+ <li> Configure and make and install proj:
+ <pre>./configure --prefix=/data/local_installations<br>make<br>make install<br></pre>
+ </li>
+ <li> Check out and build GDAL:
+ <pre>setenv CVSROOT :pserver:cvsanon at cvs.maptools.org:/cvs/maptools/cvsroot<br>cvs login<br>password: *enter*<br>cvs checkout gdal <br>cd gdal<br>./configure --prefix=/data/local_installations --with-libz=internal --with-png=internal --with-libtiff=internal --with-geotiff=internal<br>make<br>make install<br></pre>
+The options included here force gdal to compile with internal code
+rather than using
+other libraries for png/libz/libtiff/geotiff (in case end users do not
+have these libraries installed). </li>
+ <li> Check out and build OpenEV:
+ <pre>setenv CVSROOT <tt>:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev</tt><enter><br>cvs checkout openev<br></enter>password: *enter*<br><enter>./configure --with-gtk-prefix=/data/local_installations --with-gl-prefix=/data/local_installations --with-gtkgl-prefix=/data/local_installations --prefix=/data/local_installations --with-ogr<br>make<br></enter></pre>
+ </li>
+You may have to adjust the makefiles (Makefile and
+pymod/Makefile) to
+find the necessary headers on solaris/irix (configure doesn't always
+work properly). In particular, "-I/data/local_installations/include"
+may need to be added to Makefile and pymod/Makefile depending on where
+gtk/glib installed the headers. <li> Creating a distribution: There is
+a "mkdist" script in OpenEV's
+"delivery" directory that will
+copy the necessary files into two directories under "delivery"-
+"common", and "(Platform)", where
+(Platform) is either Linux, IRIX64, or SunOS. You will have to edit
+mkdist to find the libraries
+properly on your machine before running it, and may have to change the
+version numbers. Prior to running mkdist, you should make sure that
+none of your local files are in the openev directories (especially
+pymod), as they will be copied to the distribution. It is best to build
+a release from clean
+openev/gdal builds. After this, you will need to set the permissions on
+the files properly, eg.:
+ <pre>#!/bin/sh<br><br># Sets file permissions in deliverable.<br><br>openev_DIR=`pwd`<br>platform_NAME=`uname -s`<br><br>case "${platform_NAME}" in<br> "Linux") plat_DIR="${openev_DIR}/Linux";;<br> "SunOS") plat_DIR="${openev_DIR}/SunOS";;<br> "IRIX64") plat_DIR="${openev_DIR}/IRIX64";;<br> *) echo "Unknown Platform! Exiting..."; exit 1;;<br>esac<br><br>common_DIR="${openev_DIR}/common"<br><br>cd "${plat_DIR}"<br>find . -type f -exec chmod a+r {} \;<br>find . -type d -exec chmod 755 {} \;<br>find . -name "*.so*" -exec chmod 755 {} \;<br>find . -name "openev.py" -exec chmod 755 {} \;<br>find . -name "openev" -exec chmod 755 {} \;<br>find . -name "python" -exec chmod 755 {} \;<br>find . -name "gdaladdo" -exec chmod 755 {} \;<br>find . -name "gdalinfo" -exec chmod 755 {} \;<br>find . -name "gdal_translate" -exec chmod 755 {} \;<br>find . -name "gvtest" -exec chmod 755 {} \;<br><br>cd "${common_DIR}"<br>find . -type f -exec chmod a+r {} \;<br>find . -type d -exec chmod 755 {} \;<br></pre>
+After running mkdist, you must also be sure to create links in the lib
+directory to match those in the installation you copied from, and to
+change the ownership and group of both common and (Platform)
+recursively to "root". The common and (Platform) directories can then
+be tarred up for distribution. </li>
+</ol>
+<h3>Windows</h3>
+<ol>
+ <li> The following steps should be done in a DOS command shell. This
+description is for compiling with
+Microsoft Visual C++ version 6.0: </li>
+ <li> Download python source and follow the build instructions for
+windows. </li>
+ <li> Download and Mesa and follow the build instructions for windows
+(the OpenGL headers in MSVC++ may be too old- need at least OpenGL 1.1
+for raster symbols to work in openev). </li>
+ <li> Check out pkgsrc from sourceforge:
+ <pre>setenv CVSROOT <tt>:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev</tt><br>cvs checkout pkgsrc<br></pre>
+This contains versions of glib, gtk, etc. that have been slightly
+modified to compile
+and work properly on windows. </li>
+ <li> Edit pkgsrc's nmake.opt to point to the correct directories on
+your machine. </li>
+ <li> Find Microsoft Visual C++ (MSVC++)'s VCVARS32.BAT file and run
+it (this sets up the environment variables that MSVC++ needs). </li>
+ <li> nmake /f makefile.vc </li>
+ <li> Check out gdal, update the directory locations in nmake.opt for
+your machine. </li>
+ <li> nmake /f makefile.vc (at the top level of gdal) </li>
+ <li> Check out openev parallel to gdal and pkgsrc </li>
+ <li> nmake /f makefile.vc </li>
+</ol>
+Note that sometimes windows makefiles get messed up (something to do
+with linefeeds). If you get a cryptic error, open the file in MSVC++,
+accept its changes if it beeps at you, delete
+extra lines that shouldn't be there, and save. The windows makefiles
+are also not always updated properly. You may have to add/remove things
+based on the linux/unix versions if the problem isn't the linefeeds.
+<h2>Maintenance Issues</h2>
+<ul>
+ <li> Updating- Often people work with different versions of proj,
+GDAL, and even python/gtk. If you see an error message that
+mentions something beginning with "pj", eg. "pj_get_defs", you
+may need to update your proj library. </li>
+ <li> New modules- Before using new python modules (or other
+open source software) found on the web, check to ensure that their
+licenses are LGPL-compliant (Library or Lesser GNU Public License). </li>
+</ul>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+<br>
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_classify_example.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_classify_example.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.tif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_colour_raster.tif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_components.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_components.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_components.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,143 @@
+<html>
+<head>
+<title>OpenEV Components</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+
+<body>
+<h1> OpenEV Components</h1>
+<h2>GTK</h2>
+A complete description of GTK can be found at the
+<a href="http://www.gtk.org/">GTK Website</a>. A few points are
+noted here:
+<p>
+
+<ul>
+<li> GTK+ stands for "The GIMP Toolkit", and was created as part of the GIMP
+ ("GNU Image Manipulation Program") implementation. It is used for
+ creating graphical user interfaces.
+
+<li> It is written in c, and in version 1.2.x (the version that OpenEV
+ uses), it is composed of three main libraries:
+ <ol>
+ <li> glib- provides definitions and routines for lists, trees, memory
+ allocation,basic data types (points, lines), etc.
+ <li> gdk ("The GIMP Drawing Kit")- provides functions to trap keyboard and
+ mouse events, and also to create a drawable window and draw basic
+ objects such as lines, points, rectangles etc. The code in gdk is
+ highly platform-dependent: event trapping, window drawing are
+ very different between X-windows systems such as Linux, and Windows.
+ gdk wraps these functions into a common API so that the gtk code can
+ be less platform dependent. Events include button press/click/releases,
+ key pressing, cursor motion, etc.
+ <li> gtk - provides more advanced widgets such as buttons, toolbars,
+ menus, tree views, file selection dialogs. For instance, the gtk
+ button (gtkbutton.c) contains functions that know how to draw a button
+ in a window, and functions to execute when gdk events are trapped
+ (eg. what to do when the button is pressed, how to show it is
+ raised/lowered, etc). These are based heavily on gdk functions.
+ </ol>
+<li> All of OpenEV's windows (the main viewing window, dialogs, etc.) build
+upon the GtkWindow class.
+<li> There is a helpful online <a href="http://www.moeraki.com/pygtktutorial/pygtktutorial/index.html">tutorial</a> describing GTK's python bindings
+with examples.
+</ul>
+
+<h2>OpenGL</h2>
+
+<ul>
+<li> OpenGL defines a hardware-independent software interface to graphics
+ hardware. It specifies how various drawing-related functions should
+ be defined (names, parameters, etc.). The advantage of this is that
+ code using this API can work with any hardware that supplies an OpenGL
+ driver.
+
+<li> Mesa implements this API in software- if <path to OpenEV>/lib/Mesa
+ is added to your LD_LIBRARY_PATH variable on Linux/Unix, Mesa (libGL.so,
+ libGLU.so) will be used. Hardware-accelerated platforms provide the
+ interface without the need for Mesa, and are faster (though sometimes
+ flakey). Mesa relies on having
+ the "glx" extension on X-Windows systems and the "wgl" routines on
+ Windows. These extend the window systems enough so that the basic OpenGL
+ commands can be defined in an efficient manner. For instance, on X
+ servers, the glx extension allows OpenGL to bypass the X server's
+ involvement and render graphics directly in places where it is necessary for
+ performance. For more on Mesa, see <a href="http://www.mesa3d.org/">this site</a>.
+
+<li> The actual OpenGL commands in OpenEV are all at the c-level.
+</ul>
+
+An example of OpenGL commands follows:
+<pre>
+ if (view->dragging_mode)
+ {
+ gvgeocoord x[4], y[4];
+
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->state.mpos_y,
+ x+0, y+0 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->state.mpos_y,
+ x+1, y+1 );
+ gv_view_area_map_pointer( view,
+ view->last_mpos_x, view->last_mpos_y,
+ x+2, y+2 );
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->last_mpos_y,
+ x+3, y+3 );
+
+ glColor3f(1.0, 0.5, 0.0);
+ glBegin(GL_LINE_LOOP);
+ glVertex2(x[0], y[0]);
+ glVertex2(x[1], y[1]);
+ glVertex2(x[2], y[2]);
+ glVertex2(x[3], y[3]);
+ glEnd();
+ }
+</pre>
+
+This is the piece of code that draws the little orange rectangle when
+you left-click and drag to zoom in on a region. It takes the corner
+coordinates of the area you dragged out, maps them into georeferenced
+coordinates (the gv_view_area_map_pointer calls), sets the drawing
+colour to orange (the glColor3f command), specifies that it is beginning
+to draw a closed loop (the glBegin call), draws the vertices, then
+ends the loop with glEnd. Mesa or your hardware driver provide the
+definitions of the OpenGL commands (glColor3f, glBegin, etc.). For
+more, see the gv_view_area_expose function in gvviewarea.c, or the draw
+functions in the layer c-code (gvrasterlayer.c, gvshapeslayer.c).
+
+<h2>gtkglarea</h2>
+
+GTK defines gtk_drawing_area as a base class for widgets that need a box
+to draw into. gtkglarea extends this class to allow it to accept OpenGL
+commands for drawing. OpenEV's gvviewarea adds the concept of layers
+and tools, and adds the OpenGL commands necessary for georeferenced
+display, 3D, etc. For more information, see
+<a href="http://sal.kachinatech.com/F/3/GTKGLAREA.html">this site</a>.
+
+<h2>proj</h2>
+
+Proj is used by GDAL to do projection transformations, for instance
+between lat/longs and utm. OpenEV will function without proj, but in certain
+cases the georeferenced display will not be correct. For instance, when a
+georeferenced MFF2 file is read in,
+corner coordinates are specified in lat/longs even if the image is
+projected in utm coordinates. In the utm case, GDAL must convert the corner
+coordinates from lat/longs to utm prior to display so that the image does
+not appear incorrectly warped. Proj is used in this conversion. For more
+information see the <a href="http://www.remotesensing.org/proj/">Proj website</a>.
+
+<h2>Gnuplot</h2>
+
+Provides plotting functionality. This is used in OpenEV through the
+gvplot.py wrapper. For more information, see the
+<a href="http://www.comnets.rwth-aachen.de/doc/gnu/gnuplot37/gnuplot.html">Gnuplot website</a>.
+
+<p>
+<a href="DEVCOURSE_gdal.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_gdal.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_gdal.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_gdal.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,97 @@
+<html>
+<head>
+<title>GDAL (Geospatial Data Abstraction Library)</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+<h1>GDAL Summary (from an OpenEV perspective)</h1>
+<ul>
+<li> A library used to read/write datasets
+
+<li> Datasets fall in two main categories from OpenEV's perspective:
+ raster, and vector. Raster files
+ are image data, a complete 2 or more dimensional array of values displayed
+ in OpenEV as a grayscale grid (one or two bands) or in colour if there
+ are more than 2 bands (one colour grid for each of three bands, with
+ the option to use another band to specify the degree of transparency).
+ Vector files consist
+ of a set of points, lines, or polygons (groups of points).
+ Here is an example of a raster image displayed in an OpenEV window:
+ <img src="DEVCOURSE_colour_raster.gif">
+ <p>
+ Here is an example of a vector file, displayed in an OpenEV window:
+ <img src="DEVCOURSE_shape_example.gif">
+
+<li> GDAL started out as a raster library, then pulled in OGR to become a
+ vector library as well. OpenEV does not use GDAL/OGR to read shapefiles- it
+ has its own internal code to read in this information (shpopen.c), but it
+ does use OGR to open other types of vector files (eg. UK.NTF, Arc/Info
+ Binary Coverage, Mapinfo File). OGR is an optional configuration option
+ in both gdal and OpenEV- on by default in gdal, off in OpenEV.
+ There is separate code in OpenEV that is only compiled when ogr is
+ turned on (gvogr.c)- this converts the ogr objects to a GvShapes
+ object (GvShapes is the class that OpenEV uses to represent collections
+ of vector objects for display). In gdal,
+ OGR is also used in doing coordinate transformations.
+
+<li> Aside: OGR used to stand for "OpenGIS Simple Features Reference
+ Implementation", however it no longer is compliant with the Simple
+ Feature specification, so although the term OGR is still used,
+ its meaning is irrelevant.
+
+<li> GDAL reads in a file and gathers the basic information needed for display.
+ For a raster file, the most basic information is the image size, the offset
+ where the actual data starts within the file or fileset, the datatype, and
+ how the data is stored (eg. byte order, band interleaving etc.). Additional
+ information may also be pulled out and stored (eg. metadata, georeferencing
+ information), depending on the format. The information is stored as a
+ gdal Dataset (see Dataset in gdal.py for code). For a vector file, the
+ number and type of shapes stored must be known, along with how to extract
+ the vectors and attribute information. This information may be stored in
+ an OpenEV GvShapes object directly (if read from a shapefile), or stored
+ in an ogr Dataset and converted to a GvShapes object before display.
+
+<li> GDAL can take in extra information from other libraries if configured to
+ do so. For instance, if it is configured with --libtiff=internal, it will use
+ internal code for tiffs that just contains enough information to read
+ basic fields. However, it can also be configured to link to an external
+ tiff library that may offer more specific information on certain fields,
+ provided the library follows the expected API. Some filetypes can only be
+ read by linking to external libraries (eg. jpeg 2000); these are not
+ configured in by default.
+ The gdal web page indicates the maximum number of formats supported, not
+ the default. Some versions of OpenEV have a formats tool (Help->Formats
+ menu entry) that searches GDAL's driver list at runtime and displays
+ a widget summarizing this information.
+
+
+<li> GDAL utilities (apply to rasters only):
+<ol>
+<li>gdal_translate- Translate files into other formats, window files,
+ rescale files, extract bands.
+<li>gdaladdo- Add tiled overviews to a raster.
+<li>gdalinfo- Give information about a raster file (format, size, metadata).
+<li>gdal_warp- Reprojection and warping utility, mosaicing.
+<li>gdaltindex- Build a shapefile with a record for each input raster
+file, an attribute containing the filename, and a polygon geometry outlining
+the raster.
+<li> rgb2pct.py- compute a pseudocolor table for an rgb image.
+<li>gdal_merge.py- Mosaic a set of images.
+<li>gdal-config- Information about the gdal installation.
+</ol>
+For more, see the <a href="http://www.remotesensing.org/gdal/gdal_utilities.html">GDAL Utilities</a> website.
+<li>There are also OGR utilities for vectors:
+<ol>
+<li> ogrinfo- Give information about a vector file.
+<li> ogr2ogr- Convert between ogr-supported formats.
+<li> ogrtindex- Create a tileindex (file containing the identities and
+spatial extent of a list of files).
+</ol>
+For more, see the <a href="http://gdal.velocet.ca/projects/opengis/ogrhtml/ogr_utilities.html">OGR Utilities</a> website.
+</ul>
+<a href="DEVCOURSE_python_bindings.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_greyscale_raster.tif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_greyscale_raster.tif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss2.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss3.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss3.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss4.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss4.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss5.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_label_ss5.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_mini_raster.tif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_mini_raster.tif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss2.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss3.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_open3d_ss3.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_openev_files.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_openev_files.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_openev_files.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <title>Main OpenEV Files</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Main OpenEV Files</h1>
+The following is not intended to be a high-level description of
+OpenEV's classes, as a complete description can be found in the
+<a href="http://openev.sourceforge.net/lib_design_doc/openev.html">Library
+Design Document</a>.
+This is meant to describe the purpose and a bit
+about six key openev files. These should provide a suitable starting
+point for learning and experimentation.
+<h2>openev</h2>
+This is a shell script that can be used to launch openev. All it does
+is set some environment variables, then run
+openev.py. It varies depending on the type of installation.
+<p>Here are some examples:
+</p>
+<p>Type 1:
+</p>
+<pre>#!/bin/sh<br>OPENEV_HOME=`dirname $0`/..<br><br># Setup Environment Variables for OpenEV<br><br>PYTHONHOME=${OPENEV_HOME}<br>PYTHONPATH=${OPENEV_HOME}/pymod:${PYTHONPATH}<br>GEOTIFF_CSV=${OPENEV_HOME}/share/gdal<br>GDAL_DATA=${OPENEV_HOME}/share/gdal<br>PROJ_LIB=${OPENEV_HOME}/share/proj<br>LD_LIBRARY_PATH=${OPENEV_HOME}/lib:${LD_LIBRARY_PATH}<br>PATH=${OPENEV_HOME}/bin:${PATH}<br><br># check for accelerated hardware flag<br>if [ "${1}" = "-h" ]; then<br> shift<br> echo "Setup for user installed hardware acceleration"<br>else<br> echo "Default software rendering mode (use -h if accelerated video card installed)."<br> LD_LIBRARY_PATH=${OPENEV_HOME}/lib/Mesa:${LD_LIBRARY_PATH}<br>fi<br><br>export PYTHONHOME PYTHONPATH LD_LIBRARY_PATH PATH OPENEV_HOME GEOTIFF_CSV<br><br><br># Run OpenEV<br>${OPENEV_HOME}/pymod/openev.py "$@"<br></pre>
+This one will run without requiring a setup script to be sourced,
+because it sets all the environment variables it needs. This is
+the type of script included in Frank Warmerdam's ftp site
+distributions.
+<p>Type 2:
+</p>
+<pre>#!/bin/sh<br>${PYTHONHOME}/bin/python ${OPENEVHOME}/pymod/openev.py $*<br></pre>
+This type assumes that a setup script (eg. .cshrc) has set all the
+necessary
+variables, and simply launches OpenEV.
+<h2>openev.py</h2>
+This is a python script that creates an OpenEV application instance and
+launches a view.
+<p></p>
+<pre>import gviewapp<br>import gview<br>import gtk<br>import sys<br>import os<br>import getopt<br><br>if __name__ == '__main__':<br><br> <br> # get command line options and args<br> # openev -m menufile -i iconfile -t toolfile image1 image2 ......<br> (options, ifiles) = getopt.getopt(sys.argv[1:], 'm:i:t:p:')<br> <br> if os.path.isdir(os.path.join(gview.home_dir, 'config')):<br> mfile = os.path.join(gview.home_dir, 'config', 'DefaultMenuFile.xml')<br> ifile = os.path.join(gview.home_dir, 'config', 'DefaultIconFile.xml')<br> pfile = os.path.join(gview.home_dir, 'config', 'DefaultPyshellFile.xml')<br> else:<br> mfile=None<br> ifile=None<br> pfile=None<br> <br> tfile = None<br> <br> for opt in options[0:]:<br> if opt[0] == '-m':<br> mfile=opt[1]<br> elif opt[0] == '-i':<br> ifile=opt[1]<br> elif opt[0] == '-p':<br> pfile=opt[1]<br> elif opt[0] == '-t':<br> tfile=opt[1]<br> <br> app = gviewapp.GViewApp(toolfile=tfile,menufile=mfile,iconfile=ifile,pyshellfile=pfile)<br> gview.app = app # handle to the application for other modules to use<br> app.subscribe('quit',gtk.mainquit) # connect to gtk's quit mechanism<br> app.show_layerdlg() # show layer dialog<br> app.new_view(None) # create initial view window<br> app.do_auto_imports() # imports modules specified in preferences<br><br> for item in ifiles:<br> app.file_open_by_name(item) # open command line files<br><br> gtk.mainloop() # start the main event loop<br><br></pre>
+<h2>gview.py</h2>
+This provides access to the c-level openev code. Layers, view areas,
+rasters,
+etc. are defined here, however no GUI's are defined gview.py- this is
+left
+to other modules.
+As an example, here is the snippet of gview.py code that creates the
+point of
+interest tool:
+<pre>class GvPoiTool(GvTool):<br> """Point of Interest Selection Tool<br><br> Signals:<br><br> poi-changed -- generated when the POI has been changed.<br> """<br> <br> get_type = _gv.gv_poi_tool_get_type<br> def __init__(self, _obj=None):<br> if _obj: self._o = _obj; return<br> self._o = _gv.gv_poi_tool_new()<br><br> def get_point(self):<br> """ Returns the current POI """<br> return _gv.gv_poi_tool_get_point(self._o)<br><br> def set_point(self, point):<br> """ Sets the current POI.<br><br> point -- a tuple (column, row)<br> """<br> return _gv.gv_poi_tool_new_point(self._o, point)<br></pre>
+It inherits from the GvTool class:
+<pre>class GvTool(_gtk.GtkObject):<br> get_type = _gv.gv_tool_get_type<br> def __init__(self, _obj=None):<br> if _obj: self._o = _obj; return<br> <br> def activate(self, view):<br> _gv.gv_tool_activate(self._o, view._o)<br> <br> def deactivate(self, view):<br> _gv.gv_tool_deactivate(self._o, view._o)<br> <br> def get_view(self):<br> v_o = _gv.gv_tool_get_view(self._o)<br> if v_o is None:<br> return None<br> else:<br> return GvViewArea(_obj=v_o)<br> <br> def set_boundary(self, boundary):<br> """Set constraint rectangle.<br><br> boundary -- boundary is a tuple in the form (column,row,width,height)<br> """<br> return _gv.gv_tool_set_boundary(self._o, boundary)<br></pre>
+You can connect to the POI tool's poi-changed signal using the connect
+function:
+<pre>class my_object:<br> def __init__(self):<br> # The poi tool is stored in the main application's toolbar:<br> # Get a handle to the main application through gview (gview.app<br> # is set to the main application in openev.py). This makes<br> # use of the fact that every module is only loaded once in<br> # an application, unless the "reload" command is called<br> # on the module. All subsequent imports point to the same<br> # space in memory. This means that setting gview.app in <br> # openev.py results in app being accessible wherever gview is<br> # loaded.<br> # The application is sometimes passed as an argument<br> # to make it less confusing in OpenEV's tools, but the<br> # end effect is the same.<br><br> import gview<br> gview.app.toolbar.poi_tool.connect('poi-changed',self.my_update_cb)<br><br> def my_update_cb(self,*args)<br> poi_info = self.app.toolbar.get_poi()<br> txt=str(poi_info[0])+' '+str(poi_info[1])<br></pre>
+This connects the poi tool's "poi-changed" signal to your object's
+"my_update_cb" callback. Note that the poi tool's "connect" function
+is inherited from gtk.GtkObject through the GvTool base class.
+<p></p>
+<h2>gviewapp.py and gvviewwindow.py</h2>
+These modules provide gui's to go with the gview.py objects, and
+super-structures to control their interaction.
+<p>The top-level application
+is the GViewApp class in gviewapp.py. It does not have its own gui, but
+initializes the layer dialog, view manager, selection manager, toolbar,
+tools, and preferences. The first view window is launched through a
+call
+to the GViewApp's "new_view" function, which creates a new GvViewWindow
+and adds tool menu entries to it.
+gviewapp.py also contains the code for the edit toolbar and preference
+dialog GUIs.
+</p>
+<p>gvviewwindow.py contains the code to create an OpenEV view. This
+consists
+of a GtkWindow with an embedded menubar, icon bar, and GvViewArea (the
+black area- see gview.py for the wrappers, gvviewarea.c for the
+nitty-gritty).
+</p>
+<p>Other python files that provide GUIs include layerdlg.py (the layer
+dialog),
+oeattedit.py (the vector attributes dialog launched from the edit
+menu),
+gvvectorpropdlg.py (the vector properties dialog launched by right
+clicking on a vector file in the layer dialog), and gvrasterpropdlg.py
+(the raster properties dialog). </p>
+<p></p>
+<h2>gvsignaler.py</h2>
+One other class that you should be aware of as an OpenEV developer is
+the
+Signaler class (code below):
+<pre>"""<br>MODULE<br> gvsignaler<br> <br>DESCRIPTION<br> Provides an event subscription/notification mechanism a bit like<br> Gtk signal handling. Classes which derive from Signaler can<br> publish a list of named signals. These signals can then be<br> attached to arbitrary callback methods/functions using subscribe().<br> More than one callback function per signal can be attached.<br> The Signaler executes the callback functions with the notify()<br> method.<br><br> Arguments to the callback functions are (in order):<br> 1. The Signaler instance.<br> 2. Any signal specific arguments provided to notify().<br> 3. Subscriber baggage arguments provided to subscribe().<br> The baggage arguments act like the 'data' argument of Gtk signals.<br>"""<br><br>class UnpublishedSignalError(Exception): pass<br>class SignalExistsError(Exception): pass<br><br>class Signaler:<br> "Base class for objects with published signals"<br> signal = {} # Prevents AttributeErrors<br><br> def publish(self, *sigs):<br> "Publish one or more named signals"<br> if not self.__dict__.has_key('signal'):<br> self.signal = {}<br> for s in sigs:<br> if self.signal.has_key(s):<br> raise SignalExistsError<br> self.signal[s] = [0, []] # Blocked flag, handlers list<br><br> def subscribe(self, name, meth, *args):<br> "Attach a callback function/method to a signal"<br> try:<br> self.signal[name][1].append((meth, args))<br> except KeyError:<br> raise UnpublishedSignalError<br> <br> def unsubscribe(self, name, meth):<br> "Remove a callback function/method for a named signal"<br> try:<br> l = len(self.signal[name][1])<br> for si in range(l):<br> if self.signal[name][1][si][0] == meth:<br> del self.signal[name][1][si]<br> break<br> except KeyError:<br> raise UnpublishedSignalError<br><br> <br> def notify(self, name, *args):<br> "Execute callbacks attached to the named signal"<br> try:<br> sig = self.signal[name]<br> except KeyError:<br> raise UnpublishedSignalError<br> # Check for blocked signal<br> <br> if sig[0] == 0:<br> for s in sig[1]:<br> apply(s[0], (self,) + args + s[1])<br><br> def block(self, name):<br> "Prevent a signal from being emitted"<br> try:<br> self.signal[name][0] = 1<br> except KeyError:<br> raise UnpublishedSignalError<br><br> def unblock(self, name):<br> "Allows a blocked signal to be emitted"<br> try:<br> self.signal[name][0] = 0<br> except KeyError:<br> raise UnpublishedSignalError<br><br></pre>
+An object of this class stores a dictionary of signals that it will
+recognize.
+A new signal is added to the dictionary using the "publish" function,
+and
+the signal is emitted using the "notify" function. Another object can
+connect to this signal using the "subscribe" function, which appends
+the
+desired callback (passed through the subscribe arguments) to the list
+of callbacks for that signal. "notify" cycles through all attached
+callbacks
+for a given signal, applying them. The block/unblock functions are used
+to temporarily prevent the callbacks from being executed. This is
+similar
+to the gtk signaling mechanism, with the difference that the gtk
+signals
+are defined at the c-level, and are emitted and connected to through
+python wrappers. The gtk mechanism uses the terms "connect" and "emit"
+rather than "subscribe" and "notify". Some objects inherit both
+mechanisms,
+for example the Layer Dialog class:
+<pre>class LayerDlg(GtkWindow,gvsignaler.Signaler):<br> def __init__(self):<br> GtkWindow.__init__(self)<br> self.set_title('Layers')<br> self.set_usize(250, 500)<br> self.set_border_width(3)<br> self.set_policy(TRUE,TRUE,FALSE)<br> self.connect('delete-event',self.close)<br> shell = GtkVBox(spacing=3)<br> self.add(shell)<br> <br> # Bunch of other code...<br><br> # Layer list<br> layerbox = GtkScrolledWindow()<br> shell.pack_start(layerbox)<br> if self.thumbnail:<br> layerlist = GtkCList(cols=3)<br> else:<br> layerlist = GtkCList(cols=2)<br> <br> layerbox.add_with_viewport(layerlist)<br> layerlist.set_shadow_type(SHADOW_NONE)<br> layerlist.set_selection_mode(SELECTION_SINGLE)<br> layerlist.set_row_height(THUMB_H + 4)<br> layerlist.set_column_width(0, EYE_W)<br> if self.thumbnail:<br> layerlist.set_column_width(1, THUMB_W + 4)<br> layerlist.connect('select-row', self.layer_selected)<br> layerlist.connect('button-press-event', self.list_clicked)<br><br><br> # Bunch of other code...<br><br> # Publish signals<br> self.publish('active-view-changed')<br> <br></pre>
+In this case, 'delete-event' is a gtk signal (the little x on the
+layer dialog box being clicked), as are 'select-row' and
+'button-press-event', but 'active-view-changed' is
+a Signaler signal.
+<p>As a historical note, the GViewApp class used to be in openev.py,
+then
+was separated out to its own gviewapp.py file. </p>
+<p><a href="DEVCOURSE_tutorial1.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+</p>
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.dbf
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.dbf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shp
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shp
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shx
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_point_classes.shx
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_print_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_print_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_example.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_example.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss2.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss3.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss3.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss4.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss4.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss5.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_pyshell_ss5.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_python_bindings.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_python_bindings.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_python_bindings.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<title>Python Bindings</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+Python is a scripting language, a bit like matlab. You can find detailed information
+at the main <a href="http://www.python.org">Python Website</a>, or a summary in the
+<a href="COURSE1_python.html">python section</a> of Frank Warmerdam's course notes.
+
+<p>
+<h1>Python Bindings</h1>
+
+Python bindings wrap c-code into modules that can be imported by python:
+<ul>
+<li> pygtk (_gtkmodule.so/gtk.py under OpenEV/lib/python2.1/site-packages on
+ Linux/Unix) provides python bindings to gtk functions. _gtkmodule.so contains
+ the binary functions; gtk.py wraps them in a friendlier interface. For more, see the
+ <a href="http://www.daa.com.au/~james/pygtk/">PyGTK Website</a>.
+
+<li> OpenEV's python bindings are provided by _gvmodule.so and _gtkmissing.so,
+ and wrapped in gview.py, gvviewwindow.py (among others). Some of OpenEV's bindings
+ are generated using the the python script mkgv.py and a text file
+ specifying a little information about each function (gv.defs). This is based
+ on pygtk's method of generating bindings; the mkgv.py script
+ calls pygtk's "generate.py" module with a few arguments. The output
+ of mkgv.py is two files, gvmodule_defs.c and gvmodule_impl.c, that contain the
+ code for the bindings. Some of the functions are too
+ complicated to have automatically generated bindings; these are in gvmodule.c.
+ These three files are compiled and their object files included in _gvmodule.so.
+</ul>
+
+<p>
+A more detailed description of python bindings and an example are given in the
+<a href="COURSE1_python.html#section2">Python Binding</a> section of Frank's course notes.
+<p>
+<a href="DEVCOURSE_openev_files.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss2.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss2.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss3.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss3.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss4.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_rasterfile_ss4.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_scripts.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_scripts.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_scripts.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>Scripting with OpenEV/GDAL</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+<h1>Scripting with OpenEV/GDAL</h1>
+
+OpenEV and GDAL's python functions can also be used in standalone scripts.
+For example, the following script takes in a shapefile and picks out
+the shapes that have [field] = [value], where [field] is one of the
+shape's attributes, and [value] is one of the values that attribute can
+take on. It saves these to a file [inputfile]_[field]_[value].shp, where
+[inputfile] is the input shapefile name minus its extension.
+<pre>
+import gview
+import sys
+
+if __name__ == '__main__':
+
+ if len(sys.argv) < 4:
+ print "Query_polygons.py: "
+ print " Get relevant polygons from a vector layer."
+ print ""
+ print "Usage: Query_polygons.py shapefile field value"
+ else:
+ fshp = sys.argv[1]
+ field = sys.argv[2]
+ value = sys.argv[3]
+ fshp2 = fshp[:-4] + '_' + field + '_' + value + '.shp'
+
+ # Turn the shapefile into a GvShapes object
+ sdata=gview.GvShapes(shapefilename=fshp)
+
+ # Create a new shapes object to store the
+ # selected shapes
+ new_shapes=gview.GvShapes()
+
+ for shp_indx in range(len(sdata)):
+ temp_shp = sdata[shp_indx]
+ if temp_shp is None:
+ continue
+
+ if temp_shp.get_property(field) == value:
+ new_shapes.append(temp_shp.copy())
+
+ new_shapes.save_to(fshp2) # save the selected shapes to a file
+
+</pre>
+<p>
+<a href="DEVCOURSE_building_maintenance.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.dbf
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.dbf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shp
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shp
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shx
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shape_example.shx
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shapefile_ss1.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_shapefile_ss1.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_subpixel_interpolation.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_subpixel_interpolation.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tools_commands.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tools_commands.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tools_commands.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,290 @@
+<html>
+<head>
+<title>Extending OpenEV</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+<h1>Extending OpenEV- Tools and Commands</h1>
+
+<h2>Python Shell Commands</h2>
+The first method of extending OpenEV's functionality is to add
+new functions or commands to the python shell. Examples of this
+would be the "display" function and "newview" command.
+Functions are regular python functions imported as soon as the
+python shell is launched via a "from gvshell import *" command.
+You can import your own functions in OpenEV's python shell if
+you have placed your module in OpenEV's python path.
+Commands, such as "newview", follow a more complicated structure
+and differ from functions in the following way:
+<ol>
+<li> They are intercepted rather than being passed to the
+python shell's interpreter.
+<li> They use the syntax "commandname arg1 arg2..." rather than
+"commandname(arg1,arg2,...)"
+<li> They have associated usage strings that are displayed when
+you enter "commands" at the prompt.
+<li> They have argument checking.
+</ol>
+Here is an example of the python shell and the results of the
+display function and newview commands:
+<img src="pyshell_example.gif">
+<p>
+The relevant files here are:
+<ul>
+<li> gviewapp.py- contains the callback (pyshell) that launches the python
+shell.
+<pre>
+ def pyshell(self, *args):
+ import pyshell
+ pyshell.launch(pyshellfile=self.pyshellfile)
+</pre>
+<li> pyshell.py- defines the interactive python shell, MyInteractiveConsole.
+This shell is based on python's code.InteractiveConsole, but overrides some
+of the commands. For instance, instead of passing a command line directly to
+the python interpreter, the "push" function in MyInteractiveConsole does
+the following (excerpts of the code have cut out and replaced with
+summaries):
+<pre>
+ def push(self, line):
+ ( update command shell history list if present )
+
+ ( if current entry is a macro command, do some macro-specific stuff )
+
+ ( if journaling is on, do record the command to the journal file )
+
+ if len(self.cmdlist) > 0:
+ # determine if the line starts with a command
+ cmd_name, remainder = parse_interpreter_line(line)
+
+ if self.cmdlist.has_key( cmd_name ):
+ # if code gets here, user has entered a registered
+ # command (eg. newview). This part parses the
+ # command, converts it to text that can be run
+ # as a python function, then pushes it through
+ # the interpreter.
+
+ ( convert command line to python function text )
+
+ return code.InteractiveConsole.push(self,txt)
+
+
+ # If line does not start with a command, push it
+ # through the interpreter as-is.
+ return code.InteractiveConsole.push(self,line)
+
+</pre>
+<li> gvshell.py- contains additional regular python functions that get
+imported into the python shell (display, get_roi, roi).
+<li> gvcommand.py- this contains the code that parses the core commands
+and defines the base class for core commands.
+<li> gvcorecmds.py- this contains the core commands implemented to date.
+</ul>
+
+
+<h2>Tools</h2>
+The idea behind the tool mechanism and the methods of registering a tool
+(automatic and non-automatic) are described in the
+<a href="../customization.html">customization</a> section of
+OpenEV's help.
+<p>
+The base tool class is defined as follows in gviewapp.py:
+<pre>
+
+class Tool_GViewApp:
+ # Abstract base class to derive tools from
+ def __init__(self,app=None):
+ self.app = app
+ self.menu_entries = Tool_GViewAppMenuEntries()
+ self.icon_entries = Tool_GViewAppIconEntries()
+ self.pymenu_entries = Tool_GViewAppMenuEntries()
+ self.pyicon_entries = Tool_GViewAppIconEntries()
+
+class Tool_GViewAppMenuEntries:
+ # Class to store entries to be added to openev's menu
+ def __init__(self):
+ self.entries = {}
+
+ def set_entry(self,item,position=0,callback=None,accelerator=None):
+ # item = a string describing menu location
+ # position = default location in the menu (integer): Ignored if an
+ # xml menu entry is specified for the tool. Note:
+ # when used, the position refers to position in the
+ # lowest level menu. Eg. if a menu entry is
+ # 'File/menu1/entryN', position refer's to entryN's
+ # position within menu1, not menu1's position in
+ # File. For more flexibility, use the xml form of
+ # configuration.
+ # callback = callback
+ # accelerator = shortcut key
+
+ if (type(item) == type('')):
+ if (type(position) == type(0)):
+ self.entries[item] = (position,callback, accelerator)
+ else:
+ raise AttributeError,"position should be an integer"
+ else:
+ raise AttributeError,"Menu entry item must be a string"
+
+(similar class for Icon entries)
+
+</pre>
+This defines the way the tools add menu or icon entries to OpenEV's toolbar,
+and stores a handle to the application so that the tool can interact
+with it. Below is a simple tool that adds a new menu
+entry Tools/Example, and when called prints out a list of the tools loaded
+in the application.
+<pre>
+#!/usr/bin/env python
+import gviewapp
+
+class Tool_example(gviewapp.Tool_GViewApp):
+
+ def __init__(self, app=None,startpath=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.init_menu()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Example...",1,self.example_tool_cb)
+
+ def example_tool_cb(self,*args):
+ print self.app.Tool_List
+
+
+TOOL_LIST=['Tool_example']
+</pre>
+Placing this tool in OpenEV's "tools" directory will register it
+automatically. The relevant sections of gviewapp.py are:
+<p>
+Initialization: <p>
+The tools are loaded up and stored in
+self.Tool_List. Tools passed as a command line argument are
+loaded using self.load_tools_file; auto-registering tools
+(those in OpenEV's "tools" directory) are loaded using
+self.scan_tools_directories. These create an instance of the
+tool, tool_inst, and append a tuple consisting of
+(tool_name,tool_inst) to the Tool_List.
+<pre>
+class GViewApp(Signaler):
+ def __init__(self,toolfile=None,menufile=None,iconfile=None,pyshellfile=None):
+ self.view_manager = ViewManager()
+ self.sel_manager = gvselbrowser.GvSelectionManager( self.view_manager )
+ self.pref_dialog = None
+ self.filename = None
+
+ # Toolbar
+ self.toolbar = Toolbar()
+ self.view_manager.set_toolbar( self.toolbar )
+
+ # Other dialogs, etc.
+ self.layerdlg = layerdlg.Launch()
+ self.view_manager.set_layerdlg(self.layerdlg)
+
+ self.publish('quit')
+ self.publish('rfl-change')
+
+ # Verify that float() works properly.
+ try:
+ x = float('0.9')
+ except:
+ gvutils.warning( 'It appears that float() doesn\'t work properly on your system.\nThis is likely due to use of a numeric locale with an alternate decimal\nrepresentation. Please try setting the LC_NUMERIC environment variable\nto C and restarting OpenEV.' )
+
+ # Default configuration files for view and python shell
+ self.menufile=menufile
+ self.iconfile=iconfile
+ self.pyshellfile=pyshellfile
+
+ # External tools to import and add to view menu
+ self.Tool_List = []
+ if toolfile is not None:
+ self.load_tools_file( toolfile )
+
+ self.scan_tools_directories()
+
+ # Tool index: a dictionary with the tool name as a
+ # key and the tool's position in the list as the value
+ self.tool_index = {}
+ for idx in range(len(self.Tool_List)):
+ self.tool_index[self.Tool_List[idx][0]]=idx
+
+ self.shell = None
+</pre>
+New views: <p>
+When a new view is created, the main application cycles through
+its tool list, and appends their menu and icon entries to the menu/icon bars.
+<pre>
+ def new_view(self, title=None, menufile=None,iconfile=None, *args):
+ # If menu/icon files aren't specified, use application-wide
+ # defaults
+ if ((menufile is None) and (self.menufile is not None)):
+ menufile=self.menufile
+ if ((iconfile is None) and (self.iconfile is not None)):
+ iconfile=self.iconfile
+
+ view_window = gvviewwindow.GvViewWindow(app=self, title=title, menufile=menufile,
+ iconfile=iconfile)
+ view_name=view_window.title
+ view_menu = view_window.menuf
+
+ if ((len(self.Tool_List) > 0) and (menufile is None)):
+ # If no menu configuration file is specified, put
+ # tools in the default positions specified by
+ # the tool menu entry's position parameter.
+ for cur_tool_list in self.Tool_List:
+ cur_tool = cur_tool_list[1]
+ if hasattr(cur_tool.menu_entries.entries,'keys'):
+ for item in cur_tool.menu_entries.entries.keys():
+ view_menu.insert_entry(
+ cur_tool.menu_entries.entries[item][0],
+ item,
+ cur_tool.menu_entries.entries[item][2],
+ cur_tool.menu_entries.entries[item][1],
+ (view_name))
+
+ # Icons- Note: currently it is assumed that the tool icons are
+ # xpms. Support for pixmaps and widgets will be added
+ # later if necessary (icon type would have to be detected
+ # from last entry of the relevant tool icon entry, and
+ # a function would have to be created to deal with them.
+ # They are slightly more complicated than the xpm case
+ # and wouldn't use insert_tool_icon. Would also need
+ # code in the complextoolentry case to avoid an icon
+ # of one type (eg. xpm) being replaced by another type
+ # (eg. widget, pixmap).
+ #
+ # ALSO: GtkToolbar does not allow callback information
+ # to be specified, so the viewname cannot be
+ # passed as an argument to tool icon callbacks
+ # the way it is for menu callbacks. However,
+ # if the view is needed, it can be obtained
+ # using:
+ # view=args[0].get_toplevel()
+ # The view title is under:
+ # view['title']. Note that this is not quite
+ # the same as the view's self.title, but is based
+ # on it (usually 'OpenEV: '+self.title)
+
+ if ((len(self.Tool_List) > 0) and (iconfile is None)):
+ for cur_tool_list in self.Tool_List:
+ cur_tool=cur_tool_list[1]
+ for item in cur_tool.icon_entries.entries:
+ view_window.insert_tool_icon(
+ item[0], # filename
+ item[1], # label
+ item[2], # hint text
+ item[4], # callback
+ item[5], # help topic
+ item[3], # position
+ )
+ view_window.show()
+ return view_window
+
+
+</pre>
+
+<a href="DEVCOURSE_scripts.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Help</a><br>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial1.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial1.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial1.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,287 @@
+<html>
+<head>
+<title>Tutorials 1</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+<h1>Tutorial 1: General Overview</h1>
+<ul>
+<li>Launch openev, and load up DEVCOURSE_greyscale_raster.tif (it should be
+in openev's html/developer_info directory).
+<li>Launch the <a href="../layerdlg.html">layers</a> dialog (Edit->Layers...).
+<p>
+<img src="../layerdlg.gif">
+<p>
+<li>Place the mouse over the layer dialog, click to select it, then hit the "F1" key. This should bring up
+OpenEV's layer dialog help. This is one of OpenEV's standard help mechanisms- if you
+place the mouse over a dialog or view window and hit the "F1" key, it will bring up
+the help for that dialog, if help is available for it.
+<li>Right-click on the greyscale raster layer name. This will bring up a
+<a href="../gvrasterpropdlg.html">raster properties</a> dialog.
+<p>
+<img src="../gvrasterpropdlg_general.gif">
+<p>
+<li>Under the "Raster Source tab, change the view scaling by sliding the
+Scale Min and Scale Max slider bars. You can also type the minimum
+and maximum values in. In a greyscale image, values falling below
+Scale Min are set to black, and those above Scale Max are white.
+<li>You can also change the view scaling by clicking on the
+enhancement icons (<img src="../linear.gif"><img src="../log.gif">
+<img src="../equalize.gif"><img src="../nonelut.gif">
+<img src="../windowed.gif">) on the <a href="../mainwindow.html">main window</a>
+icon bar.
+<li>Select 10:1 from the zoom control menu <img src="../zoom_control.gif">, then
+under the "Draw Style" tab, toggle the "Subpixel Interpolation"
+menu between "Off (Nearest)" and "Linear".
+<p>
+<img src="DEVCOURSE_subpixel_interpolation.gif">
+<p>
+<li>Click the <img src="../seeall.gif"> icon or press the "Home" key to rescale the raster to its
+default display size.
+<li>Click <img src="../classify.gif"> to bring up the classification dialog.
+<li>Toggle through the colour ramps menu to the "Green-Yellow-Red" Ramp, then click "Apply".
+<li>Click the <img src="../legend.gif"> icon to create a legend for it.
+<img src="DEVCOURSE_classify_example.gif">
+<li>The colour ramps are simple text files located in the "ramps" directory of
+OpenEV. The green-yellow-red one below is defined by the file "green_yellow_red_ramp.txt",
+and contains the following:
+<pre>
+Green-Yellow-Red
+0
+0.0 (0.0, 1.0, 0.0, 1.0)
+0.5 (1.0, 1.0, 0.0, 1.0)
+1.0 (1.0, 0.0, 0.0, 1.0)
+</pre>
+The first line specifies the name, the second line indicates the type of colour ramp
+(0 for continuous, 1 for discrete values), and the subsequent lines indicate the
+colours to vary between, specified as a red-green-blue-alpha grouping, where alpha
+is the opacity level. You can reset the location of your ramps directory by editing the
+".openev" file in your home directory to contain the line (this one sets it to /data/ramps):
+<pre>
+ramp_directory=/data/ramps
+</pre>
+<li>Now place the mouse over the window and press control and the left mouse button, and
+drag out a region on the image. This should draw an orange rectangle highlighting the
+area you have selected, and when the mouse button is released, OpenEV will zoom in to
+this area. Pressing control and holding the left mouse button without dragging will
+result in a continuous zoom in; the right mouse button is used to zoom out. There
+many other <a href="../viewarea_keys.html">key sequences</a> that
+can be used to zoom in different ways.
+<li>Next launch the Interactive Python Shell ("Edit->Python Shell").
+<p>
+<img src="../pyshell_default.gif">
+<p>
+<li>At the command prompt, enter "get im1", then "show im1" (without the quotes). A
+new window should pop up:
+<p>
+<img src="DEVCOURSE_pyshell_ss1.gif">
+<p>
+This demonstrates the use of two OpenEV Python shell core commands, get
+(extract the underlying data from the currently active view/layer into a
+shell variable- in this case the shell variable will be called "im1"),
+and show (display an array or GvShapes variable in
+an OpenEV view). If "get /s im1" is used instead of "get im1", OpenEV will
+try to grab a screenshot rather than extracting the underlying data (note:
+with some video card drivers this doesn't work very well):
+<p>
+<img src="DEVCOURSE_pyshell_ss2.gif">
+<p>
+If you are not using the /s option and want to extract only part of the
+data, you can specify a "Region of Interest" (ROI) on the OpenEV view using
+the ROI Tool:
+<ol>
+<li> Activate the ROI tool by selecting the "Edit->Edit Toolbar" menu entry
+ and pressing the "Draw ROI" button.
+<li> Left click and drag out the ROI on your OpenEV view (it should appear
+as an orange rectangle).
+</ol>
+<p>
+If an ROI is drawn, "get im2" should grab the data that corresponds to
+the region you selected rather than the whole image. ROI's are ignored
+if the screenshot (/s) option is used.
+<li>Regular Python functions can also be run from the command
+shell (the difference between OpenEV commands and regular Python functions is
+explained in the <a href="../pyshell.html">Python shell help</a>).
+On startup, OpenEV's Python shell imports a variety of functions from
+<a href="http://www.pfdubois.com/numpy">Numeric Python</a> for creating and
+manipulating arrays of data. Enter "shape(im1)" to see the size of
+im1 (it should be 512x512 since the whole image was extracted),
+then set the first 50 rows and lines to zero: "im1[:50,:50]=0".
+Enter "newview" to create a new OpenEV view, then "display(im1)"
+to see the the altered im1 in that view (display is a function that
+behaves similarly to the show command- if you want to display
+the results of an expression rather than just a variable, you
+should use display rather than show, eg. "display(im+75))":
+<p>
+<img src="DEVCOURSE_pyshell_ss4.gif">
+<p>
+Python arrays are indexed from 0:N-1, where N is the length of the
+array in the dimension being indexed. Slices take the form
+start:stop:step, where start is the start index, stop is the index
+of the element after the last element to be included, and
+step is the step size. If the start, stop, or step indices are left out,
+they are set to 0,N, and 1 respectively for a dimension of length N.
+Continuing to operate on im1, try setting "im1[::2,:]=0". This will
+set every second line to zero:
+<p>
+<img src="DEVCOURSE_pyshell_ss5.gif">
+<p>
+Numeric Python offers much more array manipulation capability, including
+matrix addition/subtraction, multiplication/division
+(both element-wise and regular multiplication), and logical operations.
+It also overloads common operators such as "+" so that
+elementwise addition can be accomplished using statements like
+"im3=im1+im2", where im1 and im2 are same-size arrays. It also has
+a number of other modules that can be imported to do
+more sophisticated operations (eg. FFT).
+
+Note that if you are not using floating point arrays, some
+operations may result in overflow errors. These errors can be avoided
+either by using floating point arrays to start with, or
+by casting the arrays in the statement, for
+example: "im3=im1.astype('d')+im2".
+The type codes in Numeric Python include:
+<ul>
+<li> Character ('c')
+<li> Integer ('1','s','i','l')
+<li> Unsigned Integer ('b','w','u')
+<li> Float ('f','d')
+<li> Complex ('F','D')
+</ul>
+<p>
+The division within each type corresponds to different numbers of bits
+used to store the type (eg. 8-bit versus 16-bit integer). You can
+create arrays of any of these types in Numeric Python using the
+"array", "ones", and "zeros" functions.
+
+<li> Try entering "b=arange(10)", then
+"plot(b,xaxis='my x',yaxis='my y',title='my plot')" in the Python shell. The
+Numerical Python "arange" function creates an array of values (in this case,
+the array [0,1,2,3,4,5,6,7,8,9]). The plot function call above
+plots the array b, and labels it with 'my x' as the x axis, 'my y' as
+the y axis, and 'my plot' as the title. OpenEV's plot function is based on
+<a href="http://www.comnets.rwth-aachen.de/doc/gnu/gnuplot37/gnuplot.html">Gnuplot</a>.
+<p>
+<img src="DEVCOURSE_pyshell_ss3.gif">
+<p>
+Enter "commands" and "functions" at the command line to see lists of the
+available OpenEV commands and currently loaded Python functions. "help /g" or "help -g"
+will display these in graphical format.
+<p>
+<img src="pyshell_help.gif">
+<p>
+<li>Launch a new view ("File->New View"), and select "File->Open 3D".
+Choose "DEVCOURSE_greyscale_raster.tif" as
+both the drape and the DEM (Digital Elevation Map). Set the mesh level of detail
+(LOD) to 5. This means that OpenEV will use the values in DEVCOURSE_greyscale_raster.tif to
+provide both the intensity (drape) and height (DEM) values in display. The mesh
+LOD specifies the resolution of the grid used to sample the DEM for height values
+(higher LOD means better resolution).
+<p>
+<img src="DEVCOURSE_open3d_ss1.gif">
+<p>
+<li>The view will initially appear grey because the view is quite zoomed in and
+there is not a lot of variation in DEVCOURSE_greyscale_raster.tif. Press Control and hold
+down the right mouse button to zoom out until you can see the raster more clearly.
+<p>
+<img src="DEVCOURSE_open3d_ss2.gif">
+<p>
+This example demonstrates the limitations of using a regular grid of values
+to sample a DEM- it doesn't work well on an image that is mostly uniform, but
+has a few radical changes. It looks okay for many natural scenes, but will have
+to be updated if urban fly-throughs are to look good in OpenEV. The next image
+shows the results if the mesh LOD is upped to 8:
+<p>
+<img src="DEVCOURSE_open3d_ss3.gif">
+<p>
+This is somewhat better, but much slower to render. Some applications use a
+triangulated irregular network (TIN) representation of the DEM to get around this
+problem- this allows higher resolution where it is needed; lower where
+the scene is uniform. This sort of thing will be a consideration if further
+development is done on OpenEV's 3D capabilities.
+<li>Press "+" and "-" on the keyboard to see the height scaling change. Holding
+the "Shift" button while pressing these will give steps that are 10 times larger.
+<li>Press "F2" to toggle between 2-D and 3-D viewing modes.
+<li>Launch the <a href="../gvprint.html">Print</a> dialog using File->Print or
+the <img src="../print.gif">
+icon.
+<p>
+<img src="DEVCOURSE_print_ss1.gif">
+<p>
+This dialog will allow you to print what you see in OpenEV's view area directly to
+a printer or to file.
+<li>In a new view, load up the file "DEVCOURSE_vector_classes.shp" from openev's html/developer_info
+directory.
+<li>Launch the vector layer properties dialog by right-clicking on the
+DEVCOURSE_vector_classes.shp layer in the layer dialog.
+<li>Alter the edge and fill colours of the polygons using the "Areas" section under
+the "Draw Styles" tab.
+<p>
+<img src="DEVCOURSE_vector_layerstyles.gif">
+<p>
+<li>Enable the "Select" tool on the edit toolbar ("Edit/Edit Toolbar...") by clicking on it.
+Launch the vector attributes dialog (Edit->Vector Layer Attributes), and select
+one of the polygons by left-clicking on it. Each polygon has a an attribute called
+"class" that has a value of "office", "gym", or "playground".
+<li>Click <img src="../classify.gif"> to bring up the classification dialog
+for vector layers, and apply one of the ramps. This should colour the polygons according
+to their class. If a vector file has several attribute fields, the menu bar in the
+top right corner of the dialog will allow you to choose which one the classification
+should use to distinguish between polygons.
+<img src="DEVCOURSE_vector_classify.gif">
+<p>
+Vector files containing point and line objects can also be manipulated through
+their vector property dialogs and the classification tool.
+<li>OpenEV also has a number of other standard items, briefly described here:
+<ol>
+<li>File->Import: This asks for a (raster) filename, then converts the raster to GeoTiff format
+and creates tiled overviews for it. The new raster is saved to a file with extension ".tif".
+<li>File->Save Project (only in some OpenEV distributions): This saves the current
+openev state (number of views, what is loaded in
+them) to an xml file. For instance, if you start OpenEV, load up "DEVCOURSE_greyscale_raster.tif", and
+then save the project to projectfile_example.opf (.opf = Openev Project File), it will
+contain:
+<pre>
+<GViewApp>
+ <GvViewWindow module="gvviewwindow" width="620" height="680" x="46" y="94">
+ <title> View 1</title>
+ <GvViewArea Mode="0" Raw="0">
+ <Translation x="-256.0" y="-256.0"/>
+ <Zoom> 0.211888298392</Zoom>
+ <Background red="0.0" green="0.0" blue="0.0" alpha="1.0"/>
+ <Layers>
+ <GvRasterLayer mode="1" mesh_lod="7.162109375" visible="1" read_only="0" name="/data/openev/html/DEVCOURSE_greyscale_raster.tif">
+ <Prototype band="1">/data/openev/html/DEVCOURSE_greyscale_raster.tif</Prototype>
+ <Source index="0" min="0.0" max="255.0" nodata="-100000000.0" band="1">/data/openev/html/DEVCOURSE_greyscale_raster.tif</Source>
+ </GvRasterLayer>
+ </Layers>
+ </GvViewArea>
+ </GvViewWindow>
+</GViewApp>
+</pre>
+This file indicates that there is one view, with title "View 1", of width 620 and height 680 pixels.
+The view area is translated -256 pixels in both x and y directions and has a zoom level 0.211888298392.
+The background is black, and the view area contains a single raster layer, DEVCOURSE_greyscale_raster.tif.
+When "projectfile_example.opf" is loaded up in openev, the views present when the project file
+was saved (in this case, "View 1" with DEVCOURSE_greyscale_raster.tif in it) will be recreated, and all other
+views closed. "Save Project" uses the "serialize" functions found in gviewapp.py, gvviewwindow.py,
+and others to create a list of the items to include in the project file, and uses gdal.SerializeXMLTree
+to convert this list to XML text for writing to a file. GvViewWindowFromXML in gvviewwindow.py recreates
+a view based on the values saved in the project file.
+<li>Edit->Undo: Undoes the last editing operation performed on a vector layer.
+<li>Edit->Go To: Translate the view to center on the location entered in the Go To dialog.
+<li>Edit->3D Position: Translate the 3D position to the location and orientation entered in the
+3D Position dialog.
+<li>Edit->Preferences: Allows the user to set various preferences. See the
+<a href="../preferences.html">Preferences</a> section of OpenEV's help for more.
+</ol>
+</ul>
+
+
+<a href="DEVCOURSE_tutorial2.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Main</a><br>
+
+</body>
+</html>
+
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial2.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial2.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial2.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,217 @@
+<html>
+<head>
+<title>Tutorial 2</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+
+<h1>Developer Tutorial 1: Working with Vectors</h1>
+
+The first part of this tutorial demonstrates the mechanism that OpenEV uses for
+displaying points and polygons. Start by loading up the shapefile examined
+in the <a href="DEVCOURSE_tutorial1.html">General Overview</a> (if you are continuing
+directly from the first tutorial and still have the classified shapes view, use it
+and skip the first four steps):
+<ul>
+<li>In a new view, load up the file "DEVCOURSE_vector_classes.shp" from openev's html
+directory.
+<li>Launch the vector layer properties dialog by right-clicking on the
+DEVCOURSE_vector_classes.shp layer in the layer dialog.
+<li>Alter the edge and fill colours of the polygons using the "Areas" section under
+the "Draw Styles" tab.
+<p>
+<img src="DEVCOURSE_vector_layerstyles.gif">
+<p>
+<li>Launch the vector attributes dialog (Edit->Vector Layer Attributes), and select
+one of the polygons by left-clicking on it. Each polygon has a an attribute called
+"class" that has a value of "office", "gym", or "playground".
+<li>Click <img src="../classify.gif"> to bring up the classification dialog
+for vector layers, and apply one of the ramps. This should colour the polygons according
+to their class. If a vector file has several attribute fields, the menu bar in the
+top right corner of the dialog will allow you to choose which one the classification
+should use to distinguish between polygons.
+<p>
+<img src="DEVCOURSE_vector_classify.gif">
+<p>
+</ul>
+<p>
+After the classification ramp has been applied, re-select a shape to
+refresh the vector properties dialog. A new field, "_gv_ogrfs" appears as
+a property in each shape. This is the field that openev uses to specify how that
+shape should be displayed. The "BRUSH" section indicates fill colour (for the
+"office" class, this is yellow, or "ffff00ff" when expressed in red-green-blue-alpha
+form). The "PEN" section indicates edge colour. The vector attributes dialog
+specifies properties of a layer; these are over-ridden by the "_gv_ogrfs" field.
+For point shapes, this field can also be used to specify the symbol to use to
+represent the point, and to indicate any labelling. For instance, setting
+_gv_ogrfs for a point shape to the string:
+<pre>
+LABEL(dy:-10.0,dx:10.0,t:{Alias},f:"-adobe-helvetica-medium-r-normal-*-*-240-*-*-p-*-iso10646-1",c:#FEFF06);SYMBOL(c:#FF00FFFF,id:ogr-sym-5)
+</pre>
+creates a magenta (c:#FF00FFFF) filled square (id:ogr-sym-5) symbol with a yellow (c:#FEFF06)
+helvetica font (f:"-adobe-helvetica-medium-r-normal-*-*-240-*-*-p-*-iso10646-1") label based on
+the contents of the point shape's Alias field (t:{Alias}). The label is offset 10 pixels in the x
+and y directions from the symbol (dy:-10.0,dx:10.0). The symbol may be one of the vector symbols
+(ogr-sym-*) or a raster symbol (in this case, id should be a path to the raster file to use). The
+label text can be derived from a field (as above), or specified directly (eg. t:"Hello" instead of
+t:{Alias} would write "Hello" as a label).
+
+<ul>
+<li> Launch a new view, create a new shapes layer by pressing <img src="../layerdlg_new.gif"> on
+the Layers dialog, and select "Draw Labels" on the toolbar ("Edit->Edit Toolbar").
+<li> Place the mouse over the OpenEV view area, click to activate it, and press "Enter" on the keyboard.
+<li> From the "Label Edit Tool" dialog that appears, select Font: helvetica (adobe) on Linux or Arial on Windows,
+Font Style: medium (normal on Windows), Size: 17 pixels (16 on Windows).
+
+<li> In the "Label Edit Tool" Text entry box, enter "Hello", then click on the view
+area again. The "Hello" label should appear.
+<p>
+<img src="DEVCOURSE_label_ss1.gif">
+<p>
+<li> Click on the label to select it. In the "Shape Attributes" dialog, add ";SYMBOL(id:ogr-sym-5)" to the end of the _gv_ogrfs
+property. A dialog will appear asking whether you would like to add a new string-type property "_gv_ogrfs". Click "Yes" to add
+"_gv_ogrfs" to the list of properties that would be stored to a new file if the vector layer was saved through the
+"File/Save Vector Layer" menu entry. Click on the view again. You should see a filled square appear
+next to the "Hello" label.
+<p>
+<img src="DEVCOURSE_label_ss2.gif">
+<p>
+If you press "Select" on the Edit toolbar and then left-click on the label, a box should appear around
+the label.
+<li> Change the symbol id from "ogr-sym-5" to "ogr-sym-7" (a filled triangle should replace the square),
+then to the full path to DEVCOURSE_mini_raster.tif (eg. SYMBOL(id:/data/openev/html/DEVCOURSE_mini_raster.tif). Move the SYMBOL(...) section before the LABEL(...) section so that the label appears on top.
+<p>
+<img src="DEVCOURSE_label_ss4.gif">
+<p>
+One quirk of this mechanism is that if there isn't room for the raster to appear as an icon (if it is
+too large for the current zoom level and part of it would be outside the zoom area), it doesn't appear at all.
+If the raster is not visible, drag the label to the center of the view.
+There is no scaling mechanism for raster icons yet.
+<li> In addition to the manual methods used above, labels based on shape properties can be added to
+points layers through the vector attributes dialog. This uses a similar mechanism to the one described
+above to alter the display, but provides a simpler interface. In this case, the "_gv_ogrfs_point" property
+is set on the layer as a whole rather than the "_gv_ogrfs" property being set on individual shapes.
+Load up the file "point_classes.shp" from
+the "developer_course" directory on your cd. This contains several shapes with a single attribute,
+"class", that is either "office", "gym", or "playground". Right-click on the point_classes.shp layer
+on the layer dialog to bring up the vector layer properties, and click on the "Draw Styles" tab.
+Under the "Labels" section, change Label Field from "disabled" to "class". The points should now
+be displayed as labels. The symbol used can also be changed, using the "Points" section of the dialog.
+<p>
+<img src="DEVCOURSE_label_ss5.gif">
+<p>
+</ul>
+The next part of this tutorial manipulates vector (GvShapes) objects in the
+OpenEV Python shell to demonstrate some of their features. Create a shapefile:
+<ol>
+<li>Launch a new view
+<li>Launch toolbar (Edit->toolbar)
+<li>Select "Draw Rectangle" on the toolbar
+<li>On layer dialog, click the <img src="../layerdlg_new.gif"> icon
+<li>On the view, left-click and drag out two rectangles
+<li>Launch the vector attributes dialog (Edit->Vector Layer Attributes)
+<li>Select "Select" on the toolbar
+<li>Left click on a shape to select it
+<li>Add a property to the shape by typing "property1: 'hello'
+in the shape attributes box. Click "Yes" when it asks you
+if you want to create the new property- this will allow
+it to be saved later.
+<li>In the Shape Attributes dialog, select "integer" from the field
+properties menu and add a new property "property2: 3"
+<li>Add these properties to the second rectangle, using different values.
+</ol>
+<img src="DEVCOURSE_shapefile_ss1.gif">
+<p>
+<ul>
+<li>Save the file as a shapefile (shape_example.shp) using
+File->Save Vector Layer
+<li>Launch the Python shell (Edit->Python shell)
+</ul>
+In the Python shell, enter (note that path names are case-sensitive, even on Windows):
+<ul>
+<li>import gview
+<li>sshapes=gview.GvShapes(shapefilename='/full path/shape_example.shp')
+</ul>
+This reads in the shapefile and creates a GvShapes object (sshapes) from its contents.
+Now enter:
+<ul>
+<li>sshapes.get_schema()
+</ul>
+This gets a list of the properties stored in the shapefile.
+Now enter:
+<ul>
+<li>sshapes[0].get_properties()
+</ul>
+This accesses the first GvShape in sshapes, and will show the values of
+the properties you entered for it.
+Now enter:
+<ul>
+<li>sshapes[0].get_nodes()
+</ul>
+This returns the number of nodes in the shape- 5 for a rectangle, because
+the last and first nodes are the same. You can use:
+<ul>
+<li>sshapes[0].get_node(0)
+</ul>
+To get the location of the first node (and similar for the others). There
+is also a set_node function. More complicated shapes may have
+multiple "rings" (the main encompassing ring plus areas
+cut out of it). In these cases, you must enter the ring
+number along with the node number in the get_node and set_node functions,
+to specify which ring's nodes you are accessing (the default is ring 0,
+which is fine for simple, 1-ring shapes)
+<p>
+You can type dir(gview.GvShapes) and
+dir(gview.GvShape) to see other functions associated with shape collections
+and individual shapes.
+<p>
+OpenEV allows you to draw 3 types of shapes: points, lines, and polygons, and
+it will allow you to draw any of them in a given layer. However, it is
+important to note that the specification only allows one type of
+shape to be saved to a given shapefile, so saving the layer as a vector file
+will only save the shapes of one type.
+<p>
+Next, we will turn the GvShapes object into a GvShapesLayer, ie. a collection
+of shapes that knows how to draw itself, as opposed to just a collection
+of shapes:
+<ul>
+<li>sshapes_layer=gview.GvShapesLayer(shapes=sshapes)
+</ul>
+Create a new view to work in (File->New View), and make sure it is
+the active one by clicking on it, and by making sure it appears as the
+current view in the layer dialog box.
+<p>
+Get a handle to the GvViewArea in this view using the fact that openev
+set gview.app to the main application during initialization:
+<ul>
+<li>cview=gview.app.sel_manager.get_active_view()
+</ul>
+This grabs the active view through the selection manager, which is an object
+that keeps track of all layers, views, and selections in the application.
+Now, add the layer to the view:
+<ul>
+<li>cview.add_layer(sshapes_layer)
+</ul>
+Now create a new shape:
+<ul>
+<li>new_shape=gview.GvShape(type=gview.GVSHAPE_AREA)
+<li>new_shape.set_node(1.0,1.0,0.0,0)
+<li>new_shape.set_node(1.0,10.0,0.0,1)
+<li>new_shape.set_node(10.0,10.0,0.0,2)
+<li>new_shape.set_node(10.0,1.0,0.0,3)
+<li>new_shape.set_node(1.0,1.0,0.0,4)
+</ul>
+Add it to the collection:
+<ul>
+</li>sshapes.append(new_shape)
+</ul>
+The new shape should appear in the view.
+<p>
+
+<a href="DEVCOURSE_tutorial3.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Main</a><br>
+
+</body>
+</html>
+
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial3.html
===================================================================
--- packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial3.html (rev 0)
+++ packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_tutorial3.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,142 @@
+<html>
+<head>
+<title>Tutorial 3</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<body>
+
+<h1>Developer Tutorial 2: Working with rasters</h1>
+
+<ul>
+<li>Start openev and launch the Python shell (Edit->Python shell)
+</ul>
+Load the colour raster example as a Numeric Python array using:
+<ul>
+<li>imgarr=LoadFile('DEVCOURSE_colour_raster.tif')
+</ul>
+If openev was not started from the directory containing DEVCOURSE_colour_raster.tif,
+you will have to enter the full path in the filename. The array can be
+displayed in the current view using:
+<ul>
+<li>display(imgarr)
+</ul>
+<img src="DEVCOURSE_rasterfile_ss1.gif">
+<p>
+This method can be used to display any greyscale (NxM) or
+red-green-blue (3xNxM) Numeric Python array. Now, change
+imgarr a bit:
+<ul>
+<li>imgarr[:,:100,:100]=0
+</ul>
+and press the refresh button <img src="../refresh.gif"> on
+the iconbar. You should see the top left corner turn black.
+<p>
+<img src="DEVCOURSE_rasterfile_ss2.gif">
+<p>
+Now launch the toolbar (Edit->Tool bar) and select "Draw ROI".
+Left click and drag out a region on the image
+<p>
+<img src="DEVCOURSE_rasterfile_ss3.gif">
+<p>
+Now get the region of interest from the image using the
+get_roi() command:
+<ul>
+<li>img2=get_roi(imgarr)
+</ul>
+Display it in a new view:
+<ul>
+<li>newview
+<li>display(img2)
+</ul>
+Save it as a tiff file that can be loaded up by openev or other
+applications:
+<ul>
+<li>SaveArray(img2,'mini_raster.tif','GTiff')
+</ul>
+
+<h2>Working with rasters in code</h2>
+
+Now we will try something similar that goes more under the hood
+of OpenEV/gdal:
+<ul>
+<li>imgds=gdal.Open('DEVCOURSE_colour_raster.tif')
+</ul>
+Typing dir(imgds) and dir(gdal.Dataset) shows the properties of the
+image and the functions available to the class. The gdal.Dataset
+class stores all the information that gdal was able to pull from the
+image file, including ground control points (GCPs) and metadata, and
+provides functions to access the data in each raster band.
+<p>
+Now, turn it into a GvRaster:
+<ul>
+<li>imgraster=gview.GvRaster(dataset=imgds)
+</ul>
+A GvRaster can also be created by passing the filename directly:
+<ul>
+<li>imgraster=gview.GvRaster(filename='DEVCOURSE_colour_raster.tif')
+</ul>
+The GvRaster class allows you to manipulate the data stored in
+the gdal Dataset (or file). For instance, the functions
+pixel_to_georef/georef_to_pixel allow you to convert from
+pixel/line coordinates to georeferenced coordinates. It also
+stores (at the c-level) scaling minimum and maximum values
+to use in display, and provides functions to retrieve
+and change them. The GvRaster
+also has 'data-changed' and 'data-changing' signal that were
+meant to be used in the context of editing and the undo mechanism, but these
+have never really been used because currently OpenEV's editing capabilities
+(through the toolbar) are limited to vectors.
+<p>
+Next, create a raster layer from the raster, and display it in a new
+view:
+<ul>
+<li>imgrlayer=gview.GvRasterLayer(raster=imgraster)
+<li>newview
+<li>cview=gview.app.sel_manager.get_active_view()
+<li>cview.add_layer(imgrlayer)
+</ul>
+This will show one of the bands of the image in greyscale in the view.
+Now we will add the others:
+<ul>
+<li>imgraster2=gview.GvRaster(dataset=imgds,real=2)
+<li>imgraster3=gview.GvRaster(dataset=imgds,real=3)
+</ul>
+The real=2 and real=3 arguments indicate that the raster should
+be formed from bands 2 and 3 of imgds (default is band 1). It should
+be noted here that gvviewwindow.py in OpenEV uses a different type of
+call to create these rasters:
+<ul>
+<li>green_raster = gview.manager.get_dataset_raster(dataset,2)
+</ul>
+This call goes through the gview manager to ensure that the data for
+a given dataset is only stored in one place in memory, even if the
+image is loaded as a layer in several views. This saves space if,
+for instance, a user is looking at the same image in two views at
+different zoom levels.
+<p>
+Attach the new rasters to the layer:
+<ul>
+<li>imgrlayer.set_source(1,imgraster2)
+<li>imgrlayer.set_source(2,imgraster3)
+</ul>
+You should see the image take on colours. You can also add on an alpha
+band (in this case, we set it to the blue band:
+<ul>
+<li>imgrlayer.blend_mode_set(gview.RL_BLEND_FILTER)
+<li>imgrlayer.set_source(3,imgraster3)
+</ul>
+Now, the colours that have blue components show up with an intensity
+proportional to the blue component: (red,green,blue)*blue/255. The
+blend_mode_set call tells OpenGL to use the alpha component; without it,
+the usual red-green-blue image will be shown.
+<ul>
+<li>imgrlayer.blend_mode_set(gview.RL_BLEND_OFF)
+</ul>
+<p>
+<a href="DEVCOURSE_tools_commands.html">Next</a><br>
+<a href="DEVCOURSE.html">Developer Course Outline</a><br>
+<a href="../openevmain.html">OpenEV Main</a><br>
+
+</body>
+</html>
+
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.dbf
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.dbf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shp
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shp
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shx
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classes.shx
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classify.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_classify.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_layerstyles.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/DEVCOURSE_vector_layerstyles.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/pyshell_example.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/pyshell_example.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/pyshell_full.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/pyshell_full.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/developer_info/pyshell_help.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/developer_info/pyshell_help.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/edittools.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/edittools.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/edittools.html
===================================================================
--- packages/openev/branches/upstream/current/html/edittools.html (rev 0)
+++ packages/openev/branches/upstream/current/html/edittools.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,256 @@
+<html>
+<head>
+<title>Edit Tools</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Edit Tools</h1>
+
+The follow tools allow manipulation of vectors, as well as some special
+view management operations. Only one mode may be active at a time (with the
+exception of Link Views), and most operate on a single vector layer (with the
+exception of Zoom, Draw ROI, and Link Views) which must be the active layer
+in the <a href="layerdlg.html">Layer Management Dialog</a>. The various
+vector editing tools will attempt to make a vector layer active if there is
+no active layer, or if the active layer is not a vector layer. It is a
+common frustration to be unable to select or modify vectors because they are
+not in the active layer.<p>
+
+Most of the editing modes have particular button combinations to do actions,
+but in all editing modes the standard <a href="viewarea_keys.html">View Area
+Button/Key Sequences</a> remain valid. Note that while not explicitly disabled
+in 3D mode the various editing interactions will generally not work properly
+in 3D mode.<p>
+
+Also, note that essentially all editing operations can be undone by hitting
+Control-Z or selecting Edit->Undo in the menu.<p>
+
+<img src="edittools.gif">
+
+<p>
+
+<h2>Select</h2>
+
+Select mode allows selection of vector features, and limited manipulation
+of those features. Selected features are highlighted with small diamonds
+around the nodes. Selection may be accomplished in several ways:
+
+<ul>
+<li> <b>LeftButton-Click</b>: Select the feature at the click location. Note
+that points and lines have only a modest tolerance for selection. Clicking
+inside a filled area will select the area. If more than one features overlaps
+the click location, only one will be selected (based on internal stacking
+order).
+
+<li> <b>LeftButton-Drag</b>: Drags out a box and on release selects all
+features intersecting the box. Note that the box drag has to start at a
+location where there is no feature, otherwise it will be interpreted as a
+single selection, and the selected feature will be dragged instead of a box
+being drawn. <p>
+
+<li> <b>Shift-LeftButton-Click</b>: Operates like LeftButton-Click, but adds
+or removes the selected feature from the current selection instead of clearing
+the existing selection. In most editing systems this would be
+Control-LeftButton-Click, but that is already bound to continuous zoom.<p>
+
+</ul>
+
+While in selection mode it is also possible to drag the selected features
+around by left clicking on a selected feature, and dragging. If multiple
+features are already selected, they are all dragged as a group. <p>
+
+The <b>Delete</b> or <b>Backspace</b> key may be used to delete the
+currently selected feature(s).<p>
+
+
+<h2>Zoom</h2>
+
+Zoom mode is not for editing of vector features, but instead adds some
+simplified view operations. The following are always available via the
+generic <b>Control</b> chorded alternatives described in
+<a href="viewarea_keys.html">View Area Button/Key Sequences</a>
+but in zoom mode these simplier alternatives are made available.<p>
+
+<ul>
+
+<li> <b>LeftButton-DoubleClick</b>: Zoom in by one increment (normally
+a factor of two), and recenter on target location.<p>
+
+<li> <b>LeftButton-Drag</b>: Drag out a zoom rectangle, and zoom on release.<p>
+
+<li> <b>LeftButton-PressAndHold</b>: Continuous zoom in.<p>
+
+<li> <b>RightButton-DoubleClick</b>: Zoom out by one increment
+(normally a factor of two), and recenter on target location.<p>
+
+<li> <b>RightButton-PressAndHold</b>: Continuous zoom out.<p>
+
+<li> <b>MiddleButton-Drag</b>: Drag the image to pan.<p>
+
+</ul>
+
+<h2>Point Edit</h2>
+
+Point edit mode is for creation of point features.<p>
+
+Each <b>LeftButton-Clock</b> in the view will result in a new point feature
+being created, and after creation it will be the selected feature. The
+<b>Delete</b> key can be used to delete the currently selected point if there
+is one. It is not possible to move, or otherwise manipulate points in this
+mode. Switch to <b>Select</b> mode to do that.<p>
+
+<h2>Point Query</h2>
+
+Point Query mode operates the same as Point Edit mode, but it operates on a
+point query layer, instead of a normal vector layer. <p>
+
+On entering Point Query mode, a new point query layer will be created if one
+is not already available on the current view. Otherwise the point query layer
+will be made the active layer if it is not already active. <p>
+
+Point query layers can show location and raster pixel value information for
+the selected points. The <a href="gvpquerypropdlg.html">Point Query
+Properties</a> panel has options for controlling what is shown for each
+query point.<p>
+
+<h2>Draw Line</h2>
+
+Line edit mode is for digitizing new line features. Note that Select
+mode is used to modify existing lines, and Node edit mode is used to modify
+individual nodes within an existing line. <p>
+
+The <b>LeftButton-Click</b> action is used to initiate digitizing of a
+new polyline. Subsequent left clicks will add new nodes to the polyline.
+The <b>RightButton-Click</b> or <b>Escape</b> key can be used to terminate
+line mode. While digitizing a line, the <b>Delete</b> key can be used to
+delete the last node added.<p>
+
+Note that while digitizing a line undo support is temporarily disabled.<p>
+
+<h2>Rotate/Resize</h2>
+
+Rotate/resize mode allows lines, areas and point symbols to be rotated and
+resized. At this time textual labels and plain points (not using symbols)
+cannot be rotated or resized.<p>
+
+The <b>LeftButton-Click</b> action can be used to select a shape to operate
+on. Once selected the shape will be drawn with the normal selection styling
+but a resize/rotate control will also be drawn in red, centered on the shape
+to be modified. It will look something like this:<p>
+
+<img src="rotatetool.gif"><p>
+
+The <b>LeftButton-Drag</b> action on the red two-directional arrowhead
+will rotate the shape in question. A <b>LeftButton-Drag</b> action on the
+red one directional arrow head will allow scaling the shape larger or smaller.
+A <b>RightButton-Drag</b> action on either arrowhead will result in a rotation
+and scaling effect.<p>
+
+Rotation and scaling are around a center point for the shape (the crossing
+point of the two arrows). Rotation and scaling applied to a point symbol
+result in the angle and scaling parameters being modified. Rotation and
+scaling applied to a line or area shape result in the actual vertex
+locations being modified.<p>
+
+Note that selecting the boxes around vertex of lines or areas has no effect
+in rotation and scaling mode. The <b>Escape</b> key may be used to terminate
+a rotation or scaling drag.<p>
+
+<h2>Draw Rectangle</h2>
+
+Rectangle drawing mode is for digitizing and modifying rectangular area
+features. While the rectangles created are just stored internally as normal
+area polygons, like
+those produced by Draw Area, rectangle mode offers special editing capabilities
+that maintains the rectangular constraint.<p>
+
+In rectangle mode <b>LeftButton-Drag</b> can be used to draw a new rectangle
+feature. If you click on the corner of an existing rectangle, that corner
+can be dragged, resizing the existing rectangle. If you click on the edge
+of an existing rectangle, that edge can be dragged resizing the existing
+rectangle.<p>
+
+The <b>Escape</b> key can be used to abort creation of a new rectangle, but
+while dragging an edge or corner of an existing rectangle it will just stop
+the dragged, equivelent to releasing the button. <p>
+
+<h2>Draw Area</h2>
+
+Area drawing mode is for digitizing area (polygon) features, which can contain
+holes. Moving existing areas is done with Select mode, and adding, removing
+or moving nodes in an existing polygon is done with Node Edit mode.<p>
+
+Digitizing a new polygon is accomplished by <b>LeftButton-Click</b>ing at
+each vertex location. When complete a <b>RightButton-Clock</b> terminates
+the process, and the polygon is closed.<p>
+
+Adding an internal ring (a hole) to an existing polygon is done by digitizing
+a new polygon entirely within the old polygon. The nesting is recognised, and
+the new polygon is treated as an internal ring to the main polygon. Note that
+this implies it is impossible to digitize a separate polygon that is inside
+another polygon ... to accomplish this, digitize it elsewhere, and then drag
+it into the area. If you digitize an a new polygon that starts inside
+another polygon, but goes outside the parent, it will be discarded on
+termination as a corrupt hole.<p>
+
+<h2>Edit Node</h2>
+
+Edit node mode is used to add, move, and remove individual nodes making up
+point, line and area features. To create new features use the point,
+line and area drawing modes.<p>
+
+In order to manipulate the nodes of a feature it is necessary to feature
+select the feature. Node editing mode only supports selection of a single
+feature at a time, by <b>LeftButton-Click</b>ing on it. Area selects are
+not supported. Selecting a feature will highlight all it's nodes at which
+point one of them can be selected, by left clicking on it.<p>
+
+A new node may be introduced into the selected feature by
+<b>LeftButton-Press</b>ing on an edge, but not too close to a node. The
+new node may then be positioned by dragging it before releasing.<p>
+
+An existing node is selected by clicking on it (or very close to it), at
+which point the node will be highlighted and filled in. The node may then
+be dragged to a new location. A node may be deleted by hitting the
+<b>Delete</b> key.<p>
+
+<h2>Draw Labels</h2>
+
+Label mode is used to draw labels on a shapes layer.
+
+<h2>Draw ROI</h2>
+
+The ROI tool allows a rectangular region of interest (ROI) to be drawn. The
+value of a raster rectangle selected with the ROI tool can also be used
+with the get_roi() function to create a subregion array for use with
+Numeric Python. <p>
+
+The ROI tool does not operate on a feature layer. It draws a free standing
+rectangle by <b>LeftButton-Drag</b>ing it out. Edges, and corners can also
+be grabbed and dragged.<p>
+
+<h2>Choose POI</h2>
+
+The POI tool allows a point of interest (POI) to be drawn. The location
+of the selected pixel can be found using the get_poi() function. The
+POI tool does not operate on a feature layer. It can be used to draw a
+free standing point by <b>LeftButton-Click</b>ing.
+
+<h2>Link Views</h2>
+
+Selecting Link Views will cause the view of each all windows to be
+linked. Pressing the button again will unlink the views. Any change of
+view in a linked window will result in all other windows also being updated
+similarly.<p>
+
+View characteristics includes the view position, zoom level, and rotation in
+2D. In 3D this includes the view position, view direction, and vertical
+exaggeration. View characters does not include details about layers
+displayed, layer colors or anything of that sort.<p>
+
+Link windows will only operate correctly if all views are in the same
+coordinate system. For instance, if one view is georeferenced in UTM, and
+another is in lat/long degrees, the linked views will not operate in a useful
+manner.<p>
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/equalize.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/equalize.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/exporttool_advgui.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/exporttool_advgui.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/exporttool_basicgui.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/exporttool_basicgui.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/files.html
===================================================================
--- packages/openev/branches/upstream/current/html/files.html (rev 0)
+++ packages/openev/branches/upstream/current/html/files.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,135 @@
+<html>
+<head>
+<title>File Access</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>File Access</h1>
+
+OpenEV supports a number of raster and vector file formats for display. The
+File->Open action will check to see if the selected file is a shapefile
+(ends in .shp) and if so attempt to load it as a new vector layer. If not, it
+will attempt to open it as a GDAL supported file format (listed below), and
+display it as a raster layer. If this fails, the optional OGR library is
+tried to see if it is another supported vector format. <p>
+
+Note that the File->Import action only operates on GDAL supported raster
+files. Vector files cannot be "imported". <p>
+
+<h2>Supported Raster Formats</h2>
+
+OpenEV uses
+<a href="http://www.remotesensing.org">GDAL</a> (Geospatial Data Abstraction
+Library) for accessing raster files, so any file formats supported by GDAL
+should be supported by OpenEV. The original, and authoritative list of
+<a href="http://www.remotesensing.org/gdal/formats_list.html">GDAL
+Supported Formats</a> should be checked for a current format list, and
+details of each format. <p>
+
+<table border>
+
+<tr>
+<th>Long Format Name</th>
+<th>Code</th>
+<th>Georeferencing</th>
+</tr>
+
+<tr><td> Arc/Info Binary Grid
+</td><td> AIG
+</td><td> Yes
+</td></tr>
+
+<tr><td> CEOS (Spot for instance)
+</td><td> CEOS
+</td><td> No
+</td></tr>
+
+<tr><td> First Generation USGS DOQ
+</td><td> DOQ1
+</td><td> Yes
+</td></tr>
+
+<tr><td> New Labelled USGS DOQ
+</td><td> DOQ2
+</td><td> Yes
+</td></tr>
+
+<tr><td> Military Elevation Data
+</td><td> DTED
+</td><td> Yes
+</td></tr>
+
+<tr><td> Eosat Fast Format
+</td><td> EFF
+</td><td> No
+</td></tr>
+
+<tr><td> ESRI .hdr Labelled
+</td><td> EHdr
+</td><td> Yes
+</td></tr>
+
+<tr><td> Arc/Info Binary Grid
+</td><td> GIO
+</td><td> Yes
+</td></tr>
+
+<tr><td> TIFF / GeoTIFF
+</td><td> GTiff
+</td><td> Yes
+</td></tr>
+
+<tr><td> Erdas Imagine .hfa
+</td><td> HFA
+</td><td> No
+</td></tr>
+
+<tr><td> Atlantis HKV Blob
+</td><td> HKV
+</td><td> Yes
+</td></tr>
+
+<tr><td> JPEG JFIF
+</td><td> JPEG
+</td><td> Yes
+</td></tr>
+
+<tr><td> Atlantis MFF
+</td><td> MFF
+</td><td> Yes
+</td></tr>
+
+<tr><td> PCI .aux Labelled
+</td><td> PAux
+</td><td> No
+</td></tr>
+
+<tr><td> Portable Network Graphics
+</td><td> PNG
+</td><td> No
+</td></tr>
+
+<tr><td> USGS SDTS DEM
+</td><td> SDTS
+</td><td> Yes
+</td></tr>
+
+<tr><td> SAR CEOS
+</td><td> SAR_CEOS
+</td><td> Yes
+</td></tr>
+
+</table>
+
+<h2>Supported Vector Formats</h2>
+
+OpenEV includes builtin support for reading and writing ESRI Shapefiles.
+This is a widely used file format for simple vector features with attributes,
+including support for points, polylines and polygonal areas (potentially
+with holes).<p>
+
+Additional formats can be read via an optional linkage to the OGR
+vector library, providing support for formats such as Mapinfo, SDTS, S-57,
+Tiger, and NTF. <p>
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/gvogrdlg.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvogrdlg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvpquerypropdlg.html
===================================================================
--- packages/openev/branches/upstream/current/html/gvpquerypropdlg.html (rev 0)
+++ packages/openev/branches/upstream/current/html/gvpquerypropdlg.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<title>Point Query Properties</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Point Query Properties</h1>
+
+The Point Query Properties dialog is used to display and edit properties of a
+point query layer. It can be launched by right clicking on the desired
+point query layer in the Layer Manipulation Dialog.<p>
+
+<h2>General</h2>
+
+<img src="gvpquerypropdlg_general.gif"><p>
+
+<ul>
+<li> <b>Layer</b>: view, and modify the layer name. This name is also
+displayed in the Layer Manipulation dialog.<p>
+
+<li> <b>Visibility</b>: Make this layer visible, or invisible. The same
+thing can be accomplished with the eye icon on the Layer Manipulation
+dialog.<p>
+
+<li> <b>Editable</b>: Toggle whether this layer can be edited or not using
+the various vector editing tools.<p>
+
+</ul>
+
+<h2>Drawing Style</h2>
+
+<img src="gvpquerypropdlg_drawstyle.gif"><p>
+
+<ul>
+<li> <b>Color</b>: Set the color used to draw the points, and text for
+the point query layer. <p>
+
+<li> <b>Point Size</b>: Set the size of the point cross hair (in screen
+pixels). <p>
+
+<li> <b>Coordinate</b>: Select coordinate display option for point query
+points.<p>
+
+<ol>
+<li> <b>Off</b>: Disable display of point coordinates.
+<li> <b>Raster Pixel/Line</b>: Display pixel/line (row/column) locations
+on the top raster layer under this location.
+<li> <b>Georeferenced</b>: Show georeferenced coordinates in the georeferencing
+system of the view.
+<li> <b>Geodetic (lat/long)</b>: Show coordinates reproject into latitude and
+longitude.<p>
+</ol>
+<p>
+
+<li> <b>Pixel Value</b>: Select whether raster pixel values from the top most
+raster layer under the point should be displayed (<b>On</b>) or not
+(<b>Off</b>).<p>
+
+</ul>
+
+
+</body>
+</html>
+
+
+
+
+
Added: packages/openev/branches/upstream/current/html/gvpquerypropdlg_drawstyle.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvpquerypropdlg_drawstyle.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvpquerypropdlg_general.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvpquerypropdlg_general.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvprint.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvprint.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvprint.html
===================================================================
--- packages/openev/branches/upstream/current/html/gvprint.html (rev 0)
+++ packages/openev/branches/upstream/current/html/gvprint.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,57 @@
+<html>
+<head>
+<title>Printing Dialog</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Printing Dialog</h1>
+
+The OpenEV Print Dialog is used to capture the contents of a view for
+printing, or other purposes. <p>
+
+<img src="gvprint.gif"></td><p>
+
+<ul>
+
+<li> <b>Driver</b>: One of:
+<ol>
+<li> PostScript: This is the only driver that supports the Paper and Scale
+controls in order to control placement on a page. The Output Type: Greyscale
+option should produce Level 1 PostScript that will work on any PostScript
+print.<p>
+<li> TIFF: Produces an RGB or Greyscale TIFF file. The resulting file is
+not georeferenced.<p>
+<li> PNG: Produces an RGB or Greyscale PNG file suitable for web publishing.<p>
+<li> Windows Print Driver: Prints via an installed MS Windows print driver.
+In this case the Print button leads to a dialog for selection of a specific
+driver, and control of other printer options. The image will always be
+printed as large as possible given the selection of paper type. <p>
+</ol>
+
+<li> <b>Device</b>: Select whether the resulting output is spooled directly
+to the printer or saved to a file. This option is always File for PNG and
+TIFF, and always Spool To Printer for Windows Print Driver. PostScript may
+be spooled, or directed to a file. <p>
+
+<li> <b>File/Command</b>: If the Device is File this is the name of a file
+to save the print to. If it is Spool to Printer this will be a command to
+be used to spool to the printer. The PostScript text will be directed to
+the standard input of the indicated command.<p>
+
+<li> <b>Output Type</b>: Either Greyscale or Color to control the type of
+output produced.<p>
+
+<li> <b>Paper</b>: (PostScript only) Select the paper size. This is used
+to establish size and positioning of the view.<p>
+
+<li> <b>Scale</b>: (PostScript only) Modifies the scale at which the print
+is produced. A value of 0.5 would cause the view to be 50% the normal size,
+but still centered on the paper. <p>
+
+<li> <b>Resolution</b>: The resolution at which the current view will be
+rendered for output. A value of 2.0 would cause the view to be internally
+rendered at double the resolution of the screen display for output. <p>
+
+<ul>
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg.html
===================================================================
--- packages/openev/branches/upstream/current/html/gvrasterpropdlg.html (rev 0)
+++ packages/openev/branches/upstream/current/html/gvrasterpropdlg.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,121 @@
+<html>
+<head>
+<title>Raster Properties</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Raster Properties</h1>
+
+The Raster Properties dialog is used to display properties of a raster
+display layer. It can be launched by right clicking on the desired
+raster layer in the Layer Manipulation Dialog.<p>
+
+<h2>General</h2>
+
+<img src="gvrasterpropdlg_general.gif"><p>
+
+<ul>
+<li> <b>Layer</b>: view, and modify the layer name. This name is also
+displayed in the Layer Manipulation dialog.<p>
+
+<li> <b>Visibility</b>: Make this layer visible, or invisible. The same
+thing can be accomplished with the eye icon on the Layer Manipulation
+dialog.<p>
+
+<li> <b>Editable</b>: Currently this control has no effect.<p>
+
+</ul>
+
+<h2>Drawing Style</h2>
+
+<img src="gvrasterpropdlg_drawstyle.gif"><p>
+
+<ul>
+<li> <b>Modulation Color</b>: Set the color to modulate the layer with.
+Selecting red, green or blue will cause the layer to only affect red,
+green or blue, with other RGB components <i>showing through</i>. An RGB
+composite can be created from three layers by setting each to be modulated
+by different component colors.<p>
+
+Setting the opacity of the modulation
+color (via the custom... entry) effectivly sets the opacity (alpha) for
+the whole layer. Alpha blending can also be achieved using the Alpha band
+of RGB layers on the Raster Sources tab.<p>
+
+<li> <b>Subpixel Interpolation</b>: Determines whether screen values should
+be deduced from image values by linear interpolation, or decimation (pick
+one of possible pixels).<p>
+
+</ul>
+
+<h2>Raster Sources</h2>
+
+<img src="gvrasterpropdlg_source.gif"><p>
+
+The Raster Sources tab allows control of the input raster bands used
+to generate the display layer. Each input component can be independently
+scaled, band mappings can be changed, and components can be set to use
+fixed scales instead of source bands. <p>
+
+<b>Band</b>: Select the band to use for this component from the
+file for this layer. At this time it is not possible to alter the source
+file after creation of the raster layer. If the value <b>constant</b> is
+selected instead of a band number, the scaling min/max controls will be
+replaced with an entry control which can be used to enter a single fixed
+value to use for that component for the entire layer.<p>
+
+Non-eight bit data (16bit integer, and floating point) is scaled to eight
+bit (range 0-255) before compositing, or putting through the layer lookup
+table. The scale minimum is mapped to 0, and the scale maximum to 255.
+The default scaling values are selected based on a 2% tail trim of a
+histogram of 10000 sample pixels from the image. Values outside the
+initial min/max range may be selected by typing them into text entry
+control.<p>
+
+<b>Scale Min</b>: Set the minimum value for scaling to eight bit.<p>
+
+<b>Scale Max</b>: Set the maximum value for scaling to eight bit.<p>
+
+<h2>LUT</h2>
+
+<img src="gvrasterpropdlg_lut.jpg"><p>
+
+The LUT tab only appears for complex raster layers, and allows five options
+for how the 2D (real and imaginary) components of the complex data will be
+mapped into a color for display. The options are:
+
+<ol>
+<li> Magnitude and Phase: Produce an image with HSV hue indicated by the
+phase, and HSV value indicated by the magnitude of the complex values.<p>
+
+<li> Phase: Produce an image with HSV hue indicating the phase of the
+complex values.<p>
+
+<li> Magnitude: Produce a red scale image showing the magnitude of the
+real and imaginary values.<p>
+
+<li> Real: Produce a greyscale image showing only the real component of
+the complex data. <p>
+
+<li> Imaginary: Produce a greyscale image showing only the imaginary
+component of the complex data.
+
+</ol>
+
+The displayed color swatch is the 2D LUT, with the vertical axis indicating
+increasing real values downwards, and the horizontal axis indiating increasing
+imaginary values to the right. <p>
+
+<h2>Image Info</h2>
+
+<img src="gvrasterpropdlg_imageinfo.gif"><p>
+
+The Image Info tab displays additional information about the image, including
+any metadata stored within the file. <p>
+
+</body>
+</html>
+
+
+
+
+
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg_drawstyle.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvrasterpropdlg_drawstyle.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg_general.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvrasterpropdlg_general.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg_imageinfo.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvrasterpropdlg_imageinfo.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg_lut.jpg
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvrasterpropdlg_lut.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvrasterpropdlg_source.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvrasterpropdlg_source.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvvectorpropdlg.html
===================================================================
--- packages/openev/branches/upstream/current/html/gvvectorpropdlg.html (rev 0)
+++ packages/openev/branches/upstream/current/html/gvvectorpropdlg.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,50 @@
+<html>
+<head>
+<title>Vector Properties</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Vector Properties</h1>
+
+The Vector Properties dialog is used to display and edit properties of a
+vector layer. It can be launched by right clicking on the desired
+vector layer in the Layer Manipulation Dialog.<p>
+
+<h2>General</h2>
+
+<img src="gvvectorpropdlg_general.gif"><p>
+
+<ul>
+<li> <b>Layer</b>: view, and modify the layer name. This name is also
+displayed in the Layer Manipulation dialog.<p>
+
+<li> <b>Visibility</b>: Make this layer visible, or invisible. The same
+thing can be accomplished with the eye icon on the Layer Manipulation
+dialog.<p>
+
+<li> <b>Editable</b>: Toggle whether this layer can be edited or not using
+the various vector editing tools.<p>
+
+</ul>
+
+<h2>Drawing Style</h2>
+
+<img src="gvvectorpropdlg_drawstyle.gif"><p>
+
+<ul>
+<li> <b>Points</b>: Set the color, and pixel cross hair size for point
+shapes in this layer (if any). The point size is measured in screen pixels.<p>
+
+<li> <b>Lines</b>: Set the line color for line shapes.<p>
+
+<li> <b>Areas</b>: Set the edge, and fill colors for areas.<p>
+
+</ul>
+
+
+</body>
+</html>
+
+
+
+
+
Added: packages/openev/branches/upstream/current/html/gvvectorpropdlg_drawstyle.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvvectorpropdlg_drawstyle.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/gvvectorpropdlg_general.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/gvvectorpropdlg_general.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/help.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/help.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/idle.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/idle.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/layerdlg.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/layerdlg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/layerdlg.html
===================================================================
--- packages/openev/branches/upstream/current/html/layerdlg.html (rev 0)
+++ packages/openev/branches/upstream/current/html/layerdlg.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<title>Layers Management Dialog</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Layers Management Dialog</h1>
+
+The OpenEV Layers Management Dialog is used to manage the order of display
+layers within a view, to change between views, and to launch properties panels
+for layers.<p>
+
+<table border=0><tr>
+<td><img src="layerdlg.gif"></td>
+
+<td>
+<ul>
+<li>
+The option menu at the top of the dialog may be used to select a view
+to operate on. Selecting an alternate view will cause that view to be
+popped up, as well as displaying the views layers in the Layers Management
+Dialog.<p>
+
+<li> Each layer is listed with it's name (typically the file it comes from),
+and an eye icon (if visible). The order of the layers indicates their
+precidence when drawn, with the top most layer in the list drawn over
+all other layers.<p>
+
+<li> Left clicking on a layer will cause it to become the selected
+(highlighted) layer. Many operations such as enhancements, and vector
+editing operate on the selected layer of the selected view. <p>
+
+<li> Clicking on the eye will cause the layer to toggle between
+being visible, and not being visible. <p>
+
+<li> Right clicking on the layer will cause a layer properties dialog to
+be displayed.<p>
+
+</ul>
+
+</td>
+
+</table>
+
+<ul>
+
+<li> The <img src="layerdlg_raise.gif"> icon will cause currently selected
+layer to move up in the layer dialog, causing it to be drawn over the layer
+that was previously above it. <p>
+
+<li> The <img src="layerdlg_lower.gif"> icon will cause currently selected
+layer to move down in the layer dialog, causing it to be drawn under the layer
+that was previously below it. <p>
+
+<li> The <img src="layerdlg_new.gif"> icon can be used to create a new
+vector layer for digitizing into.<p>
+
+<li> The <img src="layerdlg_delete.gif"> icon can be used to delete the
+currently selected layer.<p>
+
+</ul>
+
+<p>
+
+
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/layerdlg_delete.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/layerdlg_delete.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/layerdlg_lower.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/layerdlg_lower.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/layerdlg_new.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/layerdlg_new.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/layerdlg_raise.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/layerdlg_raise.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/legend.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/legend.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/linear.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/linear.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/log.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/log.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/logo.jpg
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/logo.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/mainwindow.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/mainwindow.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/mainwindow.html
===================================================================
--- packages/openev/branches/upstream/current/html/mainwindow.html (rev 0)
+++ packages/openev/branches/upstream/current/html/mainwindow.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,286 @@
+<html>
+<head>
+<title>Main OpenEV Window</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Main OpenEV Window</h1>
+
+The main OpenEV display window contains the geospatial data viewing
+area, as well as menus and an iconbar. The button and key sequences for
+manipulating view state are decribed in the separate
+<a href="viewarea_keys.html">View Area Button/Key Sequences</a> page.<p>
+
+The area at the bottom of the view window is the <b>track tool</b> and
+display position and raster value under the cursor. Details preferences
+for controlling the tracking tool are available in the application
+preferences panel (Edit->Preferences).<P>
+
+<img src="mainwindow.gif"><p>
+
+<h2>Icon Bar</h2>
+
+<dl compact>
+
+<dt><img src="openfile.gif">
+<dd><b>Open File</b>:
+Open a raster or vector file, and add to this view. Same as File->Open.<p>
+
+<dt><img src="print.gif">
+<dd><b>Print</b>:
+Launch the <a href="gvprint.html">Printing Dialog</a> to print the current
+view.<p>
+
+<dt><img src="nonelut.gif">
+<dd><b>Remove Enhancement</b>:
+Remove any greyscale enhancement lut (such as applied by the equalize
+icon) from the active raster layer. Does nothing if no raster layer is
+selected in the layers dialog.
+Note that a linear scaling stretch will still be in effect for
+non-eight bit data.<p>
+
+<dt><img src="linear.gif">
+<dd><b>Linear Enhancement</b>:
+Perform a linear stretch enhancement.<p>
+
+<dt><img src="equalize.gif">
+<dd><b>Histogram Equalization</b>:
+Apply a histogram equalization enhancement LUT to the active raster. This
+is a non-linear constrast stretch intended to flatten out the post-enhancement
+histogram. See the GvRasterLayer::equalize() method in pymod/gview.py for
+details on the algorithm used. Does nothing if a raster layer is not
+selected in the layers dialog. <p>
+
+<dt><img src="log.gif">
+<dd><b>Logarithmic Enhancement</b>:
+Perform a logarithmic stretch enhancement. The enhancment lut is recomputed
+to map the minimum to zero, the maximum to 255 and intermediate values
+based on logarithmic scaling. See GvRasterLayer::log() for algorithmic
+details.<p>
+
+<dt><img src="windowed.gif">
+<dd><b>Windowed Raster Re-enhancement</b>:
+Recompute the last enhancement (linear, equalize, logarithmic) based on
+pixels currently visible in the view. The scaling min/max and enhancement
+are recomputed. In 3D mode substantial numbers of pixels not actually
+visible in the view may be included in the calculation.
+<p>
+
+<dt><img src="classify.gif">
+<dd><b>Classify Raster</b>:
+Launches a dialog for applying a pseudo-color classification to a single
+raster band. This is a GIS style classification, not a multispectral
+classification. The dialog can only be launched if a raster layer is
+selected. The dialog is not currently further documented.
+<p>
+
+<dt><img src="legend.gif">
+<dd><b>Show Legend</b>:
+Launches a dialog displaying the current classification legend generated
+by the Classify Raster dialog. If there is no classification in force on
+the current raster, or if no raster layer is selected nothing will
+happen.
+<p>
+
+<dt><img src="seeall.gif">
+<dd><b>Fit all Layers</b>:
+Resets the view position, and zoom level such that all the data in all
+view layers is shown. As currently implemented the any rotation is lost.
+<p>
+
+<dt><img src="zoom_control.gif">
+<dd><b>Zoom Control</b>:
+Displays the zoom level of the currently selected raster layer. A value of
+1:2 would indicate decimation by 2, while 2:1 would indicate duplication
+of raw pixels by a factor of two. The user can selected a desired zoom level
+from popup menu, or directly type in zoom ratios. The control has no
+effect when a non-raster layer is selected.
+<p>
+
+<dt><img src="zoomin.gif">
+<dd><b>Zoom In</b>:
+Zoom in (making features bigger) by a factor of 2.
+
+<dt><img src="zoomout.gif">
+<dd><b>Zoom Out</b>:
+Zoom out (making features larger) by a factor of 2.
+
+<dt><img src="refresh.gif">
+<dd><b>Refresh Raster from Disk</b>:
+Causes the current raster layer to be reloaded from disk, or from it's
+source Numeric Python array. There are various levels of caching applied
+in OpenEV, and data is normally only re-read from disk when not available
+in memory. If a file is updated on disk (or a display numerical python
+array is updated) the refresh function can be used to force the display
+to be resyncronized from the source data. Applies to the active raster layer.
+If no raster layer is active nothing happens.
+<p>
+
+<dt><img src="worldg.gif"> <img src="worldrgb.gif">
+<dd><b>Georeferenced Display</b>:
+When the black and white icon is visible, the view is being displayed
+in raw pixel/line coordinates for the source raster. When the color icon
+is displayed the view is trying to display in georeferenced units (if
+any are available). Selecting this icon will toggle the state. This
+icon is generally used to switch between raw and warped images for images
+that include control points that will define a polynomial warp (such as
+many CEOS images). The initial state of this icon is determined by the
+"Display Georeferenced" control on the Raster tab of the
+<a href="preferences.html">Preferences</a> dialog.
+<p>
+
+<dt><img src="help.gif">
+<dd><b>Online Help</b>:
+Launch the OpenEV online help, the same as Help->Help.
+<p>
+
+<dt><img src="help.gif">
+<dd><b>Online Help</b>:
+Launch the OpenEV online help, the same as Help->Help.
+<p>
+
+<dt><img src="busy.gif"> <img src="idle.gif">
+<dd><b>Busy/Idle Indicator</b>:
+The red icon shows when the application is busy, and the green icon
+displays when the application is idle. Due to the background loading of
+data the application will often be busy for a short time after initially
+displaying a raster. Pressing the icon has no effect, and even when the
+application is busy it should remain responsive if somewhat more sluggish
+than when idle.
+<p>
+
+</dl>
+
+<h2>Menus</h2>
+
+<h3>File</h3>
+
+<dl compact>
+
+<dt> Import
+<dd> Import raster for optimized access. The user is prompted to select
+a raster data file. This is converted into tiled GeoTIFF format in the current
+working directory, overview levels are built, and the imported file is
+added to the current view (as if it had been opened).<p>
+
+The imported file is optimized for fast access, but may lose some information
+from the source file (such as metadata). Note that vector files cannot
+be imported.<p>
+
+<dt> Open
+<dd> Open a raster or vector file, and add it to the current view as a new
+layer. For files with a greater than eight bit data type, min/max values
+will be computed for scaling purposes. The resulting layer will be assigned
+the name of the source file. <p>
+
+<dt> Open 3D
+<dd> Brings up a dialog for selection of a drape and elevation raster. They
+are added to the current view as a 3D image, and the view is placed in 3D
+mode. <p>
+
+<dt> Save Vector Layer
+<dd> Brings up a file selector for entry of a filename to save the active
+vector layer to. The file saved to will be in ESRI Shapefile format. ESRI
+Shapefiles can only support one type of geometry per file (point, line, area)
+so if the active layer has a mixture, only one of the types (the first
+encountered) will be saved. Feature attributes are only saved if they are
+described by a schema on the layer, as is the case with vectors loaded
+from a shapefile. <p>
+
+<dt> New View
+<dd> Creates a new OpenEV view window with an independent set of data
+layers, and makes it the current view. <p>
+
+<dt> Print
+<dd> Launches the <a href="gvprint.html">Printing Dialog</a> for printing
+the view contents.<p>
+
+<dt> Recent Filenames
+<dd> A list of recently opened files is maintained in this menu. Selecting
+one is equivelent to doing a File->Open, and entering the displayed name.<p>
+
+<dt> Close
+<dd> Close the current window. If this is the last main display window for
+this OpenEV process the user is prompted if they want to exit the
+whole process.<p>
+
+<dt> Exit
+<dd> Close all windows, and terminate OpenEV. The user is prompted for
+confirmation.<p>
+
+</dl>
+
+<h2>Edit</h2>
+
+<dl compact>
+
+<dt> Undo
+<dd> Undoes the last undoable operation. Currently only the various
+vector editing operations are undoable. View changes, layer property
+changes and addition or deletion of layers are not undable. The undo
+stack is not bounded, and so in theory
+many undo steps are available; however, certain operations, like destruction
+of undoable layers results in clearing of the entire undo stack. <p>
+
+<dt> Layers...
+<dd> Launches the <a href="layerdlg.html">Layer Management Dialog</a> for
+manipulating view layers. <p>
+
+<dt> Vector Layer Attributes...
+<dd> Launches the vector features attributes dialog for inspecting, and
+changing the attributes of the selected feature.<p>
+
+<dt> Edit Toolbar...
+<dd> Launches the <a href="edittools.html">Edit Tools</a> for controlling
+editing mode.<P>
+
+<dt> Go To...
+<dd> Launches a simple dialog for recentering the view around a particular
+georeferenced location.<P>
+
+<dt> Python Shell...
+<dd> Launches a <a href="pyshell.html">Python Shell</a>. This is a
+dialog for interactively entering Python commands for simple image
+processing and other scripting needs.<P>
+
+<dt> 3D Position...
+<dd> Launches a dialog for setting the 3D view position and direction.<p>
+
+<dt> Preferences...
+<dd> Launches the application preferences panel for viewing, and modifying
+application wide preferences.<p>
+
+<dt> Python Shell...
+<dd> Launches the python shell for doing numerical python operations.<p>
+
+<dt> 3D Position...
+<dd> Launches the 3D position dialog for viewing, and modifying the 3D view
+position.<p>
+
+</dl>
+
+<h2>Help</h2>
+
+Note that online help is displayed as HTML
+files, and OpenEV needs access to an HTML viewing application. On Windows
+the default system HTML viewer is used. On Unix various well known browsers
+are searched for (ie. netscape, Mosaic). The user can customize this in the
+application preferences panel available under Edit->Preferences.<p>
+
+The help topic for most dialogs can be launched directly by hitting F1 after
+clicking on the dialog.<p>
+
+<dl>
+
+<dt> Help
+<dd> Displays application help. <p>
+
+<dt> Web Page
+<dd> Displays the OpenEV web page.
+
+<dt> About
+<dd> Display OpenEV information, and credits.<p>
+
+</dl>
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/nonelut.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/nonelut.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/onetoone.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/onetoone.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/open3d.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/open3d.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/open3d.html
===================================================================
--- packages/openev/branches/upstream/current/html/open3d.html (rev 0)
+++ packages/openev/branches/upstream/current/html/open3d.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,94 @@
+<html>
+<head>
+<title>Open 3D</title>
+</head>
+<body bgcolor="#ffffff">
+
+<h1>Open 3D</h1>
+
+OpenEV is capable of displaying 3D views as well as 2D views. To setup a
+3D view use the <b>File->Open 3D</b> option in the menu. This launches
+the 3D layer loading dialog.<p>
+
+<img src="open3d.gif"><p>
+
+<h2>Selecting Drape, and DEM Rasters</h2>
+
+Displaying a raster in 3D requires two components. One is the drape image.
+The image to be displayed in 3D. The other component is the raster used as
+a source of elevation information (the DEM raster). The Open 3D dialog
+contains two embedded file selectors, one for selecting the drape image
+and one for selecting the DEM raster. Any OpenEV supported raster format
+can be used for the drape and the DEM. Supported raster formats are
+discussed in the <a href="files.html">File Access</a> help topic.<p>
+
+Once selected OpenEV will create a 3D mesh over which to drape the drape
+image, based on elevation values from the DEM image. The density of the
+mesh is determined by the DEM Level of Detail control described later, but
+it is typically at substantially lower resolution than the drape image. Each
+mesh location is sampled from the DEM raster. If the location lies outside
+the DEM raster a value of zero is assumed.<p>
+
+It is not necessary for the drape and DEM images to have the same resolution
+or the same exact region; however, areas of the drape image lying outside
+the DEM will not have proper elevations assigned. Areas of the DEM outside
+the drape image will not be used. <b>The coordinate system of the drape and
+DEM images should be compatible.</b> OpenEV does not check this, so if the
+coordinate systems are different it is likely that no overlap will occur, or
+the elevations selected will be inappropriate. <p>
+
+<h2>Mesh Level Of Detail</h2>
+
+The <b>Mesh Level of Detail</b> selector allows control over the density of
+the elevation mesh. A highly refined mesh will result in more accurate
+geometry, with one mesh point per drape pixel being the most refined the mesh
+can be (at level 8). The least refined mesh (normally used for 2D display)
+has only one mesh point at each corner of the 256x256 drape tiles, and is
+mesh level of detail 0.<p>
+
+<b>Highly refined meshes take alot more memory, and will generally slow down
+redraws substantially.</b> The default mesh density (level of detail 3) has
+one mesh vertex every 32 pixels. Level of details in excess of 5 (one mesh
+vertex every 8 pixels) can become painfully slow even on accelerated systems.
+<p>
+
+<h2>Height Scaling Factor</h2>
+
+The height scaling factor is a multiplier applied to all elevations. A value
+of one gives a physically realistic display if the elevations are in the
+same units as the image georeferencing (ie. meters). It may be desirable to
+exaggerate the elevations to make 3D effects more visible by setting a
+scaling factor greater than one.<p>
+
+In some cases elevations are in different units, and the scaling factor can
+be used to correct for this. For instance, if the georeferenced display is
+in meters, but the elevations are in decimeters, a scaling factor of 0.1 will
+correct things.<p>
+
+<h2>Height Clamping</h2>
+
+The toggles for clamping minimum and maximum height can be used to
+restrict the range of mesh heights, according to the values in their
+corresponding text fields. This can be useful if the raster
+used as a DEM has invalid points that OpenEV is treating as valid data.
+This clamping is a one-time operation that acts on the data as it is
+read in to set the mesh values; it does not affect scaling operations
+that act on the view as a result of key-press events.
+<p>
+
+<h2>3D View Mode</h2>
+
+Once the OK button is hit, a new raster layer will be created, with associated
+3D mesh values. Depending on the level of detail selected for the mesh this
+may take some time.<p>
+
+Once complete the view is placed into <b>3D Mode</b>, and a different set of
+controls are used to maneuver.
+Mouse and keyboard controls for 3D mode are described on the
+<a href="viewarea_keys.html">View Area Button/Key Sequences</a> page.<p>
+
+Scrollbars, and the various vector editing controls should not be used in 3D
+mode as they will behave inproperly.<p>
+
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/openevmain.html
===================================================================
--- packages/openev/branches/upstream/current/html/openevmain.html (rev 0)
+++ packages/openev/branches/upstream/current/html/openevmain.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,37 @@
+<html>
+<head>
+<title>OpenEV</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+
+<p><img SRC="logo.jpg" height=75 width=290 ALT="OpenEV"><p>
+
+OpenEV is an application for viewing and analysing raster and vector
+geospatial data in 2D and 3D. OpenEV is an Open Source product, more
+information, and source code can be found at the OpenEV Web Page
+(<a href="http://openev.sourceforge.net/">http://openev.sourceforge.net/</a>).
+<p>
+
+<h1>OpenEV Online Help Pages</h1>
+
+<ul>
+<li> <a href="viewarea_keys.html">View Area Button/Key Sequences</a>
+<li> <a href="layerdlg.html">Layers Management Dialog</a>
+<li> <a href="gvrasterpropdlg.html">Raster Properties Dialog</a>
+<li> <a href="gvvectorpropdlg.html">Vector Properties Dialog</a>
+<li> <a href="gvpquerypropdlg.html">Point Query Properties Dialog</a>
+<li> <a href="gvprint.html">Printing Dialog</a>
+<li> <a href="edittools.html">Editing Toolbar</a>
+<li> <a href="pyshell.html">Interactive Python Shell</a>
+<li> <a href="mainwindow.html">Main Window</a>
+<li> <a href="open3d.html">Open 3D View</a>
+<li> <a href="preferences.html">Application Preferences</a>
+<li> <a href="files.html">File Access</a>
+<li> <a href="performance.html">Performance Tuning</a>
+<li> <a href="customization.html">Customization</a>
+<li> <a href="developer_info/DEVCOURSE.html">Developer Information</a>
+</ul>
+
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/openfile.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/openfile.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/performance.html
===================================================================
--- packages/openev/branches/upstream/current/html/performance.html (rev 0)
+++ packages/openev/branches/upstream/current/html/performance.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,132 @@
+<html>
+<head>
+<title>OpenEV Performance Tuning</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>OpenEV Performance Tuning</h1>
+
+OpenEV is designed to be a high performance viewing environment. Nevertheless
+there are a number of factors to keep in mind to optimize performance.
+These are three main areas to address to get good performance.<p>
+
+<h2>Accelerated OpenGL Support</h2>
+
+OpenEV is based on OpenGL, a standard for high performance 2D and 3D
+rendering. Software versions of OpenGL are available which do all operations
+in memory using conventional CPU resources, but these implementations tend to
+be much slower than optimized OpenGL drivers that utilize capabilities of
+accelerated 3D video cards.<p>
+
+In general OpenEV will operate <i>much</i> faster on systems with accelerated
+OpenGL support. On Windows NT, it is generally sufficient to install
+vendor provided drivers if you have a 3D video card (most medium to high
+end video cards). On Silicon Graphics systems, accelerated support is
+the standard. On Sun systems it may be available depending on the card
+in use. On Linux it is often necessary to hunt down and install 3D accelerated
+drivers from one of a number of sources, though software vendors like
+<a href="http://www.xig.com/">Xi Graphics</a> offer good OpenGL drivers for
+many popular cards on Linux. <p>
+
+Without accelerated OpenGL support redraws will be much slower (often 50x
+slower). The effect of this on user interaction can be reduced by keeping
+a few things in mind:
+
+<ul>
+<li> Avoid <i>dragging</i> operations that require a redraw after each drag
+increment. This means some of the vector editing modes will be very
+painful if there is a raster being displayed. Also, avoid trying to drag
+out a rectangle for zooming.<p>
+
+<li> Avoid continuous zoom and pan. Use the PageUp/PageDown keys for zooming
+in descrete jumps, and use the arrow keys (with Shift and Control chording)
+for panning. <p>
+
+<li> Avoid having more raster layers displayed than necessary. Even if drawn
+over one another each will add substantially to redraw time. <p>
+
+<li> Don't make the view window larger than you need, as redraw time will
+be proportional to the number of screen pixels.<p>
+
+<li> Turn off linear interpolation if you don't need it in the raster
+properties panel, as it adds substantially to the redraw time.<p>
+</ul>
+
+<h2>Texture and File Caching</h2>
+
+OpenEV does two types of caching for raster data, to accelerate redisplay
+speeds. The first is the caching of raw data from the file, and the second
+is the caching of preprocessed textures. The application preferences dialog
+can be used to control the cache size for both of these, and appropriate
+settings primarily depend on the hardware available.<p>
+
+Raw data caching is done on a tiled basis, and holds raw data values, before
+scaling or other preprocessing. A substantial file cache (raw data cache)
+is most important to accelerate texture regeneration when preprocessing
+parameters such as scaling values, and color tables are changed. The disk
+cache is kept in system RAM, and should generally not be larger than 50% of
+system RAM.<p>
+
+Texture data caching involves caching of preprocessed textures. On accelerated
+systems the textures are kept in video RAM, allowing very rapid redisplay of
+the image. On software OpenGL systems the textures are cached in main memory.
+Generally speaking the textures cache should be about the size of video
+card RAM less 8MB for frame buffer memory.<p>
+
+It is critical to have enough texture cache memory to hold all the textures
+required for one complete view display or an thrashing condition can occur.
+In this situation, the display is continually redraw, with different files
+dropping out of the redraw on each refresh. To correct this problem, go into
+Edit->Preferences, and increase the texture cache size.
+
+<h2>Disk File Format</h2>
+
+OpenEV is a disk based viewer. It is intended to operate on images much
+larger than can be kept in physical RAM. While for small datasets and
+with large file cache sizes it may be practical to hold the entire image in
+memory, that is not the case for large files. To optimize access to large
+files it is helpful to organize the file for easier access. Three
+things can help in this regard, building overviews, tiling the data, and
+ensuring the data is on local (high speed) media.<P>
+
+Having pre-built overviews (pyramids) will ensure that the initial display of
+large datasets can be very fast, as only a small reduced resolution image
+needs to be read to display the overview on screen. Overviews can be built
+for most GDAL supported formats with the <i>gdaladdo</i> commandline program,
+and File->Imported rasters will always have overviews built. A few
+applications, notably Atlantis processing tasks, will produce datasets with
+pre-built overviews for fast initial viewing.<p>
+
+OpenEV naturally accesses data by tiles, typically 256x256 rectangles of the
+source file. In order to read one tile from a line interleaved raster
+file that is 10Kx10K pixels in size, it is necessary to read 256 full
+scanlines, or 2.5 million pixels of data, in order to satisfy a request for
+about 64000 pixels. While OpenEV attempts to cache those scanlines to
+satisfy other tile requests in the same row, it is often the case that the
+viewer will only need a small portion of the whole scanline for a view.
+Accessing so much extra disk content can substantiallly slow displays. By
+reorganizing the data into pre-tiled format, local full resolution access
+can be accomplished much more efficiently. This can be accomplished by
+translating a file into a tiled file format. Tiling is available (optionally)
+in the TIFF and MFF formats. The File->Import operation converts data into
+a tiled TIFF file.<p>
+
+By default OpenEV uses averaging to compute reduced resolution overviews
+for display. To display a small overview of a very large image with no
+pre-built overviews it is still necessary to read all the data, and then
+average it down for display. This can be very slow. If this is a problem
+the user is encouraged to change the <b>Sample Method</b> on the <b>Raster</b>
+preference tab in the <a href="preferences.html#Raster">Preferences Dialog</a>
+to <b>Decimate</b>. This will reduce computation effort, and can also
+substantially reduce the number of disk scanlines that need to be read
+to display an image.<p>
+
+Finally, it is generally prudent to place data files on the highest speed
+media available. Accessing datasets over slow NFS connections, or from
+CDROM will of course be much slower than having them on the local disk.
+The File->Import operation will put the imported file in the current
+working directory, under the assumption that this will be local and fast.<p>
+
+In summary, importing raster files will often substantially improve
+access time.<p>
+</body>
+</html>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/html/pref_cache.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/pref_cache.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/pref_help.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/pref_help.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/pref_raster.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/pref_raster.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/pref_tracking.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/pref_tracking.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/preferences.html
===================================================================
--- packages/openev/branches/upstream/current/html/preferences.html (rev 0)
+++ packages/openev/branches/upstream/current/html/preferences.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,145 @@
+<html>
+<head>
+<title>Preferences Dialog</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Preferences Dialog</h1>
+
+
+<h2>Tracking Tool</h2>
+
+<img src="pref_tracking.gif"><p>
+
+The tracking tool preferences are used to control the types of information
+displayed by the tracking tool. This is the display area at the bottom
+of the <a href="mainwindow.html">Main OpenEV Window</a> that shows
+information about the location pointed to by the cursor in the window. <p>
+
+<b>Coordinate</b>: Possible values are:<p>
+<ol>
+<li> Off: Do not show the cursor position in the tracking area.<p>
+<li> Raster Pixel/Line: Show the pixel/line (column/row) location of the
+cursor on the top most raster layer under the cursor.<p>
+<li> Georeferenced: Show the cursor position in the current coordinate
+system of the view (which could be pixel/line, UTM, lat/long, etc). <p>
+<li> Geodetic (lat/long): Show the cursor position in geodetic (lat/long)
+coordinates if possible. If not possible this will operate the same as
+Georeferenced.<p>
+</ol>
+<p>
+
+<b>Lat/Long Format</b>: Determins the format to display Lat/Long values for the
+tracking tool. Possible formats are:<p>
+<ul>
+<li> ddd:mm:ss.ss Degree Minute Second notation<p>
+<li> ddd.ddddddd Degrees to seven decimal places<p>
+</ul>
+<p>
+
+<b>Pixel Value</b>: Determines whether the tracker should report the top
+most raster layers pixel value under the cursor. Note that fetching the
+pixel value can be expensive for some organizations of raster file, and thus
+can slow down interactive performance. <p>
+
+<h2><a name="Raster">Raster</a></h2>
+
+<img src="pref_raster.gif"><p>
+
+<b>Display Georeferencing:</b>
+Determines whether views loaded with a raster image should operate in
+georeferenced coordinates for that raster, or in raw pixel/line. A few points
+of note:<p>
+
+<ul>
+<li> The tracking tool can report georeferenced, or geodetic coordinates even
+if the view is drawn in pixel/line coordinates.<p>
+
+<li> The coordinate system of any vector layers must match the coordinate
+system of the view in order for the vectors to correctly overlay displayed
+rasters. Thus, only use No if vectors to be overlayed are in pixel/line
+coordinates, or yes, if they are in the georeferencing system of the raster.<p>
+
+<li> If the raster has GCPs, but no affine transformation, the raster will
+be given a first, or second order warp (depending on the number of GCPs) in
+order to display the raster in the projection of the GCPs. This can be
+fairly inappropriate for raw scenes with lat/long GCPs (such as most CEOS
+scenes). <p>
+</ul>
+
+<b>Overview Sampling</b>:
+Determines the sampling method to use when downsampling rasters for displays
+of overview images. Note that the sample method is a property of a raster,
+and is established at the point the raster is first displayed in a given
+OpenEV session based on the preferences. Changing this preference will only
+affect subsequently opened rasters.<p>
+
+<ul>
+<li> <b>Average</b>: Average all the pixels contributing to an overview
+pixel.<p>
+<li> <b>Decimate</b>: Just take one of the source pixels when computing
+an overview layer (the top left). <p>
+</ul>
+
+Decimation is the default, as it is less computationally expensive and
+gives more appropriate results when viewing complex phase images.
+Averaging can give much more viewable results for noisy data such as radar
+images. However, it makes loading overviews of large images without
+pre-computed overviews much more expensive because data must always be
+loaded at full resolution and averaged down to display resolution on the
+fly, whereas decimated displays often only need to load a small portion of
+the total available scanlines in order to compute the decimated display.<p>
+
+<b>Subpixel Interpolation</b>:
+Determines how a pixel is displayed close-up.<p>
+
+<ul>
+<li> <b>Bilinear</b>: The display intensity within a pixel varies from
+its center to its edges, based on the values of surrounding pixels.<p>
+<li> <b>Off (Nearest)</b>: The display intensity within a pixel is
+constant.<p>
+</ul>
+
+<b>Autoscaling Method</b>:
+Determines the method used to scale an image.
+
+<ul>
+<li> <b>Percent Tail Trim</b>: The intensity mapping is based on the
+minimum and maximum sorted data values with a user-defined percentage
+of the highest and lowest values not included.<p>
+<li> <b>Standard Deviations</b>: The intensity mapping is based on the
+mean data value plus/minus a user-defined number of standard deviations.<p>
+</ul>
+
+<h2>Caching</h2>
+
+Caching issues are covered in more detail in the
+<a href="performance.html">Performance Tuning</a> page.<P>
+
+<img src="pref_cache.gif"><p>
+
+
+<b>File Cache</b>: Number of bytes of memory available for caching raw raster
+data from disk.<p>
+
+<b>GL Texture</b>: Number of bytes of video or system memory available
+for caching image texturse.<p>
+
+<h2>Help Browser</h2>
+
+This tab is unavailable on Windows where the system default web/html browser
+is automatically used. <p>
+
+<img src="pref_help.gif"><p>
+
+Enter a command to be used to display a web page containing help (such as
+this one). If the command includes the value "%s" then the name of the file
+or URL to display will be substituted for the %s. Otherwise it will be
+appended to the command. By default OpenEV attempts to find one of a few
+common web browsers.<P>
+
+To test a newly entered value, go to the main view window help menu and
+select a topic, or hit <b>F1</b> over the preferences panel, after clicking
+outside the text box.<p>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/print.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/print.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/pyshell.html
===================================================================
--- packages/openev/branches/upstream/current/html/pyshell.html (rev 0)
+++ packages/openev/branches/upstream/current/html/pyshell.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,362 @@
+<html>
+<head>
+<title>Interactive Numeric Python Shell</title>
+</head>
+
+<body bgcolor="#ffffff">
+<h1><a name="contents">Interactive Numeric Python Shell</a></h1>
+
+<li><a href="#section1">Introduction</a>
+<li><a href="#section2">Environment</a>
+<li><a href="#section2a">Functions</a>
+<li><a href="#section2b">Commands</a>
+<li><a href="#section3">Examples</a>
+<li><a href="#section4">Python Shell Help</a>
+</ul>
+
+<h1><a name="section1">Introduction</a></h1>
+
+The OpenEV Python Shell provides access to image data in a Python scripting
+environment with built-in mathematical functions (supplied by the Numeric
+Python module). The OpenEV Python Shell adds a thin extra layer of
+interpretation to ordinary python, allowing a slightly different syntax to be
+used for some frequently used functions for typing convenience (no brackets).
+The core convenience functions (called <I>commands</I>) are registered
+automatically when the Python Shell launches, and have more argument
+checking infrastructure than regular python functions.
+
+To illustrate the difference between python and command syntax,
+the following example shows two ways of saving an array from the
+Python Shell environment to a file: <p>
+
+<pre>
+Python:
+
+SaveArray(my_array,'my_filename')
+
+Command:
+
+save my_array my_filename
+
+</pre>
+
+Extension modules with other commands may be registered using the core
+command <I>loadext</I>, but commands require more overhead to implement and
+in most cases it is preferable to use the ordinary python syntax. <P>
+
+If you're not familiar with Python or Numeric Python (NumPy) here are some
+references:
+<ul>
+<li><a href="http://www.python.org">Python</a>
+<li><a href="http://www.pfdubois.com/numpy/">Numerical Python</a>
+</ul><P>
+
+<h1><a name="section2">Environment:</a></h1>
+At startup (from the Edit/Python Shell menu item) the Python environment
+automatically imports functions from <I>Numeric</I> and <I>gdalnumeric</I>,
+and registers the <a href="#section2b">core commands</a>. Numeric
+provides Numeric Python and gdalnumeric provides functions to access OpenEV
+image data.<P>
+
+The shell consists of a command input window (bottom) and an output window
+(top). Aside from the registered commands, it behaves in the same way as
+the Python command line interpreter. Use the
+up and down arrow keys to scroll through previous command history.<P>
+<p>
+<img src="pyshell_default.gif">
+<p>
+
+<h2><a name="section2a">OpenEV Functions:</a></h2>
+In addition to the functions imported from Numeric python, OpenEV's Python
+shell includes the following functions:
+
+<ul>
+<li><b>LoadFile(<I>filename</I>[,xoff][,yoff][,xsize][,ysize])</b> - returns
+a numpy array containing the data from <i>filename</i>. If xoff and yoff
+are specified, <I>filename</I> will be read starting at pixel (column) offset
+<I>xoff</I> and line (row) offset <I>yoff</I>.
+If <I>xsize</I> and <I>ysize</I> are
+specified, only <I>xsize</I> pixels and <I>ysize</I> lines will be read;
+otherwise, the remainder of the file will be read in. The returned
+array will have dimensions <I>ysize</I> x <I>xsize</I> if the raster is
+greyscale; N x <I>ysize</I> x <I>xsize</I> if the raster has N channels.<P>
+
+<li><b>display(<I>array</I>)</b> - appends the array to the current OpenEV view and
+displays it.<P>
+
+<li><b>roi()</b> - returns the Region Of Interest (ROI) drawn out by the ROI tool
+in the format (x, y, width, height).<P>
+
+<li><b>get_roi(<i>array</i>)</b> - given an <i>array</I>, and an ROI marked by the
+ROI tool, extract that region from <I>array</I> and return it.<P>
+
+<li><b>SaveArray(<i>array</i>,<i>filename</i>[,<i>format</i>])</b>- save <i>array</i>
+to file <i>filename</i>, using <i>format</i>. <i>format</i> must be a GDAL write-supported
+format, such as 'GTiff' (Geotiff). If <i>format</i> is not specified, it will default to
+'GTiff'.<P>
+
+<li><b>CopyDatasetInfo(<i>src</i>,<i>dst</i>)</b>- copy metadata and georeferencing
+information from GDAL dataset <i>src</i> to GDAL dataset <i>dst</i>.
+</ul>
+
+<h2><a name="section2b">Core commands:</a></h2>
+
+Commands make use of an infrastructure that simplifies usage and help access for commonly used procedures that interact with the main OpenEV application or describe the local environment. These commands are intercepted and parsed before being passed to the shell's python interpreter, and are entered with the command and arguments separated by spaces rather than by round brackets and commas. Commands cannot be loaded or used in a regular python shell; they
+only have meaning within the context of OpenEV.<P>
+
+Core command list:<P>
+<ol>
+<li><i> newview</i>- create a new OpenEV view.
+<li><i> view3d</i>- display a dem and drape in 3D mode in the current OpenEV view.
+<li><i> get</i>- grab data from the currently active OpenEV view/layer..
+<li><i> show</i>- display a Python Shell array or GvShapes variable in an OpenEV view.
+<li><i> clearview</i>- clear the current OpenEV view.
+<li><i> save</i>- save a Python Shell array or GvShapes variable to a file.
+<li><i> loadext</i>- register commands from an extension module (command equivalent of python's import keyword).
+<li><i> macro</i>- run a sequence of commands/Python statements from a text file.
+<li><i> journal</i>- save text entered at the Python Shell command line to a text file.
+<li><i> locals</i>- list this session's local variables and their type codes.
+<li><i> help</i>- display help for a function or command.
+<li><i> functions</i>- list loaded python functions, or scan a module for functions.
+<li><i> commands</i>- list registered commands.
+</ol>
+
+<h1><a name="section3">Examples</a></h1>
+Here is a small tutorial that illustrates simple python usage and some
+of OpenEV's python functions; for a more comprehensive general tutorial,
+see the <a href="http://www.python.org/doc/current/tut/tut.html">www.python.org tutorial</a>.
+
+<h2>Example 1:</h2>
+<P><dl><dd>
+
+Load a file into a Numeric python array:
+<pre class="verbatim">
+ array1 = LoadFile(`filename.foo`)
+</pre>
+
+Display it in the current view:
+<pre class="verbatim">
+ display(array1)
+</pre>
+
+
+To get the Region Of Interest (ROI) marked on the image:<P>
+<ol>
+<li>launch the Edit toolbar using the menu entry <i>Edit/Edit toolbar</i>.<P>
+<li>select "Draw ROI" to activate the ROI tool.<P>
+<li>use the ROI tool to mark a region (left click to start drawing, drag, release to finish)<P>
+<li><tt>roi()</tt> returns the ROI in (x, y, width, height)<P>
+</ol>
+
+Use the ROI tool to get a subarray:<P>
+<ol>
+<li>mark out an ROI with the tool on the image<P>
+<li><tt>array2 = get_roi(array1)</tt><P>
+</ol>
+
+To save array2 to a new file:<P>
+<pre class="verbatim">
+SaveArray(array2,'filename2.tif')
+</pre>
+
+</dl>
+
+Numeric python functions such as <i>ones</i> and <i>array</i> can also be
+used to create and manipulate arrays:
+
+<P><dl><dd>
+
+To create a floating point array of ones with 5 rows and 6 columns:<P>
+<pre class="verbatim">
+ array3=ones([5,6],Float)
+</pre>
+
+Reset rows 1 to 4, columns 1 to 5 of the array with some values:<P>
+<pre class="verbatim">
+ array3[1:5,1:6]=array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]],Float)
+</pre>
+
+Square it:<P>
+<pre class="verbatim">
+ array3=power(array3,2)
+</pre>
+
+Display it in the current view:<P>
+<pre class="verbatim">
+ display(array3)
+</pre>
+
+Some important points to note are:<P>
+<ol>
+<li> Numeric python arrays are indexed from zero.<P>
+<li> In slicing a Numeric python array using index range N:M, elements N, N+1, ...M-1 are included.<P>
+</ol>
+
+</dl>
+
+<h2>Example 2</h2>
+
+We are starting with Python shell (Edit->Python Shell... menu item). You
+should load some raster file into OpenEV to work with.<p>
+
+<ul>
+
+ <li> Get active layer<p>
+
+ <pre>
+layer = gview.app.sel_manager.get_active_layer()
+ </pre>
+
+ ...and load data array into memory:<p>
+
+ <pre>
+ds = layer.get_parent().get_dataset()
+data = DatasetReadAsArray(ds)
+ </pre>
+
+ Note: using the core command <I>get</I> with the argument <I>data</I>
+ (ie. enter "get data" at the command line) will perform these three steps
+ for you.<p>
+
+ If you don't want open and display your input data with OpenEV, but want
+ load the file(s) in memory, make some calculations and display result,
+ you can use other approach instead of previous steps:<p>
+
+ <pre>
+data = LoadFile('filename.l1b')
+ </pre>
+
+ (In this sample we will work with NOAA AVHRR data in L1B format).<p>
+
+ <li> Now we are ready to operate with loaded data. For example,
+ calculate normalised difference vegetation index (NDVI) with NOAA
+ AVHRR data. In this case NDVI is calculated as
+ (Band2 - Band1)/(Band2 + Band1). We assume we have already calibrated
+ data in our file.<p>
+
+ <pre>
+ndvi = (data[1] - data[0]) / (data[1] + data[0])
+ </pre>
+
+ <li> Display result and, optionally, save it into file:<p>
+
+ <pre>
+display(ndvi)
+SaveArray(ndvi,'ndvi.tif','GTiff')
+ </pre>
+
+ Note, that in all our computations arrays are fully loaded into
+ memory. Be sure you have enough resources for this. For large arrays
+ loading and calculations may take some time.<p>
+
+ <li> Another operation: let's make a RGB composite image. In general
+ case this operation should be interactively controlled by the user,
+ because band colors should be carefully adjusted to produce the best
+ looking results. But we will simplify our task. NOAA AVHRR data has
+ 10-bit depth (GDAL stores them in 16-bit integer), so we just scale
+ input data to 8-bit and fill three-component array.<p>
+
+ <pre>
+rgb = zeros((3, ds.RasterYSize, ds.RasterXSize), UnsignedInt8)
+for i in range(3):
+ rgb[i] = (data[i] * 256 / 1024).astype(UnsignedInt8)
+display(rgb)
+ </pre>
+
+ This code produces a RGB composite from the first three channels of
+ the input image, but you can unroll the loop and use channels you
+ want. Following code uses channel 5 as red, 2 as green and 3 as blue:<p>
+
+ <pre>
+rgb[0] = (data[4] * 256 / 1024).astype(UnsignedInt8)
+rgb[1] = (data[1] * 256 / 1024).astype(UnsignedInt8)
+rgb[2] = (data[3] * 256 / 1024).astype(UnsignedInt8)
+ </pre>
+
+ <li> Now we will use other data as a sample. Let load ASTER Level 1B
+ dataset (the second band) and try to calibrate it. This dataset
+ already reprocessed and should be calibrated with the simple linear
+ function. Function coefficients contained in the metadata records with
+ the appropriate number at the end (2 in case of the second band).<p>
+
+ <pre>
+layer = gview.app.sel_manager.get_active_layer()
+ds = layer.get_parent().get_dataset()
+data = DatasetReadAsArray(ds)
+incl = float(ds.GetMetadata()["INCL2"])
+offset = float(ds.GetMetadata()["OFFSET2"])
+data_cal = data * incl + offset
+display(data_cal)
+ </pre>
+
+</ul>
+
+
+<h1><a name="section4">Python Shell Help</a></h1>
+
+The python shell has three commands used to provide help on functions
+and commands:
+<ol>
+<li><i> help</i>- display help for a function or command.
+<li><i> commands</i>- list registered commands.
+<li><i> functions</i>- list loaded python functions, or scan a module for functions.
+</ol>
+
+These commands make use of python __doc__ strings and any help text
+files that are registered. Help text files should only be used when
+there is some reason for not updating the python __doc__ string itself
+(eg. if documentation were going to be available in multiple languages,
+or if the package is from a third party and you don't want to use
+the doc string), or if the python documentation is fine but
+it is desirable to display help for some
+functions/commands that are not loaded so that the user is made
+aware of them. In the latter case, the help text file should be
+regenerated from the python documentation each time one of the functions'
+documentation changes (at least for releases).
+
+Help text files may have entries of the following three formats:
+
+<pre>
+COMMAND_NAME=my_command
+Module: my_module
+Group: my_group
+Html: my_html.html
+
+documentation...
+
+FUNCTION_NAME=my_func
+Module: my_module
+Html: my_html.html
+
+documentation...
+
+BUILTIN_NAME=my_builtin
+Module: my_module
+Html: my_html.html
+
+documentation...
+</pre>
+
+where my_command, my_func, and my_builtin are a user-defined command,
+function, and builtin (bound C) function respectively. The Html entry
+is used to indicate an html file with more information, and is optional
+(currently, the python shell will not do anything with html information
+other than store the name of the link- this may be used in future though).
+The Module name is required to deal with the case of two modules defining
+different commands/functions with the same name. The COMMAND_NAME,
+FUNCTION_NAME, BUILTIN_NAME, Module, and Html parts of the text file are
+case-sensitive (ie. an error will occur if the case is not as above).
+See gvcorecmds.py's RegisterHelp
+function for how to register a help file with the interpreter (this
+function determines the location of gvcorecmds_help.txt assuming that
+it is in the same directory as gvcorecmds.py, and loads the text from
+it if it is present). The suggested convention
+for text help files is that if they are needed, they be placed
+in the same directory as the commands/functions they relate to, and have the
+same name as the command module, minus the '.py', plus '_help.txt'.
+<p>
+
+<a href="#contents">Top</a><p>
+<a href="openevmain.html>OpenEV Help</a><p>
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/pyshell_default.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/pyshell_default.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/refresh.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/refresh.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/rotatetool.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/rotatetool.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/seeall.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/seeall.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/tool_hist.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/tool_hist.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/tool_roigeneral.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/tool_roigeneral.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/tools_openev.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/tools_openev.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/veclayerselect.html
===================================================================
--- packages/openev/branches/upstream/current/html/veclayerselect.html (rev 0)
+++ packages/openev/branches/upstream/current/html/veclayerselect.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,62 @@
+<html>
+<head>
+<title>Vector Layer Selection</title>
+</head>
+<body bgcolor="#ffffff">
+<h1>Vector Layer Selection</h1>
+
+The Vector Layer Selection dialog is displayed when the user selects
+a supported vector file other than a shapefile. It allows the user to
+select the layers they want to select out of the file, as well as potentially
+loading only a subarea or subset.
+<p>
+
+<img src="gvogrdlg.gif"><p>
+
+The dialog sections are:<p>
+
+<ul>
+<li> <b>Layers List</b>: Clicking on layers will toggle whether they should
+be loaded or not. When a layer is to be loaded, the check mark will be
+drawn in black. By default no layers are loaded.<p>
+
+<li> <b>Clip To View</b>: This toggle button can be enabled to request that
+only vectors in the current view area should be loaded. Note that any
+vector that appears to intersect the current 2D bounding rectangle will be
+loaded and complete individual vector features are still loaded ... no
+actual clipping occurs within features. However, any features outside the
+area of the view will not be loaded.<P>
+
+<li> <b>Execute SQL</b>: An SQL statement-like statement can be entered
+in the text area to the left of this button. Hit execute and the result
+of the query will be returned as a layer. Note that when accessing a real
+database (such as PostgreSQL or Oracle) this request is passed through to
+the underlying database. Simple file formats only support a simplified
+SQL WHERE statement. See the
+<a href="http://gdal.velocet.ca/projects/opengis/">OGR</a> library web page
+for further details.<p>
+
+<li> <b>Accept</b>: Loads the currently selected layers (if any) according
+to the current Clip To View setting.<p>
+
+<li> <b>Load All</b>: Loads all layers according to the current Clip To
+View setting.<p>
+
+<li> <b>Cancel</b>: Closes the dataset without any loading.<p>
+
+<li> <b>Help</b>: Displays this page.<P>
+
+</ul>
+
+<hr>
+
+The Vector Layer Selection dialog is not current user accessable when
+reading from Shapefiles, but from Python it can be used even for shapefiles
+by calling GvViewWindow.file_open_ogr_by_name() instead of the higher level
+GvViewArea.file_open_by_name().<p>
+
+</body>
+</html>
+
+
+
Added: packages/openev/branches/upstream/current/html/viewarea_keys.html
===================================================================
--- packages/openev/branches/upstream/current/html/viewarea_keys.html (rev 0)
+++ packages/openev/branches/upstream/current/html/viewarea_keys.html 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,134 @@
+<html>
+<head>
+<title>View Area Button/Key Sequences</title>
+</head>
+<body BGCOLOR="#FFFFFF">
+<h1>View Area Button/Key Sequences</h1>
+
+<h2>2D Mode</h2>
+<ul>
+<li> <b>Control-LeftButton-DoubleClick</b>: Zoom in by one increment (normally
+a factor of two), and recenter on target location.<p>
+
+<li> <b>Control-LeftButton-Drag</b>: Drag out a zoom rectangle, and zoom on release.<p>
+
+<li> <b>Control-LeftButton-PressAndHold</b>: Continuous zoom in.<p>
+
+<li> <b>Control-RightButton-DoubleClick</b>: Zoom out by one increment
+(normally a factor of two), and recenter on target location.<p>
+
+<li> <b>Control-RightButton-PressAndHold</b>: Continuous zoom out.<p>
+
+<li> <b>Control-MiddleButton-Drag</b>: Drag the image to pan.<p>
+
+<li> <b>Control-F1</b>: Flip image in the horizontal direction.<p>
+
+<li> <b>Control-F2</b>: Flip image in the vertical direction.<p>
+
+<li> <b>Control-Z</b>: Undo one edit operation.<p>
+
+<li> <b>Shift-Leftbutton-Drag</b>: Rotate about center of view.<p>
+
+<li> <b>Escape</b>: Cancels drag and rubber banding operations.<p>
+
+<li> <b>Page Up</b>: Zoom in one increment (normally a factor of two).<p>
+
+<li> <b>Page Down</b>: Zoom out one increment (normally a factor of two).<p>
+
+<li> <b>Home</b>: Zoom/pan such that all layers are visible in the view.<p>
+
+<li> <b>Delete</b>: Delete currently selected vector shapes (if any).<p>
+
+<li> <b>LeftArrow</b>: move view ten pixels left<p>
+
+<li> <b>RightArrow</b>: move view ten pixels right<p>
+
+<li> <b>UpArrow</b>: move view ten pixels up<p>
+
+<li> <b>DownArrow</b>: move view ten pixels down<p>
+
+<li> <b>Control-LeftArrow</b>: move view 3/4 of the view width left<p>
+
+<li> <b>Control-RightArrow</b>: move view 3/4 of the view width right<p>
+
+<li> <b>Control-UpArrow</b>: move view 3/4 of the view height up<p>
+
+<li> <b>Control-DownArrow</b>: move view 3/4 of the view height down<p>
+
+<li> <b>Shift-LeftArrow</b>: move view 3/8 of the view width left<p>
+
+<li> <b>Shift-RightArrow</b>: move view 3/8 of the view width right<p>
+
+<li> <b>Shift-UpArrow</b>: move view 3/8 of the view height up<p>
+
+<li> <b>Shift-DownArrow</b>: move view 3/8 of the view height down<p>
+
+</ul>
+
+<h2>3D Mode</h2>
+<ul>
+ There are two states, <b>Panning</b> which requires no additional key presses,
+ and <b>Translation</b> which requires the <b>Control</b> key to be held down. Both states
+ share forwards and backwards motion controls. This allows you to move forward/backwards
+ as well as change your viewing direction or position simultaneously.<p>
+
+ <li>Forward/Backwards (Zooming) Controls: Common to Both Panning and Translating States.<p>
+ <ul>
+ <li> <b>LeftButton-Hold</b>: Move forward along current line of sight<p>
+
+ <li> <b>MiddleButton-Hold</b>: Nothing<p>
+
+ <li> <b>RightButton-Hold</b>: Move backwards along current line of sight<p>
+
+ <li> <b>LeftButton-DoubleClick</b>: Move forward along current line of sight by one increment<p>
+
+ <li> <b>RightButton-DoubleClick</b>: Move backwards along current line of sight by one increment<p>
+ </ul>
+
+ <li> Pan Mode <b>AnyMouseButton-Hold</b>: Change viewing direction<p>
+ <ul>
+ <li><b>Mouse Forwards</b>: look down<p>
+ <li><b>Mouse Backwards</b>: look up<p>
+ <li><b>Mouse Left</b>: look right<p>
+ <li><b>Mouse Right</b>: look left<p>
+ </ul>
+
+ <li> Translate Mode <b>Control-AnyMouseButton-Hold</b>: Change position<p>
+ <ul>
+ <li><b>Mouse Forwards</b>: move down<p>
+ <li><b>Mouse Backwards</b>: move up<p>
+ <li><b>Mouse Left</b>: move to right<p>
+ <li><b>Mouse Right</b>: move to left<p>
+ </ul>
+
+<li> <b>LeftArrow</b>: move left<p>
+
+<li> <b>RightArrow</b>: move right<p>
+
+<li> <b>UpArrow</b>: move up<p>
+
+<li> <b>DownArrow</b>: move down<p>
+
+<li> <b>PageUp</b>: Move forward along current line of sight by 0.1 increment<p>
+
+<li> <b>Shift-PageUp</b>: Move forward along current line of sight by one increment<p>
+
+<li> <b>PageDown</b>: Move backwards along current line of sight by 0.1 increment<p>
+
+<li> <b>Shift-PageDown</b>: Move backwards along current line of sight by one increment<p>
+
+<li> <b>-</b> decrease height field scaling factor (by 0.01)<p>
+
+<li> <b>_</b> decrease height field scaling factor (by 0.1)<p>
+
+<li> <b>=</b> increase height field scaling factor (by 0.01)<p>
+
+<li> <b>+</b> increase height field scaling factor (by 0.1)<p>
+
+<li> <b>F2</b>: switch between 2D and 3D mode<p>
+
+<li> <b>Home</b>: reset viewing position<p>
+</ul>
+
+</body>
+</html>
Added: packages/openev/branches/upstream/current/html/windowed.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/windowed.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/worldg.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/worldg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/worldrgb.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/worldrgb.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/zoom_control.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/zoom_control.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/zoomin.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/zoomin.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/html/zoomout.gif
===================================================================
(Binary files differ)
Property changes on: packages/openev/branches/upstream/current/html/zoomout.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: packages/openev/branches/upstream/current/install-sh
===================================================================
--- packages/openev/branches/upstream/current/install-sh (rev 0)
+++ packages/openev/branches/upstream/current/install-sh 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,256 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ -x "$src".exe ] ; then
+ src=${src}.exe
+ echo "Cygwin hack - actually installing "$src
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
Property changes on: packages/openev/branches/upstream/current/install-sh
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/invdistance.c
===================================================================
--- packages/openev/branches/upstream/current/invdistance.c (rev 0)
+++ packages/openev/branches/upstream/current/invdistance.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,164 @@
+/******************************************************************************
+ * $Id: invdistance.c,v 1.3 2001/04/22 17:33:24 pgs Exp $
+ *
+ * Project: CIETMAP / OpenEV
+ * Purpose: Weighted Inverse Distance Interpolator (point to raster)
+ * This implementation is independent of OpenEV, but does depend
+ * directly on GDAL.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: invdistance.c,v $
+ * Revision 1.3 2001/04/22 17:33:24 pgs
+ * changed WIDInterpolate to take variable exponent for d
+ *
+ * Revision 1.2 2001/02/05 14:45:09 warmerda
+ * make padfWeight optional
+ *
+ * Revision 1.1 2000/09/12 19:17:46 warmerda
+ * New
+ *
+ */
+
+#include "invdistance.h"
+#include "cpl_conv.h"
+
+/************************************************************************/
+/* WIDInterpolate() */
+/************************************************************************/
+
+/**
+ * Weighted Inverse Distance Interpolation
+ *
+ * This algorithm interpolates the pixel values of a raster (in a GDAL
+ * band) using a simple inverse distance interpolator with an additional
+ * per point weighting factor. The algorithm support GDALProcessFunc style
+ * progress reporting, and user termination support.
+ *
+ * @param nPoints the number of input sample points (entries in the padfX,
+ * padfY, padfValue and padfWeight arrays).
+ *
+ * @param padfX the X locations of sample points in raster pixel/line
+ * coordinates.
+ *
+ * @param padfY the Y locations of sample points in raster pixel/line
+ * coordinates.
+ *
+ * @param padfValue the data value for each sample point.
+ *
+ * @param padfWeight a relative weighting for each sample point. Use NULL
+ * to default to equal weighting (implies all are 1.0).
+ *
+ * @param hBand the output GDAL band to which results should be written.
+ *
+ * @param fExponent the exponent to apply to the distance calculate in the
+ * weighting formula
+ *
+ * @param pfnProgress progress function (see GDALDummyProgress() for more
+ * information), use NULL if no progress function desired.
+ *
+ * @param pCBData callback data passed to pfnProgress.
+ *
+ * @return A CPL error number on failure, or CPLE_None on success. Note that
+ * a user interrupt will result in CPLE_UserInterrupt.
+ */
+
+int WIDInterpolate( int nPoints, double *padfX, double *padfY,
+ double *padfValue, double *padfWeight,
+ GDALRasterBandH hBand, double fExponent,
+ GDALProgressFunc pfnProgress, void * pCBData )
+
+{
+ int nXSize, nYSize, nError = CPLE_None, iY, iPoint;
+ float *pafScanline;
+ double *padfDeltaYSquared;
+
+ if( pfnProgress == NULL )
+ pfnProgress = GDALDummyProgress;
+
+ nXSize = GDALGetRasterBandXSize( hBand );
+ nYSize = GDALGetRasterBandYSize( hBand );
+
+ padfDeltaYSquared = (double *) CPLMalloc(sizeof(double) * nPoints);
+ pafScanline = (float *) CPLMalloc(sizeof(float) * nXSize);
+
+ for( iY = 0; iY < nYSize; iY++ )
+ {
+ int iX;
+
+ if( !pfnProgress( iY / (double) nYSize, NULL, pCBData ) )
+ {
+ nError = CPLE_UserInterrupt;
+ break;
+ }
+
+ /* Precompute DeltaY Squared for point. It will remain constant
+ over the scanline. */
+ for( iPoint = 0; iPoint < nPoints; iPoint++ )
+ {
+ padfDeltaYSquared[iPoint] =
+ (padfY[iPoint]-(double)iY) * (padfY[iPoint]-(double)iY);
+ }
+
+ for( iX = 0; iX < nXSize; iX++ )
+ {
+ double dfNumerator=0.0, dfDenominator = 0.0;
+ double dfX = iX;
+
+ for( iPoint = 0; iPoint < nPoints; iPoint++ )
+ {
+ double dfDistSquared, dfDeltaX;
+ double dfWeight;
+
+ dfDeltaX = (padfX[iPoint] - dfX);
+
+ dfDistSquared = dfDeltaX*dfDeltaX + padfDeltaYSquared[iPoint];
+
+ if (fExponent != 2.0)
+ {
+ //if the exponent is not 2, use the exponent / 2
+ //as the distance is already squared
+ dfDistSquared = pow(dfDistSquared, fExponent / 2.0);
+ }
+
+ if( padfWeight == NULL )
+ dfWeight = 1.0 / dfDistSquared;
+ else
+ dfWeight = padfWeight[iPoint] / dfDistSquared;
+
+ dfDenominator += dfWeight;
+ dfNumerator += dfWeight * padfValue[iPoint];
+ }
+
+ pafScanline[iX] = dfNumerator / dfDenominator;
+ }
+
+ GDALRasterIO( hBand, GF_Write, 0, iY, nXSize, 1,
+ pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
+ }
+
+ pfnProgress( 1.0, NULL, pCBData );
+
+ CPLFree( pafScanline );
+ CPLFree( padfDeltaYSquared );
+
+ return nError;
+}
Added: packages/openev/branches/upstream/current/invdistance.h
===================================================================
--- packages/openev/branches/upstream/current/invdistance.h (rev 0)
+++ packages/openev/branches/upstream/current/invdistance.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * $Id: invdistance.h,v 1.2 2001/04/22 17:33:24 pgs Exp $
+ *
+ * Project: CIETMAP / OpenEV
+ * Purpose: Weighted Inverse Distance Interpolator (point to raster)
+ * This implementation is independent of OpenEV, but does depend
+ * directly on GDAL.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: invdistance.h,v $
+ * Revision 1.2 2001/04/22 17:33:24 pgs
+ * changed WIDInterpolate to take variable exponent for d
+ *
+ * Revision 1.1 2000/09/12 19:17:47 warmerda
+ * New
+ *
+ */
+
+#ifndef __INVDISTANCE_H__
+#define __INVDISTANCE_H__
+
+#include "gdal.h"
+
+CPL_C_START
+
+int WIDInterpolate( int nPoints, double *padfX, double *padfY,
+ double *padfValue, double *padfWeight,
+ GDALRasterBandH hBand, double fExponent,
+ GDALProgressFunc pfnProgress, void * pCBData );
+
+CPL_C_END
+
+#endif /*__INVDISTANCE_H__ */
Added: packages/openev/branches/upstream/current/ipgcplayer.c
===================================================================
--- packages/openev/branches/upstream/current/ipgcplayer.c (rev 0)
+++ packages/openev/branches/upstream/current/ipgcplayer.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,414 @@
+/******************************************************************************
+ * $Id: ipgcplayer.c,v 1.15 2004/02/23 20:16:36 gmwalter Exp $
+ *
+ * Project: InSAR Peppers
+ * Purpose: Implementation of GCP Layer.
+ *
+ * This layer is intended specifically for use in InSAR Peppers, and
+ * should only be changed on behalf of Atlantis, though it can
+ * serve as an example of custom layer drawing for others.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: ipgcplayer.c,v $
+ * Revision 1.15 2004/02/23 20:16:36 gmwalter
+ * Checked in changes for insar.
+ *
+ * Revision 1.14 2003/12/10 15:29:42 gmwalter
+ * Undid changes as requested.
+ *
+ * Revision 1.13 2003/12/06 22:23:22 gmwalter
+ * Checked in changes made by insar group.
+ *
+ * Revision 1.12 2003/02/27 03:59:21 warmerda
+ * added view to gv_shapes_layer_get_draw_info
+ *
+ * Revision 1.11 2002/11/05 04:05:32 warmerda
+ * geocoord update
+ *
+ * Revision 1.10 2001/08/08 17:44:12 warmerda
+ * use gv_shape_type() macro
+ *
+ * Revision 1.9 2001/06/15 15:30:29 warmerda
+ * try setting glPointSize to 1 when drawing GCPs
+ *
+ * Revision 1.8 2000/09/18 21:12:43 srawlin
+ * reduced icon size from 10 to 5.5
+ *
+ * Revision 1.7 2000/08/30 14:06:19 warmerda
+ * make it easier to change symbol size
+ *
+ * Revision 1.6 2000/08/16 14:52:43 warmerda
+ * added excluded support
+ *
+ * Revision 1.5 2000/08/15 20:09:31 warmerda
+ * default color properly
+ *
+ * Revision 1.4 2000/08/14 19:45:21 warmerda
+ * use geo_x, geo_y for G point
+ *
+ * Revision 1.3 2000/08/14 15:05:52 warmerda
+ * updated substantially
+ *
+ * Revision 1.2 2000/08/04 14:14:12 warmerda
+ * GvShapes shape ids now persistent
+ *
+ * Revision 1.1 2000/07/14 18:24:57 warmerda
+ * New
+ *
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include "ipgcplayer.h"
+#include "gvutils.h"
+#include <GL/gl.h>
+#include <string.h>
+
+/* Approximate size on screen of symbols in pixels */
+#define SYMBOL_SIZE 5.5
+
+static void ip_gcp_layer_class_init(IpGcpLayerClass *klass);
+static void ip_gcp_layer_init(IpGcpLayer *layer);
+static void ip_gcp_layer_setup(GvLayer *layer, GvViewArea *view);
+static void ip_gcp_layer_draw(GvLayer *layer, GvViewArea *view);
+static void ip_gcp_layer_draw_selected(GvShapeLayer *layer,
+ GvViewArea *view);
+
+GtkType
+ip_gcp_layer_get_type(void)
+{
+ static GtkType gcp_layer_type = 0;
+
+ if (!gcp_layer_type)
+ {
+ static const GtkTypeInfo gcp_layer_info =
+ {
+ "IpGcpLayer",
+ sizeof(IpGcpLayer),
+ sizeof(IpGcpLayerClass),
+ (GtkClassInitFunc) ip_gcp_layer_class_init,
+ (GtkObjectInitFunc) ip_gcp_layer_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ gcp_layer_type = gtk_type_unique(gv_shapes_layer_get_type(),
+ &gcp_layer_info);
+ }
+ return gcp_layer_type;
+}
+
+static void
+ip_gcp_layer_class_init(IpGcpLayerClass *klass)
+{
+ GvLayerClass *layer_class;
+ GvShapeLayerClass *shape_layer_class;
+
+ layer_class = (GvLayerClass*) klass;
+ shape_layer_class = (GvShapeLayerClass*) klass;
+
+ layer_class->setup = ip_gcp_layer_setup;
+ layer_class->draw = ip_gcp_layer_draw;
+ shape_layer_class->draw_selected = ip_gcp_layer_draw_selected;
+}
+
+static void
+ip_gcp_layer_init(IpGcpLayer *layer)
+{
+}
+
+GtkObject *
+ip_gcp_layer_new(void)
+{
+ GvShapes *data;
+ IpGcpLayer *layer = IP_GCP_LAYER(gtk_type_new(
+ ip_gcp_layer_get_type()));
+
+ data = GV_SHAPES(gv_shapes_new());
+ gv_data_set_name( GV_DATA(data), "GCPs" );
+ gv_shapes_layer_set_data( GV_SHAPES_LAYER(layer), data );
+ gv_data_set_name( GV_DATA(layer), "GCPs" );
+
+ return GTK_OBJECT(layer);
+}
+
+/*******************************************************/
+
+static void
+ip_gcp_layer_setup(GvLayer *rlayer, GvViewArea *view)
+{
+}
+
+static void
+ip_gcp_draw_circle( gfloat center_x, gfloat center_y, gfloat radius )
+
+{
+ gvfloat angle;
+
+#ifndef PI
+#define PI 3.1415927
+#endif
+
+ glBegin( GL_LINE_LOOP );
+ for( angle = 0.0; angle <= 2.00001*PI; angle += (PI/24.0) )
+ {
+ gfloat x, y;
+
+ x = sin(angle) * radius + center_x;
+ y = cos(angle) * radius + center_y;
+
+ glVertex2f( x, y );
+ }
+ glEnd();
+}
+
+static void
+ip_gcp_layer_draw_gcp( GvViewArea *view, IpGcpLayer *layer,
+ GvShape *shape, int selected )
+
+{
+ GvProperties *properties = gv_shape_get_properties(shape);
+ const char *value;
+ const char * type;
+ gfloat x, y, geo_x, geo_y, raw_x, raw_y;
+ GLgeocoord radius_x, radius_y;
+ GvColor color;
+ GvShapeDrawInfo drawinfo;
+
+ /* get and set color */
+ gv_shapes_layer_get_draw_info( view, GV_SHAPES_LAYER(layer), &drawinfo );
+ gv_color_copy( color, drawinfo.point_color );
+
+ gv_shapes_layer_override_color( shape, color, "_gv_color" );
+
+ glPointSize(1);
+ glColor4fv( color );
+
+ /* Compute main drawing location */
+ x = gv_shape_get_x(shape, 0, 0 );
+ y = gv_shape_get_y(shape, 0, 0 );
+
+ radius_x = 1.0;
+ radius_y = 0.0;
+ gv_view_area_correct_for_transform( view,
+ radius_x, radius_y,
+ &radius_x, &radius_y );
+ radius_x = SYMBOL_SIZE * sqrt(radius_x*radius_x + radius_y*radius_y);
+
+ /* fetch the georeferenced location in view coordinate system */
+ value = gv_properties_get( properties, "geo_x" );
+ if( value != NULL )
+ geo_x = atof(value);
+ else
+ geo_x = x;
+
+ value = gv_properties_get( properties, "geo_y" );
+ if( value != NULL )
+ geo_y = atof(value);
+ else
+ geo_y = y;
+
+ /* fetch the features location in view coordinate system */
+ value = gv_properties_get( properties, "raw_x" );
+ if( value != NULL )
+ raw_x = atof(value);
+ else
+ raw_x = x;
+
+ value = gv_properties_get( properties, "raw_y" );
+ if( value != NULL )
+ raw_y = atof(value);
+ else
+ raw_y = y;
+
+ /* draw based on type */
+ type = gv_properties_get( properties, "gcp_type" );
+ if( type == NULL )
+ type = "F&G";
+
+ value = gv_properties_get( properties, "excluded" );
+ if( value != NULL && atoi(value) > 0 )
+ type = "excluded";
+
+ if( strcmp(type,"excluded") == 0 )
+ {
+ /* draw excluded X */
+ glBegin(GL_LINES);
+ glVertex2f( x-radius_x*0.707, y-radius_x*0.707 );
+ glVertex2f( x+radius_x*0.707, y+radius_x*0.707 );
+ glVertex2f( x+radius_x*0.707, y-radius_x*0.707 );
+ glVertex2f( x-radius_x*0.707, y+radius_x*0.707 );
+ glEnd();
+ }
+
+
+ if( strcmp(type,"G&E") == 0 )
+ {
+ /* draw triangle */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f( geo_x, geo_y+radius_x );
+ glVertex2f( geo_x-radius_x*0.866, geo_y-radius_x*0.5);
+ glVertex2f( geo_x+radius_x*0.866, geo_y-radius_x*0.5);
+ glVertex2f( geo_x, geo_y+radius_x );
+ glEnd();
+
+ ip_gcp_draw_circle( geo_x, geo_y, radius_x );
+ }
+
+ if( strcmp(type,"F&E") == 0 )
+ {
+ /* draw triangle */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f( raw_x, raw_y+radius_x );
+ glVertex2f( raw_x-radius_x*0.866, raw_y-radius_x*0.5);
+ glVertex2f( raw_x+radius_x*0.866, raw_y-radius_x*0.5);
+ glVertex2f( raw_x, raw_y+radius_x );
+ glEnd();
+
+ /* draw cross hair */
+ glBegin(GL_LINES);
+ glVertex2f( raw_x, raw_y-radius_x );
+ glVertex2f( raw_x, raw_y+radius_x );
+ glVertex2f( raw_x+radius_x, raw_y );
+ glVertex2f( raw_x-radius_x, raw_y );
+ glEnd();
+
+ }
+
+ if( strcmp(type,"F&G") == 0 )
+ {
+ /* draw cross hair */
+ glBegin(GL_LINES);
+ glVertex2f( raw_x, raw_y-radius_x );
+ glVertex2f( raw_x, raw_y+radius_x );
+ glVertex2f( raw_x+radius_x, raw_y );
+ glVertex2f( raw_x-radius_x, raw_y );
+ glEnd();
+
+ ip_gcp_draw_circle( geo_x, geo_y, radius_x );
+
+ /* connect with line */
+ glBegin(GL_LINES);
+ glVertex2f( raw_x, raw_y );
+ glVertex2f( geo_x, geo_y );
+ glEnd();
+ }
+
+ if( strcmp(type,"F&G&E") == 0 )
+ {
+ /* draw triangle */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f( raw_x, raw_y+radius_x );
+ glVertex2f( raw_x-radius_x*0.866, raw_y-radius_x*0.5);
+ glVertex2f( raw_x+radius_x*0.866, raw_y-radius_x*0.5);
+ glVertex2f( raw_x, raw_y+radius_x );
+ glEnd();
+
+ /* draw cross hair */
+ glBegin(GL_LINES);
+ glVertex2f( raw_x, raw_y-radius_x );
+ glVertex2f( raw_x, raw_y+radius_x );
+ glVertex2f( raw_x+radius_x, raw_y );
+ glVertex2f( raw_x-radius_x, raw_y );
+ glEnd();
+
+ ip_gcp_draw_circle( geo_x, geo_y, radius_x );
+
+ /* connect with line */
+ glBegin(GL_LINES);
+ glVertex2f( raw_x, raw_y );
+ glVertex2f( geo_x, geo_y );
+ glEnd();
+ }
+
+ /* Draw selection box around base point, if selected */
+ if( selected )
+ {
+ /* draw triangle */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f( x-radius_x*1.25, y-radius_x*1.25 );
+ glVertex2f( x+radius_x*1.25, y-radius_x*1.25 );
+ glVertex2f( x+radius_x*1.25, y+radius_x*1.25 );
+ glVertex2f( x-radius_x*1.25, y+radius_x*1.25 );
+ glVertex2f( x-radius_x*1.25, y-radius_x*1.25 );
+ glEnd();
+ }
+}
+
+static void
+ip_gcp_layer_draw(GvLayer *rlayer, GvViewArea *view)
+{
+ IpGcpLayer *layer = IP_GCP_LAYER(rlayer);
+ gint i, points;
+ gint *selected, presentation;
+ gint hit_selected = FALSE;
+ GvShape *shape;
+
+ presentation = GV_LAYER(layer)->presentation;
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ for (i=0; i < points; ++i)
+ {
+ if (selected[i] && !presentation)
+ {
+ hit_selected = 1;
+ continue;
+ }
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_POINT )
+ ip_gcp_layer_draw_gcp( view, layer, shape, FALSE );
+ }
+
+ if (hit_selected && ! GV_SHAPE_LAYER(layer)->flags & GV_DELAY_SELECTED)
+ {
+ ip_gcp_layer_draw_selected(GV_SHAPE_LAYER(layer), view);
+ }
+}
+
+static void
+ip_gcp_layer_draw_selected(GvShapeLayer *rlayer, GvViewArea *view)
+{
+ IpGcpLayer *layer = IP_GCP_LAYER(rlayer);
+ gint i, points;
+ gint *selected;
+ GvShape *shape;
+
+ selected = GV_SHAPE_LAYER_SELBUF(layer);
+
+ points = gv_shapes_num_shapes(GV_SHAPES_LAYER(layer)->data);
+
+ for (i=0; i < points; ++i)
+ {
+ if ( !selected[i] )
+ continue;
+
+ shape = gv_shapes_get_shape(GV_SHAPES_LAYER(layer)->data, i);
+ if( shape != NULL && gv_shape_type(shape) == GVSHAPE_POINT )
+ ip_gcp_layer_draw_gcp( view, layer, shape, TRUE );
+ }
+}
+
+
Added: packages/openev/branches/upstream/current/ipgcplayer.h
===================================================================
--- packages/openev/branches/upstream/current/ipgcplayer.h (rev 0)
+++ packages/openev/branches/upstream/current/ipgcplayer.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * $Id: ipgcplayer.h,v 1.1 2000/07/14 18:24:57 warmerda Exp $
+ *
+ * Project: InSAR Peppers
+ * Purpose: InSAR Peppers GCP Layer declarations.
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: ipgcplayer.h,v $
+ * Revision 1.1 2000/07/14 18:24:57 warmerda
+ * New
+ *
+ */
+
+#ifndef __IPGCPLAYER_H__
+#define __IPGCPLAYER_H__
+
+#include "gvshapeslayer.h"
+
+#define IP_TYPE_GCP_LAYER (ip_gcp_layer_get_type ())
+#define IP_GCP_LAYER(obj) (GTK_CHECK_CAST ((obj), IP_TYPE_GCP_LAYER, IpGcpLayer))
+#define IP_GCP_LAYER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), IP_TYPE_GCP_LAYER, IpGcpLayerClass))
+#define IP_IS_GCP_LAYER(obj) (GTK_CHECK_TYPE ((obj),IP_TYPE_GCP_LAYER))
+#define IP_IS_GCP_LAYER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
+ IP_TYPE_GCP_LAYER))
+
+typedef struct _IpGcpLayer IpGcpLayer;
+typedef struct _IpGcpLayerClass IpGcpLayerClass;
+
+struct _IpGcpLayer
+{
+ GvShapesLayer layer;
+};
+
+struct _IpGcpLayerClass
+{
+ GvShapesLayerClass parent_class;
+};
+
+GtkType ip_gcp_layer_get_type(void);
+GtkObject* ip_gcp_layer_new(void);
+
+#endif /* __IPGCPLAYER_H__ */
Added: packages/openev/branches/upstream/current/llrasterize.c
===================================================================
--- packages/openev/branches/upstream/current/llrasterize.c (rev 0)
+++ packages/openev/branches/upstream/current/llrasterize.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,645 @@
+/******************************************************************************
+ * $Id: llrasterize.c,v 1.9 2004/11/23 06:14:55 warmerda Exp $
+ *
+ * Project: CIETMAP / OpenEV
+ * Purpose: Vector rasterization code (initially GvAreaShapes to GDAL raster).
+ * Author: Frank Warmerdam, warmerda at home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam <warmerda at home.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: llrasterize.c,v $
+ * Revision 1.9 2004/11/23 06:14:55 warmerda
+ * avoid use of rint() - not portable
+ *
+ * Revision 1.8 2004/11/19 23:59:37 gmwalter
+ * Check in Aude's rasterization updates.
+ *
+ * Revision 1.7 2004/10/20 18:33:55 warmerda
+ * Cietmap bug 3233: fix screwup in last scanline under some circumstances.
+ *
+ * Revision 1.6 2001/08/08 04:26:43 warmerda
+ * fixed leak of polyInts array
+ *
+ * Revision 1.5 2001/03/29 14:59:56 warmerda
+ * added fill_short flag to control handling of slivers
+ *
+ * Revision 1.4 2000/09/27 14:04:31 warmerda
+ * removed debugging printf
+ *
+ * Revision 1.3 2000/09/21 02:54:50 warmerda
+ * removed debug stuff
+ *
+ * Revision 1.2 2000/09/15 01:57:43 warmerda
+ * added copyright header
+ *
+ */
+
+/*
+ * NOTE: This code was adapted from the gdImageFilledPolygon() function
+ * in libgd.
+ *
+ * http://www.boutell.com/gd/
+ */
+
+#include <stdlib.h>
+#include "gvrasterize.h"
+
+static int llCompareInt(const void *a, const void *b)
+{
+ return (*(const int *)a) - (*(const int *)b);
+}
+
+/************************************************************************/
+/* llImageFilledPolygon() */
+/* */
+/* Perform scanline conversion of the passed multi-ring */
+/* polygon. Note the polygon does not need to be explicitly */
+/* closed. The scanline function will be called with */
+/* horizontal scanline chunks which may not be entirely */
+/* contained within the valid raster area (in the X */
+/* direction). */
+/************************************************************************/
+
+/* KNOWN BUGS: */
+
+/* 1) Because the nodes" coordinates of the polygons are casted to integers */
+/* before being passed to the routine, the computation of intersections */
+/* between raster lines and the polygon"s segments is not accurate and may */
+/* cause pixels to be considered as inside the shape when they don"t even */
+/* touch it. */
+/* 2) Pixels falling at the bottom of a shape on an horizontal segment are */
+/* never taken into account. */
+/* 3) When a polygon lies partly outside the extent of the raster file */
+/* beyond the last line, and one of its node falls */
+/* on the last line, wrong pixels are considered outside. */
+/* 4) Cones facing down (\./ ) are not filled on the last line. */
+/* 5) Possible core dumps. */
+
+void llImageFilledPolygon(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, llPoint *p,
+ int bFillShort,
+ llScanlineFunc pfnScanlineFunc, void *pCBData )
+{
+ int i;
+ int y;
+ int miny, maxy;
+ int x1, y1;
+ int x2, y2;
+ int ind1, ind2;
+ int ints, n, part;
+ int *polyInts, polyAllocated;
+
+ if (!nPartCount) {
+ return;
+ }
+
+ n = 0;
+ for( part = 0; part < nPartCount; part++ )
+ n += panPartSize[part];
+
+ polyInts = (int *) malloc(sizeof(int) * n);
+ polyAllocated = n;
+
+ miny = p[0].y;
+ maxy = p[0].y;
+ for (i=1; (i < n); i++) {
+ if (p[i].y < miny) {
+ miny = p[i].y;
+ }
+ if (p[i].y > maxy) {
+ maxy = p[i].y;
+ }
+ }
+ if( miny < 0 )
+ miny = 0;
+ if( maxy >= nRasterYSize )
+ maxy = nRasterYSize-1;
+
+ /* Fix in 1.3: count a vertex only once */
+ for (y=miny; (y <= maxy); y++) {
+ int partoffset = 0;
+
+ part = 0;
+ ints = 0;
+
+ for (i=0; (i < n); i++) {
+
+ if( i == partoffset + panPartSize[part] ) {
+ partoffset += panPartSize[part];
+ part++;
+ }
+
+ if( i == partoffset ) {
+ ind1 = partoffset + panPartSize[part] - 1;
+ ind2 = partoffset;
+ } else {
+ ind1 = i-1;
+ ind2 = i;
+ }
+
+ y1 = p[ind1].y;
+ y2 = p[ind2].y;
+ if( (y1 < y && y2 < y) || (y1 > y && y2 > y) )
+ continue;
+
+ if (y1 < y2) {
+ x1 = p[ind1].x;
+ x2 = p[ind2].x;
+ } else if (y1 > y2) {
+ y2 = p[ind1].y;
+ y1 = p[ind2].y;
+ x2 = p[ind1].x;
+ x1 = p[ind2].x;
+ } else {
+ /* skip horizontal segments */
+ continue;
+ }
+
+ /*
+ ** the commented out test was intended to ensure the last
+ ** scanline of the polygon gets filled in properly. Otherwise
+ ** it would often be dropped. But it doesn't always work, and
+ ** much worse is that sometimes it results in a bogus extra
+ ** transition that screws everything up.
+ ** See CIETMap 3233 at DMSG.
+ */
+ if( y < y2 /* || y2 == maxy */ )
+ polyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1;
+ }
+
+ /*
+ * It would be more efficient to do this inline, to avoid
+ * a function call for each comparison.
+ */
+ qsort(polyInts, ints, sizeof(int), llCompareInt);
+
+ for (i=0; (i < (ints)); i+=2) {
+ if( !bFillShort && polyInts[i] == polyInts[i+1] )
+ continue;
+
+ if( polyInts[i] < nRasterXSize && polyInts[i+1] >= 0 )
+ pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] );
+ }
+ }
+
+ free( polyInts );
+}
+
+/************************************************************************/
+/* llImageFilledPolygon() */
+/* */
+/* Perform scanline conversion of the passed multi-ring */
+/* polygon. Note the polygon does not need to be explicitly */
+/* closed. The scanline function will be called with */
+/* horizontal scanline chunks which may not be entirely */
+/* contained within the valid raster area (in the X */
+/* direction). */
+
+/* NEW: Nodes' coordinate are kept as double in order */
+/* to compute accurately the intersections with the lines */
+
+/* Two methods for determining the border pixels: */
+
+/* 1) method = 0 */
+/* Inherits algorithm from version above but with several bugs */
+/* fixed except for the cone facing down. */
+/* A pixel on which a line intersects a segment of a */
+/* polygon will always be considered as inside the shape. */
+/* Note that we only compute intersections with lines that */
+/* passes through the middle of a pixel (line coord = 0.5, */
+/* 1.5, 2.5, etc.) */
+
+/* 2) method = 1: */
+/* A pixel is considered inside a polygon if its center */
+/* falls inside the polygon. This is somehow more robust unless */
+/* the nodes are placed in the center of the pixels in which */
+/* case, due to numerical inaccuracies, it's hard to predict */
+/* if the pixel will be considered inside or outside the shape.*/
+
+/************************************************************************/
+
+void ImageFilledPolygon0(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData);
+
+
+void ImageFilledPolygon1(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData);
+
+void dllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData,
+ int method)
+{
+
+ if ( method == 0 )
+ ImageFilledPolygon0(nRasterXSize,
+ nRasterYSize,
+ nPartCount,
+ panPartSize,
+ p,
+ pfnScanlineFunc,
+ pCBData);
+
+ else if (method == 1)
+ ImageFilledPolygon1(nRasterXSize,
+ nRasterYSize,
+ nPartCount,
+ panPartSize,
+ p,
+ pfnScanlineFunc,
+ pCBData);
+
+ return;
+
+}
+
+
+
+
+/***********************************************************************
+Method one
+----------
+Known bugs:
+Cones facing down (\./ ) are not filled on the last line.
+************************************************************************/
+void ImageFilledPolygon0(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData)
+{
+ int i;
+ int y, y1, y2;
+ int miny, maxy,minx,maxx;
+ double dminy, dmaxy ;
+ double dx1, dy1;
+ double dx2, dy2;
+ double dy;
+ double intersect, slope;
+
+
+ int ind1, ind2;
+ int ints, n, part;
+ int *polyInts, polyAllocated;
+
+
+ int horizontal_x1, horizontal_x2;
+
+ int inter, left, right;
+
+
+ if (!nPartCount) {
+ return;
+ }
+
+ n = 0;
+ for( part = 0; part < nPartCount; part++ )
+ n += panPartSize[part];
+
+ polyInts = (int *) malloc(sizeof(int) * n);
+ polyAllocated = n;
+
+ dminy = p[0].y;
+ dmaxy = p[0].y;
+ for (i=1; (i < n); i++) {
+
+ if (p[i].y < dminy) {
+ dminy = p[i].y;
+ }
+ if (p[i].y > dmaxy) {
+ dmaxy = p[i].y;
+ }
+ }
+ miny = (int) dminy;
+ maxy = (int) dmaxy;
+
+
+ if( miny < 0 )
+ miny = 0;
+ if( maxy >= nRasterYSize )
+ maxy = nRasterYSize-1;
+
+
+ minx = 0;
+ maxx = nRasterXSize - 1;
+
+
+ /* Fix in 1.3: count a vertex only once */
+ for (y=miny; y <= maxy; y++) {
+ int partoffset = 0;
+
+ dy = y +0.5; /* center height of line*/
+
+
+ part = 0;
+ ints = 0;
+
+ /*Initialize polyInts, otherwise it can sometimes causes a seg fault */
+ for (i=0; (i < n); i++) {
+ polyInts[i] = -1;
+ }
+
+
+ for (i=0; (i < n); i++) {
+
+
+ if( i == partoffset + panPartSize[part] ) {
+ partoffset += panPartSize[part];
+ part++;
+ }
+
+ if( i == partoffset ) {
+ ind1 = partoffset + panPartSize[part] - 1;
+ ind2 = partoffset;
+ } else {
+ ind1 = i-1;
+ ind2 = i;
+ }
+
+
+ dy1 = p[ind1].y;
+ dy2 = p[ind2].y;
+
+
+ y1 = (int) dy1;
+ y2 = (int) dy2;
+
+
+ if( ( y1 < y && y2 < y) || (y1 > y && y2 > y) )
+ continue;
+
+
+ if (y1 < y2) {
+ dx1 = p[ind1].x;
+ dx2 = p[ind2].x;
+ } else if (y1 > y2) {
+ dy2 = p[ind1].y;
+ dy1 = p[ind2].y;
+ y2 = (int) dy2;
+ y1 = (int) dy1;
+ dx2 = p[ind1].x;
+ dx1 = p[ind2].x;
+ } else /* (y1 == y2) */
+ {
+
+ /*AE: DO NOT skip bottom horizontal segments
+ -Fill them separately-
+ They are not taken into account twice.*/
+ if (p[ind1].x > p[ind2].x)
+ {
+ horizontal_x1 = (int) p[ind2].x;
+ horizontal_x2 = (int) p[ind1].x;
+
+ if ( (horizontal_x1 > maxx) || (horizontal_x2 < minx) )
+ continue;
+
+ /*fill the horizontal segment (separately from the rest)*/
+ pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2);
+ continue;
+ }
+ else /*skip top horizontal segments (they are already filled in the regular loop)*/
+ continue;
+
+ }
+
+
+ if( y < y2 )
+ {
+
+ intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
+ slope = (dx2-dx1) / (dy2-dy1);
+
+ /*the intersection must fall in the same x-range of the segment*/
+ inter = (int) intersect;
+ if (dx1 <= dx2)
+ {
+ left = (int)dx1;
+ right = (int)dx2;
+ }
+ else {
+ left = (int)dx2;
+ right = (int)dx1;
+ }
+
+
+ if (inter < left)
+ inter = left;
+ else if ( inter > right )
+ inter = right;
+
+ polyInts[ints++] = inter;
+
+ }
+ }
+
+
+
+ /*Sort intersections*/
+ qsort(polyInts, ints, sizeof(int), llCompareInt);
+
+
+ for (i=0; (i < (ints)); i+=2) {
+
+ if( polyInts[i] <= maxx && polyInts[i+1] >= minx )
+ {
+ pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1]);
+ }
+
+ }
+ }
+
+ free( polyInts );
+}
+
+/*************************************************************************
+Method 2:
+=========
+No known bug
+*************************************************************************/
+
+void ImageFilledPolygon1(int nRasterXSize, int nRasterYSize,
+ int nPartCount, int *panPartSize, dllPoint *p,
+ llScanlineFunc pfnScanlineFunc, void *pCBData)
+{
+ int i;
+ int y;
+ int miny, maxy,minx,maxx;
+ double dminy, dmaxy;
+ double dx1, dy1;
+ double dx2, dy2;
+ double dy;
+ double intersect;
+
+
+ int ind1, ind2;
+ int ints, n, part;
+ int *polyInts, polyAllocated;
+
+
+ int horizontal_x1, horizontal_x2;
+
+
+ if (!nPartCount) {
+ return;
+ }
+
+ n = 0;
+ for( part = 0; part < nPartCount; part++ )
+ n += panPartSize[part];
+
+ polyInts = (int *) malloc(sizeof(int) * n);
+ polyAllocated = n;
+
+ dminy = p[0].y;
+ dmaxy = p[0].y;
+ for (i=1; (i < n); i++) {
+
+ if (p[i].y < dminy) {
+ dminy = p[i].y;
+ }
+ if (p[i].y > dmaxy) {
+ dmaxy = p[i].y;
+ }
+ }
+ miny = (int) dminy;
+ maxy = (int) dmaxy;
+
+
+ if( miny < 0 )
+ miny = 0;
+ if( maxy >= nRasterYSize )
+ maxy = nRasterYSize-1;
+
+
+ minx = 0;
+ maxx = nRasterXSize - 1;
+
+ /* Fix in 1.3: count a vertex only once */
+ for (y=miny; y <= maxy; y++) {
+ int partoffset = 0;
+
+ dy = y +0.5; /* center height of line*/
+
+
+ part = 0;
+ ints = 0;
+
+
+ /*Initialize polyInts, otherwise it can sometimes causes a seg fault */
+ for (i=0; (i < n); i++) {
+ polyInts[i] = -1;
+ }
+
+
+ for (i=0; (i < n); i++) {
+
+
+ if( i == partoffset + panPartSize[part] ) {
+ partoffset += panPartSize[part];
+ part++;
+ }
+
+ if( i == partoffset ) {
+ ind1 = partoffset + panPartSize[part] - 1;
+ ind2 = partoffset;
+ } else {
+ ind1 = i-1;
+ ind2 = i;
+ }
+
+
+ dy1 = p[ind1].y;
+ dy2 = p[ind2].y;
+
+
+ if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
+ continue;
+
+
+
+
+ if (dy1 < dy2) {
+ dx1 = p[ind1].x;
+ dx2 = p[ind2].x;
+ } else if (dy1 > dy2) {
+ dy2 = p[ind1].y;
+ dy1 = p[ind2].y;
+ dx2 = p[ind1].x;
+ dx1 = p[ind2].x;
+ } else /* if (fabs(dy1-dy2)< 1.e-6) */
+ {
+
+ /*AE: DO NOT skip bottom horizontal segments
+ -Fill them separately-
+ They are not taken into account twice.*/
+ if (p[ind1].x > p[ind2].x)
+ {
+ horizontal_x1 = (int) floor(p[ind2].x+0.5);
+ horizontal_x2 = (int) floor(p[ind1].x+0.5);
+
+ if ( (horizontal_x1 > maxx) || (horizontal_x2 < minx) )
+ continue;
+
+
+ /*fill the horizontal segment (separately from the rest)*/
+ pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1 );
+ continue;
+ }
+ else /*skip top horizontal segments (they are already filled in the regular loop)*/
+ continue;
+
+ }
+
+
+
+ if(( dy < dy2 ) && (dy >= dy1))
+ {
+
+ intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
+
+ polyInts[ints++] = (int) floor(intersect+0.5);
+ }
+ }
+
+
+
+ /*
+ * It would be more efficient to do this inline, to avoid
+ * a function call for each comparison.
+ */
+ qsort(polyInts, ints, sizeof(int), llCompareInt);
+
+
+ for (i=0; (i < (ints)); i+=2) {
+
+ if( polyInts[i] <= maxx && polyInts[i+1] >= minx )
+ {
+ pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] - 1 );
+
+ }
+
+ }
+ }
+
+
+ free( polyInts );
+}
+
+
Added: packages/openev/branches/upstream/current/makefile.vc
===================================================================
--- packages/openev/branches/upstream/current/makefile.vc (rev 0)
+++ packages/openev/branches/upstream/current/makefile.vc 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,94 @@
+GVIEW_ROOT=.
+
+!INCLUDE nmake.opt
+
+GV_INSTALL_HOME = $(NM_BIN_DIR)\..
+GV_INSTALL_HTML = $(GV_INSTALL_HOME)\html
+GV_INSTALL_PICS = $(GV_INSTALL_HOME)\pics
+GV_INSTALL_TOOLS = $(GV_INSTALL_HOME)\tools
+GV_INSTALL_RAMPS = $(GV_INSTALL_HOME)\ramps
+GV_INSTALL_XMLCONFIG = $(GV_INSTALL_HOME)\xmlconfig
+
+CC = cl
+CXX = cl
+
+INC = /I$(NM_GLIB_DIR) /I$(NM_GLIB_DIR)/gmodule /I$(NM_GTK_DIR) /I$(NM_GTK_DIR)\gdk \
+ /I$(NM_GTKGLAREA_DIR) \
+ /I$(GDAL_HOME)\port /I$(GDAL_HOME)\gcore /I$(GDAL_HOME)\ogr \
+ /I$(GDAL_HOME)\ogr\ogrsf_frmts
+
+CFLAGS = $(INC) $(GV_OPTFLAGS) /DHAVE_OGR
+
+OBJ = gvviewarea.obj gvdata.obj gvlayer.obj \
+ gvpolylines.obj gvlinelayer.obj gvtool.obj gvlinetool.obj \
+ gvtoolbox.obj gvshapelayer.obj gvselecttool.obj gextra.obj \
+ gvareas.obj gvarealayer.obj gvareatool.obj gvtess.obj \
+ gvnodetool.obj gvundo.obj gvpoints.obj gvpointlayer.obj \
+ gvpointtool.obj gvpquerylayer.obj gvviewlink.obj gvroitool.obj \
+ gvmesh.obj gvrasterlayer.obj gvraster.obj gvrasterlut.obj \
+ gvrasteraverage.obj gvrasterconvert.obj gvrastercache.obj \
+ gvtracktool.obj gtkcolorwell.obj gvsymbolmanager.obj gvprint.obj \
+ crs.obj gvproperties.obj gvshapes.obj gvshape.obj gvshapeslayer.obj \
+ gvshapefile.obj shpopen.obj dbfopen.obj gvutils.obj gvtessshape.obj \
+ gvzoompantool.obj gvmanager.obj gvrastersource.obj gvtexturecache.obj \
+ ipgcplayer.obj gvrecttool.obj gvwinprint.obj appcurlayer.obj \
+ invdistance.obj gvrasterize.obj llrasterize.obj gvogr.obj \
+ gvrenderinfo.obj gvskirt.obj gvpoitool.obj gvrecords.obj \
+ gvrotatetool.obj gvautopan.obj
+
+GVLIB = gv.lib
+
+LIBS = $(GDAL_HOME)/gdal_i.lib $(NM_GTKGLAREA_DIR)/gtkglarea.lib \
+ $(NM_GTK_DIR)/gtk/gtk-1.3.lib \
+ $(NM_GTK_DIR)/gdk/gdk-1.3.lib $(NM_GLIB_DIR)/glib-1.3.lib \
+ GLU32.lib opengl32.lib gdi32.lib user32.lib shell32.lib
+
+default: $(GVLIB) gvtest.exe py_modules
+
+py_modules:
+ cd pymod
+ nmake /f makefile.vc
+ cd ..
+
+.c.obj:
+ $(CC) $(CFLAGS) /c $*.c
+
+.cpp.obj:
+ $(CC) $(CFLAGS) /c $*.cpp
+
+$(GVLIB): gv_config.h $(OBJ)
+ if exist $(GVLIB) del $(GVLIB)
+ lib /out:$(GVLIB) $(OBJ)
+
+gvtest.exe: testmain.obj $(GVLIB)
+ link /debug testmain.obj $(GVLIB) $(LIBS) /out:gvtest.exe
+
+gv_config.h: gv_config.h_win32
+ copy gv_config.h_win32 gv_config.h
+
+clean:
+ cd pymod
+ nmake /f makefile.vc clean
+ cd ..
+ -del gvtest.exe
+ -del *.obj
+ -del *.lib
+ -del *.dll
+
+full_install: install
+ if not exist $(GV_INSTALL_HTML) mkdir $(GV_INSTALL_HTML)
+ if not exist $(GV_INSTALL_PICS) mkdir $(GV_INSTALL_PICS)
+ if not exist $(GV_INSTALL_TOOLS) mkdir $(GV_INSTALL_TOOLS)
+ if not exist $(GV_INSTALL_RAMPS) mkdir $(GV_INSTALL_RAMPS)
+ if not exist $(GV_INSTALL_XMLCONFIG) mkdir $(GV_INSTALL_XMLCONFIG)
+ copy html\*.* $(GV_INSTALL_HTML)
+ copy pics\*.* $(GV_INSTALL_PICS)
+ copy tools\*.* $(GV_INSTALL_TOOLS)
+ copy ramps\*.* $(GV_INSTALL_RAMPS)
+ copy xmlconfig\*.* $(GV_INSTALL_XMLCONFIG)
+
+install: default
+ copy gvtest.exe $(NM_BIN_DIR)
+ cd pymod
+ nmake /f makefile.vc install
+ cd ..
Added: packages/openev/branches/upstream/current/nmake.opt
===================================================================
--- packages/openev/branches/upstream/current/nmake.opt (rev 0)
+++ packages/openev/branches/upstream/current/nmake.opt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,12 @@
+
+GDAL_HOME=$(GVIEW_ROOT)\..\gdal
+
+NM_ROOT=$(GVIEW_ROOT)\..\PKGSRC
+
+!INCLUDE $(NM_ROOT)/nmake.opt
+
+GV_OPTFLAGS = /nologo /Ox
+#GV_OPTFLAGS = /nologo /Zi /MD /Fd$(GVIEW_ROOT)\openev.pdb
+
+#GV_OPTFLAGS = $(NM_OPTFLAGS)
+
Added: packages/openev/branches/upstream/current/pics/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/pics/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/pics/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,51 @@
+/atlantis_logo.xpm/1.1/Fri Jul 28 20:03:27 2000//
+/busy.xpm/1.1/Thu Jun 29 16:12:31 2000//
+/ck_off_l.xpm/1.1/Tue Aug 13 17:44:36 2002/-kb/
+/ck_on_l.xpm/1.1/Tue Aug 13 17:44:36 2002/-kb/
+/classify.xpm/1.1/Wed Mar 21 05:38:54 2001//
+/delete.xpm/1.1/Thu Jan 20 14:50:07 2000//
+/equalize.xpm/1.4/Thu Aug 10 20:44:43 2000//
+/eye.xpm/1.1/Fri Nov 26 22:34:53 1999//
+/geo_innovation.xpm/1.1/Fri Jul 28 20:03:26 2000//
+/help.xpm/1.2/Mon Jun 26 13:34:06 2000//
+/idle.xpm/1.1/Thu Jun 29 16:12:31 2000//
+/legend.xpm/1.1/Wed Mar 21 05:32:54 2001//
+/linear.xpm/1.1/Thu Mar 22 18:46:32 2001//
+/log.xpm/1.1/Tue Oct 16 18:55:43 2001//
+/lower.xpm/1.1/Thu Jan 20 14:50:07 2000//
+/new.xpm/1.1/Thu Jan 20 14:50:07 2000//
+/node_cursor.xbm/1.1/Thu Nov 11 15:41:21 1999//
+/node_cursor_mask.xbm/1.1/Thu Nov 11 15:41:21 1999//
+/nonelut.xpm/1.4/Thu Aug 10 20:44:44 2000//
+/onetoone.xpm/1.2/Mon Jun 26 13:34:06 2000//
+/openev.xpm/1.2/Fri Jun 16 14:28:25 2000//
+/openfile.xpm/1.2/Mon Jun 26 13:34:06 2000//
+/pan_left.xpm/1.1/Mon Apr 9 18:28:41 2001//
+/pan_rght.xpm/1.1/Mon Apr 9 18:49:33 2001//
+/print.xpm/1.2/Mon Jun 26 13:34:06 2000//
+/raise.xpm/1.1/Thu Jan 20 14:50:07 2000//
+/recenter.xpm/1.1/Thu Sep 11 14:18:38 2003/-kb/
+/refresh.xpm/1.1/Wed Aug 2 19:18:29 2000//
+/root.xpm/1.1/Thu Mar 22 18:46:32 2001//
+/save.xpm/1.1/Mon Jun 26 16:22:45 2000//
+/seeall.xpm/1.1/Thu Jun 15 13:54:27 2000//
+/sym_circle.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_cross.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_filled_circle.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_filled_square.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_filled_star.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_filled_triangle.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_square.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_star.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_triangle.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_vertical.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/sym_x.xpm/1.1/Tue May 8 23:23:50 2001/-kb/
+/vexcel_logo.xpm/1.2/Tue Jun 28 18:14:35 2005/-kb/
+/warning.xpm/1.1/Thu Aug 24 18:02:00 2000//
+/windowed.xpm/1.2/Wed Dec 12 15:15:50 2001//
+/worldg.xpm/1.1/Fri Jul 6 17:05:42 2001//
+/worldrgb.xpm/1.1/Fri Jul 6 17:05:42 2001//
+/zoomin.xpm/1.3/Mon Jun 26 13:34:06 2000//
+/zoomout.xpm/1.3/Mon Jun 26 13:34:06 2000//
+/zoomrect.xpm/1.1/Thu Sep 11 14:18:38 2003/-kb/
+D
Added: packages/openev/branches/upstream/current/pics/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/pics/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/pics/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/pics
Added: packages/openev/branches/upstream/current/pics/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/pics/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/pics/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/pics/atlantis_logo.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/atlantis_logo.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/atlantis_logo.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,308 @@
+/* XPM */
+static char * atlantis_logo_xpm[] = {
+"221 55 250 2",
+" c None",
+". c #000000",
+"+ c #800000",
+"@ c #008000",
+"# c #808000",
+"$ c #000080",
+"% c #800080",
+"& c #008080",
+"* c #C0C0C0",
+"= c #C0DCC0",
+"- c #A6CAF0",
+"; c #001031",
+"> c #000008",
+", c #000808",
+"' c #000810",
+") c #000818",
+"! c #000821",
+"~ c #000829",
+"{ c #001018",
+"] c #001021",
+"^ c #001029",
+"/ c #001031",
+"( c #001039",
+"_ c #001821",
+": c #001829",
+"< c #001831",
+"[ c #001842",
+"} c #00184A",
+"| c #001852",
+"1 c #002131",
+"2 c #002139",
+"3 c #002152",
+"4 c #00215A",
+"5 c #002163",
+"6 c #002173",
+"7 c #002942",
+"8 c #00294A",
+"9 c #00295A",
+"0 c #00297B",
+"a c #00314A",
+"b c #003163",
+"c c #0031CE",
+"d c #00396B",
+"e c #003973",
+"f c #00398C",
+"g c #004A84",
+"h c #004A8C",
+"i c #00529C",
+"j c #005AAD",
+"k c #0063B5",
+"l c #0063FF",
+"m c #006BBD",
+"n c #006BC6",
+"o c #0073CE",
+"p c #0073DE",
+"q c #0073E7",
+"r c #007BEF",
+"s c #008CFF",
+"t c #00FFFF",
+"u c #080808",
+"v c #081010",
+"w c #081821",
+"x c #082129",
+"y c #082131",
+"z c #082139",
+"A c #08214A",
+"B c #082931",
+"C c #082939",
+"D c #082942",
+"E c #08296B",
+"F c #083142",
+"G c #08314A",
+"H c #08316B",
+"I c #083952",
+"J c #08395A",
+"K c #083973",
+"L c #101010",
+"M c #101021",
+"N c #101818",
+"O c #101821",
+"P c #102939",
+"Q c #10314A",
+"R c #10398C",
+"S c #104252",
+"T c #104263",
+"U c #10427B",
+"V c #104A94",
+"W c #181818",
+"X c #181821",
+"Y c #182129",
+"Z c #185273",
+"` c #212121",
+" . c #212929",
+".. c #212931",
+"+. c #215273",
+"@. c #21639C",
+"#. c #292929",
+"$. c #293131",
+"%. c #293942",
+"&. c #293952",
+"*. c #313139",
+"=. c #316B9C",
+"-. c #3184C6",
+";. c #393939",
+">. c #394242",
+",. c #39424A",
+"'. c #394263",
+"). c #394A4A",
+"!. c #394A52",
+"~. c #394A5A",
+"{. c #424242",
+"]. c #42424A",
+"^. c #424A4A",
+"/. c #424A52",
+"(. c #42525A",
+"_. c #426373",
+":. c #4A4A4A",
+"<. c #4AB5EF",
+"[. c #525252",
+"}. c #525A5A",
+"|. c #5A8494",
+"1. c #5A94C6",
+"2. c #636363",
+"3. c #636B6B",
+"4. c #63737B",
+"5. c #6B737B",
+"6. c #6BB5E7",
+"7. c #737373",
+"8. c #737B7B",
+"9. c #7B7B7B",
+"0. c #7B8C94",
+"a. c #848484",
+"b. c #848C94",
+"c. c #8C949C",
+"d. c #8CCEF7",
+"e. c #949494",
+"f. c #94949C",
+"g. c #949CA5",
+"h. c #94B5C6",
+"i. c #9C9CA5",
+"j. c #9CC6E7",
+"k. c #9CDEFF",
+"l. c #A5A5A5",
+"m. c #A5A5AD",
+"n. c #A5ADAD",
+"o. c #A5ADB5",
+"p. c #A5B5B5",
+"q. c #A5BDC6",
+"r. c #A5CEF7",
+"s. c #ADADAD",
+"t. c #ADADB5",
+"u. c #ADB5B5",
+"v. c #ADBDCE",
+"w. c #ADC6D6",
+"x. c #ADCED6",
+"y. c #ADD6EF",
+"z. c #ADEFFF",
+"A. c #B5B5B5",
+"B. c #B5BDBD",
+"C. c #B5C6D6",
+"D. c #BDC6C6",
+"E. c #BDCECE",
+"F. c #C6C6C6",
+"G. c #C6C6CE",
+"H. c #C6CECE",
+"I. c #C6CED6",
+"J. c #C6EFF7",
+"K. c #C6FFFF",
+"L. c #CECECE",
+"M. c #CED6D6",
+"N. c #CED6DE",
+"O. c #CEDEDE",
+"P. c #CEDEE7",
+"Q. c #CEE7EF",
+"R. c #CEE7F7",
+"S. c #CEFFFF",
+"T. c #D6D6D6",
+"U. c #D6DEDE",
+"V. c #D6E7EF",
+"W. c #D6FFFF",
+"X. c #DEDEDE",
+"Y. c #DEE7E7",
+"Z. c #E7E7E7",
+"`. c #E7E7EF",
+" + c #E7EFF7",
+".+ c #E7FFFF",
+"++ c #EFEFEF",
+"@+ c #EFF7FF",
+"#+ c #EFFFFF",
+"$+ c #F7F7F7",
+"%+ c #F7F7FF",
+"&+ c #F7FFFF",
+"*+ c #FFFFFF",
+"=+ c #FFFFFF",
+"-+ c #FFFFFF",
+";+ c #FFFFFF",
+">+ c #FFFFFF",
+",+ c #FFFFFF",
+"'+ c #FFFFFF",
+")+ c #FFFFFF",
+"!+ c #FFFFFF",
+"~+ c #FFFFFF",
+"{+ c #FFFFFF",
+"]+ c #FFFFFF",
+"^+ c #FFFFFF",
+"/+ c #FFFFFF",
+"(+ c #FFFFFF",
+"_+ c #FFFFFF",
+":+ c #FFFFFF",
+"<+ c #FFFFFF",
+"[+ c #FFFFFF",
+"}+ c #FFFFFF",
+"|+ c #FFFFFF",
+"1+ c #FFFFFF",
+"2+ c #FFFFFF",
+"3+ c #FFFFFF",
+"4+ c #FFFFFF",
+"5+ c #FFFFFF",
+"6+ c #FFFFFF",
+"7+ c #FFFFFF",
+"8+ c #FFFFFF",
+"9+ c #FFFFFF",
+"0+ c #FFFFFF",
+"a+ c #FFFFFF",
+"b+ c #FFFFFF",
+"c+ c #FFFFFF",
+"d+ c #FFFFFF",
+"e+ c #FFFFFF",
+"f+ c #FFFFFF",
+"g+ c #FFFFFF",
+"h+ c #FFFFFF",
+"i+ c #FFFFFF",
+"j+ c #FFFFFF",
+"k+ c #FFFFFF",
+"l+ c #FFFFFF",
+"m+ c #FFFFFF",
+"n+ c #FFFFFF",
+"o+ c #FFFFFF",
+"p+ c #FFFFFF",
+"q+ c #FFFFFF",
+"r+ c #FFFFFF",
+"s+ c #FFFFFF",
+"t+ c #FFFFFF",
+"u+ c #FFFFFF",
+"v+ c #FFFFFF",
+"w+ c #FFFFFF",
+"x+ c #FFFFFF",
+"y+ c #FFFBF0",
+"z+ c #A0A0A4",
+"A+ c #808080",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;.A+L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . :.l.l.l.l.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . L l.l.l.l.l.l.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l.l.l.l.l.l.l.a.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . L l.l.l.e.l.l.l.l.$.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > > > > > > > > > > > > > > > > > > > > > . . . . . . > > > > > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e.l.l.7.:.. . l.l.a.W . . . . . . . . . . . . c c c c c c . . . . . . > > > > > > > > > > > > > > > > > > > > > . . . . . . > > > > > . . . . . . . . . . . . > ~ ; ; ' . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . c . . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c c c c . . . . . . c c c c c c , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; c . . . . . . . u l.l.7.#.. . . . l.l.#.c . . . . . . . . . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . n c c c c c 5 . . . . . . . . ! c c c c c c c c c c c ! . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c c c c b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c c ' . . . . . . l.l.7.. . . . . 2.l.l.c c c . . . . . . . . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . n c c c c c 5 . . . . . . . . c c c c c c c c c c c c c c . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . > c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c c c c b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 c c c . . . . . l.9.2.. . . . . . l.l.#.c c c c c . . . . . . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . n c c c c c 5 . . . . . . ' c c c c c c c c c c c c c c ] . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . c c c c c . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c c c c b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . c c c c c . . e.l.7.. . . . . . . #.l.a.. c c c c c c 5 . . . . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . n c c c c c 5 . . . . . . c c c c c c b b b c c c c c c . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . ! c c c c c c . . . . . . . . . . . c c c c c c c c c c c c c c c c c c c c c b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c : #.l.9.. . . . . . . . l.l.#.. c c c c c c c c . . . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . m c c c c c 5 . . . . . > c c c c b b d d b b b b b c ! . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . ' c c c c c c c . . . . . . . . . . . 5 c c c c c c c c c c c c c c c c c c c c b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c l.3.. . . . . . . . L l.#.. . c c c c c c c c c ; . . . . c c c c c c . . . . . c c c c c c c c c c c c c c c c c c c c c c . . . . . n c c c c c 5 . . . . . m c c c c . . . . . . > b b c . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c . . . . . . . . . . . b b b b b b b c c c c c c b b b b b b b b . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c . . . . . . . . . l.f.L . . c c c c c c c c c c c . . . c c c c c c . . . . . c b b b b b b b c c c c c c b b b b b b b . . . . . . n c c c c c 5 . . . . . n c c c c c . . . . . . . . < . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . ; c c c c c c c c c ' . . . . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c c . . . . . . . . l.l.$.. . . c c c c c c c c c c c c 5 . c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . n c c c c c c c c ; . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c c c ' . . . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c c c c . . . . . . {.l.;.. . . . c c c c c c c c c c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . ' n n c c c c c c c c c c . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . | c c c c c c c c c c c c . . . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c c c c c c 5 . . . . u l.2.#.. . . . c c c c c c c c c c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . n n c c c c c c c c c c c ! . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . } c c c c c c l c c c c c c ! . . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . . c c c c c c c p c c c c c c . . . . l.e.W . . . . . c c c c c c c c c c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . n n b c c c c c c c c c c ! . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . c c c c c c b b . c c c c c c , . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . ' c c c c c c 4 . s c c c c c c . . l.a.;.. . . . . . c c c c c c p c c c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . . ' b d b b b c c c c c c c . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . 5 c c c c c b d . . c c c c c c c . . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . . c c c c c c c . . g c c c c c c . u k.{.. . . . . . . c c c c c c s s c c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . . . . > b d d b b c c c c c c . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . c c c c c c b . . . . c c c c c c ; . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c 1 . . . . . . . . . . . . . . . . . . . . . c c c c c c c ' . . . n c c c c c -.k.;.. . . . . . . . c c c c c c . b s c c c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . . . . . . . . > c c c c c c c . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . c c c c c c b b |.d.<.. . c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . . . . ! c c c c c c b . d.6. at .. c c c c c r.3.. . . . . . . . . c c c c c c . . . s s c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . . . . . . . . . . . o c c c c . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . c c c c c c b d u p.A+:.<.. 3 c c c c c 4 . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . . . . c c c c c c b . Q.b.8.<.W ] c c c - 0./.. . . . . . . . . c c c c c c . . . . s c c c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . . ] . . . . . . . . . c c c c c . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . c c c c c c b b y.&+a.:.-. at .. c c c c c c } . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . . . ( c c c c c b . . J.s.7.$.-.. c c d.j.U c c . . . . . . . . c c c c c c . . . . . > s c c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . 1 c c c c c c c c c c c c c c . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . c c c c c c b b . v.l.7.{.1.+.. ' c c c c c c . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . . . c c c c c c b . . V.b.2.#.=.. ' 6.r./.c c c . . . . . . . . c c c c c c . . . . . . . s c c c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . c c c c c c c c c c c c c c c . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . c c c c c c c d . . . X.7.a.#.. . . ' c c c c c c . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . . c c c c c c b . . . g.7.:.7.u . _.k.}.c c c c c ' . . . . . . c c c c c c . . . . . . . . < s c c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . . c c c c c c c c c c c c c c . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . > c c c c c c b b . . . . #.#.. . . . . c c c c c c . . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . | c c c c c b . . . . . #.` . . ,.k.[.b c c c c c c . . . . . . c c c c c c . . . . . . . . . . s c c c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . 8 c c c c c c c c c c c c b . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . c c c c c c b b . . . . . . . . . . . . > c c c c c c . . . . . . . . . c c c c c c . . . . . . . . . . . . . c c c c c c c c c c c c c c c c c c . . . . . . c c c c c c b . . . . . . . . Y k.2.. . b c c c c c ; . . . . . c c c c c c . . . . . . . . . . . s s c . . . . . . . . . . . . . c c c c c c . . . . . . . . . . . . . n c c c c c 5 . . . . . c G b b b c c c c c b b b . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . b b d d b d . . . . . . . . . . . . . . ' b d d b b 2 . . . . . . . . b d d b d b . . . . . . . . . . . . . . d b b d b b d b b d b b d b b d b . . . . . . b d d b d b . . . . . . . . O r.4.. . . 8 b b d b b < . . . . . b b d b b b . . . . . . . . . . . . . s . . . . . . . . . . . . . b d d b d d . . . . . . . . . . . . . d b d d b d . . . . . . . . . d b d b d d b . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l.<.. . . . . . . . . . O k.2.u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . b.1.k . . . . . . . . . O k.0.u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . . . . W l.` . . . . . . . . . O r.0.u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' . . . . $.l.#.. . . . . . . . . Y r.3.u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . #.$.L . . . . . . . . . . . . . . u #.$.u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' ' . . . . l.i.' . . . . . . . . %.- 5.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u #.#.W . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u #.#.W . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . T.L.T.A.b.a.b.* L.L.f.. . . . . . B.L.L.L.e.9.9.f.L.L.L.. . . . . * L.T.. . . . L.L.B.* * * * * B.* * * [.. . . T.L.L.O . . . . . . . L.L.u.> , D.* * * * * L.L.* * * * * A.4.q.7.* L.. . . . L.L.F.* B.* B.B.B.* * B.. . . L.L.... . . . . a.L.L.G.f.9.A+l.L.L.L.u . . . . . . . . . . . . . . . . ++L.L.. . . F.L.L.L.e.. . . . . . . L.L.9.. . . . . A.L.L.B.e.A+A+f.L.L.T.u . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . A.L.F.{.;.;.;.{.{.2.L.L.#.. . . . T.L.L.%.>.{.{.>.{.2.e.L.T.#.. . . * L.L.. . . . L.L.{.{.{.;.{.{.{.{.{.{.{.. . . L.L.L.L.a.. . . . . . L.L.s.' ' :.>.{.>.{.{.L.L.{.{.{.{.{.g.w.7./.L.L.. . . . L.L.7.{.;.>.{.{.{.{.{.{.. . . L.L.$.. . . . A.L.n.>.{.{.>.{.{.2.B.L.L.. . . . . . . . . . . . . . . . ++L.L.. . . &+L.L.L.L.2.. . . . . ` L.L.a.. . . . L.L.L.;.{.;.;.;.:.7.* L.L.. . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . B.L.L.#.. . . . . . . l.s.W . . F.L.9.{.#.. . . . . . . l.7.7.. . . F.L.L.. . . . L.L.` . . . . . . . . . . . . . L.L.L.L.L.L.. . > . . L.L.u., ' , . f.l.u . L.L.' . . . l.l.7.. . L.L.. . . . L.L.:.. . . . . . . . . . . . L.L.#.. . . L.L.f.W . . . . . . . s.f.7.:.. . . . . . . . . . . . . . . ++L.L.. . . &+L.L.Z.X.L.L.. . . . W L.L.7.. . . L.L.a.. . . . . . . $.F.b.7.L . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . b.* T.L.L.L.L.f.:.. . . . . . L.L.{.#.. . . . . . . . . u . . , , F.M.L.. . . . L.L.T.L.L.L.L.L.T.L.L.7.. . ' . L.T.W [.U.L.L.a.. . . L.L.s.' v ' a.l.` . . L.L., . $.l.l.2.. > . L.M.. . . . L.N.L.L.L.L.L.L.L.L.G.. . . ' M.M.;.. . . L.L.. . . . . . . . . . u . . . . . . . . . . . . . . . . . ++L.L.. . . &+L.L.;.X.T.L.L.2.. . ` L.L.a.. . $+L.L.. . . . . . . . . u . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . 3.:.{.7.f.T.L.L.L.L.. . . . L.L.{.. . . . . . . . . . . . . . . G.L.M.' , . . L.M.f.f.f.f.f.e.f.f.e.2.. > . . L.L.M . u F.M.M.{.. . L.M.u.' { ' n.l.` > . L.L.' Y &+l.7.. ' . . L.L.. . . . L.L.u.l.n.l.l.n.n.n.g., . . . L.L.... . Y L.L.. . . . . . . . . . . . . . . . . . . . . . . . . . . . ++L.L.. . . &+L.L.. . L.* L.L.$.. #.L.L.a.. . &+L.L.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . u :.:.. . . . L #.;.:.2.L.L.#.. . B.L.2.. . . . . . . . . . a.2.. . . F.L.T.. . . . M.P.%.#.#.Y Y Y #.#.Y #.. . . . T.M.Y . . . B.* M.G.. L.M.t.' { 4.n.n.. . . L.L.L.Y.l.9.. . ' . . M.L.. . . > L.L.3.....$.$.$...#.W . . . . L.L.$.. . :.L.L.2.. . . . . . . . . . a.:.. . . . . . . . . . . . . . . ++L.L.. . . &+L.L.. . . A.A.* L.T.W L.L.9.. . &+L.L.:.. . . . . . . . . . a.:.. . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . L.L.f.. . . . . . . . L.L.;.. . . L.L.A.. . . . . . . . L.L.e.{.. . * L.L.. . . . L.L.Y . . ' ' { ' , . > ' . . > M.M.M ' , ' , L g.M.L.M.N.t.{ : q.o.a.. ' . u.G.`.9.> ' > ' , . . M.T.. , , ' P.N.[.. . . . . . > . > . . . L.L.... . . L.L.L.:.. . . . . . . [.L.L.{.. . . . . . . . . . . . . . . ++L.L.. . . &+T.L.. . . . . f.e.L.L.L.L.A+. . L.F.L.L.A.. . . . . . . 2.L.L.. . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . {.L.L.L.n.:.$.#.}.F.L.L.[.{.. . . 2.L.L.L.s.:.W O }.L.L.L.[.{.u . . F.L.L.. . > . L.M.b.9.A+9.8.8.A+0.0.0.0., , . M.M.O , , , v { .c.M.N.P.B.1 P v.q.p.' /.o.o.I.b.Y , ' , , . , ' M.O.] { , . L.M.[.. . . . . . . . . > . . L.L.$.. . . u.l.L.L.L.a.:.M #.:.L.L.L.2.. . . . . . . . . . . . . . . . ++L.L.. . . &+L.L.. . . . . u a.A+L.L.L.7.. . . A.f.L.L.L.7.:.W #.:.L.L.L.:.. . . . L.L.L.. . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . #.3.:.:.7.a.A+2.>.;.>.{.' . . . . L 7.:.}.7.a.A+2.>.>.{.;.. . . . >.}.(.. ' . . [.}.}.[.[.}.[.[.}.[.[.[.[., ' { _.4.P { { { _ : _ 1 0.0.|.4.Q J.- x.w.q.w.w.h.0.< { { ] _ 1 1 { v }.}.> . . . [.[.Y . . ' ' . ' . . ' > . . [.}.> > . . . . 8.2.:.[.7.a.A+2.>.{.{.. . . . . . . . . . . . . . . . . s.[.[.. . . &+:.:.. . . . . . . [.7.2.:.W . . . . :.2.2.:.[.7.a.7.2.{.;.` . . . . &+:.[.:.. . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . L O L > . . . . . . . . . . . . . L N L . . . > . > . . . . . . . > > . . . . . ' ' , ' ' ' ' v v { { _ _ 1 B C S T T T T +.+. at .=.=..+W.S.S.S.J.h.+.+.T S C 1 _ : _ { { ' { ] ] ' ' , . . > . ' . ' > > . . . . . . . . . . . . . . . . ' L N L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . L L L u . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . > > . > . . > > > > > > > > > > > > > > > > > > > > > > > > > > > > > . > > ' ' . ' ' > ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ] ] ] ! ] : 1 z D G I T T +.+.=.1.1.6.6.6.d.&+&+&+&+&+S.1.=.+.+.T S J Q D 2 x 1 ] ] ] ] ' ' ' ' ' ' ' ' ' ' ' . > . > > > > ' . ' > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > . . . . . . > > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+"' ' ' ' ' ' ! ! ' ' ' ' ' ' ! ' ' ! ! ' ! ! ! ! ! ! ! ! ~ ~ ~ ~ ~ ~ ~ ~ ~ ( ; ; ; ( ; ; ( ( ( [ ( [ [ [ [ [ } } } } } | 4 4 4 4 b 4 E H H K R R V =. at .@.-.-.<.<.d.k.K.#+&+&+&+&+&+&+K.k.d.6.<.-.-. at .@.V V R U K H E E b | 4 4 4 } | | } } } } [ [ [ [ [ ( ( ( ( ( ( ( ( ; ; ; ; ~ ( ~ ~ : ~ ~ ~ ~ ! ! ! ! ! ! ! ! ! ! ' ' ' ! ' ' ' ! ! ' ' ! ' ' ' ' ' ' ' ' ' ' ' ' ' ' > ' > > > > > > > > > > . . > . . > . > . . . > > . . . . . . . . . . . . . . . ",
+"> > > > > . > > > > > > > > > > > > > > > > > > > > > > > > > > > > > . ' . > ' ' ' ' ' . ' ' ' ' ' ' ' ' ' ' ' ' ! ! ' ' ] ' ] ] ! ] ] ~ < z C A Q J T +.V @.=.1.6.6.6.d.k.k.k.d.d.6.6.1.-.+.+.+.T J Q D z y < : ~ ! ! ] ' ' ' ' ! ! ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' > ' . ' ' . > > > > > > > > . . > > > > > > > > > > > . > > > . > > > . > > > > > . . . . . . . . . . . . . . . . . . . > . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . . . . . . . ' , , ' , ' , ' ' v v ] { { 1 C F S Q Q S Q S +.S +.+.=.+.+.T +.S Q Q Q S S F B : ] { v v ' ' ' ' ' , ' , ' ' > . ' . ' . . . . > . . . . . . . . . . . . . > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . . . . > > ' > . . . > . . . > . > . ' . . > , , ' ' { 1 _ ] ] ' ' { { _ _ 1 : _ x 1 F Q F 2 1 1 1 1 x w { { v v v ] _ 1 _ ' . . ' . > > ' . > . > . . . . . . > ' > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' ' > ' . . ' { { ' , , , , , , , ' ' { ' ' ' v { { 1 y _ { { v ' ' { { ' ' , , . . , ' , ' ] { ' , . > . ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . . . . . . . . , ' { ' . . . ' . . ' . . . ' , . , , ' > > > . , ' { _ { ' , ' > . ' ' ' , . . . . . > . > ' . > > . ' { ' , ' > > . . . . . . . > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . , ' ' , . . . . > . . . . . > . . . . ' . . . . ' . ' . . ' ' v { v , ' ' . . . . ' . . ' . > . > > . . . . . . . > . . > , ' ' , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > ' , , ' > . . . . . . . . . > . . > . . . ' . . . . . . . . > . . . ' ' { , . . . > . . . . . . . . . ' > > . . . . . . . . . > . . . . > . , ' , > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > ' . . > . . . . . . . . . . . . . . . . . . . . . . . . . . . . > . . . . . ' , ' v ' > ' . > . . . . . > . . . . . > . . . . . . . . . . . . . . . . . . . . . > , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > , > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' , ' , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' , ' , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};
Added: packages/openev/branches/upstream/current/pics/busy.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/busy.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/busy.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char *busy {
+/* width height num_colors chars_per_pixel */
+" 22 18 2 1",
+/* colors */
+"a c None",
+". c #ff0000",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.aaaaaaaaaaaaaa.aaa",
+"aaaa.aaaaaaaaaaaa.aaaa",
+"aaaaa.aaaaaaaaaa.aaaaa",
+"aaaaaa.aa....aa.aaaaaa",
+"aaaaaaa.......aaaaaaaa",
+"aaaaaa..........aaaaaa",
+"aa..................aa",
+"aaaaaa..........aaaaaa",
+"aaaaaaa........aaaaaaa",
+"aaaaaa.aa....aa.aaaaaa",
+"aaaaa.aaaaaaaaaa.aaaaa",
+"aaaa.aaaaaaaaaaaa.aaaa",
+"aaa.aaaaaaaaaaaaaa.aaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/ck_off_l.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/ck_off_l.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/ck_off_l.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,30 @@
+/* XPM */
+static char *ck_on_l_2[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 2",
+/* colors */
+"`` c #CCCCCC",
+" . c #EEEEEE",
+" , c #444444",
+"`. c None",
+
+/* pixels */
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.```.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.``` ..`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.` ,.`.`.````` ..`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.``` ,.````` ..`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.````````` ..`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.````` ..`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.` ..`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`."
+};
\ No newline at end of file
Added: packages/openev/branches/upstream/current/pics/ck_on_l.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/ck_on_l.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/ck_on_l.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,28 @@
+/* XPM */
+static char *ck_on_l_2[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 2 2",
+/* colors */
+"`` c #000000",
+"`. c None",
+
+/* pixels */
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.```.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`````.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.```.`.`.```````.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`````.```````.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.```````````.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.```````.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.```.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.",
+"`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`."
+};
Added: packages/openev/branches/upstream/current/pics/classify.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/classify.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/classify.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char * classify_xpm[] = {
+"22 18 6 1",
+" c None",
+". c #000000",
+"+ c #0000FF",
+"@ c #FFFCFC",
+"# c #FF0000",
+"$ c #008000",
+" ",
+" ................ ",
+" .++++++++++++++. ",
+" ................ ",
+" .@@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@@. ",
+" .@@@@@.....@@@@. ",
+" .@@@@.@@@@@.@@@. ",
+" .@@@.@@@@@@@@@@. ",
+" .@@@.@@@@@@@@@@. ",
+" .@@@.@@@@@@@@@@. ",
+" .@@@.@@@@@@@@@@. ",
+" .@@@.@@@@@@@@@@. ",
+" .@@@@.@@@@@.@@@. ",
+" .@@@@@.....@@@@. ",
+" .@@@@@@@@@@@@@@. ",
+" ................ ",
+" "};
Added: packages/openev/branches/upstream/current/pics/delete.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/delete.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/delete.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,22 @@
+/* XPM */
+static char * delete_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000",
+"+ c #7F7F7F",
+" ",
+" ",
+" .+ .+ ",
+" ...+ ...+ ",
+" ...+ ...+ ",
+" ...+ ...+ ",
+" ......+ ",
+" ....+ ",
+" ....+ ",
+" ......+ ",
+" ...++...+ ",
+" ...+ ...+ ",
+" ...+ ...+ ",
+" .+ .+ ",
+" ",
+" "};
Added: packages/openev/branches/upstream/current/pics/equalize.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/equalize.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/equalize.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,31 @@
+/* XPM */
+static char *bmp854[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.................aa",
+"aaa.#############...aa",
+"aaa.aaaaaaaaaaa.#a#.aa",
+"aaa.aaaaaaaaaa.#aa#.aa",
+"aaa.aaaaaaaaa.#aaa#.aa",
+"aaa.aaaaaaaa.#aaaa#.aa",
+"aaa.aaaaaaa.#aaaaa#.aa",
+"aaa.aaaaaaa.#aaaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa...#aaaaaaaaaaa#.aa",
+"aaa.................aa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
+
+
Added: packages/openev/branches/upstream/current/pics/eye.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/eye.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/eye.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char * eye_xpm[] = {
+"21 21 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ",
+" ",
+" ",
+" ....... ",
+" ........... ",
+" ............... ",
+" ................. ",
+" ....++....+..++.... ",
+"....++.........+++...",
+"..++++.........+++++.",
+"..++++.........++++..",
+" ...+++.......++++.. ",
+" ...++.......++... ",
+" ....+.....+.... ",
+" ........... ",
+" ....... ",
+" ",
+" ",
+" ",
+" "};
Added: packages/openev/branches/upstream/current/pics/geo_innovation.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/geo_innovation.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/geo_innovation.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2015 @@
+/* XPM */
+static char * geo_innovation_xpm[] = {
+"113 80 1932 2",
+" c None",
+". c #FFFFFF",
+"+ c #FEFEFE",
+"@ c #FDFDFE",
+"# c #FDFDFD",
+"$ c #FEFEFF",
+"% c #FAFAFB",
+"& c #EFEFF1",
+"* c #E1E0E5",
+"= c #D3D1DC",
+"- c #C8C5D3",
+"; c #BCB9CB",
+"> c #B3B1C4",
+", c #ADAABF",
+"' c #A9A6BB",
+") c #A8A5BB",
+"! c #AAA6BC",
+"~ c #B3B0C3",
+"{ c #BBB9CA",
+"] c #C6C4D2",
+"^ c #D2D0DB",
+"/ c #DEDCE4",
+"( c #EDEDF0",
+"_ c #F9F9F9",
+": c #FDFDFF",
+"< c #FCFCFD",
+"[ c #F9F8FA",
+"} c #E6E4EB",
+"| c #CAC8D5",
+"1 c #A9A8BD",
+"2 c #8C8AA6",
+"3 c #737192",
+"4 c #626285",
+"5 c #57567E",
+"6 c #515079",
+"7 c #4A4B74",
+"8 c #454671",
+"9 c #40426D",
+"0 c #3F416C",
+"a c #3E3F6B",
+"b c #3D3F6B",
+"c c #3E3F6A",
+"d c #41436E",
+"e c #464671",
+"f c #505078",
+"g c #57577E",
+"h c #626186",
+"i c #6F6D91",
+"j c #8583A2",
+"k c #A19FB6",
+"l c #C0BECE",
+"m c #DCDBE2",
+"n c #F4F3F5",
+"o c #FCFCFC",
+"p c #FDFDFC",
+"q c #FBFCFB",
+"r c #EDECF0",
+"s c #CAC8D7",
+"t c #9D99B2",
+"u c #747293",
+"v c #5A597F",
+"w c #3C3E69",
+"x c #333762",
+"y c #2D305F",
+"z c #272C5A",
+"A c #242958",
+"B c #212756",
+"C c #1F2554",
+"D c #1E2453",
+"E c #1C2251",
+"F c #1D2351",
+"G c #1C2351",
+"H c #1D2452",
+"I c #202554",
+"J c #232957",
+"K c #272C59",
+"L c #2C2F5E",
+"M c #323562",
+"N c #393B67",
+"O c #44446F",
+"P c #616084",
+"Q c #8583A1",
+"R c #DCDBE4",
+"S c #F9F9FA",
+"T c #FEFDFE",
+"U c #FBFBFC",
+"V c #E1E0E7",
+"W c #ADAABD",
+"X c #787596",
+"Y c #58577F",
+"Z c #43446E",
+"` c #333562",
+" . c #282C5B",
+".. c #212755",
+"+. c #1D2352",
+"@. c #1A214F",
+"#. c #191F4E",
+"$. c #191D4D",
+"%. c #191C4B",
+"&. c #181B4A",
+"*. c #191B4A",
+"=. c #191C4A",
+"-. c #181C4A",
+";. c #181D4B",
+">. c #191D4C",
+",. c #181C4C",
+"'. c #191D4B",
+"). c #1B204E",
+"!. c #1C2150",
+"~. c #1E2352",
+"{. c #212654",
+"]. c #242856",
+"^. c #292D5D",
+"/. c #313561",
+"(. c #3D3E6B",
+"_. c #4E4E77",
+":. c #7B7A98",
+"<. c #BCBCCA",
+"[. c #F2F2F5",
+"}. c #FDFCFC",
+"|. c #F3F1F4",
+"1. c #C3C1D1",
+"2. c #8885A3",
+"3. c #5D5C83",
+"4. c #42436E",
+"5. c #2F3261",
+"6. c #252A59",
+"7. c #1E2452",
+"8. c #1B214F",
+"9. c #191E4E",
+"0. c #181D4C",
+"a. c #181C4B",
+"b. c #181B4B",
+"c. c #191B4B",
+"d. c #181B49",
+"e. c #272A54",
+"f. c #484B70",
+"g. c #6D6F8D",
+"h. c #8B8CA6",
+"i. c #A3A4B9",
+"j. c #B9BAC8",
+"k. c #CDCCD8",
+"l. c #D8D8E1",
+"m. c #E2E2E9",
+"n. c #E5E6ED",
+"o. c #E7E7EE",
+"p. c #E6E6EC",
+"q. c #E3E3EA",
+"r. c #D8D9E0",
+"s. c #CCCCD7",
+"t. c #BCBCCB",
+"u. c #AAABBF",
+"v. c #9696AF",
+"w. c #7E7F9C",
+"x. c #706F90",
+"y. c #9290AA",
+"z. c #D9D9E1",
+"A. c #FCFDFD",
+"B. c #EFEEF2",
+"C. c #BBB8CB",
+"D. c #4E4F78",
+"E. c #363966",
+"F. c #1A204F",
+"G. c #191E4D",
+"H. c #181A4A",
+"I. c #1A1D4B",
+"J. c #3B3E66",
+"K. c #717391",
+"L. c #A7A9BB",
+"M. c #D7D7DF",
+"N. c #F1F0F4",
+"O. c #F4F1F5",
+"P. c #EFEDF2",
+"Q. c #ECE9F0",
+"R. c #E8E6EE",
+"S. c #E5E2EB",
+"T. c #E2DFE8",
+"U. c #DFDCE5",
+"V. c #DEDBE4",
+"W. c #DDD9E4",
+"X. c #DCD9E4",
+"Y. c #DDDAE3",
+"Z. c #E1DEE7",
+"`. c #E4E2EA",
+" + c #E8E6ED",
+".+ c #EBE9EF",
+"++ c #EEECF1",
+"@+ c #F3F2F5",
+"#+ c #F2F1F4",
+"$+ c #E8E8EC",
+"%+ c #FCFCFE",
+"&+ c #ECECEF",
+"*+ c #AEABBF",
+"=+ c #6E6C90",
+"-+ c #4A4B75",
+";+ c #303460",
+">+ c #232755",
+",+ c #1B2150",
+"'+ c #191F4D",
+")+ c #2C2F5B",
+"!+ c #56597A",
+"~+ c #A7A8BC",
+"{+ c #DCDCE3",
+"]+ c #F2F0F5",
+"^+ c #EDEBF1",
+"/+ c #E5E3EC",
+"(+ c #DDDAE5",
+"_+ c #D5D1DD",
+":+ c #CCC9D7",
+"<+ c #C3BFD0",
+"[+ c #BAB5C9",
+"}+ c #B3AEC4",
+"|+ c #ADA8C0",
+"1+ c #ACA6BF",
+"2+ c #A49FB7",
+"3+ c #9E99B3",
+"4+ c #9D98B3",
+"5+ c #9E98B3",
+"6+ c #9F9AB4",
+"7+ c #A29DB5",
+"8+ c #A6A1BA",
+"9+ c #ACA7BF",
+"0+ c #BBB6CA",
+"a+ c #C3BFD1",
+"b+ c #CCC8D6",
+"c+ c #D5D1DE",
+"d+ c #DEDBE6",
+"e+ c #E6E4EC",
+"f+ c #EDEBF2",
+"g+ c #F3F1F6",
+"h+ c #F7F7F8",
+"i+ c #B8B5C7",
+"j+ c #706D90",
+"k+ c #44456F",
+"l+ c #2B2F5D",
+"m+ c #1A204E",
+"n+ c #1C204D",
+"o+ c #5C5F7F",
+"p+ c #B9BBCA",
+"q+ c #F1EFF4",
+"r+ c #DAD7E3",
+"s+ c #BEB9CC",
+"t+ c #AEA8C0",
+"u+ c #9F99B5",
+"v+ c #908BA9",
+"w+ c #84809F",
+"x+ c #6F6B90",
+"y+ c #676489",
+"z+ c #605E84",
+"A+ c #5C5A80",
+"B+ c #706D92",
+"C+ c #59597F",
+"D+ c #52527B",
+"E+ c #52527A",
+"F+ c #53547B",
+"G+ c #56567D",
+"H+ c #5B5980",
+"I+ c #666489",
+"J+ c #6E6B8F",
+"K+ c #837F9F",
+"L+ c #A09AB4",
+"M+ c #AEA9BF",
+"N+ c #BCB8CA",
+"O+ c #CBC7D7",
+"P+ c #DBD8E2",
+"Q+ c #EEEBF1",
+"R+ c #F5F4F8",
+"S+ c #FBFAFD",
+"T+ c #D2CFDA",
+"U+ c #83809F",
+"V+ c #515078",
+"W+ c #202655",
+"X+ c #272A57",
+"Y+ c #80829B",
+"Z+ c #DAD9E1",
+"`+ c #F1F0F3",
+" @ c #D9D7E1",
+".@ c #C9C5D5",
+"+@ c #B7B3C6",
+"@@ c #A19CB5",
+"#@ c #8C87A5",
+"$@ c #797697",
+"%@ c #69678B",
+"&@ c #4F4F77",
+"*@ c #464772",
+"=@ c #3E406B",
+"-@ c #343764",
+";@ c #323462",
+">@ c #41426F",
+",@ c #303260",
+"'@ c #3F416D",
+")@ c #292C5C",
+"!@ c #2A2D5C",
+"~@ c #2B2E5D",
+"{@ c #2C2F5D",
+"]@ c #2E315F",
+"^@ c #303361",
+"/@ c #333663",
+"(@ c #383B67",
+"_@ c #3E406C",
+":@ c #454771",
+"<@ c #69678A",
+"[@ c #8A86A3",
+"}@ c #A19CB6",
+"|@ c #B9B5C9",
+"1@ c #D8D5E1",
+"2@ c #E8E5ED",
+"3@ c #F1EFF3",
+"4@ c #F8F7FA",
+"5@ c #F5F4F6",
+"6@ c #ADAAC0",
+"7@ c #5F5E84",
+"8@ c #383C67",
+"9@ c #191B49",
+"0@ c #222551",
+"a@ c #888AA1",
+"b@ c #E8E7EC",
+"c@ c #EEECF0",
+"d@ c #E1DDE6",
+"e@ c #CECAD7",
+"f@ c #B5B0C6",
+"g@ c #8682A1",
+"h@ c #777496",
+"i@ c #5A5981",
+"j@ c #4A4C75",
+"k@ c #363766",
+"l@ c #292C5A",
+"m@ c #252958",
+"n@ c #222755",
+"o@ c #1E2653",
+"p@ c #1F2555",
+"q@ c #2F3460",
+"r@ c #2D315F",
+"s@ c #1B2250",
+"t@ c #1C2250",
+"u@ c #1C2352",
+"v@ c #1F2553",
+"w@ c #2F3160",
+"x@ c #353866",
+"y@ c #55557E",
+"z@ c #656489",
+"A@ c #6F6D90",
+"B@ c #9D96B2",
+"C@ c #B7B2C7",
+"D@ c #CDC9D6",
+"E@ c #DFDDE6",
+"F@ c #EDEBEF",
+"G@ c #F7F5F8",
+"H@ c #FCFBFD",
+"I@ c #D9D8E1",
+"J@ c #8988A4",
+"K@ c #272A56",
+"L@ c #7F809A",
+"M@ c #ECEAF0",
+"N@ c #DAD8E2",
+"O@ c #C5C2D2",
+"P@ c #ABA6BE",
+"Q@ c #8F8AA8",
+"R@ c #726E92",
+"S@ c #5B5981",
+"T@ c #55547D",
+"U@ c #3C3E6A",
+"V@ c #2F3260",
+"W@ c #222756",
+"X@ c #1F2453",
+"Y@ c #1A214E",
+"Z@ c #1E2351",
+"`@ c #282C59",
+" # c #1B1F4E",
+".# c #202352",
+"+# c #232553",
+"@# c #1A1F4D",
+"## c #19204F",
+"$# c #2C305D",
+"%# c #2F3362",
+"&# c #2D315E",
+"*# c #393B68",
+"=# c #464871",
+"-# c #5A5880",
+";# c #737094",
+"># c #8E89A7",
+",# c #A9A3BD",
+"'# c #C4C0D1",
+")# c #DBD8E3",
+"!# c #ECEAEF",
+"~# c #F6F5F6",
+"{# c #FBFBFD",
+"]# c #FDFEFE",
+"^# c #BEBBCB",
+"/# c #6A678B",
+"(# c #3B3D69",
+"_# c #232857",
+":# c #191F4F",
+"<# c #191C49",
+"[# c #525378",
+"}# c #DCDDE3",
+"|# c #DDDBE4",
+"1# c #A19DB6",
+"2# c #827E9E",
+"3# c #656387",
+"4# c #4D4C76",
+"5# c #393B66",
+"6# c #363864",
+"7# c #1A2050",
+"8# c #181E4D",
+"9# c #202351",
+"0# c #292B5A",
+"a# c #1D204D",
+"b# c #222554",
+"c# c #292C59",
+"d# c #1C224F",
+"e# c #393C68",
+"f# c #4B4B75",
+"g# c #636187",
+"h# c #807D9D",
+"i# c #A39EB7",
+"j# c #C1BDCF",
+"k# c #DAD8E1",
+"l# c #F8F8FA",
+"m# c #B9B6C8",
+"n# c #5D5C81",
+"o# c #232753",
+"p# c #9C9DB1",
+"q# c #F2F1F3",
+"r# c #E2DFE9",
+"s# c #CAC6D5",
+"t# c #ADA9BE",
+"u# c #8783A1",
+"v# c #636087",
+"w# c #494A73",
+"x# c #373966",
+"y# c #2A2E5D",
+"z# c #232856",
+"A# c #2C305E",
+"B# c #19204E",
+"C# c #1E2250",
+"D# c #252856",
+"E# c #2C2E5D",
+"F# c #181C49",
+"G# c #1F2350",
+"H# c #2A2C5A",
+"I# c #202451",
+"J# c #292E5C",
+"K# c #353865",
+"L# c #484973",
+"M# c #646288",
+"N# c #847FA0",
+"O# c #A7A3BA",
+"P# c #E3E0E9",
+"Q# c #F2F1F6",
+"R# c #FAFAFC",
+"S# c #F8F8F9",
+"T# c #AEABC0",
+"U# c #5D5B81",
+"V# c #2E315E",
+"W# c #3F426A",
+"X# c #D2D2DB",
+"Y# c #EDEBF0",
+"Z# c #D9D6E2",
+"`# c #B6B1C7",
+" $ c #9390AC",
+".$ c #6F6D8E",
+"+$ c #363866",
+"@$ c #282D5A",
+"#$ c #202653",
+"$$ c #1A1E4E",
+"%$ c #212351",
+"&$ c #262857",
+"*$ c #252756",
+"=$ c #1C1F4D",
+"-$ c #222553",
+";$ c #1A2250",
+">$ c #1F2653",
+",$ c #282C5A",
+"'$ c #4B4C75",
+")$ c #68678B",
+"!$ c #8F8BA8",
+"~$ c #B8B3C7",
+"{$ c #D7D4E0",
+"]$ c #ECEAF1",
+"^$ c #F4F3F7",
+"/$ c #9F9DB3",
+"($ c #53537C",
+"_$ c #2B2F5E",
+":$ c #686B89",
+"<$ c #E1E1E7",
+"[$ c #E4E1EA",
+"}$ c #A29EB6",
+"|$ c #747093",
+"1$ c #5A5A81",
+"2$ c #292D5C",
+"3$ c #191F4C",
+"4$ c #1F2451",
+"5$ c #1E214F",
+"6$ c #212452",
+"7$ c #292B59",
+"8$ c #1E2150",
+"9$ c #232653",
+"0$ c #292C5B",
+"a$ c #373967",
+"b$ c #757294",
+"c$ c #9D99B3",
+"d$ c #C6C3D2",
+"e$ c #E3E1E9",
+"f$ c #F5F4F7",
+"g$ c #FBFBFB",
+"h$ c #A3A0B7",
+"i$ c #50507A",
+"j$ c #8487A0",
+"k$ c #DEDAE4",
+"l$ c #B9B5C8",
+"m$ c #8E8BA7",
+"n$ c #3B3D6B",
+"o$ c #222856",
+"p$ c #242855",
+"q$ c #252857",
+"r$ c #1D214E",
+"s$ c #1C1F4E",
+"t$ c #343564",
+"u$ c #232654",
+"v$ c #414370",
+"w$ c #616085",
+"x$ c #908BA8",
+"y$ c #BCB7CB",
+"z$ c #DDDAE4",
+"A$ c #F2F0F4",
+"B$ c #BFBDCD",
+"C$ c #58577E",
+"D$ c #9495AB",
+"E$ c #DBD9E3",
+"F$ c #B3AFC3",
+"G$ c #837E9E",
+"H$ c #58587F",
+"I$ c #3A3C69",
+"J$ c #2E3160",
+"K$ c #212553",
+"L$ c #222655",
+"M$ c #1A1D4A",
+"N$ c #262956",
+"O$ c #1A1C4C",
+"P$ c #272A58",
+"Q$ c #272A59",
+"R$ c #383A67",
+"S$ c #57567C",
+"T$ c #8B86A5",
+"U$ c #D9D5E1",
+"V$ c #F0EFF3",
+"W$ c #D5D3DD",
+"X$ c #6A698C",
+"Y$ c #303360",
+"Z$ c #1B2151",
+"`$ c #82839C",
+" % c #F0EFF2",
+".% c #D9D6E0",
+"+% c #B2AEC2",
+"@% c #7F7A9B",
+"#% c #343664",
+"$% c #222757",
+"%% c #202453",
+"&% c #222654",
+"*% c #282B59",
+"=% c #1B1E4C",
+"-% c #1C204E",
+";% c #262A58",
+">% c #5C5A81",
+",% c #7D7899",
+"'% c #D6D2DD",
+")% c #F1F0F5",
+"!% c #FDFCFE",
+"~% c #E2E1EA",
+"{% c #777595",
+"]% c #757693",
+"^% c #EBEAEF",
+"/% c #D6D3DE",
+"(% c #AAA5BE",
+"_% c #4B4B74",
+":% c #202654",
+"<% c #202552",
+"[% c #202553",
+"}% c #1B1E4D",
+"|% c #262856",
+"1% c #1A1E4D",
+"2% c #1D2150",
+"3% c #2A2D5A",
+"4% c #41426C",
+"5% c #535279",
+"6% c #7D799A",
+"7% c #A9A4BD",
+"8% c #F6F6F8",
+"9% c #918EAA",
+"0% c #42456E",
+"a% c #545879",
+"b% c #EFEFF2",
+"c% c #DAD7E2",
+"d% c #ACA7BE",
+"e% c #767496",
+"f% c #4C4C76",
+"g% c #2D2F5F",
+"h% c #1F2352",
+"i% c #202452",
+"j% c #1A1E4C",
+"k% c #1B1D4D",
+"l% c #242755",
+"m% c #292B58",
+"n% c #1D204E",
+"o% c #252855",
+"p% c #191D4A",
+"q% c #262B58",
+"r% c #282D59",
+"s% c #383C69",
+"t% c #454770",
+"u% c #716E91",
+"v% c #ACA8BE",
+"w% c #F2F1F5",
+"x% c #C4C1D1",
+"y% c #2F325C",
+"z% c #E2E2E8",
+"A% c #E3E0E8",
+"B% c #7D789A",
+"C% c #1B204F",
+"D% c #1A1E4B",
+"E% c #212554",
+"F% c #1D214F",
+"G% c #171C4A",
+"H% c #2A2D5B",
+"I% c #1F2250",
+"J% c #272957",
+"K% c #1F2452",
+"L% c #2B305E",
+"M% c #484972",
+"N% c #7E799A",
+"O% c #B6B1C5",
+"P% c #DFDDE5",
+"Q% c #F6F5F8",
+"R% c #F3F2F6",
+"S% c #7F7C9D",
+"T% c #353766",
+"U% c #B9B9C7",
+"V% c #EAE7ED",
+"W% c #C5C0D2",
+"X% c #8A85A5",
+"Y% c #525279",
+"Z% c #1C204F",
+"`% c #272B5A",
+" & c #1C1E4D",
+".& c #272B58",
+"+& c #212451",
+"@& c #1D1F4E",
+"#& c #1E204E",
+"$& c #282A58",
+"%& c #282C58",
+"&& c #232655",
+"*& c #212352",
+"=& c #1A1C4A",
+"-& c #52537B",
+";& c #8884A4",
+">& c #C0BCCE",
+",& c #E7E5EC",
+"'& c #FAF9FC",
+")& c #FCFDFC",
+"!& c #B7B4C6",
+"~& c #4D4C75",
+"{& c #626685",
+"]& c #F0EEF3",
+"^& c #D0CCDA",
+"/& c #9995B0",
+"(& c #5C5A82",
+"_& c #1A2150",
+":& c #282B58",
+"<& c #1A1C4B",
+"[& c #1C1E4C",
+"}& c #2B2E5C",
+"|& c #333664",
+"1& c #938FAB",
+"2& c #CBC8D7",
+"3& c #EEEDF1",
+"4& c #7A7697",
+"5& c #D1D2DC",
+"6& c #AEAAC1",
+"7& c #3E3F6C",
+"8& c #232858",
+"9& c #181E4C",
+"0& c #1A1D4C",
+"a& c #1B1F4F",
+"b& c #1F2351",
+"c& c #242756",
+"d& c #262957",
+"e& c #1D204F",
+"f& c #3D3F6A",
+"g& c #6D698E",
+"h& c #A9A6BD",
+"i& c #E0DEE7",
+"j& c #BFBCCC",
+"k& c #53527A",
+"l& c #6E718F",
+"m& c #EFECF3",
+"n& c #C6C2D3",
+"o& c #8985A5",
+"p& c #505079",
+"q& c #212450",
+"r& c #282B57",
+"s& c #1E2151",
+"t& c #1C1E4E",
+"u& c #181F4D",
+"v& c #84819F",
+"w& c #C8C4D5",
+"x& c #F7F6F9",
+"y& c #8A86A4",
+"z& c #3A3C68",
+"A& c #A7A3BB",
+"B& c #67658A",
+"C& c #393A67",
+"D& c #191C4C",
+"E& c #191E4C",
+"F& c #1E224F",
+"G& c #262A59",
+"H& c #222453",
+"I& c #363765",
+"J& c #ABA6BD",
+"K& c #DEDBE5",
+"L& c #D8D6E0",
+"M& c #615F85",
+"N& c #616384",
+"O& c #F0EEF2",
+"P& c #C9C6D4",
+"Q& c #8581A1",
+"R& c #4A4A73",
+"S& c #1E2251",
+"T& c #222452",
+"U& c #252956",
+"V& c #8985A3",
+"W& c #C7C3D4",
+"X& c #EEECF2",
+"Y& c #B1AEC1",
+"Z& c #494972",
+"`& c #B2B2C2",
+" * c #E6E3EB",
+".* c #69688C",
+"+* c #202755",
+"@* c #202251",
+"#* c #262A57",
+"$* c #2A2C5B",
+"%* c #363865",
+"&* c #6C6B8E",
+"** c #B0ACC1",
+"=* c #E2E0E8",
+"-* c #FBFAFC",
+";* c #242753",
+">* c #EAE9EE",
+",* c #D8D5E0",
+"'* c #9C98B2",
+")* c #53547C",
+"!* c #2D305E",
+"~* c #212653",
+"{* c #363F68",
+"]* c #323A64",
+"^* c #1B1F4D",
+"/* c #1B1E4E",
+"(* c #181B4C",
+"_* c #31335D",
+":* c #4E5074",
+"<* c #383A63",
+"[* c #1E204F",
+"}* c #1F224F",
+"|* c #7B7D98",
+"1* c #353860",
+"2* c #9894AF",
+"3* c #D4D1DE",
+"4* c #EBEAEE",
+"5* c #6F6C8F",
+"6* c #585B7D",
+"7* c #F1EEF2",
+"8* c #8681A1",
+"9* c #434470",
+"0* c #272F5A",
+"a* c #7C95AC",
+"b* c #B1D5E3",
+"c* c #A3C5D6",
+"d* c #ACCFDD",
+"e* c #444F75",
+"f* c #363862",
+"g* c #B3B5C2",
+"h* c #F1F2F3",
+"i* c #D5D6DE",
+"j* c #BFC0CC",
+"k* c #1E224E",
+"l* c #232754",
+"m* c #1F2251",
+"n* c #272B59",
+"o* c #333761",
+"p* c #8C8FA6",
+"q* c #CDCFD7",
+"r* c #4E5274",
+"s* c #19204D",
+"t* c #817E9E",
+"u* c #EEEDF2",
+"v* c #DDDCE4",
+"w* c #5D5C82",
+"x* c #252B59",
+"y* c #191A4A",
+"z* c #8B8EA5",
+"A* c #E9E7ED",
+"B* c #BAB5CA",
+"C* c #737092",
+"D* c #7A93AB",
+"E* c #A9CADA",
+"F* c #38436A",
+"G* c #1B204D",
+"H* c #637796",
+"I* c #7992AA",
+"J* c #3C486E",
+"K* c #354067",
+"L* c #7790A8",
+"M* c #7189A4",
+"N* c #2A325D",
+"O* c #1B1E4B",
+"P* c #C9CBD4",
+"Q* c #D8D9DF",
+"R* c #343862",
+"S* c #8486A0",
+"T* c #A4A6B7",
+"U* c #5F6283",
+"V* c #535679",
+"W* c #71728D",
+"X* c #8789A0",
+"Y* c #9D9FB1",
+"Z* c #2A2D58",
+"`* c #4E5174",
+" = c #82859C",
+".= c #727490",
+"+= c #9FA2B3",
+"@= c #2F325B",
+"#= c #6A6D8C",
+"$= c #6A6C8A",
+"%= c #898CA3",
+"&= c #A7A8BA",
+"*= c #4A4D72",
+"== c #B8BBC7",
+"-= c #EEEEF0",
+";= c #7A7C96",
+">= c #9698AB",
+",= c #272C57",
+"'= c #3E426A",
+")= c #999CAE",
+"!= c #9C9FB1",
+"~= c #333660",
+"{= c #1B1D4C",
+"]= c #9092A6",
+"^= c #686988",
+"/= c #A1A4B5",
+"(= c #676989",
+"_= c #585A7C",
+":= c #A4A7B9",
+"<= c #8B8DA4",
+"[= c #1E2553",
+"}= c #6F6C90",
+"|= c #B4AFC5",
+"1= c #FCFBFC",
+"2= c #D2D1DC",
+"3= c #51517A",
+"4= c #B2B2C3",
+"5= c #AFA9C2",
+"6= c #656589",
+"7= c #313362",
+"8= c #1E2552",
+"9= c #B1D5E1",
+"0= c #5D6F8E",
+"a= c #6D819F",
+"b= c #6D849F",
+"c= c #2D355F",
+"d= c #8CA9BE",
+"e= c #8EACC0",
+"f= c #86A2B9",
+"g= c #9EBFCF",
+"h= c #343D67",
+"i= c #AFD2E0",
+"j= c #7187A3",
+"k= c #92B0C3",
+"l= c #FCFAF9",
+"m= c #6B6F8C",
+"n= c #B7B9C7",
+"o= c #DADBE1",
+"p= c #A6A7B9",
+"q= c #F8F9F9",
+"r= c #42466C",
+"s= c #A0A1B4",
+"t= c #EFF0F1",
+"u= c #A2A4B5",
+"v= c #F9FAF9",
+"w= c #737593",
+"x= c #9597AB",
+"y= c #F7F8F7",
+"z= c #F0F0F3",
+"A= c #7D7E9A",
+"B= c #878AA1",
+"C= c #DDDDE2",
+"D= c #989AAE",
+"E= c #353964",
+"F= c #CCCED7",
+"G= c #D6D7DE",
+"H= c #9092A7",
+"I= c #41446A",
+"J= c #D5D7DD",
+"K= c #CECFD7",
+"L= c #6B6C8A",
+"M= c #777997",
+"N= c #F4F4F6",
+"O= c #44486E",
+"P= c #EFF0F2",
+"Q= c #A9AABB",
+"R= c #C4C6CF",
+"S= c #C7C8D4",
+"T= c #30345D",
+"U= c #CBCDD6",
+"V= c #D0D2D8",
+"W= c #E4E4EB",
+"X= c #2C2F5A",
+"Y= c #F2F4F3",
+"Z= c #8E91A7",
+"`= c #6E718D",
+" - c #323563",
+".- c #626187",
+"+- c #A7A1BC",
+"@- c #E0DEE8",
+"#- c #C5C3D3",
+"$- c #CECDD9",
+"%- c #DFDCE6",
+"&- c #A59FB9",
+"*- c #5C5B81",
+"=- c #2C3560",
+"-- c #B7DCE6",
+";- c #46537A",
+">- c #222955",
+",- c #839EB6",
+"'- c #B6DDE7",
+")- c #48567A",
+"!- c #B7DDE8",
+"~- c #90AFC1",
+"{- c #A9CCDA",
+"]- c #819CB4",
+"^- c #768EA7",
+"/- c #A1C1D0",
+"(- c #6F87A3",
+"_- c #AACDDC",
+":- c #474C6F",
+"<- c #505376",
+"[- c #42456A",
+"}- c #636787",
+"|- c #383C65",
+"1- c #FCFBFA",
+"2- c #646785",
+"3- c #CACBD5",
+"4- c #9397AC",
+"5- c #2F325E",
+"6- c #F9FAF8",
+"7- c #636685",
+"8- c #BFC0CD",
+"9- c #C0C2CD",
+"0- c #E1E2E6",
+"a- c #757893",
+"b- c #ECECF0",
+"c- c #D5D6DD",
+"d- c #D3D5DD",
+"e- c #DBDCE2",
+"f- c #6F718E",
+"g- c #FAFCFA",
+"h- c #474970",
+"i- c #202250",
+"j- c #CCCCD6",
+"k- c #797B97",
+"l- c #181D4A",
+"m- c #A3A4B7",
+"n- c #CED0D7",
+"o- c #9D9EB2",
+"p- c #E0E2E5",
+"q- c #71738E",
+"r- c #585C7C",
+"s- c #464A6F",
+"t- c #9FA2B4",
+"u- c #282B56",
+"v- c #E6E7EB",
+"w- c #CACAD5",
+"x- c #3B4066",
+"y- c #59587E",
+"z- c #9D97B2",
+"A- c #F9F8FB",
+"B- c #BAB8C9",
+"C- c #E1E1E8",
+"D- c #1D2350",
+"E- c #A6C8D8",
+"F- c #8BA6BD",
+"G- c #333D67",
+"H- c #5F7192",
+"I- c #A2C3D5",
+"J- c #455378",
+"K- c #B7DDE9",
+"L- c #5D718F",
+"M- c #475479",
+"N- c #232956",
+"O- c #829DB3",
+"P- c #9ABACB",
+"Q- c #242B56",
+"R- c #A1C2D2",
+"S- c #829DB4",
+"T- c #32355F",
+"U- c #F5F5F6",
+"V- c #B7BAC6",
+"W- c #3B3E65",
+"X- c #3E4169",
+"Y- c #525678",
+"Z- c #FBFBF9",
+"`- c #5C5D80",
+" ; c #82859D",
+".; c #393C64",
+"+; c #F1F1F3",
+"@; c #55587A",
+"#; c #5A5D7E",
+"$; c #393D64",
+"%; c #EAEAEE",
+"&; c #81859C",
+"*; c #4C4F73",
+"=; c #F6F7F6",
+"-; c #A3A6B6",
+";; c #373B62",
+">; c #797D97",
+",; c #FAFCF9",
+"'; c #494D71",
+"); c #323660",
+"!; c #F5F6F8",
+"~; c #656788",
+"{; c #D1D3DB",
+"]; c #9FA0B3",
+"^; c #AFB1BE",
+"/; c #D6D6DD",
+"(; c #BFC1CC",
+"_; c #AFB0BF",
+":; c #E8E9EC",
+"<; c #CCCDD6",
+"[; c #A7A7B9",
+"}; c #393C63",
+"|; c #DEDFE5",
+"1; c #AFB1C0",
+"2; c #191B4C",
+"3; c #2A2E5C",
+"4; c #525379",
+"5; c #9690AD",
+"6; c #D6D2DF",
+"7; c #F7F7FA",
+"8; c #B6B4C6",
+"9; c #42446E",
+"0; c #EBEAF1",
+"a; c #D9D6E1",
+"b; c #9A94B0",
+"c; c #53537A",
+"d; c #272B5B",
+"e; c #47557A",
+"f; c #A8C9D9",
+"g; c #B5DDE7",
+"h; c #B5D9E6",
+"i; c #758CA7",
+"j; c #95B4C8",
+"k; c #B5DAE6",
+"l; c #B1D4E1",
+"m; c #3E4B71",
+"n; c #3F4C72",
+"o; c #ADD0DC",
+"p; c #B4D7E4",
+"q; c #92B1C3",
+"r; c #28305B",
+"s; c #6E738F",
+"t; c #EBEDEE",
+"u; c #FAFAFA",
+"v; c #F5F6F6",
+"w; c #2F335B",
+"x; c #C2C3CF",
+"y; c #676B8A",
+"z; c #43476E",
+"A; c #44476D",
+"B; c #8688A0",
+"C; c #E8EAED",
+"D; c #2B2E59",
+"E; c #595C7C",
+"F; c #9FA1B4",
+"G; c #F4F5F5",
+"H; c #8588A1",
+"I; c #DBDDE3",
+"J; c #F7F8F8",
+"K; c #B1B1C1",
+"L; c #E7E8EC",
+"M; c #E5E6EB",
+"N; c #262A55",
+"O; c #747694",
+"P; c #525578",
+"Q; c #EDEDEF",
+"R; c #F3F4F4",
+"S; c #D7D8DE",
+"T; c #30345F",
+"U; c #B2B5C1",
+"V; c #BDBDCA",
+"W; c #EEEFF2",
+"X; c #7B7C97",
+"Y; c #9EA0B3",
+"Z; c #EEF0F2",
+"`; c #606381",
+" > c #1C1F4C",
+".> c #2B2E5B",
+"+> c #292D5B",
+"@> c #505077",
+"#> c #938DAB",
+"$> c #B8B6C8",
+"%> c #43446F",
+"&> c #191A4B",
+"*> c #E9E9EF",
+"=> c #D9D5E0",
+"-> c #9B95B1",
+";> c #262C5A",
+">> c #1E2450",
+",> c #2B315C",
+"'> c #1F2551",
+")> c #171C49",
+"!> c #1E2350",
+"~> c #29305C",
+"{> c #181D4D",
+"]> c #343861",
+"^> c #252A54",
+"/> c #1C214E",
+"(> c #3A3D68",
+"_> c #212552",
+":> c #242854",
+"<> c #252754",
+"[> c #2F335C",
+"}> c #2E315D",
+"|> c #1F2252",
+"1> c #383A65",
+"2> c #272B57",
+"3> c #2E325C",
+"4> c #252954",
+"5> c #212453",
+"6> c #343962",
+"7> c #242754",
+"8> c #252957",
+"9> c #343762",
+"0> c #202353",
+"a> c #948FAC",
+"b> c #C0BECF",
+"c> c #474971",
+"d> c #E0DFE7",
+"e> c #56577C",
+"f> c #1A1F4C",
+"g> c #212854",
+"h> c #313A64",
+"i> c #4C5072",
+"j> c #262955",
+"k> c #53537B",
+"l> c #9691AC",
+"m> c #D7D3DF",
+"n> c #CECCD9",
+"o> c #4E4F77",
+"p> c #CBCBD6",
+"q> c #A6A1B9",
+"r> c #5E5D82",
+"s> c #202754",
+"t> c #7892AB",
+"u> c #B2D6E4",
+"v> c #B3D9E4",
+"w> c #B4DAE5",
+"x> c #3C476E",
+"y> c #92AFC6",
+"z> c #5C6E8D",
+"A> c #787B94",
+"B> c #ECEDED",
+"C> c #F4F5F7",
+"D> c #F6F6F6",
+"E> c #3E4167",
+"F> c #EAECED",
+"G> c #636584",
+"H> c #5A5980",
+"I> c #F9F9FB",
+"J> c #595980",
+"K> c #AEAEC0",
+"L> c #B0AAC2",
+"M> c #686589",
+"N> c #313461",
+"O> c #8DA8BF",
+"P> c #ADD0DE",
+"Q> c #46557A",
+"R> c #272D59",
+"S> c #37416A",
+"T> c #445177",
+"U> c #6E83A0",
+"V> c #2D3661",
+"W> c #4D5B7E",
+"X> c #526183",
+"Y> c #666A89",
+"Z> c #F6F6F7",
+"`> c #7B7D99",
+" , c #2A2C58",
+"., c #33365F",
+"+, c #6F728E",
+"@, c #5D607F",
+"#, c #707290",
+"$, c #3D4068",
+"%, c #464A6E",
+"&, c #636684",
+"*, c #535578",
+"=, c #737591",
+"-, c #2D305B",
+";, c #33355F",
+">, c #5A5E7E",
+",, c #3D4168",
+"', c #5A5D7D",
+"), c #2C305A",
+"!, c #676C88",
+"~, c #5D6080",
+"{, c #6C6F8B",
+"], c #484B6F",
+"^, c #40446A",
+"/, c #656786",
+"(, c #595D7D",
+"_, c #646786",
+":, c #2B305A",
+"<, c #646289",
+"[, c #E1DFE8",
+"}, c #E6E5EA",
+"|, c #69668A",
+"1, c #8586A0",
+"2, c #ECE8EF",
+"3, c #BDB8CC",
+"4, c #767295",
+"5, c #383A68",
+"6, c #3F4A71",
+"7, c #B7DEE9",
+"8, c #556689",
+"9, c #232A55",
+"0, c #455175",
+"a, c #445277",
+"b, c #7B95AE",
+"c, c #A3C5D4",
+"d, c #94B1C5",
+"e, c #99B7C9",
+"f, c #222754",
+"g, c #9BBBCD",
+"h, c #A2C1D3",
+"i, c #A2C6D3",
+"j, c #91ADC2",
+"k, c #CFD0D9",
+"l, c #A9ABBB",
+"m, c #565779",
+"n, c #C2C6CF",
+"o, c #F2F3F5",
+"p, c #787994",
+"q, c #353761",
+"r, c #DADBE3",
+"s, c #D7D9DF",
+"t, c #CBCCD6",
+"u, c #E3E5E8",
+"v, c #D9DAE1",
+"w, c #FAFBFA",
+"x, c #4F5278",
+"y, c #A5A7B7",
+"z, c #DDDFE4",
+"A, c #C8C9D4",
+"B, c #C5C7D0",
+"C, c #F2F3F4",
+"D, c #E2E2E7",
+"E, c #8789A1",
+"F, c #E8E8EA",
+"G, c #222653",
+"H, c #DFE0E4",
+"I, c #D7D9DD",
+"J, c #D0D1DB",
+"K, c #D2D3DC",
+"L, c #ECEDEE",
+"M, c #DBDBE2",
+"N, c #FAFAF8",
+"O, c #3B3F67",
+"P, c #ACAEBD",
+"Q, c #DADCE1",
+"R, c #BABBCA",
+"S, c #383C64",
+"T, c #3B3D6A",
+"U, c #726F92",
+"V, c #B7B2C8",
+"W, c #E9E7EE",
+"X, c #F6F5F9",
+"Y, c #7E7B9B",
+"Z, c #54567A",
+"`, c #F0EEF4",
+" ' c #8884A2",
+".' c #444670",
+"+' c #5B6C8C",
+"@' c #B7DEE7",
+"#' c #303963",
+"$' c #435074",
+"%' c #A3C7D3",
+"&' c #B4D9E4",
+"*' c #344068",
+"=' c #7289A5",
+"-' c #8AA6BB",
+";' c #94B3C4",
+">' c #637896",
+",' c #B1D5E2",
+"'' c #272E59",
+")' c #627395",
+"!' c #282E59",
+"~' c #8486A1",
+"{' c #C5C6D2",
+"]' c #B9BCC8",
+"^' c #ACADBD",
+"/' c #B4B6C2",
+"(' c #5E6181",
+"_' c #545779",
+":' c #A3A5B8",
+"<' c #202253",
+"[' c #EEF0F1",
+"}' c #7A7D97",
+"|' c #FBFBFA",
+"1' c #FAFAF9",
+"2' c #979AAE",
+"3' c #B9BCC7",
+"4' c #BFC0CB",
+"5' c #171C4B",
+"6' c #A0A1B5",
+"7' c #A4A5B7",
+"8' c #DADAE2",
+"9' c #757793",
+"0' c #F5F6F7",
+"a' c #373A63",
+"b' c #6D6F8E",
+"c' c #353862",
+"d' c #F3F3F5",
+"e' c #8B8DA3",
+"f' c #5B5E81",
+"g' c #FBFCFA",
+"h' c #3A3E65",
+"i' c #BEBFCA",
+"j' c #D0D1D9",
+"k' c #595C7F",
+"l' c #1A1F4F",
+"m' c #474871",
+"n' c #EFEEF3",
+"o' c #A5A2B9",
+"p' c #44456E",
+"q' c #E6E6EB",
+"r' c #DBD7E3",
+"s' c #9F9CB4",
+"t' c #57567D",
+"u' c #4A567C",
+"v' c #B7DEE8",
+"w' c #5C718F",
+"x' c #758DA6",
+"y' c #9BBACC",
+"z' c #3C466F",
+"A' c #B6DCE5",
+"B' c #667C99",
+"C' c #536486",
+"D' c #232B56",
+"E' c #7E98B0",
+"F' c #9FC0CF",
+"G' c #7189A3",
+"H' c #A0C0D2",
+"I' c #BDBECA",
+"J' c #222552",
+"K' c #D7D8E0",
+"L' c #9192A9",
+"M' c #8E90A6",
+"N' c #8E90A7",
+"O' c #E5E6E9",
+"P' c #CBCCD5",
+"Q' c #ACACBD",
+"R' c #42456C",
+"S' c #2E315C",
+"T' c #7F829A",
+"U' c #F1F2F4",
+"V' c #7A7C98",
+"W' c #F9FAFA",
+"X' c #8A8CA1",
+"Y' c #242853",
+"Z' c #292B57",
+"`' c #F1F1F4",
+" ) c #C5C7D2",
+".) c #AFB2BF",
+"+) c #999AB0",
+"@) c #E4E5E9",
+"#) c #86889F",
+"$) c #4C5073",
+"%) c #494D70",
+"&) c #8587A0",
+"*) c #EDEEF0",
+"=) c #2D305C",
+"-) c #B4B7C6",
+";) c #2A2D57",
+">) c #2D2F5E",
+",) c #9C97B2",
+"') c #D7D3E0",
+")) c #F5F5F7",
+"!) c #CECCD8",
+"~) c #A6A7BA",
+"{) c #6D6C8E",
+"]) c #1C1F4F",
+"^) c #89A6BB",
+"/) c #B7DBE8",
+"() c #A3C4D4",
+"_) c #B3D7E4",
+":) c #7D96AE",
+"<) c #262D5A",
+"[) c #B0D6E2",
+"}) c #9BBCCC",
+"|) c #91AFC2",
+"1) c #B6DCE9",
+"2) c #90ADC0",
+"3) c #B0D4E0",
+"4) c #485579",
+"5) c #616483",
+"6) c #F4F4F4",
+"7) c #E5E8EB",
+"8) c #787B96",
+"9) c #AEB2C0",
+"0) c #EAEAED",
+"a) c #E4E6EB",
+"b) c #C0C1CC",
+"c) c #1F234F",
+"d) c #F2F2F4",
+"e) c #80829C",
+"f) c #E1E3E8",
+"g) c #AAACBB",
+"h) c #43466D",
+"i) c #F1F2F2",
+"j) c #D3D4DB",
+"k) c #C5C6D0",
+"l) c #505378",
+"m) c #BDBECB",
+"n) c #C7C9D4",
+"o) c #7D8198",
+"p) c #E3E4E9",
+"q) c #EFEFF0",
+"r) c #84889F",
+"s) c #F7F8F9",
+"t) c #C5C5D0",
+"u) c #676A88",
+"v) c #727691",
+"w) c #B1B1C0",
+"x) c #C4C6D1",
+"y) c #C3C5CE",
+"z) c #D3D4DC",
+"A) c #D8DAE0",
+"B) c #717093",
+"C) c #FAF9FB",
+"D) c #787696",
+"E) c #333563",
+"F) c #535579",
+"G) c #F1F0F2",
+"H) c #CECAD8",
+"I) c #4F4E76",
+"J) c #3D4870",
+"K) c #506082",
+"L) c #434F74",
+"M) c #2F3A62",
+"N) c #566689",
+"O) c #4C5B7F",
+"P) c #222854",
+"Q) c #404D73",
+"R) c #5D6E8F",
+"S) c #333C65",
+"T) c #3C3F67",
+"U) c #6E728F",
+"V) c #6A6C8B",
+"W) c #30345E",
+"X) c #646886",
+"Y) c #6A6D8B",
+"Z) c #535777",
+"`) c #44486D",
+" ! c #3F416B",
+".! c #525579",
+"+! c #4D5175",
+"@! c #484B71",
+"#! c #6F728F",
+"$! c #626584",
+"%! c #5F6282",
+"&! c #31345F",
+"*! c #242953",
+"=! c #5E6281",
+"-! c #2E305C",
+";! c #5E6280",
+">! c #31355D",
+",! c #727491",
+"'! c #41466B",
+")! c #505474",
+"!! c #45496E",
+"~! c #252854",
+"{! c #686A89",
+"]! c #696C8A",
+"^! c #353962",
+"/! c #CBC7D6",
+"(! c #F0EFF4",
+"_! c #C9C9D4",
+":! c #ABA7BF",
+"<! c #6C698D",
+"[! c #3C3D6A",
+"}! c #AFAAC0",
+"|! c #E5E4EB",
+"1! c #595C7E",
+"2! c #CCC8D8",
+"3! c #918DA9",
+"4! c #56557D",
+"5! c #1D2353",
+"6! c #1A1F4E",
+"7! c #282A59",
+"8! c #1E2353",
+"9! c #515179",
+"0! c #8D88A6",
+"a! c #CECBD9",
+"b! c #A7A4B9",
+"c! c #454570",
+"d! c #C0C1CD",
+"e! c #B6B0C5",
+"f! c #7A7597",
+"g! c #292C58",
+"h! c #2B2E5A",
+"i! c #737093",
+"j! c #B1ACC2",
+"k! c #E4E2EB",
+"l! c #E4E3EA",
+"m! c #6A688D",
+"n! c #D5D2DF",
+"o! c #A29DB6",
+"p! c #646187",
+"q! c #222857",
+"r! c #1A1D4D",
+"s! c #1B1D4F",
+"t! c #232652",
+"u! c #383B66",
+"v! c #9B97B0",
+"w! c #D2CEDC",
+"x! c #4D4D76",
+"y! c #A2A4B7",
+"z! c #928DA9",
+"A! c #353764",
+"B! c #232555",
+"C! c #1A1D4E",
+"D! c #2C305C",
+"E! c #323461",
+"F! c #595981",
+"G! c #908CA8",
+"H! c #EAE9ED",
+"I! c #817D9C",
+"J! c #3B3C69",
+"K! c #E7E4EC",
+"L! c #BFBBCD",
+"M! c #53527B",
+"N! c #343665",
+"O! c #1A204D",
+"P! c #181B48",
+"Q! c #272958",
+"R! c #1B1F4C",
+"S! c #2F3361",
+"T! c #8683A1",
+"U! c #BEB9CB",
+"V! c #E5E3EA",
+"W! c #F9F7FA",
+"X! c #D1CFDB",
+"Y! c #E9E8ED",
+"Z! c #E0DDE8",
+"`! c #B4B0C5",
+" ~ c #807C9D",
+".~ c #232554",
+"+~ c #1B1D4B",
+"@~ c #393D68",
+"#~ c #343663",
+"$~ c #4C4D76",
+"%~ c #7B7798",
+"&~ c #B6B2C6",
+"*~ c #B3B1C2",
+"=~ c #272C5B",
+"-~ c #57597C",
+";~ c #EDECF1",
+">~ c #DCD9E1",
+",~ c #B3AEC5",
+"'~ c #837F9E",
+")~ c #313462",
+"!~ c #1C2151",
+"~~ c #252A57",
+"{~ c #212656",
+"]~ c #5A5A82",
+"^~ c #B2ADC3",
+"/~ c #A7A4BA",
+"(~ c #686A88",
+"_~ c #F0EFF5",
+":~ c #BBB7CA",
+"<~ c #8884A3",
+"[~ c #282B5A",
+"}~ c #232958",
+"|~ c #373A66",
+"1~ c #8682A0",
+"2~ c #DCD9E2",
+"3~ c #F5F3F6",
+"4~ c #F4F3F6",
+"5~ c #8F8CA7",
+"6~ c #727591",
+"7~ c #E2DFE7",
+"8~ c #BDBACD",
+"9~ c #626086",
+"0~ c #41426D",
+"a~ c #252A58",
+"b~ c #1D1F4F",
+"c~ c #3F406C",
+"d~ c #616086",
+"e~ c #9490AB",
+"f~ c #E8E8ED",
+"g~ c #5E6080",
+"h~ c #9D98B4",
+"i~ c #323561",
+"j~ c #6D6A8E",
+"k~ c #C5C1D1",
+"l~ c #E4E1E9",
+"m~ c #8987A4",
+"n~ c #494973",
+"o~ c #4C4F74",
+"p~ c #E9E6EE",
+"q~ c #ADA8BF",
+"r~ c #7F7B9B",
+"s~ c #636088",
+"t~ c #40406D",
+"u~ c #212655",
+"v~ c #1B224F",
+"w~ c #202454",
+"x~ c #3D3F6C",
+"y~ c #807D9C",
+"z~ c #A8A3BB",
+"A~ c #CFCBDA",
+"B~ c #E8E7ED",
+"C~ c #FDFCFD",
+"D~ c #9E9BB3",
+"E~ c #504F78",
+"F~ c #B8B8C8",
+"G~ c #E1DEE8",
+"H~ c #A09BB4",
+"I~ c #57577F",
+"J~ c #2C305F",
+"K~ c #242655",
+"L~ c #292D5A",
+"M~ c #232757",
+"N~ c #747193",
+"O~ c #9B97B2",
+"P~ c #A29FB6",
+"Q~ c #787A95",
+"R~ c #EBEBEF",
+"S~ c #D3D0DC",
+"T~ c #9490AC",
+"U~ c #6E6B8E",
+"V~ c #2F325F",
+"W~ c #2D315D",
+"X~ c #1F2454",
+"Y~ c #908CA9",
+"Z~ c #D2CFDB",
+"`~ c #BAB8C8",
+" { c #3D3F69",
+".{ c #353961",
+"+{ c #C5C5D1",
+"@{ c #E5E1EB",
+"#{ c #CECAD9",
+"${ c #8F8BA9",
+"%{ c #716F91",
+"&{ c #303461",
+"*{ c #41436D",
+"={ c #55557B",
+"-{ c #6E6C8F",
+";{ c #AFABC1",
+">{ c #D8D6DF",
+",{ c #8B88A6",
+"'{ c #4C4C78",
+"){ c #6E708E",
+"!{ c #CBCAD6",
+"~{ c #E1DDE9",
+"{{ c #CDC9D8",
+"]{ c #9994AF",
+"^{ c #7C779A",
+"/{ c #5D5B82",
+"({ c #1B2251",
+"_{ c #303462",
+":{ c #2E325F",
+"<{ c #4E4E76",
+"[{ c #9893AE",
+"}{ c #CCC8D7",
+"|{ c #B5B2C5",
+"1{ c #6E6C8E",
+"2{ c #5A5D7F",
+"3{ c #E8E6EC",
+"4{ c #ACA8BF",
+"5{ c #9691AE",
+"6{ c #8581A0",
+"7{ c #68668A",
+"8{ c #57577D",
+"9{ c #2A2D5D",
+"0{ c #242757",
+"a{ c #323662",
+"b{ c #242957",
+"c{ c #1D2252",
+"d{ c #494B73",
+"e{ c #616186",
+"f{ c #717091",
+"g{ c #7E7B9A",
+"h{ c #E7E4EB",
+"i{ c #E1E0E8",
+"j{ c #9A96B2",
+"k{ c #5F5F83",
+"l{ c #393C67",
+"m{ c #5D5F80",
+"n{ c #BBBCCB",
+"o{ c #EDEAF0",
+"p{ c #D3CFDD",
+"q{ c #C2BED0",
+"r{ c #767395",
+"s{ c #66658A",
+"t{ c #5A5A80",
+"u{ c #474872",
+"v{ c #40416E",
+"w{ c #464872",
+"x{ c #363965",
+"y{ c #42446F",
+"z{ c #2F3360",
+"A{ c #41426E",
+"B{ c #474873",
+"C{ c #4F5078",
+"D{ c #9993AF",
+"E{ c #AFAAC2",
+"F{ c #C4C0D2",
+"G{ c #D3CFDC",
+"H{ c #E0DDE7",
+"I{ c #D0CDD9",
+"J{ c #85819F",
+"K{ c #9797AF",
+"L{ c #EBE9F0",
+"M{ c #BBB6C9",
+"N{ c #ADA7C0",
+"O{ c #9F99B4",
+"P{ c #928DAB",
+"Q{ c #7B7899",
+"R{ c #737193",
+"S{ c #6D6A8D",
+"T{ c #6A668B",
+"U{ c #7A7798",
+"V{ c #5D5D83",
+"W{ c #5C5C82",
+"X{ c #5E5E83",
+"Y{ c #626287",
+"Z{ c #68658A",
+"`{ c #7B7898",
+" ] c #918CAA",
+".] c #9E99B4",
+"+] c #ADA9C0",
+"@] c #C9C5D6",
+"#] c #ECEBF2",
+"$] c #CDCBD7",
+"%] c #9795AE",
+"&] c #636186",
+"*] c #4F5374",
+"=] c #85879F",
+"-] c #BABAC9",
+";] c #E9EAEE",
+">] c #EBE9EE",
+",] c #D5D2DE",
+"'] c #C5C1D2",
+")] c #BEBACD",
+"!] c #B6B2C7",
+"~] c #AFAABF",
+"{] c #AAA6BD",
+"]] c #A8A4BC",
+"^] c #A9A5BC",
+"/] c #AAA7BD",
+"(] c #BDBACC",
+"_] c #CDC9D7",
+":] c #E5E3E9",
+"<] c #ECEBEF",
+"[] c #FBFCFD",
+"}] c #A8A5B9",
+"|] c #757393",
+"1] c #4E5075",
+"2] c #85869E",
+"3] c #B5B5C5",
+"4] c #E7E6EB",
+"5] c #E5E3EB",
+"6] c #E3E1E8",
+"7] c #E3E2E8",
+"8] c #E6E4EA",
+"9] c #EBE8EE",
+"0] c #B8B8B9",
+"a] c #999999",
+"b] c #A9A9A9",
+"c] c #929292",
+"d] c #7F7F80",
+"e] c #BEA6AC",
+"f] c #DD748B",
+"g] c #ECB0C5",
+"h] c #D95E7D",
+"i] c #F8E9F0",
+"j] c #EEEEF2",
+"k] c #C8C6D2",
+"l] c #938FA9",
+"m] c #6B698D",
+"n] c #3E406A",
+"o] c #484C71",
+"p] c #80839C",
+"q] c #9698AE",
+"r] c #AAABBE",
+"s] c #B6B8C6",
+"t] c #C0C0CD",
+"u] c #C5C5D2",
+"v] c #C8C8D4",
+"w] c #C7C7D4",
+"x] c #C2C2D1",
+"y] c #BABBCB",
+"z] c #AFB1C1",
+"A] c #A2A4B9",
+"B] c #9495AD",
+"C] c #8E8EA8",
+"D] c #AFAEC2",
+"E] c #BFBFC0",
+"F] c #404040",
+"G] c #848484",
+"H] c #7D7D7D",
+"I] c #A8888D",
+"J] c #D3445F",
+"K] c #DD7F93",
+"L] c #CD2148",
+"M] c #F8E2EB",
+"N] c #E7E6EC",
+"O] c #C9C7D5",
+"P] c #A09DB5",
+"Q] c #777495",
+"R] c #5F5E83",
+"S] c #262B59",
+"T] c #1B2050",
+"U] c #1C2350",
+"V] c #616184",
+"W] c #9A99B2",
+"X] c #C5C4D1",
+"Y] c #626262",
+"Z] c #8B8B8C",
+"`] c #949494",
+" ^ c #ABABAC",
+".^ c #969696",
+"+^ c #DBDBDC",
+"@^ c #575758",
+"#^ c #727272",
+"$^ c #DFDFDF",
+"%^ c #868686",
+"&^ c #909090",
+"*^ c #E6E6E6",
+"=^ c #AAAAAB",
+"-^ c #B4B4B4",
+";^ c #555555",
+">^ c #B1B1B2",
+",^ c #7F7F7F",
+"'^ c #B1B1B1",
+")^ c #AEAEAF",
+"!^ c #CBC9D8",
+"~^ c #AFACC1",
+"{^ c #8E8CA8",
+"]^ c #767495",
+"^^ c #4F5079",
+"/^ c #333662",
+"(^ c #57557F",
+"_^ c #606084",
+":^ c #717191",
+"<^ c #9090A9",
+"[^ c #CDCCD7",
+"}^ c #676768",
+"|^ c #8E8E8F",
+"1^ c #F2F2F3",
+"2^ c #CDCDCD",
+"3^ c #A8A8A9",
+"4^ c #424242",
+"5^ c #F4F4F5",
+"6^ c #353535",
+"7^ c #363636",
+"8^ c #EEEEEE",
+"9^ c #B5B5B5",
+"0^ c #5B5B5B",
+"a^ c #B4B4B5",
+"b^ c #323232",
+"c^ c #777777",
+"d^ c #C4C4C5",
+"e^ c #A6A6A6",
+"f^ c #656565",
+"g^ c #F7F6F8",
+"h^ c #C9C6D5",
+"i^ c #A19EB6",
+"j^ c #9794AF",
+"k^ c #908EAA",
+"l^ c #8D8AA7",
+"m^ c #8B88A5",
+"n^ c #9390AB",
+"o^ c #9B98B1",
+"p^ c #A5A3B9",
+"q^ c #B2AFC3",
+"r^ c #C4C4C4",
+"s^ c #464646",
+"t^ c #A4A4A5",
+"u^ c #3A3A3A",
+"v^ c #C3C3C4",
+"w^ c #434343",
+"x^ c #383838",
+"y^ c #A8A8A8",
+"z^ c #666667",
+"A^ c #818181",
+"B^ c #B6B6B7",
+"C^ c #2F2F2F",
+"D^ c #797979",
+"E^ c #AAAAAA",
+"F^ c #2D2D2D",
+"G^ c #D9D9DA",
+"H^ c #636364",
+"I^ c #C1C1C1",
+"J^ c #A0A0A0",
+"K^ c #BEBEBF",
+"L^ c #DDDDDE",
+"M^ c #B0B0B0",
+"N^ c #C6C6C7",
+"O^ c #888888",
+"P^ c #D1D1D1",
+"Q^ c #9A9A9A",
+"R^ c #F5F5F5",
+"S^ c #D4D4D4",
+"T^ c #ADADAD",
+"U^ c #BDBDBE",
+"V^ c #ABABAB",
+"W^ c #8B8B8B",
+"X^ c #B9B9BA",
+"Y^ c #A2A2A2",
+"Z^ c #C7C7C7",
+"`^ c #EAEAEA",
+". + . + . . + . + . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ",
+". + + + . . + + + . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ",
+"+ . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ",
+"+ + + + + + @ + @ @ @ @ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ @ @ @ @ @ @ @ # @ @ # @ @ @ @ # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ . + @ @ @ @ + @ @ @ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ % & * = - ; > , ' ) ! , ~ { ] ^ / ( _ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : @ : @ : : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + < [ } | 1 2 3 4 5 6 7 8 9 0 a b c 0 d e 7 f g h i j k l m n o + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ : @ @ @ @ @ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + + + + p q r s t u v 7 w x y z A B C D E F E E E G H D I B J K L M N O 6 P Q > R S p T + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : $ @ $ : : : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + @ @ # U V W X Y Z ` ...+. at .#.$.$.%.%.%.&.&.*.=.%.%.%.=.-.;.>.,.'.$.).!.~.{.].^./.(._.:.<.[.}.@ @ + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ + + + @ + @ @ $ $ $ $ $ $ $ $ $ $ $ $ + + + @ @ |.1.2.3.4.5.6.7.8.9.0.a.b.c.*.d.&.*.&.*.c.b.-.a.%.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.@ + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ $ $ $ @ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ B.C.X D.E.z D F.G.>.*.&.*.H.H.H.H.c.c.*.*.&.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.X.Y.U.Z.`. +.+++ at +#+R $+U %++ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : @ @ @ : : @ @ $ $ $ $ $ $ $ $ $ $ @ + @ &+*+=+-+;+>+,+'+;.%.c.*.c.*.*.H.H.*.*.*.a.)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+2+3+4+5+6+7+8+9+}+0+a+b+c+d+e+f+g+h+% # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ + @ @ @ @ $ $ $ $ $ $ $ $ $ + # @+i+j+k+l+I m+>.c.*.*.*.*.*.c.c.&.*.*.&.n+o+p+q+++S.r+:+s+t+u+v+w+X x+y+z+A+B+C+D+6 E+F+G+H+z+I+J+X K+v+L+M+N+O+P+e+Q+R+S+# @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ $ : @ $ : : : @ $ $ $ $ $ $ + + + o T+U+V+M W+m+>.c.&.*.*.c.c.c.c.*.&.*.c.X+Y+Z+`+e+ @. at +@@@#@$@%@v &@*@=@N -@;@>@,@'@l+)@!@~@{@]@^@/@(@_@:@_.H+<@X [@}@|@. at 1@2 at 3@4@< @ + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + + : + @ + + @ + @ $ $ $ $ $ @ @ < 5 at 6@7 at 8@J 8.$.c.*.*.c.c.c.c.*.*.*.*.9 at 0@a at b@c at d@e at f@3+g at h@i at j@0 k@]@l at m@n at o@p at q@F 8.F r@@.F. at .s@t at u@~.v at B m@ .w at x@=@y at z@A at w+B@C at D@E at F@G at H@< + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ : $ $ @ $ $ $ $ $ @ # I at J@_.l++.9.%.*.*.c.c.c.c.c.c.*.*.b.K at L@m M at N@O at P@Q at R@S at T@U at V@ .W at X@t at Y@F.#.Z@`@ #'.'.'..#+#>.;.;.0.0.0.G.@###Y at +.$#%#&#V@*#=#-#;#>#,#'#)#!#~#{#@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ . + @ : : @ @ : : @ @ $ $ $ $ ]#o ^#/#(#_#:#a.*.*.*.c.c.c.c.c.c.*.=.<#[#}#++|#'#1#2#3#4#5#6#]@v at s@7##.8#;.a.b.9#X+c.*.c.*.*.-.0#a#*.*.*.*.c.*.=.c.b#c#!.#.7#d#v at A y e#f#g#h#i#j#k#^+l#< @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ + @ @ @ @ $ $ @ + % m#n#` v@'+&.*.*.c.c.c.c.c.c.*.*.*.o#p#q#r#s#t#u#v#w#x#y#z#A#B#'+;.c.*.*.*.*.C#D#*.*.H.H.H.*.*.%.E#F#&.*.*.*.%.G#H#I#=.*.b.a.0.'+F.G ..J#K#L#M#N#O#. at P#Q#R## + + @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : $ : : : @ $ + + S#T#U#V#F >.*.*.c.c.c.c.c.c.*.*.*.=.W#X#Y#Z#`# $.$_.+$@$#$E .$$%.*.*.H.&.*.*.%$&$&.*.H.H.H.H.H.c.b.9#*$*.*.a.=$c#-$*.*.*.*.*.*.*.*.%.>.#.;$>$,$E.'$)$!$~${$]$S @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + + $ $ + + @ + @ @ + + ^$/$($_$8.>.*.*.c.c.c.c.c.c.*.*.*.%.:$<$[$.@}$|$1$N 2$v@@.3$4$5$c.*.H.H.H.*.*.D#6$*.b.H.H.H.H.H.H.c.*.c.7$=$8$X+9$%.*.*.H.H.H.H.H.H.H.H.c.=.0.'+ at .v@0$a$6 b$c$d$e$f$< @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ $ $ $ @ + g$h$i$2$,+;.*.c.c.c.c.c.c.c.c.*.*.'.j$]+k$l$m$%@7 n$o$s@'+0.'.p$=.*.H.H.H.H.*.q$r$%.H.H.H.H.H.H.H.H.*.c.a.s$t$u$%.&.*.H.H.H.H.H.H.H.H.H.H.H.&.9@*.>.3$s at W+A#v$w$x$y$z$A${#@ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : @ : : : @ @ p B$C$~@,+;.*.c.c.c.c.c.c.c.c.*.*.I.D$3 at E$F$G$H$I$J$K$L${.%.%.n at M$9@*.H.*.*.*.N$5$b.&.H.H.H.H.H.H.9@*.=.O$P$Q$P$>.b.&.*.H.H.H.H.H.H.H.H.H.H.H.&.&.*.*.%.>.#.H z R$S$T$}+U$V${#@ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ + @ @ @ @ W$X$Y$Z$>.*.*.c.c.c.c.c.c.c.*.*.-.`$ %.%+%@%f #%A $%'+'.=.%%&%8$-.c.c.*.*.%.P$=$9@*.H.H.H.H.H.*.*.*.a.u$*%=%a.-%;%-.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.&.*.*.%.'+s at W@;@>%,%|+'%)%!%@ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : $ : + # ~%{%R$+.>.*.*.c.c.c.c.c.c.*.*.*.b.]%^%/%(%$@_%]@:%F.n+c.c.*.I.<%[%}%*.*.=.s$|%1%*.*.H.H.H.H.&.*.*.=.N$D#2%b.*.*.*.3%%.*.&.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.*.*.*.;.m+v at 4%5%6%7%/%N.{#+ @ @ @ @ @ @ @ + + + + ",
+"+ . + @ $ @ @ + @ + 8%9%0%..>.d.*.c.c.c.c.c.c.c.*.*.F#a%b%c%d%e%f%g%7.B#,+%.*.*.<#h%%.%.i%j%%.k%l%%.*.*.H.H.H.H.&.*.c.-$m%=$*.*.*.H.H.*.n%o%&.*.H.H.H.H.H.H.H.H.H.H.H.H.&.*.*.*.*.&.p%9#q%r%s%#%t%u%v%c%w%%+@ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ + # x%Y ,$F.=.*.*.c.c.c.c.c.c.c.*.*.y%z%A%+ at B%f%^@D #.;.C%&.*.&.=%D%*.*.=.E%F%&%=.*.c.c.H.H.H.H.G%9#`@9#c.*.*.H.H.H.H.&.c.H%-.*.H.H.H.H.H.H.H.H.H.H.H.H.&.&.=.I%J%P$;%I%=.%.K%L%A#M%N%O%P%Q%%++ @ @ @ @ @ + + + + ",
+". . + @ : : @ : @ R%S%T%E >.*.*.*.c.c.c.c.c.c.c.&.D%U%V%W%X%Y%^@W at G.%.%.1%c.*.%.Z%9@&.*.<#a#`%p%c.c.c.c.H.b.*. &.&+&*.c.*.*.*.H.H.H.H.H.*.&$@&*.H.H.H.H.H.H.H.*.a.%.%.#&$&%&&&*&=&d.&.*.*.&.%.$#X at V@-&;&>&,&'&@ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ + )&!&~&B >.c.*.c.c.c.c.c.c.c.c.c.*.{&]&^&/&(&/@:%_&%.*.1%c.*.*. #b.&.*.*.n+-%-.&%=.*.H.*.*.-%;%*&*.c.*.*.H.H.H.H.H.H.H.H.*.I.:&&.*.H.*.&.b.b.<&-$.&X+N$[&*.a.c.*.*.*.*.*.&.*.-.}&:#C |&1$1&2&3@< @ @ @ @ @ + + + + ",
+". . + @ : : @ + 3&4&M ,+%.*.c.c.c.c.c.c.c.c.c.b.n%5&d+6&R at 7&8&@.'+*.&.9&*.*.0&>.&.&.&.a&n+*.-.1%b&*.*.I.c&-$%.*.*.*.H.H.H.H.H.H.H.H.H.H.*.b.%&&.*.c.*.6$X+X+d&e&a.c.*.*.*.*.*.&.H.H.H.H.H.*.a.H%>.F.A f&g&h&i&S#%+@ @ @ @ + + + + ",
+"+ + + @ $ + + + j&k&_#G.&.c.c.c.c.c.c.c.c.c.c.&.l&m&n&o&p&l+d#8#%.*.;.;.*.%.G.*.*.*. #1%*.*.*.=.b&D%&%[%=.*.*.H.H.H.H.H.H.H.H.H.*.*.c.*.*.*.P$q&H#r&u$s&&.*.*.*.*.c.&.H.H.H.H.H.H.H.H.H.H.*.c.P$t&u&d#l+'$v&w&f+U @ @ @ @ + + + + ",
+". . + + $ $ @ x&y&z&,+%.*.c.c.c.c.c.c.c.c.c.c.e&X#U.A&B&C&B B#%.c.c.D&*.9 at E&%.c.%.@#0&*.H.H.c.%.F&G&I.*.*.H.H.H.H.H.H.H.H.H.H.H.*.*.j%H&9#d&%&3%=.*.*.9@*.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.*..#9$%.B#W+I&g#J&K&h+%++ @ @ + + + + ",
+"+ . + @ : @ @ L&M& .G.*.c.c.c.c.c.c.c.c.c.c.c.N&O&P&Q&R&2$,+>.9@*.c.c.*.c.D&c.-.E&%.c.*.*.<#F%S&'.I%k%*.c.H.H.H.H.H.H.&.&.a.=.T&X+X+U&@&-.=.&.J%*.*.*.*.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.c.I.l@*.>._&`%=#V&W&X&< @ @ @ + + + + ",
+"+ + + @ @ @ @ Y&Z&C >.c.c.c.c.c.c.c.c.c.c.c.a.`& *F$.*R$+*#.%.*.*.*.*.c.*.*.*.G.c.c.*.*.1%Z%'.&.*.=.%%&.&.H.H.H.c.&.%.@*d&#*d&5$&.*.%.&.*.*.=.*&c.*.H.H.H.&.-.&.*.*.H.H.H.H.H.H.H.H.H.H.H.H.*.-.$**.%.#.I %*&***=*S @ @ @ + + + + ",
+". + + @ : @ -*T$R$t@%.*.c.c.c.c.c.c.c.c.c.c.;*>*,*'*)*!*G >.c.~*{*]*^*c.*.c.c.c.d.*.%./*>.-.(*_*:*<*i%a.&.b.b.[*>+D#D#}*=.-.*.*.*.&.*.&.H.*.-.u$a.*.&.&.*.%.|*1**.*.H.H.H.H.H.H.H.H.H.H.H.H.&.-.H#*.c.>.t@}&g 2*3*f$# @ @ + + + + ",
+"+ + + @ + # 4*5*y #.*.*.c.c.c.c.c.c.c.c.c.b.6*7*. at 8*9*m at m+0*a*b*c*d*e*&.c.c.&.&.%.>.;.-.c.f*g*h*i*j*k*i%K%F&l*m*'.-.b.*.&.&.d.c.&.*.&.&.c.&.*.n*b.d.o*p*=%+&q*r*9@&.b.b.*.&.b.b.&.&.&.b.&.&.&.=.H#*.*.c.s*z#8 t*'#u*p @ @ + + + + ",
+". . + + + @ v*w*x*G.y*H.c.c.c.c.c.c.c.c.c.&.z*A*B*C*R$C u&D*E*F*a.G*j%v at H*I*J*D&K*L*M*N*O*P*Q*R*2%Z@*%S*T*U*,.V*W*X*Y*Z*`* =.=+=@=I.#=T*$==.;*%=&=*===-=;=J.>=,='=)=!=~={=]=^=/=(=a._=:=<=D&&.c.H#*.H.c.$.[=e#}=|=e+1=@ @ + + + + ",
+"+ + + + $ # 2=3=B %.y*H.c.c.c.c.c.c.c.c.c.%.4=e$5=6=7=E 8=9=0='.a=b=c=d=e=f=g=h=i=j=g=k='=l=m=0&=.0&n=o=p=q=r=s=t=u=v=w=x=y=:=z=A=B=C=D=_ E=F=G=H=I=J=K=L=M=N=O=P=Q=R=S=T=% U=V=W=X=Y=Z=`=&.&.*.H#*.H.*.8#E -.-+- at -R#@ @ + + + + ",
+"+ + + @ + @ #-w#C %.y*H.c.c.c.c.c.c.c.c.c.,.$-%-&-*-{@,+=---;->-,-'-)-!-~-{-]-^-/-a.(-_-:-q <-%.F#[-% }-|-1-2-3-4-5-6-7-8-9--.0-a-b-c-d-e-f-g-h-i-a.j-k-l-m-n-o-p-t&q-b-r-q s-t-i*u-v-w-x-*.*.=.H#c.c.&.;.,+!*y-z-)#A-@ @ + + + + ",
+". . + @ @ # B-k++.=.b.H.c.c.c.c.c.c.c.c.c.F#C-)#5+G+0$@.D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z-`- ;@+.;+;@;#;q $;%;&;y%v=*;=;-;#;;;>;,;';);8$!;~;%.{;];^;/;;*(;_;a@:;=&<;[;l@};|;1;a.*.-.l at 2;*.&.;.m+3;4;5;6;7;@ + + + + + ",
+"+ + + @ @ # 8;9;+.=.c.H.c.c.c.c.c.c.c.c.c.=.0;a;b;c;d;B#D&e;f;g;h;i;h%j;k;l;m;n;o;p;q;r;'.s;t;u;v;w;x;=;%;y;z;A-A;B;C;D;_ 6*E;+;}*F;S#G;H;);I;J;K;K$L;M;N;h*O;P;Q;R;S;T;U;V;+#W;X;Y;Z;& `;^* & >.>0&<&=.'.C%+>@>#>3*7;< + + + + + ",
+". . + @ + # $>%>+.%.&>H.c.c.c.c.c.c.c.c.c.*.*>=>->c; .##%.-.E&;>>>a.a.E&,>'>)>&.!>~>;.0.;.{>I%]>^> #/>(>o%8$m*o#m*_>l*S&:>.#-$<>b&b&[>}>|>b&-$1>{@h%2>3>i%4>5>G##*6>K$%%D#7>%%8>&%H&9>;%0>0>.#.#]@5$a#n+-%~.r at -&a>3*4@< @ + + + + ",
+"+ + + + $ @ b>c>D %.y*H.c.c.c.c.c.c.c.c.c.&.d>)#3+e>+>F.D&&.*.*.&.*.*.*.*.;.f>F#a.*.=.g>h>%.*.*.*.&.*.b&a.a.0>F%*.*.*.*.*.&.*.&.*.*.*.*.*.*.*.5$b#*.c.*.*.&.&.*.*.&.i>j>&.c.&.*.&.*.*.*.*.b.&.9@$*c.*.*.;.F.~@k>l>m>4@@ @ + + + + ",
+". . + @ + + n>o>W+D&*.H.c.c.c.c.c.c.c.c.c.b.p>P%q>r>A#s@'.*.c.c.c.*.-.s>t>u>v>w>x>D&m+y>z>=.*.*.*.*.*.i%A>B>C>D>E>-.*.*.*.*.*.*.*.*.*.*.*.&.*.6$m**.&.*.*.*.*.*.*.b&F>G>*.*.&.*.*.*.*.*.*.*.*.*.H#*.*.*.'. at .J$H>3+)#I>@ @ + + + + ",
+". . + @ @ # E$J>A >.*.H.c.c.c.c.c.c.c.c.c.c.K>`.L>M>N>+.0.*.c.c.c.*.'.O>P>Q>R>S>f>'.T>U>V> #<%W>X>'>a.Y>Z>`> ,.,=%T-+,@,%.j%#;<*#,$,a.%,$;&,o+7>n%*,=,-,;,>,o#,,',),!,-%C#~,{,4>&.],^,/,(,a.+&_,|*:,&.*.>.G /@<,7%[,-*@ @ + + + + ",
+"+ + + @ @ @ },|,3;G.*.&.c.c.c.c.c.c.c.c.c.c.1,2,3,4,5,W+'+%.c.c.c.*.6,7,8,9,0,a,v at b,c,d,e,f,g,h,i,j,!>k,l,D&*.*.m,& n,o,p,q,U r,&+s,%.t,u,v,w,x,y,z,A,B,T=C,Y+D,E,:$F,G,3-H,I,J,j%K,L,M,N,O,P,Q,R,S,d.%.9.C T,U,V,W,H@@ @ + + + + ",
+". . + @ : @ X,Y,#%@.=.*.c.c.c.c.c.c.c.c.c.c.Z,`,2& '.'6. at .'.c.c.c.*.+'@'#'$'%'&'*'g;='-';'>',''')'v>!'o,~'9#S&@&{']'{>^'/'('Z-_':'v,<'['}'!+|'|*1'2'3'4'5'6'v;7'0&x=8'9'0'a'b'Z-c'd'e'f'g'h'i'j'k',.*.a.l'A m'w+n&n'@ @ @ + + + + ",
+". + + + + $ @ o'p'7.%.*.c.c.c.c.c.c.c.c.c.c.9#q'r's't'J$+.E&c.c.c.*.u'v'w'b.x'y'z'A'B'C'D'E'F'a.G'H'[%8'I'8$0.J'K'L'.&Q,M'N'O'j%P'Q'R'U S'T'U'V'W'X'#=Y'Z'G=`'B;,. ).)+)@)'.#)v-$)g$%)&)*)^*=)-)0';)*.0.E >)v ,)')))@ @ @ + + + + ",
+". . + @ : : @ !)-#6.$.b.c.c.c.c.c.c.c.c.c.c.b.~)2 at C@{)(#o$#.c.*.*.*.])^)/)()_):)<)[)})|)8,8,1)2)3)4)9#5)6)7)Q*8)9)0)K=a)E=V;b)c)d)e){,f)D%g)P'h)i)j)k)l)m)n)o)p)-$q)r)o+s)t)['u)v)U-7>w)x)A;y)z)A)k*%.#.W+R$B)|=`.C)@ @ @ + + + + ",
+". + + @ : : @ b%D)E)F.*.*.c.c.c.c.c.c.c.c.c.&.F)G)H)T$I)}&!.>.2;*.*.a.I.J)K)L)K$G.M)N)O)P)F#Q)R)S)i%=.a.T)U)V)W)I#X)Y);)*.Z)`)l at Y) !%,.!-.+!@!*%h'#!$!a'%!&!*!=!-!;!>!c.%),!'!'.,,r-%.)!!!~!{!]!^!=.E&,+!@-+m$/!(!%+@ + @ + + + + ",
+"+ + + @ @ @ @ p *+_%:%0.*.c.c.c.c.c.c.c.c.c.b.}%_!Z.:!<![!W@#.>.c.9 at c.&.a.E&a.-.=.1%>.=.*.=.=.I.b&m@'.b.-.-.b.c.&.*.*.&.*.c.=.b.&.=.=$l%l%6$H%;%F#=.*.b.<#b.%.*.=.c.*.&.-.*.=.b.&.*.c.c.b.-.*.J'b#'.#.B 5,B&}!i&A-@ @ @ @ + + + + ",
+". . + @ : : : + |!A at r@l'%.c.c.c.c.c.c.c.c.c.c.&.1!O&2!3!4!V at 5!G.'.*.'.a.c.%.>.*.&.b.6!D%*.c.H.&.G#I.~*K$=.*.H.H.H.H.H.H.H.H.H.H.H.H.*.&.&.a.*%b#P$7!D#@&*.-.-.*.H.H.H.H.H.H.H.H.H.H.H.H.H.*.*.`@1%8#8!]@9!0!a!O&< @ @ @ @ + + + + ",
+"+ + + + $ $ + + U b!c!K%>.*.c.c.c.c.c.c.c.c.c.b.j%d!r#e!f!O G&@.'+*.=.E&*.*.G.'.&.*.*.-%s$*.*.^*C#*.-.=%].I#c.*.c.H.H.H.H.H.H.H.H.H.*.*.*.=.g!a.-.b.0&u$X+X+:>O*c.&.=.*.H.H.H.H.H.H.H.H.H.*.&.h!E&@.z 4.i!j!k!A-@ @ @ @ @ + + + + ",
+". . + + $ $ $ + @ l!m!$#F.c.b.c.c.c.c.c.c.c.c.&.*.Y-N.n!o!p!E.q!s@>.=.r!c.*.*. #c.*.*.*.n+Z%I.E%&.*.*.*.%.5$X+G#*.*.*.H.H.H.H.H.H.H.H.H.*.}%J%*.*.*.*.*.&.a.s!*$X+X+t!p%*.*.*.*.*.H.H.H.&.*.%.}&m+g>u!w$v!w!g+< + @ @ @ @ + + + + ",
+". . + @ : : @ : + p +%x!J @#&.c.c.c.c.c.c.c.c.c.H.D%y!]$/!z!g A!N-##;.>.G.*.*.%.Z%&.&.*.&.F%;%%.*.&.H.H.*.*.*.S&N$9#&.*.*.c.H.H.H.H.H.*.*.X+ &*.*.H.H.H.&.&.*.*.*.-.])B!6$P$U&r$<#*.*.*.*.c.C!D!s>E!F!G!n&H!U + + @ @ @ @ + + + + ",
+"+ + + @ @ @ @ @ + @ u*I!J!X at 9&*.c.c.c.c.c.c.c.c.&.*.t!K,K!L!Q&M!N![%O!;.F.*.*.b.}%I.*.*.p%E%n+&&%.*.&.&.H.H.&.*.=.*&0#8$P!*.*.c.H.H.H.*.a.$**.*.H.H.H.H.H.H.H.H.H.*.*.*.*.*.0&b#$&Q!D#R!<#;.n at l+S!&@T!U!V!W!@ + @ @ @ @ @ + + + + ",
+". . + @ : : : $ : + p X!z@;+,+%.*.c.c.c.c.c.c.c.c.c.=.W#Y!Z!`! ~k&N>>$m+,+%.*.*.=.h%F#M$K$=.*.}%l**.&.&.H.H.H.H.*.c.c.9$:&j%c.&.H.H.H.*.6$.~c.*.H.H.H.H.H.H.H.H.H.H.H.H.H.H.&.=.=.*.+~l%n*+>@~#~$~%~&~Z!f$< + @ @ @ @ @ @ + + + + ",
+"+ + + + + $ @ + + + # H@*~t'=~F.=.*.c.c.c.c.c.c.c.c.c.c.-~;~>~,~'~9!)~W@!~8.=.c.*.D%n at i%=.&.*.*.s$~~%.*.*.H.H.H.*.*.c.=.I.q$*%I.&.*.*.d.3%=.*.&.H.H.H.H.H.H.H.H.H.H.H.H.H.H.&.*.*.*.=.9&7#{~=#]~2#^~z$n < @ @ @ @ @ @ @ @ + + + + ",
+". . + @ $ $ $ $ $ + + @ S /~x!G&F.a.*.c.c.c.c.c.c.c.c.*.&.(~_~U.:~<~H$*#[~}~#.>.^*K$i%r$9 at H.H.c.c.>.q%=%*.H.H.H.H.c.c.*.c.a.I.D#;%0&&.I%7>a.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.&.c.>.#.G ;%|~.-1~`#2~3~o @ + @ @ @ @ @ @ @ + + + + ",
+". + + @ : : @ : : : @ + @ 4~5~:@A #.%.*.c.c.c.c.c.c.c.c.*.%.6~]&7~8~>#9~0~M a~J v at a.*.>+<&*.b.H.*.*.%.P$b~*.H.H.H.H.H.c.c.*.*.a.}%*%o%J%a.&.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.&.*.c.G. at .C l+c~d~e~; U. at +< @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ @ @ @ @ @ + + f~1~t%a~6!%.*.*.c.c.c.c.c.c.c.c.*.g~*)[$'#h~e%p&U at m@+.##>.M$>+c.*.c.H.*.*.%.d&n%&.*.*.H.H.H.H.H.c.*.*.a.I#i~.~*.c.*.c.H.H.H.H.H.H.H.H.H.*.*.*.%.E&#.E J -f#j~,)k~l~R+U @ + @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : $ : : : @ $ @ @ e+m~n~a~8.;.c.c.c.c.c.c.c.c.*.*.=.o~R p~^&q~r~s~t~r at u~v~'+w~n%9 at c.H.H.H.*.&.#*m*=.*.H.H.H.H.H.H.H.*.c.H%0&i%:&.#%.*.H.H.H.H.H.H.H.H.H.&.%.0.#.v~B A#x~F!y~z~A~B~7;C~@ + @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + + + $ @ + + + + @ $ $ + # w%D~E~l+G G.c.c.c.c.c.c.c.*.*.*.=.X=F~z=G~j#H~4&I~U at J~8&+.2$6!0.%.*.H.*.c.d.G,D#a.b.H.H.H.H.H.*.c.K~6$=.b.c.5$L~9#-.*.H.H.H.&.*.%.>.'+ at .G M~A#a T at N~O~a+d+V$U @ + @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ $ $ $ $ $ $ $ @ $ $ + + # x&P~J>i~X at G.a.c.c.c.c.c.c.c.*.*.*.^*Q~R~ +S~~$T~U~D+a V~z W~s at O!$.0.%.&.*.d.5>&&&.*.H.H.H.*.&.{=H%&.*.*.*.a.=..~l@[*c.b.%.0.E&B#,+X~6.]@[!3=}=Y~F$Z~W,R+< @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". + + @ : @ @ : @ : : @ $ $ $ $ + # l#`~X$ {o$F.D&&.&.*.c.c.c.c.c.*.-.-..{+{`+@{#{}!${%{t'4%U@&{o$7.,+B#'+8#>.>.b#N$-.&.H.*.*.-.}&0&*.*.H.&.*.*.a.;.8>g!C%#.8.D n at 0$E)*{={-{Q@;{2!G~`+'&%+@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ @ @ @ @ @ $ $ $ $ $ + @ C~>{,{'{&#v@#.D&*.*.c.c.c.c.c.c.*.&. >){!{]&~{{{`!]{^{g#/{0~/@l+a~W+~.({F.6!#$0$l'8#9&'.u$4$>.>.9&8#8#G.#.B#F.E :%)~_{:{/@c~<{M&B%[{^~}{G~P.4@< @ + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : $ : : : @ $ $ $ $ $ $ $ $ $ x&|{1{O 3;+.#.>.*.c.c.c.c.c.c.c.c.*.D%2{{;`'3{U$a+4{5{6{7{8{w#x~A!]@9{;%_#0{a{X at u@b{A#E !.c{+.7.v at u~_#;%!@V at K#x~d{e{f{g{a>P@<+{$h{]+C)@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + + @ $ @ + @ @ + @ $ $ $ $ $ $ $ $ $ @ # i{j{k{l{n*+.9.%.*.*.c.c.c.c.c.c.*.*.}%m{n{A$o{Z.p{q{|+]{ 'r{s{t{p&u{v{(#*#w{x{y{z{V@, at Y$N>A!x#J!A{B{C{J>B&r{1~D{E{F{G{H{M at R+R#!%@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ $ $ : @ $ $ $ $ $ $ $ $ $ $ # @ u;I{J{I~e#z +.6!>.a.&.*.c.c.c.c.H.*.&.=.J.K{0- at +L{[,/%. at M{N{O{P{Q&Q{R{S{T{U{9~V{W{w*X{Y{Z{j~R{`{8* ].]+]y$@]/%P##]w%S#< @ @ @ @ @ @ @ @ @ + + + ]#]#@ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ . + + $ + + + + $ + @ $ $ $ $ $ $ $ $ $ $ $ $ @ # ))$]%]&]9;z{_#E l'$.a.*.*.*.*.*.&.&.F#a.}%*]=]-];]`+>][$z$,]D@'])]l$!]~]**{]]]^]/], F$+@(]k~_],]z$:]<]#+Q%[ R#@ @ + @ @ @ @ @ @ @ @ + @ @ < []< []@ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ @ @ @ @ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + # o H{}]|]4!U at L _#+.l'>.%.%.*.*.*.*.c.&.*.<#(*H&1]2]3]R w%@+]&++^%4]} 5]`.6]7]`.8] +9]^+3 at 4~3~G at U < 0]a]b]c]@ + + @ + + @ + @ + + @ U d]e]f]g]h]i]@ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : $ : : : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ o j]k]l]m]9!n]V at G&I E F.E&9&%.%.&.*.*.c.c.b.b.b.0&X+o]Y>p]q]r]s]t]u]v]w]x]y]z]A]B]C]D] @S @ E]F]S#U G]@ @ @ + + + + + + + @ + @ H]I]J]K]L]M]@ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ : : @ + @ @ + @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + + + < N]O]P]Q]R]$~=@a{l+S]W at X@G t at T]:#m+'+'+'+#.B#F.8.,+U]D u~A +>V##%U at B{V]W]X]4~T ]#+ %+Y]Z]+ + q)`] ^.^+^@^E]#^$^%^&^*^=^-^;^>^,^'^)^@ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ $ $ $ $ $ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + @ @ # @ ]+V !^~^{^]^B&i@^^c>*{U@(@x{-@/@/^A!x#l{f&*{=#D.(^_^:^<^D][^q.R#p @ # T @ + < }^|^+ + 1^2^3^4^5^6^o 7^8^9^0^a^b^U c^>^d^e^f^+ + + @ @ @ @ @ @ @ + + + + ",
+"+ . + + $ + + + + + $ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ + @ @ # # < g^Y!c%h^B-, i^j^k^l^m^m^m$n^o^p^q^b>X!d>)%{## p @ @ + @ @ @ @ @ @ @ r^s^S < t^u^v^w^5^x^U 7^y^z^A^B^C^u;D^E^F^G^H^< @ + @ @ @ @ @ @ @ + + + + ",
+". . + @ : : : : : : : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ @ @ # # p p # @ @ @ @ @ # @ @ # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ I^J^K^L^M^N^O^P^Q^R^Q^S^E^T^E^U^V^W^X^Y^Z^c]`^@ @ @ @ @ @ @ @ @ + + + + ",
+". . + @ : : @ : : : : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ < @ @ @ @ < < @ @ @ @ < < < < < {#{#< @ < @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ @ @ @ + @ @ @ @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ @ @ @ @ @ + + + + + + + + + @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + $ $ : $ $ $ : @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+"+ + + @ + + + + @ + + @ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + + + ",
+". . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ",
+". . . + . . + . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "};
Added: packages/openev/branches/upstream/current/pics/help.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/help.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/help.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,29 @@
+/* XPM */
+static char *help[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c None",
+"a c #ffff00",
+"b c #ffffff",
+/* pixels */
+"######################",
+"######################",
+"###....###........####",
+"##.aaaa.##.bbbbbb..###",
+"#.aa..aa.#.bbbbbb.b.##",
+"#.a.##.a.#.bbbbbb....#",
+"#...##.a.#.bbbbbbbbb.#",
+"#####.aa.#.bb...bbbb.#",
+"####.aa.##.bbbbbbbbb.#",
+"###.aa.###.bb...bbbb.#",
+"###.a.####.bbbbbbbbb.#",
+"###...####.bb...bbbb.#",
+"##########.bbbbbbbbb.#",
+"###...####.bbbbbbbbb.#",
+"###.a.####...........#",
+"###...################",
+"######################",
+"######################"
+};
Added: packages/openev/branches/upstream/current/pics/idle.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/idle.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/idle.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char *idle {
+/* width height num_colors chars_per_pixel */
+" 22 18 2 1",
+/* colors */
+"a c None",
+". c #00ff00",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaa....aaaaaaaaa",
+"aaaaaaa.......aaaaaaaa",
+"aaaaaa..........aaaaaa",
+"aaaaa...........aaaaaa",
+"aaaaaa..........aaaaaa",
+"aaaaaaa........aaaaaaa",
+"aaaaaaaaa....aaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/legend.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/legend.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/legend.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char * legend_xpm[] = {
+"22 18 6 1",
+" c None",
+". c #000000",
+"+ c #0000FF",
+"@ c #FFFCFC",
+"# c #FF0000",
+"$ c #008000",
+" ",
+" ................ ",
+" .++++++++++++++. ",
+" ................ ",
+" .@@@@@@@@@@@@@@. ",
+" .@##@@@@@@@@@@@. ",
+" .@##@@........ at . ",
+" .@@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@@. ",
+" .@$$@@@@@@@@@@@. ",
+" .@$$@@........ at . ",
+" .@@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@@. ",
+" . at ++@@@@@@@@@@@. ",
+" . at ++@@........ at . ",
+" .@@@@@@@@@@@@@@. ",
+" ................ ",
+" "};
Added: packages/openev/branches/upstream/current/pics/linear.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/linear.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/linear.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,31 @@
+/* XPM */
+static char *linear[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.................aa",
+"aaa.###############.aa",
+"aaa.aaaaaaaaa.#aaa#.aa",
+"aaa.aaaaaaaaa.#aaa#.aa",
+"aaa.aaaaaaaa.#aaaa#.aa",
+"aaa.aaaaaaaa.#aaaa#.aa",
+"aaa.aaaaaaa.#aaaaa#.aa",
+"aaa.aaaaaaa.#aaaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.................aa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
+
+
Added: packages/openev/branches/upstream/current/pics/log.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/log.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/log.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,31 @@
+/* XPM */
+static char *linear[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.................aa",
+"aaa.############..#.aa",
+"aaa.aaaaaaaaa...###.aa",
+"aaa.aaaaaaa..##aaa#.aa",
+"aaa.aaaaaa.##aaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.a.#aaaaaaaaaaa#.aa",
+"aaa.a.#aaaaaaaaaaa#.aa",
+"aaa.a.#aaaaaaaaaaa#.aa",
+"aaa..#aaaaaaaaaaaa#.aa",
+"aaa..#aaaaaaaaaaaa#.aa",
+"aaa.................aa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
+
+
Added: packages/openev/branches/upstream/current/pics/lower.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/lower.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/lower.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,24 @@
+/* XPM */
+static char * lower_xpm[] = {
+"22 18 3 1",
+" c None",
+". c #000000",
+"+ c #7F7F7F",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .............. ",
+" ............+ ",
+" ..........+ ",
+" ........+ ",
+" ......+ ",
+" ....+ ",
+" ..+ ",
+" + ",
+" ",
+" ",
+" ",
+" "};
Added: packages/openev/branches/upstream/current/pics/new.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/new.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/new.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * new_xpm[] = {
+"16 16 4 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"@ c #7F7F7F",
+" ",
+" ...... ",
+" ..++++.@ ",
+" .+.++++.@ ",
+" .++.++++.@ ",
+" .....++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" .++++++++.@ ",
+" ..........@ ",
+" @@@@@@@@@@ ",
+" "};
Added: packages/openev/branches/upstream/current/pics/node_cursor.xbm
===================================================================
--- packages/openev/branches/upstream/current/pics/node_cursor.xbm (rev 0)
+++ packages/openev/branches/upstream/current/pics/node_cursor.xbm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+#define node_cursor_width 16
+#define node_cursor_height 16
+#define node_cursor_x_hot 3
+#define node_cursor_y_hot 1
+static unsigned char node_cursor_bits[] = {
+ 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00,
+ 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x0f, 0x78, 0x1f, 0x38, 0x38,
+ 0x38, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00};
Added: packages/openev/branches/upstream/current/pics/node_cursor_mask.xbm
===================================================================
--- packages/openev/branches/upstream/current/pics/node_cursor_mask.xbm (rev 0)
+++ packages/openev/branches/upstream/current/pics/node_cursor_mask.xbm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,6 @@
+#define node_cursor_mask_width 16
+#define node_cursor_mask_height 16
+static unsigned char node_cursor_mask_bits[] = {
+ 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01,
+ 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x1f, 0xfc, 0x3f, 0x7c, 0x7e,
+ 0x7c, 0x70, 0x3c, 0x00, 0x3c, 0x00, 0x1c, 0x00, };
Added: packages/openev/branches/upstream/current/pics/nonelut.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/nonelut.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/nonelut.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,28 @@
+/* XPM */
+static char *nonelut[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 3 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.................aa",
+"aaa.############....aa",
+"aaa.aaaaaaaaaaaa.##.aa",
+"aaa.aaaaaaaaaaa.#a#.aa",
+"aaa.aaaaaaaaaa.#aa#.aa",
+"aaa.aaaaaaaaa.#aaa#.aa",
+"aaa.aaaaaaaa.#aaaa#.aa",
+"aaa.aaaaaaa.#aaaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.a.#aaaaaaaaaaa#.aa",
+"aaa..#aaaaaaaaaaaa#.aa",
+"aaa.................aa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/onetoone.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/onetoone.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/onetoone.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char *onetoone[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 2 1",
+/* colors */
+". c #000000",
+"# c None",
+/* pixels */
+"######################",
+"######################",
+"######################",
+"######################",
+"####..###########..###",
+"##....#########....###",
+"##....####..###....###",
+"####..####..#####..###",
+"####..###########..###",
+"####..###########..###",
+"####..####..#####..###",
+"####..####..#####..###",
+"####..###########..###",
+"####..###########..###",
+"######################",
+"######################",
+"######################",
+"######################"
+};
Added: packages/openev/branches/upstream/current/pics/openev.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/openev.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/openev.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2520 @@
+/* XPM */
+static char * openev_xpm[] = {
+"250 32 2485 2",
+" c None",
+". c #FFFFFF",
+"+ c #FEFEF8",
+"@ c #FDFEFB",
+"# c #FCFEFE",
+"$ c #FDFFFF",
+"% c #FEFFFE",
+"& c #FEFEFC",
+"* c #FCFCFA",
+"= c #FDFDFB",
+"- c #FCFBF9",
+"; c #FAF9F7",
+"> c #FAFAF8",
+", c #FBFAFA",
+"' c #FDFAFD",
+") c #FCFBFC",
+"! c #F8F8F9",
+"~ c #F9F9FB",
+"{ c #FDFAFA",
+"] c #FCF7F8",
+"^ c #FDFAF8",
+"/ c #FCFEF8",
+"( c #FCFFFD",
+"_ c #FCFFFF",
+": c #FFFFFE",
+"< c #FFFEFA",
+"[ c #FFFDFB",
+"} c #FEFDFE",
+"| c #FEFEFE",
+"1 c #FDFEFE",
+"2 c #FFFDFF",
+"3 c #FEFAFA",
+"4 c #FEFAFB",
+"5 c #F8FBFE",
+"6 c #F3F8FC",
+"7 c #FBFDFC",
+"8 c #FEFCF9",
+"9 c #FDFCFB",
+"0 c #FBFDFB",
+"a c #FBFDF9",
+"b c #FBFEF8",
+"c c #FBFDF8",
+"d c #FCFDF9",
+"e c #FCFEF9",
+"f c #FBFEFB",
+"g c #FDFCFA",
+"h c #FBFCFB",
+"i c #FCFCFD",
+"j c #FAFCFD",
+"k c #F9FCFD",
+"l c #FBFBFC",
+"m c #FDFBFB",
+"n c #FDFBF8",
+"o c #FAFEF9",
+"p c #FBFEFC",
+"q c #FEFBFE",
+"r c #FCFAFB",
+"s c #FBFCFA",
+"t c #F9FBFA",
+"u c #FAFDFC",
+"v c #F9FDFC",
+"w c #F7FCFD",
+"x c #F6FBFC",
+"y c #FEFDFB",
+"z c #FDFEFD",
+"A c #FDFDFE",
+"B c #FEFFFD",
+"C c #FEFEFF",
+"D c #FFFEFD",
+"E c #FEFDF9",
+"F c #FDFCF7",
+"G c #FBFCF9",
+"H c #F6FBFA",
+"I c #F2FCFD",
+"J c #EDFCFC",
+"K c #E8FAFD",
+"L c #E2F5FA",
+"M c #E2F3FA",
+"N c #E6F8FC",
+"O c #EDFCFE",
+"P c #EEFCFD",
+"Q c #F4FCFD",
+"R c #F8FAFC",
+"S c #FBFCFC",
+"T c #FDFFFD",
+"U c #FFFEFE",
+"V c #FFFEFB",
+"W c #FFFEFC",
+"X c #F0F3F7",
+"Y c #E0EFF5",
+"Z c #DDF4F9",
+"` c #E0F6F9",
+" . c #E2F6FA",
+".. c #DFF4FB",
+"+. c #E0F2FB",
+"@. c #E7EFFA",
+"#. c #E8F0FB",
+"$. c #E9F2FB",
+"%. c #EAF2FC",
+"&. c #E9F1FB",
+"*. c #E5F4FA",
+"=. c #E1F7F9",
+"-. c #E2F6F9",
+";. c #E2F6F8",
+">. c #E2F5F7",
+",. c #E3F5F7",
+"'. c #E5F5F7",
+"). c #EDF8F9",
+"!. c #FBFDFD",
+"~. c #FEFBFB",
+"{. c #FDFDFA",
+"]. c #FAFEFA",
+"^. c #FBFEFD",
+"/. c #FBFBFB",
+"(. c #F3F9FB",
+"_. c #E4F1F5",
+":. c #DEF4F9",
+"<. c #DCF3F8",
+"[. c #DDF1F3",
+"}. c #E8F6F8",
+"|. c #F7FDFD",
+"1. c #FDFCFD",
+"2. c #FEFDFD",
+"3. c #FBFEFE",
+"4. c #FFFEFF",
+"5. c #FFFDFC",
+"6. c #FDFCF9",
+"7. c #F9FDFB",
+"8. c #F0FCFB",
+"9. c #E2F4F8",
+"0. c #ABCCD6",
+"a. c #7DA7B7",
+"b. c #5A8CA0",
+"c. c #55889E",
+"d. c #58889E",
+"e. c #548496",
+"f. c #578392",
+"g. c #6F96A2",
+"h. c #92B0BB",
+"i. c #CCE2E9",
+"j. c #EFFCFE",
+"k. c #FAFDFF",
+"l. c #FDFDFF",
+"m. c #FEFCFF",
+"n. c #FEFCFE",
+"o. c #FFFDFD",
+"p. c #FEFFFC",
+"q. c #B2D0D4",
+"r. c #588894",
+"s. c #4E8B9D",
+"t. c #478797",
+"u. c #468595",
+"v. c #428299",
+"w. c #42829B",
+"x. c #49849B",
+"y. c #4C879E",
+"z. c #4E89A0",
+"A. c #4A859C",
+"B. c #49869D",
+"C. c #45839B",
+"D. c #45849B",
+"E. c #46839A",
+"F. c #498298",
+"G. c #4E8296",
+"H. c #4D7D8E",
+"I. c #8AA5AC",
+"J. c #FDFAFB",
+"K. c #FCFEFC",
+"L. c #FEFAFE",
+"M. c #FDF9F9",
+"N. c #E3F3F8",
+"O. c #7E9EAF",
+"P. c #5C869A",
+"Q. c #548399",
+"R. c #4D7C90",
+"S. c #4F777F",
+"T. c #89A6AA",
+"U. c #F3FCFE",
+"V. c #FDFAFE",
+"W. c #F8FEFE",
+"X. c #FEFBFD",
+"Y. c #F8FBFD",
+"Z. c #E0F5FA",
+"`. c #A8C6D2",
+" + c #5B869B",
+".+ c #477F9A",
+"++ c #4483A3",
+"@+ c #3D82A5",
+"#+ c #3F85A7",
+"$+ c #3F83A3",
+"%+ c #3F83A2",
+"&+ c #3F819D",
+"*+ c #3D7993",
+"=+ c #3E748D",
+"-+ c #3F6E86",
+";+ c #7496A9",
+">+ c #D6E2E7",
+",+ c #F5FAFD",
+"'+ c #FBF9FC",
+")+ c #FEFCFD",
+"!+ c #FEFDFC",
+"~+ c #FEFEFD",
+"{+ c #FDFDFD",
+"]+ c #F5FEFE",
+"^+ c #B2D8E1",
+"/+ c #518EA1",
+"(+ c #3C8AA3",
+"_+ c #32839D",
+":+ c #307E97",
+"<+ c #2F7B9A",
+"[+ c #30799A",
+"}+ c #367B99",
+"|+ c #387D9B",
+"1+ c #3A7F9D",
+"2+ c #3B809E",
+"3+ c #3C819F",
+"4+ c #377C9A",
+"5+ c #367B9B",
+"6+ c #2B7295",
+"7+ c #317AA0",
+"8+ c #317CA3",
+"9+ c #357CA3",
+"0+ c #3E7EA0",
+"a+ c #2E6885",
+"b+ c #628390",
+"c+ c #F4FBFD",
+"d+ c #FEFCFC",
+"e+ c #FDFEFC",
+"f+ c #F4FCFE",
+"g+ c #CFE9F3",
+"h+ c #6393AE",
+"i+ c #4C87A5",
+"j+ c #43809D",
+"k+ c #336C84",
+"l+ c #25525D",
+"m+ c #95B3B8",
+"n+ c #EFF9FC",
+"o+ c #FBFAFD",
+"p+ c #F8FEFD",
+"q+ c #FEFAFD",
+"r+ c #FDFBFE",
+"s+ c #F6FAFC",
+"t+ c #E5F3F7",
+"u+ c #88AFC3",
+"v+ c #5E8DA7",
+"w+ c #4D83A3",
+"x+ c #3F7C9E",
+"y+ c #397599",
+"z+ c #316B8E",
+"A+ c #2E6889",
+"B+ c #336D8E",
+"C+ c #357191",
+"D+ c #367595",
+"E+ c #3B7B9A",
+"F+ c #3C7A9B",
+"G+ c #3B7698",
+"H+ c #3F6F8A",
+"I+ c #637D8A",
+"J+ c #E7F4F8",
+"K+ c #F6F8FA",
+"L+ c #FEFCFB",
+"M+ c #FCFFFE",
+"N+ c #FCFDFE",
+"O+ c #FCFDFD",
+"P+ c #FCFEFD",
+"Q+ c #F9FCFE",
+"R+ c #ADBDD2",
+"S+ c #6186A6",
+"T+ c #457CA0",
+"U+ c #3F7697",
+"V+ c #3F6C8C",
+"W+ c #2F5576",
+"X+ c #345678",
+"Y+ c #365774",
+"Z+ c #355673",
+"`+ c #375875",
+" @ c #345673",
+".@ c #385A70",
+"+@ c #325869",
+"@@ c #55839A",
+"#@ c #477A97",
+"$@ c #437695",
+"%@ c #49748F",
+"&@ c #33576B",
+"*@ c #4E6770",
+"=@ c #F1FCFE",
+"-@ c #FBFBFE",
+";@ c #FAFBFD",
+">@ c #ECFAFD",
+",@ c #95B9CD",
+"'@ c #578FB0",
+")@ c #4582A4",
+"!@ c #3C7590",
+"~@ c #1D4C5E",
+"{@ c #46656D",
+"]@ c #DFF1F4",
+"^@ c #F2F8FB",
+"/@ c #FBFAFC",
+"(@ c #FAFEFE",
+"_@ c #F9FDFE",
+":@ c #EFFBFC",
+"<@ c #A0BAC5",
+"[@ c #5F8FAA",
+"}@ c #5285A4",
+"|@ c #457898",
+"1@ c #427190",
+"2@ c #315671",
+"3@ c #385469",
+"4@ c #445A6D",
+"5@ c #415A70",
+"6@ c #45657C",
+"7@ c #466E87",
+"8@ c #497995",
+"9@ c #437896",
+"0@ c #457B9D",
+"a@ c #427693",
+"b@ c #416877",
+"c@ c #91A8AE",
+"d@ c #F6FCFC",
+"e@ c #FEFDFA",
+"f@ c #F9FEFE",
+"g@ c #F8FDFE",
+"h@ c #FBFDFE",
+"i@ c #FAFDFE",
+"j@ c #F8FCFE",
+"k@ c #95A2BB",
+"l@ c #6F91B3",
+"m@ c #4F7FA2",
+"n@ c #497491",
+"o@ c #3E596F",
+"p@ c #525F73",
+"q@ c #758191",
+"r@ c #728590",
+"s@ c #748892",
+"t@ c #768A94",
+"u@ c #788C96",
+"v@ c #758993",
+"w@ c #7A898E",
+"x@ c #859596",
+"y@ c #A0BCC8",
+"z@ c #557D93",
+"A@ c #4E7994",
+"B@ c #567C94",
+"C@ c #3F5E70",
+"D@ c #506971",
+"E@ c #EEFCFE",
+"F@ c #F9FAFE",
+"G@ c #CDE1E9",
+"H@ c #6E97B1",
+"I@ c #5D94B8",
+"J@ c #497FA1",
+"K@ c #3E677A",
+"L@ c #2C444B",
+"M@ c #B6BCC1",
+"N@ c #F6F8FB",
+"O@ c #F7F9FB",
+"P@ c #FEFEFB",
+"Q@ c #C3DAE3",
+"R@ c #7598A9",
+"S@ c #5F91AB",
+"T@ c #4D7D99",
+"U@ c #4C758D",
+"V@ c #314E62",
+"W@ c #495765",
+"X@ c #BABBC1",
+"Y@ c #E7E4E7",
+"Z@ c #E8E7ED",
+"`@ c #DBE1E9",
+" # c #A0B0BC",
+".# c #5C798C",
+"+# c #577E96",
+"@# c #4D7B98",
+"## c #4D7F9B",
+"$# c #396776",
+"%# c #648188",
+"&# c #F1FAF9",
+"*# c #F2F5F7",
+"=# c #D3E1E6",
+"-# c #CBDFE6",
+";# c #CDDFE5",
+"># c #CEDCE3",
+",# c #D1DDE4",
+"'# c #F1FAFD",
+")# c #F3FCFD",
+"!# c #D9E7EC",
+"~# c #CCE0E7",
+"{# c #C9DEE6",
+"]# c #CCE1E8",
+"^# c #C9DDE5",
+"/# c #D4E6EB",
+"(# c #E8F7F9",
+"_# c #F6FDFE",
+":# c #FAFCFC",
+"<# c #F7FDFE",
+"[# c #F0F8F9",
+"}# c #DEEEF2",
+"|# c #D2E6ED",
+"1# c #CADEE4",
+"2# c #CBDEE4",
+"3# c #CBDFE5",
+"4# c #CFE3E8",
+"5# c #D9E8EC",
+"6# c #E2EEF0",
+"7# c #F0F9FB",
+"8# c #FCFCFB",
+"9# c #FAF9F8",
+"0# c #D9E1E7",
+"a# c #C3CFD6",
+"b# c #BDCCD5",
+"c# c #BDCDD8",
+"d# c #BDCBD7",
+"e# c #DAE4ED",
+"f# c #F2FBFE",
+"g# c #E4EEF4",
+"h# c #C6D3DC",
+"i# c #C0CDD6",
+"j# c #C0CFD7",
+"k# c #BFCED7",
+"l# c #C1CED6",
+"m# c #D7DFE3",
+"n# c #F3F8FA",
+"o# c #7DA0B5",
+"p# c #6498B1",
+"q# c #49869E",
+"r# c #447988",
+"s# c #35585E",
+"t# c #B1C1C3",
+"u# c #F6FDFD",
+"v# c #F9FEFD",
+"w# c #FAFEFD",
+"x# c #F5FDFD",
+"y# c #EDFDFE",
+"z# c #ACCEDA",
+"A# c #5B8CA6",
+"B# c #5087A8",
+"C# c #5083A2",
+"D# c #3B6680",
+"E# c #4D6A79",
+"F# c #F9FBFE",
+"G# c #FEFBFC",
+"H# c #ECF8FC",
+"I# c #95AFBE",
+"J# c #7099B4",
+"K# c #5688A8",
+"L# c #517D98",
+"M# c #334D5A",
+"N# c #73797B",
+"O# c #F9F4F8",
+"P# c #E1F2F6",
+"Q# c #8FB0C2",
+"R# c #6D9BB5",
+"S# c #5A8DA3",
+"T# c #578293",
+"U# c #3C5862",
+"V# c #4F5D62",
+"W# c #DFE4E6",
+"X# c #FCFCFC",
+"Y# c #FCFDFC",
+"Z# c #F4FAFC",
+"`# c #ACBDCA",
+" $ c #65859A",
+".$ c #5783A0",
+"+$ c #5687A2",
+"@$ c #47707F",
+"#$ c #5A7179",
+"$$ c #E2E9E9",
+"%$ c #F0FAFD",
+"&$ c #94B0BD",
+"*$ c #6F9AAF",
+"=$ c #6F93A7",
+"-$ c #6F8C9F",
+";$ c #6B8393",
+">$ c #C1D4DA",
+",$ c #C3D7DE",
+"'$ c #819EAD",
+")$ c #7296AF",
+"!$ c #6F97B1",
+"~$ c #6E96B1",
+"{$ c #6B8FA8",
+"]$ c #69879A",
+"^$ c #839BA9",
+"/$ c #D0DEE2",
+"($ c #F9FBF9",
+"_$ c #FDF9F1",
+":$ c #FDFCF6",
+"<$ c #F0FAFA",
+"[$ c #C8E1E7",
+"}$ c #8CACB5",
+"|$ c #729AAD",
+"1$ c #6A93AA",
+"2$ c #6F93A8",
+"3$ c #7395A8",
+"4$ c #7698AB",
+"5$ c #7299AC",
+"6$ c #6D98AC",
+"7$ c #6F93A5",
+"8$ c #7593A1",
+"9$ c #8BA1AB",
+"0$ c #C6D2D7",
+"a$ c #FCFAF7",
+"b$ c #FCFBFD",
+"c$ c #D5E2EA",
+"d$ c #7E9CAC",
+"e$ c #749EB5",
+"f$ c #7099B5",
+"g$ c #6D8EAB",
+"h$ c #627A94",
+"i$ c #D3E6F5",
+"j$ c #94ACBD",
+"k$ c #7998AD",
+"l$ c #7498B1",
+"m$ c #7299B3",
+"n$ c #6D92A8",
+"o$ c #6C8797",
+"p$ c #96A5B0",
+"q$ c #F8F8FC",
+"r$ c #CEE5EC",
+"s$ c #799FB4",
+"t$ c #6A94AB",
+"u$ c #60879D",
+"v$ c #4E6D7E",
+"w$ c #475862",
+"x$ c #E7ECED",
+"y$ c #FDFCFC",
+"z$ c #B9D1D8",
+"A$ c #688F9E",
+"B$ c #5F8CA0",
+"C$ c #5E869A",
+"D$ c #49697B",
+"E$ c #596C7A",
+"F$ c #F3FDFE",
+"G$ c #FDFAF5",
+"H$ c #FBFDFA",
+"I$ c #F5FDFE",
+"J$ c #C3DBE5",
+"K$ c #81A3B8",
+"L$ c #6C93AA",
+"M$ c #648CA1",
+"N$ c #456575",
+"O$ c #3A4B55",
+"P$ c #D5D8DA",
+"Q$ c #F5FCFD",
+"R$ c #BED0D8",
+"S$ c #88A9BC",
+"T$ c #6892AB",
+"U$ c #628BA2",
+"V$ c #48697A",
+"W$ c #3F525B",
+"X$ c #C6CFD2",
+"Y$ c #F8FBFB",
+"Z$ c #F8F9FA",
+"`$ c #F7FDFF",
+" % c #CEDDE4",
+".% c #7290A3",
+"+% c #628DA6",
+"@% c #5D8BA4",
+"#% c #517685",
+"$% c #556B72",
+"%% c #D8DDDD",
+"&% c #F2FDFE",
+"*% c #9EBAC9",
+"=% c #749EB3",
+"-% c #6D91A6",
+";% c #648396",
+">% c #5C7587",
+",% c #B8CED9",
+"'% c #9DB4BF",
+")% c #87A4B5",
+"!% c #7195AD",
+"~% c #6B92AD",
+"{% c #6B93B0",
+"]% c #688DA7",
+"^% c #68899E",
+"/% c #5F7989",
+"(% c #85949C",
+"_% c #F4F8F8",
+":% c #FDFBF7",
+"<% c #D4E3EB",
+"[% c #8DACB9",
+"}% c #7CA0AF",
+"|% c #6F98AE",
+"1% c #688FA9",
+"2% c #618299",
+"3% c #5F7D92",
+"4% c #607F94",
+"5% c #64889E",
+"6% c #6C96AB",
+"7% c #6F95A9",
+"8% c #7292A4",
+"9% c #6B8593",
+"0% c #697A83",
+"a% c #ECF3F5",
+"b% c #F9F9F9",
+"c% c #FAF8F7",
+"d% c #D6E4EB",
+"e% c #85A4B4",
+"f% c #749DB5",
+"g% c #6891AB",
+"h% c #64859F",
+"i% c #637A93",
+"j% c #A0B9CA",
+"k% c #7B99AA",
+"l% c #7194A9",
+"m% c #6E95AC",
+"n% c #6A94AC",
+"o% c #6A96AD",
+"p% c #6992A7",
+"q% c #60808F",
+"r% c #5B6C77",
+"s% c #D4D5D9",
+"t% c #F5FCFE",
+"u% c #BBD0DA",
+"v% c #81A6BD",
+"w% c #6D93AB",
+"x% c #66899F",
+"y% c #526D7E",
+"z% c #5B6A72",
+"A% c #BFD3DB",
+"B% c #7296A5",
+"C% c #6993A5",
+"D% c #688DA0",
+"E% c #537080",
+"F% c #5F707B",
+"G% c #EFF7FA",
+"H% c #E7F2F7",
+"I% c #99B4C5",
+"J% c #7DA0B6",
+"K% c #6E93A9",
+"L% c #5B7D91",
+"M% c #354E5C",
+"N% c #869298",
+"O% c #F7F7F8",
+"P% c #EBF4F7",
+"Q% c #A0B4BE",
+"R% c #89A8BA",
+"S% c #6D91A9",
+"T% c #68849A",
+"U% c #485C6C",
+"V% c #7D8890",
+"W% c #F8FBFC",
+"X% c #F7F7F7",
+"Y% c #F7F8FA",
+"Z% c #FAFDFD",
+"`% c #F9FEFF",
+" & c #DCE9F0",
+".& c #86A0B1",
+"+& c #6F97AD",
+"@& c #6791A8",
+"#& c #567786",
+"$& c #5A6E75",
+"%& c #DBE1E0",
+"&& c #FAFAF7",
+"*& c #FBFEFF",
+"=& c #EBF7FB",
+"-& c #99B4C3",
+";& c #7BA1B6",
+">& c #6C8DA1",
+",& c #5F7B8F",
+"'& c #5D7585",
+")& c #A9BFCE",
+"!& c #8197A4",
+"~& c #67808F",
+"{& c #638095",
+"]& c #6889A1",
+"^& c #6A8FA9",
+"/& c #668AA3",
+"(& c #6F8FA4",
+"_& c #5A7687",
+":& c #677780",
+"<& c #DCE0E2",
+"[& c #F9F9FA",
+"}& c #ECF4F8",
+"|& c #A4BACA",
+"1& c #86A7BD",
+"2& c #6A8FA4",
+"3& c #69899E",
+"4& c #4C687D",
+"5& c #465C6E",
+"6& c #5B6D7E",
+"7& c #617585",
+"8& c #637C8D",
+"9& c #6A8999",
+"0& c #6D8FA2",
+"a& c #7192A4",
+"b& c #648190",
+"c& c #566C77",
+"d& c #B9C5CA",
+"e& c #FBFAFB",
+"f& c #C4D3D9",
+"g& c #8EAAB9",
+"h& c #7499AE",
+"i& c #6A8DA4",
+"j& c #6E899E",
+"k& c #617588",
+"l& c #657D8B",
+"m& c #5B7485",
+"n& c #557385",
+"o& c #67899D",
+"p& c #6E91A5",
+"q& c #7095A9",
+"r& c #6D92A6",
+"s& c #648492",
+"t& c #53656F",
+"u& c #ABAFB3",
+"v& c #F2F8FD",
+"w& c #ACBECC",
+"x& c #89ACC5",
+"y& c #7296AE",
+"z& c #6C8CA1",
+"A& c #5A7383",
+"B& c #86959E",
+"C& c #F4F9FA",
+"D& c #FDFDFC",
+"E& c #C6D8DE",
+"F& c #7A9BA9",
+"G& c #7298A9",
+"H& c #7192A3",
+"I& c #5B7583",
+"J& c #617078",
+"K& c #E9F0F1",
+"L& c #F9FBF8",
+"M& c #BED0DF",
+"N& c #89A7BB",
+"O& c #7B9CB2",
+"P& c #7090A5",
+"Q& c #4C6878",
+"R& c #51636E",
+"S& c #E3E8EB",
+"T& c #FBF9F8",
+"U& c #FCFBFA",
+"V& c #F6FBFD",
+"W& c #D3DFE5",
+"X& c #9CB2BD",
+"Y& c #84A1B1",
+"Z& c #7896AA",
+"`& c #637688",
+" * c #485460",
+".* c #D0D4D9",
+"+* c #FDFFFE",
+"@* c #F8FDFF",
+"#* c #DBE6EA",
+"$* c #8CA3B1",
+"%* c #7799AD",
+"&* c #5B7686",
+"** c #63737A",
+"=* c #E5EAE9",
+"-* c #DEECF2",
+";* c #95AEBE",
+">* c #7FA3B5",
+",* c #7794A7",
+"'* c #687F91",
+")* c #687B89",
+"!* c #728390",
+"~* c #62747D",
+"{* c #687A85",
+"]* c #687D8A",
+"^* c #698396",
+"/* c #7392A8",
+"(* c #7292A8",
+"_* c #7593A8",
+":* c #668092",
+"<* c #606F79",
+"[* c #C7CDD0",
+"}* c #CCD8E3",
+"|* c #96AFC5",
+"1* c #7B9CB5",
+"2* c #7191A6",
+"3* c #556977",
+"4* c #444F58",
+"5* c #B8BFC6",
+"6* c #DEE1E5",
+"7* c #DBE0E3",
+"8* c #CFD8DC",
+"9* c #9DACB3",
+"0* c #7592A0",
+"a* c #7393A4",
+"b* c #6D8A9A",
+"c* c #546B79",
+"d* c #9EACB1",
+"e* c #B5C5CC",
+"f* c #90ABB8",
+"g* c #7495A7",
+"h* c #7896A8",
+"i* c #617786",
+"j* c #45535F",
+"k* c #7D8895",
+"l* c #9DA8B2",
+"m* c #9FADB9",
+"n* c #8294A4",
+"o* c #7A8FA1",
+"p* c #7E96A9",
+"q* c #7C97A9",
+"r* c #63808D",
+"s* c #51636B",
+"t* c #C8CCCE",
+"u* c #FBFAFE",
+"v* c #EFF4FA",
+"w* c #A3B3C2",
+"x* c #8BA9C0",
+"y* c #7796AD",
+"z* c #7591A5",
+"A* c #6D8393",
+"B* c #9CACB4",
+"C* c #E2EBEF",
+"D* c #E2EAEE",
+"E* c #E3ECF0",
+"F* c #E6EDF0",
+"G* c #E6ECEE",
+"H* c #E6EAEB",
+"I* c #E9EAEB",
+"J* c #E8E8E8",
+"K* c #FBFBFA",
+"L* c #D1E0E6",
+"M* c #85A2AF",
+"N* c #7A9BAB",
+"O* c #7A97A6",
+"P* c #627985",
+"Q* c #667377",
+"R* c #E9EEED",
+"S* c #FCFCF8",
+"T* c #FDFCF8",
+"U* c #E1EEF7",
+"V* c #9AB1C6",
+"W* c #8BA9BE",
+"X* c #7B99AC",
+"Y* c #607B8C",
+"Z* c #435562",
+"`* c #A6AFB7",
+" = c #F8F9FB",
+".= c #FEFEFA",
+"+= c #F6FEFE",
+"@= c #B6C6D0",
+"#= c #9BB1BE",
+"$= c #84A0AE",
+"%= c #7C96A6",
+"&= c #5C6A77",
+"*= c #676F78",
+"== c #F4F5F7",
+"-= c #FBFFFE",
+";= c #D7E1E6",
+">= c #92A6B2",
+",= c #82A0B0",
+"'= c #7A9AAC",
+")= c #5D7281",
+"!= c #647178",
+"~= c #F2F6F6",
+"{= c #FCFEFB",
+"]= c #CDDBE3",
+"^= c #99B2C1",
+"/= c #7E9EB0",
+"(= c #6F8899",
+"_= c #546674",
+":= c #79858E",
+"<= c #CCD4DA",
+"[= c #E6EDEF",
+"}= c #E7EEF0",
+"|= c #E5EDF0",
+"1= c #B4C3CD",
+"2= c #788FA0",
+"3= c #7994A8",
+"4= c #7D95A8",
+"5= c #718798",
+"6= c #67767F",
+"7= c #C4CBCD",
+"8= c #F1F9FC",
+"9= c #ACBBC9",
+"0= c #98B2C7",
+"a= c #7E9AB0",
+"b= c #6A8291",
+"c= c #525D63",
+"d= c #C8CBCE",
+"e= c #F7F6F7",
+"f= c #FCF9F8",
+"g= c #FCFBF8",
+"h= c #F7F8F6",
+"i= c #EDF5F5",
+"j= c #91A9B2",
+"k= c #86A3B0",
+"l= c #728E9C",
+"m= c #5C7280",
+"n= c #98A5AB",
+"o= c #EEF8F9",
+"p= c #A7B9BF",
+"q= c #93ACB9",
+"r= c #7D99AA",
+"s= c #718897",
+"t= c #4E5E66",
+"u= c #A7AFB3",
+"v= c #F7F7FB",
+"w= c #FAF9FC",
+"x= c #E2E8EF",
+"y= c #95A1AD",
+"z= c #8D9FAE",
+"A= c #8198A9",
+"B= c #607884",
+"C= c #53626A",
+"D= c #E7ECEE",
+"E= c #FAFBFE",
+"F= c #E4EAF1",
+"G= c #A2B1C1",
+"H= c #8DA5BA",
+"I= c #839BAF",
+"J= c #8197A9",
+"K= c #8094A4",
+"L= c #8395A1",
+"M= c #96A7B1",
+"N= c #98A8B1",
+"O= c #9BAAB7",
+"P= c #9EADB8",
+"Q= c #9EA9B2",
+"R= c #A5ADB4",
+"S= c #979DA2",
+"T= c #9A9FA3",
+"U= c #F7F8F8",
+"V= c #D5E3E8",
+"W= c #8EA6B3",
+"X= c #829FAE",
+"Y= c #8099A6",
+"Z= c #6A7D86",
+"`= c #6B7679",
+" - c #EBEEED",
+".- c #F9F8F6",
+"+- c #B7CAD7",
+"@- c #94B1C8",
+"#- c #83A1B3",
+"$- c #78909E",
+"%- c #546672",
+"&- c #6A747C",
+"*- c #EEF1F5",
+"=- c #FBFAF7",
+"-- c #FEFCF8",
+";- c #EDF8FB",
+">- c #ABBEC9",
+",- c #9CB3C0",
+"'- c #8AA3B0",
+")- c #7A929E",
+"!- c #586870",
+"~- c #98A1A5",
+"{- c #D2DADF",
+"]- c #9EB0B9",
+"^- c #85A1AD",
+"/- c #7B97A7",
+"(- c #5F7080",
+"_- c #788288",
+":- c #BBCAD5",
+"<- c #9CB4C4",
+"[- c #809EAF",
+"}- c #6D8392",
+"|- c #53616B",
+"1- c #D0D5D9",
+"2- c #F9F9F8",
+"3- c #F9F7F3",
+"4- c #F8F4F0",
+"5- c #FAFAFA",
+"6- c #F2F9FC",
+"7- c #AAB9C5",
+"8- c #8CA1B1",
+"9- c #869AAA",
+"0- c #768997",
+"a- c #65757B",
+"b- c #C3CCCD",
+"c- c #DFE9EC",
+"d- c #A8BAC7",
+"e- c #8EA7BA",
+"f- c #839BAB",
+"g- c #697880",
+"h- c #818C8F",
+"i- c #EBF1F3",
+"j- c #F5F7F8",
+"k- c #FAF9F9",
+"l- c #F1FBFB",
+"m- c #A7BCC2",
+"n- c #93ACB7",
+"o- c #77909D",
+"p- c #5B707D",
+"q- c #9EABB2",
+"r- c #FCF9F7",
+"s- c #E2EDED",
+"t- c #A8BAC0",
+"u- c #95ACB8",
+"v- c #88A0AE",
+"w- c #6C7F8A",
+"x- c #545F63",
+"y- c #DEE2E1",
+"z- c #FCFBF5",
+"A- c #F8F9F4",
+"B- c #EBF2F1",
+"C- c #ACBBC0",
+"D- c #98B0BA",
+"E- c #809BA9",
+"F- c #617381",
+"G- c #727D86",
+"H- c #F8FCFC",
+"I- c #D0DBE3",
+"J- c #A6B6C4",
+"K- c #97A8BA",
+"L- c #8EA0B0",
+"M- c #899BAB",
+"N- c #899CAB",
+"O- c #8399A7",
+"P- c #859DAC",
+"Q- c #88A0AF",
+"R- c #8CA1B2",
+"S- c #8FA2B3",
+"T- c #90A1AF",
+"U- c #8F9CA6",
+"V- c #657078",
+"W- c #9CA4AB",
+"X- c #DBE6E9",
+"Y- c #98ACB9",
+"Z- c #8AA2B2",
+"`- c #899FAB",
+" ; c #788990",
+".; c #747D80",
+"+; c #DDE6EA",
+"@; c #A3B9C7",
+"#; c #8DAFC5",
+"$; c #7F9BAA",
+"%; c #687B84",
+"&; c #4D5860",
+"*; c #CACED2",
+"=; c #F9F8FB",
+"-; c #DEEAEF",
+";; c #B0C3D0",
+">; c #A0B5C3",
+",; c #95A8B6",
+"'; c #758790",
+"); c #5A676D",
+"!; c #CCD4D6",
+"~; c #FAFCFA",
+"{; c #C6CED5",
+"]; c #A7B6C0",
+"^; c #8CA3B0",
+"/; c #8097A5",
+"(; c #64727F",
+"_; c #949BA1",
+":; c #F8FCFA",
+"<; c #F1FAFB",
+"[; c #A2B8C8",
+"}; c #839DAE",
+"|; c #687A88",
+"1; c #606A73",
+"2; c #FBFAF8",
+"3; c #FDF9F5",
+"4; c #FEF9F3",
+"5; c #FCFBF7",
+"6; c #C2D1D8",
+"7; c #9CAFBC",
+"8; c #91A1AF",
+"9; c #808E9C",
+"0; c #707B82",
+"a; c #D3DDDE",
+"b; c #CCD7DC",
+"c; c #ADBCC8",
+"d; c #99ADBC",
+"e; c #8B9FAB",
+"f; c #7E8B91",
+"g; c #ABB7BC",
+"h; c #E0EAF0",
+"i; c #E3EBEF",
+"j; c #E9EFF2",
+"k; c #EAF0F3",
+"l; c #E7F1F3",
+"m; c #E3F1F4",
+"n; c #B8CCD4",
+"o; c #9FB6BE",
+"p; c #7B8E98",
+"q; c #5B6A73",
+"r; c #C1C8CB",
+"s; c #FAFBFB",
+"t; c #D8E3E6",
+"u; c #B1C2C8",
+"v; c #9AAEB9",
+"w; c #90A5B0",
+"x; c #68787F",
+"y; c #727D7D",
+"z; c #F2F6F3",
+"A; c #FDFCF5",
+"B; c #FCFDF5",
+"C; c #FBFDF6",
+"D; c #E2EBE8",
+"E; c #B1C1C4",
+"F; c #9EB5BE",
+"G; c #869EAB",
+"H; c #63717C",
+"I; c #929BA2",
+"J; c #F9FDFD",
+"K; c #C4CFD7",
+"L; c #B0BDCA",
+"M; c #A0ADBC",
+"N; c #96A4B0",
+"O; c #8B9CA4",
+"P; c #75878E",
+"Q; c #687C86",
+"R; c #647B87",
+"S; c #627786",
+"T; c #637684",
+"U; c #637380",
+"V; c #63727E",
+"W; c #5B6771",
+"X; c #5B676F",
+"Y; c #B6BFC6",
+"Z; c #DFE8EA",
+"`; c #9FB0BB",
+" > c #95ABB7",
+".> c #93A7AF",
+"+> c #809093",
+"@> c #7C8485",
+"#> c #DDDDDF",
+"$> c #F5F9FA",
+"%> c #C5D0D6",
+"&> c #A8BDC9",
+"*> c #8CA8BA",
+"=> c #8498A4",
+"-> c #535F66",
+";> c #858C92",
+">> c #FCFCF7",
+",> c #F8FDFD",
+"'> c #D5E3EA",
+")> c #B7C9D6",
+"!> c #A6B7C5",
+"~> c #A2ADB8",
+"{> c #798289",
+"]> c #747D81",
+"^> c #EBF0F2",
+"/> c #FCFDFB",
+"(> c #FFFFFB",
+"_> c #F3F8FB",
+":> c #C4CED6",
+"<> c #B0BDC8",
+"[> c #96A6B4",
+"}> c #8797A3",
+"|> c #69737A",
+"1> c #B1B6B8",
+"2> c #EAF3F6",
+"3> c #B8C9D0",
+"4> c #A8BBC9",
+"5> c #8E9FB0",
+"6> c #65737F",
+"7> c #818C91",
+"8> c #FDFBF9",
+"9> c #F8FDF9",
+"0> c #F2FDFD",
+"a> c #C1D4D9",
+"b> c #A9BCC5",
+"c> c #99A9B5",
+"d> c #89929E",
+"e> c #767C83",
+"f> c #C3CCD2",
+"g> c #B6C1CA",
+"h> c #A0ADB7",
+"i> c #A3B0BB",
+"j> c #97A4AE",
+"k> c #9CA7B0",
+"l> c #B0BAC3",
+"m> c #B2BCC5",
+"n> c #B9C2CB",
+"o> c #BCC6CF",
+"p> c #BFC9D2",
+"q> c #BFCAD3",
+"r> c #B7CAD5",
+"s> c #9EB0B8",
+"t> c #747F84",
+"u> c #606568",
+"v> c #E7E8E9",
+"w> c #FBFCFD",
+"x> c #D4DBE2",
+"y> c #BCC7D0",
+"z> c #A6B4BC",
+"A> c #97A6AD",
+"B> c #697679",
+"C> c #919A99",
+"D> c #F9FDFA",
+"E> c #DDE3E5",
+"F> c #C0C9D0",
+"G> c #ABB5C0",
+"H> c #8A95A1",
+"I> c #666F73",
+"J> c #C2C7C9",
+"K> c #F9FBFD",
+"L> c #C9CDD5",
+"M> c #B9C1CD",
+"N> c #A4AFBB",
+"O> c #9DAAAF",
+"P> c #73817F",
+"Q> c #53615B",
+"R> c #899795",
+"S> c #8C999E",
+"T> c #919CA3",
+"U> c #959BA0",
+"V> c #979EA3",
+"W> c #999FA5",
+"X> c #9BA1A6",
+"Y> c #A2A8AD",
+"Z> c #DAE0E4",
+"`> c #E5EDEE",
+" , c #ADBCC2",
+"., c #A3B5BD",
+"+, c #9DAEB3",
+"@, c #8D9A9C",
+"#, c #858C8D",
+"$, c #DADCDD",
+"%, c #E2E9EF",
+"&, c #BFC9D1",
+"*, c #A6B2BD",
+"=, c #6F7981",
+"-, c #585F64",
+";, c #E2E7EA",
+">, c #D4DEE4",
+",, c #C1CED8",
+"', c #ADB8C2",
+"), c #AAB1B8",
+"!, c #797E84",
+"~, c #848A8D",
+"{, c #FFFFFC",
+"], c #EDF1F4",
+"^, c #C8D1D7",
+"/, c #B3BFC6",
+"(, c #9FAFB7",
+"_, c #7E8A93",
+":, c #696D74",
+"<, c #E0E1E4",
+"[, c #E3E9ED",
+"}, c #AABAC6",
+"|, c #919FAB",
+"1, c #66717A",
+"2, c #ABB3B7",
+"3, c #F0FAFB",
+"4, c #C4D4D8",
+"5, c #B3C4CA",
+"6, c #9FADB5",
+"7, c #87939B",
+"8, c #858A90",
+"9, c #EDF0F3",
+"0, c #C9CDD3",
+"a, c #BCC2C8",
+"b, c #ACB3BB",
+"c, c #A3ADB6",
+"d, c #8B96A1",
+"e, c #8A949C",
+"f, c #9099A1",
+"g, c #929BA3",
+"h, c #8F989F",
+"i, c #96A0A7",
+"j, c #959EA6",
+"k, c #818F98",
+"l, c #748088",
+"m, c #60676C",
+"n, c #797C7D",
+"o, c #F5F6F6",
+"p, c #CED5DB",
+"q, c #C2CAD2",
+"r, c #AEB8BF",
+"s, c #959FA5",
+"t, c #6D7578",
+"u, c #BFC3C4",
+"v, c #D8DDDE",
+"w, c #C9D0D4",
+"x, c #B1B8C2",
+"y, c #868E98",
+"z, c #72767A",
+"A, c #E2E3E6",
+"B, c #F3F3F7",
+"C, c #CCCFD6",
+"D, c #BFC4CE",
+"E, c #AFB7C0",
+"F, c #929A9E",
+"G, c #697271",
+"H, c #CBD2CF",
+"I, c #F2F9F8",
+"J, c #F5FBFC",
+"K, c #F6F9F9",
+"L, c #EAF0F2",
+"M, c #BBC7CD",
+"N, c #B2BFC8",
+"O, c #A9B4BC",
+"P, c #9CA4AA",
+"Q, c #8F9497",
+"R, c #D6DADB",
+"S, c #D5DCE1",
+"T, c #A8B1BA",
+"U, c #8D98A2",
+"V, c #5C646B",
+"W, c #A6ABAE",
+"X, c #F4F8FA",
+"Y, c #D2D5D8",
+"Z, c #C7CBCF",
+"`, c #B1B4B8",
+" ' c #AAACAD",
+".' c #808081",
+"+' c #AAACAC",
+"@' c #FBFBF9",
+"#' c #FDFCFE",
+"$' c #E3E3E5",
+"%' c #D0D5D5",
+"&' c #B2BABB",
+"*' c #A7B4B6",
+"=' c #7D868A",
+"-' c #79797E",
+";' c #FAF8FA",
+">' c #DEE0E4",
+",' c #C9CFD6",
+"'' c #AEB7BE",
+")' c #8F979D",
+"!' c #6D7379",
+"~' c #D6DADC",
+"{' c #EAF0F1",
+"]' c #CDD6D8",
+"^' c #BAC5C8",
+"/' c #A0ACAF",
+"(' c #879195",
+"_' c #9CA1A4",
+":' c #E9E8EA",
+"<' c #C7C5C7",
+"[' c #BBB8BB",
+"}' c #AFAEB2",
+"|' c #898E95",
+"1' c #68707A",
+"2' c #7F868D",
+"3' c #83898E",
+"4' c #868C91",
+"5' c #8B9296",
+"6' c #8A9095",
+"7' c #8A9195",
+"8' c #899095",
+"9' c #84898E",
+"0' c #8D9093",
+"a' c #B9BBBB",
+"b' c #FAFBF9",
+"c' c #F2F4F1",
+"d' c #CFD2D4",
+"e' c #BEC1C5",
+"f' c #8C8F93",
+"g' c #787A7C",
+"h' c #DEDEDE",
+"i' c #FAFBF8",
+"j' c #D3D4D0",
+"k' c #C7C9C8",
+"l' c #B0B3B8",
+"m' c #82858B",
+"n' c #858688",
+"o' c #F4F4F5",
+"p' c #FAF8F9",
+"q' c #EBEBED",
+"r' c #CFD0D4",
+"s' c #BCBEC3",
+"t' c #B5B7BB",
+"u' c #8A8D8E",
+"v' c #7C7D7C",
+"w' c #F1F2F0",
+"x' c #EEF1F4",
+"y' c #C7CDD4",
+"z' c #BBC1C9",
+"A' c #B0B3BB",
+"B' c #A7A6AC",
+"C' c #939495",
+"D' c #D8DAD9",
+"E' c #E6E9E9",
+"F' c #D0D4D7",
+"G' c #B9BDC2",
+"H' c #A9AEB6",
+"I' c #70767E",
+"J' c #6E7378",
+"K' c #E9EDEE",
+"L' c #F8FAFB",
+"M' c #FAFBFC",
+"N' c #FBFBF8",
+"O' c #CFCBC7",
+"P' c #C3BDB7",
+"Q' c #AEA7A0",
+"R' c #A29B93",
+"S' c #848079",
+"T' c #B8B7B3",
+"U' c #FAF5F2",
+"V' c #D7D2CC",
+"W' c #CBC7C0",
+"X' c #B7B8B2",
+"Y' c #A0A7A3",
+"Z' c #757B7A",
+"`' c #9E9BA0",
+" ) c #FDF9FC",
+".) c #FBF7F7",
+"+) c #FAF7F5",
+"@) c #CDC8C6",
+"#) c #C6C3C1",
+"$) c #B2B1B1",
+"%) c #888888",
+"&) c #7D7D7D",
+"*) c #EDEDEE",
+"=) c #FBFBF7",
+"-) c #DAD8D4",
+";) c #D2D1CF",
+">) c #B6B8B6",
+",) c #9DA2A0",
+"') c #7B8382",
+")) c #D2D4D5",
+"!) c #DED9D9",
+"~) c #C0B7B3",
+"{) c #B7ACA5",
+"]) c #A09692",
+"^) c #7D7B7D",
+"/) c #C3C7CD",
+"() c #F2F7F8",
+"_) c #F4F7F8",
+":) c #F3F7F8",
+"<) c #F3F6F8",
+"[) c #F6F6F8",
+"}) c #FAFCFB",
+"|) c #FDFEF9",
+"1) c #E8E8E2",
+"2) c #CBC6C1",
+"3) c #B5AFAA",
+"4) c #ABA6A1",
+"5) c #827C7A",
+"6) c #84807E",
+"7) c #F7F5F6",
+"8) c #F7FCFE",
+"9) c #EFEDE5",
+"0) c #CDC7BD",
+"a) c #BAB4AC",
+"b) c #A8A3A0",
+"c) c #787475",
+"d) c #9F9D9E",
+"e) c #DDDAD6",
+"f) c #D2CDC8",
+"g) c #B4AFA9",
+"h) c #AAA6A0",
+"i) c #7A7772",
+"j) c #908D8B",
+"k) c #CCCDD0",
+"l) c #C0BEC0",
+"m) c #B4AFAF",
+"n) c #ADA5A2",
+"o) c #9B968F",
+"p) c #CDCAC1",
+"q) c #D4D2CB",
+"r) c #BFBDBB",
+"s) c #B3B2B3",
+"t) c #909095",
+"u) c #64656B",
+"v) c #C0C1C4",
+"w) c #F8F9F9",
+"x) c #F9F6EE",
+"y) c #C5BCB0",
+"z) c #B9AB9A",
+"A) c #A79886",
+"B) c #9B907D",
+"C) c #877D6E",
+"D) c #BFBBB4",
+"E) c #FDFBF6",
+"F) c #FCFCF9",
+"G) c #FEFDF8",
+"H) c #FEFAF3",
+"I) c #E2D6CC",
+"J) c #C8B9AC",
+"K) c #B7AA9B",
+"L) c #B1AA9E",
+"M) c #8B8A82",
+"N) c #686865",
+"O) c #D6D5D8",
+"P) c #F9F6F6",
+"Q) c #FBF7F4",
+"R) c #EFE9E2",
+"S) c #BEB2A8",
+"T) c #BDB0A2",
+"U) c #ABA195",
+"V) c #7D7771",
+"W) c #95918D",
+"X) c #FCFAF9",
+"Y) c #FEFEF7",
+"Z) c #F2EDE1",
+"`) c #C8BFB4",
+" ! c #C0B4AB",
+".! c #B1A8A1",
+"+! c #8B8983",
+"@! c #717370",
+"#! c #F9F8F5",
+"$! c #C7BFB8",
+"%! c #B7A89B",
+"&! c #AC9887",
+"*! c #948476",
+"=! c #706861",
+"-! c #EFF1F1",
+";! c #FCFCFE",
+">! c #F9F9F7",
+",! c #D7D1C8",
+"'! c #C3B5A5",
+")! c #AC9C8C",
+"!! c #A09183",
+"~! c #786D62",
+"{! c #A49E99",
+"]! c #FCFAFA",
+"^! c #F7FBFC",
+"/! c #FAF9F4",
+"(! c #E1D9CC",
+"_! c #C5B7A5",
+":! c #AFA090",
+"<! c #9B8D82",
+"[! c #726862",
+"}! c #BCBBB9",
+"|! c #F8F7F0",
+"1! c #CDC5B9",
+"2! c #C4B8A8",
+"3! c #ADA08C",
+"4! c #9A907D",
+"5! c #756C60",
+"6! c #AFA9A4",
+"7! c #F4F3F1",
+"8! c #C5C2BB",
+"9! c #B9B1A6",
+"0! c #ADA293",
+"a! c #A99C89",
+"b! c #A69783",
+"c! c #B5A693",
+"d! c #BAAE9F",
+"e! c #A9A096",
+"f! c #A19A97",
+"g! c #726D70",
+"h! c #838086",
+"i! c #FAFBF6",
+"j! c #FBF8EC",
+"k! c #C1B5A0",
+"l! c #BDAA8F",
+"m! c #AF9C7F",
+"n! c #A5957A",
+"o! c #8E816B",
+"p! c #C1BAB1",
+"q! c #FEFBF5",
+"r! c #F9EFE1",
+"s! c #D5C5B3",
+"t! c #C0AC97",
+"u! c #AB9782",
+"v! c #A69787",
+"w! c #6E665B",
+"x! c #7D7B76",
+"y! c #F5F7F7",
+"z! c #FBF9F1",
+"A! c #E8DED1",
+"B! c #C3B19F",
+"C! c #B39D86",
+"D! c #A18E7A",
+"E! c #7D7368",
+"F! c #B2ABA4",
+"G! c #FEFAF9",
+"H! c #FDFCF2",
+"I! c #E1D8C4",
+"J! c #C4B5A2",
+"K! c #B2A08F",
+"L! c #9C8B7F",
+"M! c #756B64",
+"N! c #A4A29E",
+"O! c #FAF8F2",
+"P! c #C8BFB2",
+"Q! c #BEAB97",
+"R! c #B59C83",
+"S! c #96816C",
+"T! c #706659",
+"U! c #FEFDF7",
+"V! c #FBFAF5",
+"W! c #F9F6F0",
+"X! c #C9BEB4",
+"Y! c #C3AE95",
+"Z! c #B29A80",
+"`! c #9C866F",
+" ~ c #756655",
+".~ c #C0BAB1",
+"+~ c #F9FAFA",
+"@~ c #F8FBFA",
+"#~ c #FDFAF1",
+"$~ c #D2C6B3",
+"%~ c #C6B29A",
+"&~ c #8F7A68",
+"*~ c #76665B",
+"=~ c #D9DAD6",
+"-~ c #FAFCF8",
+";~ c #F8F9F2",
+">~ c #F2F0E3",
+",~ c #C4BAA7",
+"'~ c #BBA98E",
+")~ c #AE9A7C",
+"!~ c #9B8C6F",
+"~~ c #7F7360",
+"{~ c #CBC4BD",
+"]~ c #F7FEFD",
+"^~ c #FBFCFE",
+"/~ c #F6F4ED",
+"(~ c #BFB9AB",
+"_~ c #B6AA94",
+":~ c #AB9D80",
+"<~ c #AF9E7C",
+"[~ c #B29C7C",
+"}~ c #B49C81",
+"|~ c #B09C84",
+"1~ c #AA9A8B",
+"2~ c #81756F",
+"3~ c #5D5656",
+"4~ c #D8D3D7",
+"5~ c #FEFCFA",
+"6~ c #FCFAF8",
+"7~ c #FAFBF5",
+"8~ c #C8BAA4",
+"9~ c #CCB698",
+"0~ c #BFA785",
+"a~ c #BDA480",
+"b~ c #A79172",
+"c~ c #B0A294",
+"d~ c #F6EEE5",
+"e~ c #FBF7F2",
+"f~ c #FEF5EC",
+"g~ c #EDDAC0",
+"h~ c #DDC6A8",
+"i~ c #C1A98B",
+"j~ c #B49D83",
+"k~ c #8F7D6B",
+"l~ c #61554B",
+"m~ c #C4BFBB",
+"n~ c #F8F9F8",
+"o~ c #FDFAF0",
+"p~ c #DECFBA",
+"q~ c #D7BFA1",
+"r~ c #BDA380",
+"s~ c #A38E72",
+"t~ c #7B6F5F",
+"u~ c #D5CEC7",
+"v~ c #FCF9FB",
+"w~ c #FDFEF7",
+"x~ c #F8F1DC",
+"y~ c #DECAAC",
+"z~ c #CBB599",
+"A~ c #B29C84",
+"B~ c #857263",
+"C~ c #685D55",
+"D~ c #E6E4E1",
+"E~ c #FBF7ED",
+"F~ c #D1C3B1",
+"G~ c #CAB198",
+"H~ c #C4A486",
+"I~ c #B19478",
+"J~ c #8D7A67",
+"K~ c #F4F0E5",
+"L~ c #FEFCF6",
+"M~ c #FEFCF7",
+"N~ c #FEFBF6",
+"O~ c #FEFAF5",
+"P~ c #F7F1E7",
+"Q~ c #E7E4DA",
+"R~ c #F6F9F1",
+"S~ c #F7FBF4",
+"T~ c #FDFCF3",
+"U~ c #F7EDE1",
+"V~ c #CEB6A5",
+"W~ c #CFB394",
+"X~ c #BDA384",
+"Y~ c #967F67",
+"Z~ c #776657",
+"`~ c #EFE7DF",
+" { c #F7FAFB",
+".{ c #FDF8E9",
+"+{ c #D4C0A4",
+"@{ c #D3B693",
+"#{ c #BFA483",
+"${ c #89745B",
+"%{ c #837769",
+"&{ c #F6F6F3",
+"*{ c #F8FBF8",
+"={ c #FCFCF4",
+"-{ c #E9E3CE",
+";{ c #CABA9C",
+">{ c #BFA984",
+",{ c #BAA680",
+"'{ c #9E8E6F",
+"){ c #80725E",
+"!{ c #F2EAE3",
+"~{ c #FEF9FA",
+"{{ c #FCFBFE",
+"]{ c #F9FEFC",
+"^{ c #F8F9F7",
+"/{ c #F8F4EB",
+"({ c #C4B9A2",
+"_{ c #BFAF8A",
+":{ c #B6A276",
+"<{ c #BCA67C",
+"[{ c #C0A67F",
+"}{ c #B59D81",
+"|{ c #A08E7A",
+"1{ c #66594F",
+"2{ c #9E9796",
+"3{ c #FCFAFD",
+"4{ c #F9FBF7",
+"5{ c #FBFAF0",
+"6{ c #DCD1BD",
+"7{ c #C7B397",
+"8{ c #C5AA87",
+"9{ c #C6A881",
+"0{ c #C3A47E",
+"a{ c #B29C83",
+"b{ c #C1B09B",
+"c{ c #EADFCE",
+"d{ c #F5EEDF",
+"e{ c #F7F1E2",
+"f{ c #EFE7D6",
+"g{ c #E7D8C2",
+"h{ c #E4CBA9",
+"i{ c #CCB28F",
+"j{ c #C1A886",
+"k{ c #AA9478",
+"l{ c #695947",
+"m{ c #8A7F78",
+"n{ c #F6F1F0",
+"o{ c #F9F6E9",
+"p{ c #DAC8AC",
+"q{ c #D5BA92",
+"r{ c #C2A97F",
+"s{ c #B09A77",
+"t{ c #A28F76",
+"u{ c #E9DECF",
+"v{ c #F1E7DF",
+"w{ c #F3EAE3",
+"x{ c #F3EADD",
+"y{ c #F1E8D2",
+"z{ c #E6D5B4",
+"A{ c #DAC19B",
+"B{ c #C3AB88",
+"C{ c #AA9579",
+"D{ c #71624F",
+"E{ c #9E988F",
+"F{ c #FDF9F0",
+"G{ c #D0C1AD",
+"H{ c #D2B79B",
+"I{ c #C9A582",
+"J{ c #C4A280",
+"K{ c #B59B81",
+"L{ c #C1B19D",
+"M{ c #DCD2BE",
+"N{ c #E5DCC8",
+"O{ c #E6DDC9",
+"P{ c #E8DFCB",
+"Q{ c #E9E0CC",
+"R{ c #E3D9C4",
+"S{ c #E0D4C1",
+"T{ c #CABCAD",
+"U{ c #C9C3B7",
+"V{ c #F9FCF5",
+"W{ c #F9FEF8",
+"X{ c #FCFBEE",
+"Y{ c #F3E4CF",
+"Z{ c #DFC0A3",
+"`{ c #CDAE89",
+" ] c #BDA282",
+".] c #8C7660",
+"+] c #87786C",
+"@] c #FDF8F2",
+"#] c #FAF9F3",
+"$] c #F7EEDA",
+"%] c #DBC29F",
+"&] c #D7B58A",
+"*] c #BA9D76",
+"=] c #8C7A5D",
+"-] c #999282",
+";] c #FCFCF3",
+">] c #E6D9C0",
+",] c #D5BE97",
+"'] c #C1A97D",
+")] c #BDA87E",
+"!] c #AD9D78",
+"~] c #97886D",
+"{] c #F8EFDE",
+"]] c #F8F0E6",
+"^] c #F8F1E8",
+"/] c #F7F3E6",
+"(] c #F8F3E8",
+"_] c #F8F2E6",
+":] c #F7F1E5",
+"<] c #F6F0E4",
+"[] c #E2DFD6",
+"}] c #F1F1EB",
+"|] c #FBF4EB",
+"1] c #CFC0A5",
+"2] c #CEB98A",
+"3] c #C1A875",
+"4] c #C2A57A",
+"5] c #C4A680",
+"6] c #C1A782",
+"7] c #BBA486",
+"8] c #867460",
+"9] c #71665C",
+"0] c #EBE8E7",
+"a] c #F5F9F8",
+"b] c #FCFCF6",
+"c] c #ECE4D6",
+"d] c #B4A38C",
+"e] c #B69E80",
+"f] c #BCA07C",
+"g] c #C4A781",
+"h] c #BBA17C",
+"i] c #C2AB87",
+"j] c #C4B08E",
+"k] c #CAB997",
+"l] c #D2C29E",
+"m] c #D2C19D",
+"n] c #D1BF9B",
+"o] c #C5AD8C",
+"p] c #B59D7D",
+"q] c #988364",
+"r] c #68583F",
+"s] c #6B6052",
+"t] c #EBE6E1",
+"u] c #FBF9F9",
+"v] c #F5F5F7",
+"w] c #F0E7D9",
+"x] c #D2BB9C",
+"y] c #CAAC84",
+"z] c #BFA67D",
+"A] c #C0A780",
+"B] c #C1A481",
+"C] c #C4AA8D",
+"D] c #CAB39A",
+"E] c #CDB69D",
+"F] c #CFB798",
+"G] c #D4BC95",
+"H] c #D1B88F",
+"I] c #BEA680",
+"J] c #B7A07F",
+"K] c #7C6A50",
+"L] c #746958",
+"M] c #E7E4DC",
+"N] c #FDFCF4",
+"O] c #D2C6B4",
+"P] c #C3AC90",
+"Q] c #BF9E7A",
+"R] c #C1A17A",
+"S] c #BEA37F",
+"T] c #BBA88A",
+"U] c #C7B690",
+"V] c #D2C097",
+"W] c #CEBC93",
+"X] c #D0BE95",
+"Y] c #CCB991",
+"Z] c #C8B58D",
+"`] c #B8A67F",
+" ^ c #9B8B77",
+".^ c #DBD3CB",
+"+^ c #FEFCEF",
+"@^ c #E5D4B8",
+"#^ c #DBBE96",
+"$^ c #C3A67E",
+"%^ c #B09675",
+"&^ c #7F6B54",
+"*^ c #A69A8D",
+"=^ c #FDFBF4",
+"-^ c #F8FCFB",
+";^ c #FCFBF3",
+">^ c #ECE0CD",
+",^ c #DAC1A0",
+"'^ c #C9AA82",
+")^ c #A88D68",
+"!^ c #7A694E",
+"~^ c #B7B09F",
+"{^ c #FCF8ED",
+"]^ c #E0CFB3",
+"^^ c #DABE97",
+"/^ c #C3A579",
+"(^ c #BEA579",
+"_^ c #B7A376",
+":^ c #B09C75",
+"<^ c #C8B594",
+"[^ c #CFBB9E",
+"}^ c #D0BFA0",
+"|^ c #D2C39F",
+"1^ c #D4C29E",
+"2^ c #D5C1A0",
+"3^ c #CFBA9B",
+"4^ c #C9B69A",
+"5^ c #BAAB95",
+"6^ c #AFA797",
+"7^ c #F8F6EB",
+"8^ c #F7F8F4",
+"9^ c #F9F2EA",
+"0^ c #CFC0A7",
+"a^ c #CDB88B",
+"b^ c #C0A775",
+"c^ c #C0A177",
+"d^ c #BEA07B",
+"e^ c #BCA17F",
+"f^ c #A08A6F",
+"g^ c #695B4A",
+"h^ c #B2ABA3",
+"i^ c #F9F8F9",
+"j^ c #F7FAFD",
+"k^ c #F8F8F8",
+"l^ c #FBF9F0",
+"m^ c #BDB1A1",
+"n^ c #928169",
+"o^ c #958063",
+"p^ c #A98F6E",
+"q^ c #B59973",
+"r^ c #B79B75",
+"s^ c #BDA47D",
+"t^ c #C0A980",
+"u^ c #C0AA7F",
+"v^ c #B7A176",
+"w^ c #A18C65",
+"x^ c #867257",
+"y^ c #726046",
+"z^ c #63553D",
+"A^ c #89806E",
+"B^ c #E0DCD2",
+"C^ c #E9E8E6",
+"D^ c #E1E0E4",
+"E^ c #DBDADD",
+"F^ c #DCD8D5",
+"G^ c #D2C3B2",
+"H^ c #CAAE8E",
+"I^ c #BF9F77",
+"J^ c #B59C76",
+"K^ c #B69F7B",
+"L^ c #B89C77",
+"M^ c #BFA582",
+"N^ c #BBA381",
+"O^ c #BBA380",
+"P^ c #BCA079",
+"Q^ c #B89A6E",
+"R^ c #AA9067",
+"S^ c #9F8A69",
+"T^ c #7A684C",
+"U^ c #5C503A",
+"V^ c #C1BBAD",
+"W^ c #EFEFE8",
+"X^ c #EEF0EE",
+"Y^ c #F4F2ED",
+"Z^ c #D7CDBF",
+"`^ c #AB9880",
+" / c #AF9571",
+"./ c #B1956D",
+"+/ c #B69D75",
+"@/ c #B49F7A",
+"#/ c #BAA37E",
+"$/ c #BCA47E",
+"%/ c #BCA37D",
+"&/ c #7D6541",
+"*/ c #776755",
+"=/ c #F2E9E4",
+"-/ c #F5F1F4",
+";/ c #F5F3F6",
+">/ c #D1C2A2",
+",/ c #CBB586",
+"'/ c #B19872",
+")/ c #957E61",
+"!/ c #6E5D47",
+"~/ c #CCC2B6",
+"{/ c #F5F4ED",
+"]/ c #EBF0ED",
+"^/ c #EAEFEE",
+"// c #F3EEE6",
+"(/ c #D3C6B5",
+"_/ c #CEB99C",
+":/ c #B19675",
+"</ c #8E7658",
+"[/ c #6E5F48",
+"}/ c #DDD5C8",
+"|/ c #EEEBE7",
+"1/ c #F2F0EC",
+"2/ c #EDE5D8",
+"3/ c #D2BBA1",
+"4/ c #CEAE88",
+"5/ c #B69770",
+"6/ c #B29973",
+"7/ c #AD966F",
+"8/ c #AE9671",
+"9/ c #B9A07C",
+"0/ c #BFA781",
+"a/ c #C5AD84",
+"b/ c #C8B182",
+"c/ c #C8AD80",
+"d/ c #C9A97F",
+"e/ c #C5A681",
+"f/ c #B19676",
+"g/ c #86715A",
+"h/ c #AB9E90",
+"i/ c #EFEAE4",
+"j/ c #EDEDEB",
+"k/ c #EDEEEC",
+"l/ c #EEE9E2",
+"m/ c #C1B39F",
+"n/ c #C0AD87",
+"o/ c #B79D73",
+"p/ c #B19470",
+"q/ c #AF9272",
+"r/ c #A88E72",
+"s/ c #715E48",
+"t/ c #786D61",
+"u/ c #ECE9E5",
+"v/ c #F3F4F5",
+"w/ c #F5F5F5",
+"x/ c #F1F1F1",
+"y/ c #ECECEC",
+"z/ c #E7E7E7",
+"A/ c #E4E4E4",
+"B/ c #E2E2E2",
+"C/ c #E5E5E5",
+"D/ c #EBEBEB",
+"E/ c #F2EFE5",
+"F/ c #B6AC9D",
+"G/ c #8C7F69",
+"H/ c #827059",
+"I/ c #836D53",
+"J/ c #8B7459",
+"K/ c #897256",
+"L/ c #877052",
+"M/ c #816C4E",
+"N/ c #756143",
+"O/ c #69573D",
+"P/ c #655847",
+"Q/ c #7A6F5F",
+"R/ c #B6B0A1",
+"S/ c #E0DED3",
+"T/ c #DDDCD7",
+"U/ c #CDCDCD",
+"V/ c #B9B9BB",
+"W/ c #A6A6A5",
+"X/ c #A49E95",
+"Y/ c #B6A28C",
+"Z/ c #C2A17E",
+"`/ c #B08F67",
+" ( c #AA9371",
+".( c #8C7B60",
+"+( c #8D7A61",
+"@( c #86755C",
+"#( c #7D6E53",
+"$( c #7D6E51",
+"%( c #7A684A",
+"&( c #766243",
+"*( c #6F5D41",
+"=( c #665740",
+"-( c #625745",
+";( c #AAA396",
+">( c #E0DDD5",
+",( c #D5D4CF",
+"'( c #D2D3D0",
+")( c #CFCCC9",
+"!( c #D0C8C0",
+"~( c #9D927F",
+"{( c #807154",
+"]( c #816F4E",
+"^( c #877453",
+"/( c #887559",
+"(( c #8A735E",
+"_( c #8C7361",
+":( c #886F5D",
+"<( c #88705E",
+"[( c #7E6554",
+"}( c #745B49",
+"|( c #5F4836",
+"1( c #8C8076",
+"2( c #E0DAD7",
+"3( c #D8D4D7",
+"4( c #D8D5D7",
+"5( c #D9D3CA",
+"6( c #ADA187",
+"7( c #92825B",
+"8( c #7A6749",
+"9( c #695741",
+"0( c #685B4C",
+"a( c #DAD3CB",
+"b( c #D6D4D0",
+"c( c #C9CDCB",
+"d( c #C3C9C6",
+"e( c #D2CCC5",
+"f( c #B7AB9E",
+"g( c #9B8A75",
+"h( c #78664C",
+"i( c #66553E",
+"j( c #6E6251",
+"k( c #CDC7BC",
+"l( c #C7C4C1",
+"m( c #C7C5C2",
+"n( c #C6BDB3",
+"o( c #B49F89",
+"p( c #987C5E",
+"q( c #8A7055",
+"r( c #867159",
+"s( c #836E56",
+"t( c #826D55",
+"u( c #866F57",
+"v( c #887257",
+"w( c #8B7354",
+"x( c #8C7451",
+"y( c #8E7451",
+"z( c #896A4D",
+"A( c #84664B",
+"B( c #715641",
+"C( c #675346",
+"D( c #B4A8A4",
+"E( c #DDD8DB",
+"F( c #DBDCDE",
+"G( c #D9DCD9",
+"H( c #E1DED9",
+"I( c #B5AA9C",
+"J( c #98876B",
+"K( c #836F4E",
+"L( c #806B51",
+"M( c #7E6651",
+"N( c #725C48",
+"O( c #584A3C",
+"P( c #9E9892",
+"Q( c #D5D5D5",
+"R( c #E7E9EB",
+"S( c #EEF1F1",
+"T( c #ECEDEE",
+"U( c #E9E9E9",
+"V( c #E1E1E1",
+"W( c #DBDBDB",
+"X( c #C8C8C8",
+"Y( c #C7C7C7",
+"Z( c #CBCBCB",
+"`( c #D4D4D4",
+" _ c #DFDFDF",
+"._ c #F4F4F4",
+"+_ c #EAEAE8",
+"@_ c #DFDED7",
+"#_ c #BDB9AD",
+"$_ c #928A7C",
+"%_ c #786F61",
+"&_ c #746859",
+"*_ c #766758",
+"=_ c #78695A",
+"-_ c #7A6D5F",
+";_ c #85796E",
+">_ c #988F87",
+",_ c #C2BDB6",
+"'_ c #D5D4CC",
+")_ c #DEE0D9",
+"!_ c #D4D7D2",
+"~_ c #CBCDCA",
+"{_ c #B2B2B1",
+"]_ c #979695",
+"^_ c #7D7C76",
+"/_ c #807769",
+"(_ c #AE957B",
+"__ c #B9936E",
+":_ c #A47F5B",
+"<_ c #8E775D",
+"[_ c #605244",
+"}_ c #766A61",
+"|_ c #72695C",
+"1_ c #716C5B",
+"2_ c #716F5E",
+"3_ c #7A7466",
+"4_ c #847C70",
+"5_ c #8D847A",
+"6_ c #9E978D",
+"7_ c #C1BEB6",
+"8_ c #CFCEC9",
+"9_ c #C0BFBD",
+"0_ c #B3B2AF",
+"a_ c #9F9B98",
+"b_ c #9F9A9A",
+"c_ c #A8A1A0",
+"d_ c #A49D94",
+"e_ c #928978",
+"f_ c #827765",
+"g_ c #786C5C",
+"h_ c #736559",
+"i_ c #74655F",
+"j_ c #766763",
+"k_ c #756662",
+"l_ c #776864",
+"m_ c #746561",
+"n_ c #70615D",
+"o_ c #887A76",
+"p_ c #BCB5B3",
+"q_ c #C5C3C1",
+"r_ c #BBBAB8",
+"s_ c #B5B4B0",
+"t_ c #BAB6AD",
+"u_ c #948D7D",
+"v_ c #857A67",
+"w_ c #7D7160",
+"x_ c #756A5D",
+"y_ c #786F67",
+"z_ c #ACA7A4",
+"A_ c #A8A7A6",
+"B_ c #9D9F9D",
+"C_ c #9EA19E",
+"D_ c #B1ADA9",
+"E_ c #9D948D",
+"F_ c #877D6F",
+"G_ c #796F5F",
+"H_ c #736A5C",
+"I_ c #716A60",
+"J_ c #908B85",
+"K_ c #91918F",
+"L_ c #969695",
+"M_ c #A19A94",
+"N_ c #998779",
+"O_ c #8A7462",
+"P_ c #807164",
+"Q_ c #756A62",
+"R_ c #72655B",
+"S_ c #6E6257",
+"T_ c #6F6257",
+"U_ c #6D6053",
+"V_ c #6E5F51",
+"W_ c #716353",
+"X_ c #766759",
+"Y_ c #79685A",
+"Z_ c #7B6A5D",
+"`_ c #78685D",
+" : c #867A75",
+".: c #D3CDCC",
+"+: c #D4D2D7",
+"@: c #D2D5D5",
+"#: c #D7DAD6",
+"$: c #E3E1DE",
+"%: c #BAB4AB",
+"&: c #887E6B",
+"*: c #756A54",
+"=: c #65594B",
+"-: c #605045",
+";: c #5C4C42",
+">: c #5D554F",
+",: c #939392",
+"': c #B9BABC",
+"): c #D1D3D2",
+"!: c #D4D3D0",
+"~: c #D0CFCD",
+"{: c #CACACA",
+"]: c #C4C4C4",
+"^: c #C0C0C0",
+"/: c #BEBEBE",
+"(: c #BFBFBF",
+"_: c #C1C1C1",
+":: c #C5C5C5",
+"<: c #D1D1D1",
+"[: c #DDDDDD",
+"}: c #EEEEEE",
+"|: c #F5F7FB",
+"1: c #DEE2E5",
+"2: c #B5B9B9",
+"3: c #9C9F9A",
+"4: c #878881",
+"5: c #797D75",
+"6: c #818279",
+"7: c #9D9A91",
+"8: c #B7B2AB",
+"9: c #C9C5C2",
+"0: c #D5D4D6",
+"a: c #DBDCDF",
+"b: c #D7DADA",
+"c: c #D6DBDB",
+"d: c #C9D1CF",
+"e: c #C5CCCB",
+"f: c #BBBEBD",
+"g: c #ABAAA8",
+"h: c #96938F",
+"i: c #89887D",
+"j: c #968B79",
+"k: c #A98D70",
+"l: c #A77E59",
+"m: c #9A7454",
+"n: c #755E4B",
+"o: c #60534D",
+"p: c #9B9091",
+"q: c #938C88",
+"r: c #8E8E85",
+"s: c #9A9B93",
+"t: c #B1B2AF",
+"u: c #C6C5C8",
+"v: c #D5D4D5",
+"w: c #D8D8D8",
+"x: c #C9CBCC",
+"y: c #BBBDC1",
+"z: c #ADAEB1",
+"A: c #9C9898",
+"B: c #9B9391",
+"C: c #9C9497",
+"D: c #A29CA0",
+"E: c #A09C9A",
+"F: c #A29F99",
+"G: c #9A9692",
+"H: c #928C8C",
+"I: c #91888C",
+"J: c #95908E",
+"K: c #A2A09A",
+"L: c #AEABA6",
+"M: c #B8B5B0",
+"N: c #C5C2BD",
+"O: c #C1BFBA",
+"P: c #C6C4BF",
+"Q: c #C2C2C2",
+"R: c #C0C1BF",
+"S: c #C0C1BA",
+"T: c #BFC1B6",
+"U: c #BFBFB6",
+"V: c #C5C1BC",
+"W: c #C9C3C2",
+"X: c #CBC5BF",
+"Y: c #C2BBB7",
+"Z: c #ACA7A6",
+"`: c #989496",
+" < c #939192",
+".< c #9B9A99",
+"+< c #ADADAA",
+"@< c #C3C0BF",
+"#< c #D3CFCB",
+"$< c #D6D1CA",
+"%< c #CCC8BE",
+"&< c #B2B0A6",
+"*< c #9E9D97",
+"=< c #858481",
+"-< c #868788",
+";< c #949597",
+">< c #B1AEAB",
+",< c #C7BBB3",
+"'< c #D1C3BB",
+")< c #C9C4C4",
+"!< c #B6B7B9",
+"~< c #A8A49F",
+"{< c #8F8B86",
+"]< c #83807A",
+"^< c #84837D",
+"/< c #93908D",
+"(< c #A6A5A2",
+"_< c #B2B2AF",
+":< c #C0C0BC",
+"<< c #C8C6C1",
+"[< c #D2CFC9",
+"}< c #D7D5D0",
+"|< c #D5D7D2",
+"1< c #D9DDDB",
+"2< c #E0E6E1",
+"3< c #E6EAE3",
+"4< c #EBEBE9",
+"5< c #EAE6E2",
+"6< c #C4C0B5",
+"7< c #969186",
+"8< c #6C6864",
+"9< c #605653",
+"0< c #615653",
+"a< c #6E6B6B",
+"b< c #8B8D90",
+"c< c #A9ACAD",
+"d< c #B9B9B6",
+"e< c #C4C0B8",
+"f< c #C0BEBA",
+"g< c #E6E6E6",
+"h< c #EDEDED",
+"i< c #F3F3F3",
+"j< c #FFFDFE",
+"k< c #F5F6F7",
+"l< c #E1E3E4",
+"m< c #C4C6C6",
+"n< c #ADAEAD",
+"o< c #9E9F9D",
+"p< c #9B9E9B",
+"q< c #A6A8A5",
+"r< c #BDBDBA",
+"s< c #CECECB",
+"t< c #D9D9D9",
+"u< c #E1E1E3",
+"v< c #DFE0E3",
+"w< c #DDDFE0",
+"x< c #D5D7D8",
+"y< c #CCCFCF",
+"z< c #C7CACA",
+"A< c #C3C5C4",
+"B< c #C3C3C2",
+"C< c #C1BFBD",
+"D< c #AE9B89",
+"E< c #A07F63",
+"F< c #997151",
+"G< c #856248",
+"H< c #604939",
+"I< c #70655F",
+"J< c #9B9798",
+"K< c #A5A3A1",
+"L< c #AEAEAB",
+"M< c #BBBBB9",
+"N< c #CDCECE",
+"O< c #D9D9DB",
+"P< c #D9DADB",
+"Q< c #CECFD1",
+"R< c #C7C7CA",
+"S< c #BFBFC1",
+"T< c #BEBDBD",
+"U< c #C0BEBC",
+"V< c #C8C5C6",
+"W< c #CCCACC",
+"X< c #C4C3C3",
+"Y< c #B2B2B2",
+"Z< c #AAAAAA",
+"`< c #A5A2A5",
+" [ c #A9A7AA",
+".[ c #B3B2B2",
+"+[ c #BFC0BD",
+"@[ c #CACAC7",
+"#[ c #CECFCC",
+"$[ c #D1D1CE",
+"%[ c #D4D4D2",
+"&[ c #D5D6D3",
+"*[ c #D6D7D6",
+"=[ c #D7D8D7",
+"-[ c #DDDDDB",
+";[ c #DEDFDA",
+">[ c #E2E2DF",
+",[ c #DEDEDD",
+"'[ c #D6D4D6",
+")[ c #CFCDCC",
+"![ c #BEBCBB",
+"~[ c #B2B0B1",
+"{[ c #B0AFB0",
+"][ c #B6B5B6",
+"^[ c #C7C6C6",
+"/[ c #D8D8D7",
+"([ c #E5E4E4",
+"_[ c #EAE9E8",
+":[ c #E2E1DE",
+"<[ c #D0CFCC",
+"[[ c #AFAEAD",
+"}[ c #AEAEAD",
+"|[ c #B5B6B6",
+"1[ c #C8C9C9",
+"2[ c #D7D6D6",
+"3[ c #DFDBD9",
+"4[ c #D9D5D3",
+"5[ c #CAC9CA",
+"6[ c #BABBBD",
+"7[ c #AEADAC",
+"8[ c #A3A3A1",
+"9[ c #A5A5A3",
+"0[ c #BDBDBD",
+"a[ c #CCCDCE",
+"b[ c #D4D5D5",
+"c[ c #D6D8D8",
+"d[ c #DBDBDA",
+"e[ c #DCDCDA",
+"f[ c #E2E3E0",
+"g[ c #E8EAE8",
+"h[ c #EEF1EE",
+"i[ c #F7F6F6",
+"j[ c #ECEBEA",
+"k[ c #CFCECB",
+"l[ c #AFAFAC",
+"m[ c #9A9A9A",
+"n[ c #979594",
+"o[ c #989594",
+"p[ c #9F9F9F",
+"q[ c #ACADAF",
+"r[ c #B9BABB",
+"s[ c #C9C9C8",
+"t[ c #D1CFCC",
+"u[ c #D7D7D5",
+"v[ c #DCDCDC",
+"w[ c #EAEAEA",
+"x[ c #EFEFEF",
+"y[ c #F2F2F2",
+"z[ c #D7D7D7",
+"A[ c #D6D6D6",
+"B[ c #DADADA",
+"C[ c #E9E9E6",
+"D[ c #EBE5DA",
+"E[ c #8F7155",
+"F[ c #826042",
+"G[ c #6C4F35",
+"H[ c #4F3D29",
+"I[ c #A49C93",
+"J[ c #E3E3E3",
+"K[ c #F6F6F6",
+"L[ c #F0F0F0",
+"M[ c #F9F9F6",
+"N[ c #F4F1E6",
+"O[ c #807562",
+"P[ c #5D492F",
+"Q[ c #4B3417",
+"R[ c #422F17",
+"S[ c #605542",
+"T[ c #DDD9D0",
+"U[ c #FAFAF6",
+"V[ c #C7C2B9",
+"W[ c #82786B",
+"X[ c #7A6E5F",
+"Y[ c #7A7165",
+"Z[ c #8E8A80",
+"`[ c #F8F7F2",
+" } c #FFFCFB",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ # # $ % & * = - - ; > , ' ) ! ~ { ] ^ / ( _ _ : < [ } } | | 1 # | } } } } } } } | | | | | | } } } } } } } } 2 } } | | | 1 1 1 1 1 1 1 1 1 1 1 1 1 | } } } } } } 3 4 5 6 7 8 9 0 a b b c d e f 0 = g h i j k l m n o p q r = s t u v v w x t * y z A | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ B | | C D E F G H I J K L M N O P Q R S T | C C U V W } } } | | | | | | | | | | | | | | | | | | | | | | | | } 2 } | | | | | | | | | | | | | | | | | | } } } } } } ) X Y Z ` ...+. at .#.$.%.&.&.*.=.-.;.>.,.'.).!.~.{.].^.q 4 /.(._.L :.<.[.}.|.1.2.z 3.| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # | 4.} 2 5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.& | | | | | | | 1 1 1 1 1 1 | | | | | | | 1 1 1 1 1 1 1 | 4.| | | | | | | | | | | | | | | | | | | | | | | | | |.q.r.s.t.u.v.w.x.y.z.z.y.A.B.C.D.E.F.G.H.I.w J.y K.^.L.M.j N.O.P.Q.R.S.T.U.V.n.z W.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # C } q X.} Y.Z.`. +.+++ at +#+$+%+&+*+=+-+;+>+,+'+)+!+~+z & & & & & & & ~+~+& & & ~+| | | | | | | ~+& ~+& ~+& & | | | | | | | & & & & & & & & & !+& & & ~+| | {+| | | ]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+9+0+a+b+c+1.d+e+# q d+f+g+h+i+j+k+l+m+n+o+n.z p+1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 C } q+r+s+t+u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+J+K+L+y 1 3.3.3.# 1 {+| } } )+} )+} } } | | | | | | } )+)+n.)+} } 1 M+1 1 | | | 1 N+1 S O+i A {+1 O+O+1 1 1 1 1 P+1 | | Q+R+S+T+U+V+W+X+Y+Y+Z+`+Y+ @. at +@@@#@$@%@&@*@=@-@)+z 1 } ;@>@,@'@)@!@~@{@]@^@/@n.z (@1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | U !+2._@:@<@[@}@|@1 at 2@3 at 4@5 at 6@7 at 8@9 at 0@a at b@c at d@e at 8 !.f at W.W.f@g at 3.3.(@(@(@f@(@(@(@1 | | | | | | h@(@f at f@(@f at f@(@3.# 1 | {+} _ at i@j@(@(@(@j at 3.(@3.(@(@(@(@!.O+1 1 1 1 Q+k at l@m at n@o at p@q at r@s at t@t at u@v at w@x at y@z at A@B at C@D at E@F at n.| 1 } ,+G at H@I at J@K at L@M at N@O at S z 1 A | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B P@[ S I Q at R@S at T@U at V@W at X@Y at Z@`@ #.#+#@###$#%#&#E y *#=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#h 6.{.:#<#[#}#|#1#;#2#3#4#5#6#7#x :#8#9#_ at 0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#i 1 z 3._.o#p#q#r#s#t#u#f at v#v#w#v#w#x#y#z#A#B#C#D#E#j.F#G#!+e+h at H#I#J#K#L#M#N#O#L.) e+K.| n.| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . M+e+P at v P#Q#R#S#T#U#V#W#! X#= Y#Z#`# $.$+$@$#$$$e@!.%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$s+9#a$b$c$d$e$f$g$h$i$j$k$l$m$m$n$o$p$q$q+n.]+r$s$t$u$v$w$x$& 1 1 | | {+z y$f at z$A$B$C$D$E$F$O+8 G$H$I$J$K$L$M$N$O$P$| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.~+@ Q$R$S$T$U$V$W$X$Y$Z$/.@ O+`$ %.%+%@%#%$%%%{.i@&%*%=%-%;%>%,%'%)%!%~%{%]%^%/%(%_%:%t <%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%R d%e%f%g%h%i%j%k%l%m%n%o%p%q%r%s%q+n.t%u%v%w%x%y%z%u & | 1 | | ~+& g i at A%B%C%D%E%F%G%t 8 E _ at H%I%J%K%L%M%N%O%| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i | 3.P%Q%R%S%T%U%V%W%X%Y%Z%& S `% &.&+&@&#&$&%&&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&k e&Q+f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&X.q v&w&x&y&z&A&B&C&P+(@3.# | D&& g k E&F&G&H&I&J&K&L&F D&f+M&N&O&P&Q&R&S&T&& | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . U&S V&W&X&Y&Z&`& *.*~+!+N+Z%K.+*@*#*$*%*q&&***=*G f at -*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*j@}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*f at l Q$e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*)+u*v*w*x*y*z*A*B*C*D*E*F*G*H*I*J*K*3.L*M*N*O*P*Q*R*S*T*W%U*V*W*X*Y*Z*`* =8 & | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .=O++=@=#=$=%=&=*===y y 1 -=3.1 *&;=>=,='=)=!=~={=|.]=^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=0=a=b=c=d=e=f=g=h=i=j=k=l=m=n=g at m o=p=q=r=s=t=u=v=w=Q+x=y=z=A=B=C=D=i E=F=G=H=I=J=K=L=M=N=O=P=Q=R=S=T=U=3.V=W=X=Y=Z=`= -{..-C&+- at -#-$-%-&-*-1.=-~+| | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . --!.;->-,-'-)-!-~-:#< < z *&3.M+*&{-]-^-/-(-_-Z%p )#:-<-[-}-|-1-2-3-4-5-6-7-8-9-0-a-b-c-d-e-f-g-h-i-j-k-b%H l-m-n-o-p-q-!.r-s-t-u-v-w-x-y-z-F A-B-C-D-E-F-G-H-l _ at I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-i@h at X-Y-Z-`- ;.;I** s +;@;#;$;%;&;*;=;r 8#| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . :%v -;;;>;,;';);!;~;E < 1 3.u 1 j@{;];^;/;(;_;^.:;<;@=[;};|;1;*#2;3;4;5;w 6;7;8;9;0;a;b;c;d;e;f;g;h;i;j;k;l;m;n;o;p;q;r;s;9 t;u;v;w;x;y;z;A;B;C;D;E;F;G;H;I;W%S J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z%s Z;`; >.>+>@>#>s;$>%>&>*>=>->;>j 1.) D&| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >>,>'>)>!>~>{>]>^>/>P@(>| P+D&N+_>:><>[>}>|>1>P+3.2>3>4>5>6>7>|.Y#G#8>9>0>a>b>c>d>e>D=f>g>h>i>j>k>l>m>n>o>p>q>r>s>t>u>v>S w>x>y>z>A>B>C>D>y & # E>F>G>H>I>J>w>A K>L>M>N>O>P>Q>R>S>T>U>V>W>X>Y>Z>K.>>`> ,.,+,@,#,$,j@%,&,*,N;=,-,;,3.| ~+P@| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ _@>,,,',),!,~,k />.={,B P+| A ],^,/,(,_,:,<,e&l [,i#},|,1,2,(@{+)+, H-3,4,5,6,7,8,9,0,a,b,c,d,e,f,g,h,g,i,j,k,l,m,n,o,h W%p,q,r,s,t,u,K.{+z ^.v,w,x,y,z,A,O+A B,C,D,E,F,G,H,I,J,j@# i at Y.Y.K,j h = L,M,N,O,P,Q,R,n#S,F>T,U,V,W,X,w>| & P@| | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X#j Y,Z,`, '.'+'h @'& {,& {+#'r+$'%'&'*'='-';'J.;'>',''')'!'~'# 2.2.1.# {']'^'/'('_':'<'['}'|'1'2'3'4'5'6'7'8';>9'0'a'($b'c'd'e'`,f'g'h') j u i'j'k'l'm'n'o'p'X#q'r's't'u'v'w'($!.{+~+~+~+D&K*y$= {+x'y'z'A'B'C'D'E'F'G'H'I'J'K'L'M'| & & | | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P+N'O'P'Q'R'S'T'g=- = & & !+~.U'V'W'X'Y'Z'`' ).)+)@)#)$)%)&)*)| | | & =)-);)>),)')))!)~){)])^)/)()_%_)_%_):)<)[)e=O%})@ |)1)2)3)4)5)6)7)b$8)s 9)0)a)b)c)d)y$- - e)f)g)h)i)j)!+& ~+~+~+~+~+& ~+& X#| ==k)l)m)n)o)p)q)r)s)t)u)v)w)X#X#| & & | | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ x)y)z)A)B)C)D)E)F)z % & G)H)I)J)K)L)M)N)O)P)Q)R)S)T)U)V)W)X)| | 1 Y)Z)`) !.!+!@!#!$!%!&!*!=!-!h at N+N+N+A N+;!e@; >!* P@:$,!'!)!!!~!{!]!h@^!/!(!_!:!<![!}!* &&|!1!2!3!4!5!6!d+1 P+z | | | | | } ;!O+7!8!9!0!a!b!c!d!e!f!g!h!p'; g g & & & | | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i!j!k!l!m!n!o!p!q!* !.1 = q!r!s!t!u!v!w!x!y!; z!A!B!C!D!E!F!G!} 1 # H!I!J!K!L!M!N!O!P!Q!R!S!T!d z | | | ~+~+D&U!V!d g E W!X!Y!Z!`! ~.~+~f@@~#~$~%~C!&~*~=~-~;~>~,~'~)~!~~~{~!+# ]~p+1 1 1 1 N+^~N+8#/~(~_~:~<~[~}~|~1~2~3~4~J.5~6~& & & & ~+| | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7~j!8~9~0~a~b~c~d~e~^ 8>8 f~g~h~i~j~k~l~m~n~s o~p~q~r~s~t~u~] v~* w~x~y~z~A~B~C~D~E~F~G~H~I~J~K~L~M~M~M~N~O~O~P~Q~R~S~T~U~V~W~X~Y~Z~`~@' {d .{+{@{#{${%{&{*{={-{;{>{,{'{){!{~{{{,>]{{+2.9 &&^{U=1 * /{({_{:{<{[{r~}{|{1{2{3{2.!+2.D&~+~+~+{+| | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4{5{6{7{8{9{0{a{b{c{d{e{f{g{h{i{j{k{l{m{n{5-s o{p{q{r{s{t{u{v{w{x{y{z{A{B{C{D{E{>!F{G{H{I{J{K{L{M{N{O{P{Q{R{S{T{U{V{W{X{Y{Z{`{ ].]+]@]8>Y##]$]%]&]*]=]-]F)^.;]>],]'])]!]~]{]]]^]/]/](]_]:]<][]}]/>2.|]1]2]3]4]5]6]7]8]9]0];!A | | | | | | | | | | | {+| | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a]b]c]d]e]f]g]h]i]j]k]l]m]n]o]p]q]r]s]t]u]v]&{w]x]y]z]A]B]C]D]E]F]G]H]I]J]K]L]M]^{N]O]P]Q]R]S]T]U]V]W]X]Y]Z]`] ^.^> 7 +^@^#^$^%^&^*^=^L&-^;^>^,^'^)^!^~^T*F){^]^^^/^(^_^:^<^[^}^|^1^2^3^4^5^6^7^8^8#9^0^a^b^c^d^e^f^g^h^i^j^N+{+{+{+{+/.5-b%X%k^5-X#| | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . g at 7 l^m^n^o^p^q^r^s^t^u^v^w^x^y^z^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^`^ /./+/@/#/$/%/$/J^J^&/*/=/-/;/P~>/,/'/)/!/~/{/]/^///(/_/:/</[/}/|/1/2/3/4/5/6/7/8/9/0/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/s+j 5-X%w/x/y/z/A/B/C/D/x/b%X#| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . *&# {.E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/`/ (.(+(@(#($(%(&(*(=(-(;(>(,('()(!(~({(](^(/(((_(:(<([(}(|(1(2(3(4(5(6(7(8(9(0(a(b(c(d(e(f(g(h(i(j(k(l(m(n(o(p(q(r(s(t(u(v(w(x(y(z(A(B(C(D(E(F(G(H(I(J(K(L(M(N(O(P(Q(R(S(T(U(V(W(Q(U/X(Y(Z(`( _U(._/.{+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #'l.Z$+_ at _#_$_%_&_*_=_-_;_>_,_'_)_!_~_{_]_^_/_(___:_<_[_}_|_1_2_3_4_5_6_7_8_9_0_a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z_A_B_C_D_E_F_G_H_I_J_K_L_M_N_O_P_Q_R_S_T_U_V_W_X_Y_Z_`_ :.:+:@:#:$:%:&:*:=:-:;:>:,:':):!:~:{:]:^:/:(:_:::<:[:C/}:b%{+| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . G#r+|:1:2:3:4:5:6:7:8:9:0:a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z:A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:`: <.<+<@<#<$<%<&<*<=<-<;<><,<'<)<!<~<{<]<^</<(<_<:<<<[<}<|<1<2<3<4<5<6<7<8<9<0<a<b<c<d<e<f<_:Y(Z(<:w: _g<h<i<X%X#| | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j<} k<l<m<n<o<p<q<r<s<t<u<v<w<x<y<z<A<B<C<.~D<E<F<G<H<I<J<K<L<M<N<O<#>P<Q<R<S<T<U<V<W<X<Y<Z<`< [.[+[@[#[$[%[&[*[=[-[;[>[,['[)[![~[{[][^[/[([_[:[<[r<[[}[|[1[2[3[4[5[6[7[8[9[n<0[a[b[c[d[e[-[f[g[h[>!i[j[k[l[m[n[o[p[q[r[s[t[u[v[C/w[x[i<X%k^5-X#| {+| | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | | 5-y[C/[:z[A[B[B/U(y/}:h<D/z/B/B/C/J*C[D[D!E[F[G[H[I[{:A[[:J[U(y/y/U(A/V(V(J[U(}:}:z/h't<z[B[ _C/J*J*w[D/D/D/}:i<K[K[i<h<C/[:B[[:C/x[._b%k^L[g< _W( _C/}:i<y[h<J[[:w:Q(t<h'C/J*w[y/h<h<}:x/K[5-{+{+X%z/v[z[A[`(A[W(V(w[x[y[w/b%/.5-X#{+| | | | {+{+{+| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | | | X#5-b%X%X%k^b%b%b%b%b%5-b%X%k^b%5-M[N[O[P[Q[R[S[T[w/K[k^5-5-/./.5-b%b%5-/.X#{+X#5-k^X%X%k^k^b%/./.5-5-5-/.X#| | | {+X#b%k^X%k^/.| | | {+| 5-k^X%b%5-{+| X#b%k^b%k^X%X%b%/.b%5-5-b%b%b%/.{+| {+| {+5-k^X%X%K[X%b%b%/.{+{+| | | | | | | {+{+{+{+{+{+| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | | | | | | | X#X#{+{+{+{+X#| | {+{+| | Y#U[V[W[X[Y[Z[`[{+{+{+| | | | | {+{+| | | | | | | {+X#X#{+{+| | | | | | {+X#/.X#| {+| | | | X#{+X#| {+{+{+| | | | | {+{+{+{+| | | | | | {+| | | | {+X#| | | | | {+X#{+{+{+{+| | {+{+| | | | | | | | | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | . . | . . | {+| {+| | {+{+| {+| . . . C A j<5. }o.U U | | | | | | {+{+{+| | | | | | | | | {+X#| | | | | | {+X#X#{+X#X#{+{+| | | | /.| X#| {+{+{+| | {+{+{+X#{+{+{+| | | | | | | | {+{+{+| {+{+| | | | {+| {+/././.{+| {+X#| . | | | | | | | | | | | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};
Added: packages/openev/branches/upstream/current/pics/openfile.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/openfile.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/openfile.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,29 @@
+/* XPM */
+static char *openfile[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808000",
+"a c None",
+"b c #ffff00",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaa...aaaaaaa",
+"aaaaaaaaaaa.aaa.a.aaaa",
+"aaaaaaaaaaaaaaaa..aaaa",
+"aaaa...aaaaaaaa...aaaa",
+"aaa.bbb.......aaaaaaaa",
+"aaa.bbbbbbbbb.aaaaaaaa",
+"aaa.bbbbbbbbb.aaaaaaaa",
+"aaa.bbbb...........aaa",
+"aaa.bbb.#########.aaaa",
+"aaa.bb.#########.aaaaa",
+"aaa.b.#########.aaaaaa",
+"aaa..#########.aaaaaaa",
+"aaa...........aaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/pan_left.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/pan_left.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/pan_left.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,28 @@
+/* XPM */
+static char * pan_left_xpm[] = {
+"22 18 7 1",
+" c None",
+". c #000000",
+"+ c #333366",
+"@ c #6666CC",
+"# c #9999FF",
+"$ c #CCCCFF",
+"% c #FFFFFF",
+" ",
+" .+ ",
+" . at + ",
+" .@@+ ",
+" .@@#+ ",
+" .@@##+++++++ ",
+" .@@##$$$$$$$+ ",
+" .@@@#$$$$$$$%+ ",
+" .@@@##$$$%%%%%+ ",
+" .@@@##$$$%%%%%+ ",
+" .@@@#$$$$$$$%+ ",
+" .@@##$$$$$$$+ ",
+" .@@##+++++++ ",
+" .@@#+ ",
+" .@@+ ",
+" . at + ",
+" .+ ",
+" "};
Added: packages/openev/branches/upstream/current/pics/pan_rght.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/pan_rght.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/pan_rght.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,28 @@
+/* XPM */
+static char * pan_rght_xpm[] = {
+"22 18 7 1",
+" c None",
+". c #333366",
+"+ c #000000",
+"@ c #6666CC",
+"# c #9999FF",
+"$ c #CCCCFF",
+"% c #FFFFFF",
+" ",
+" .+ ",
+" . at + ",
+" .@@+ ",
+" .#@@+ ",
+" .......##@@+ ",
+" .$$$$$$$##@@+ ",
+" .%$$$$$$$#@@@+ ",
+" .%%%%%$$$##@@@+ ",
+" .%%%%%$$$##@@@+ ",
+" .%$$$$$$$#@@@+ ",
+" .$$$$$$$##@@+ ",
+" .......##@@+ ",
+" .#@@+ ",
+" .@@+ ",
+" . at + ",
+" .+ ",
+" "};
Added: packages/openev/branches/upstream/current/pics/print.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/print.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/print.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,30 @@
+/* XPM */
+static char *print[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 5 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ff0000",
+"c c #ffffff",
+/* pixels */
+"aaaaa............aaaaa",
+"aaaaa.cccccccccc.aaaaa",
+"aaaaa.c..ccccccc.aaaaa",
+"aaaaa.cccccccccc.aaaaa",
+"aaaaa.c........c.aaaaa",
+"aaaaa.cccccccccc.aaaaa",
+"aaaaa.c........c.aaaaa",
+"aaaa..cccccccccc..aaaa",
+"aaaa..............aaaa",
+"aa...#ccc#ccc#ccc...aa",
+"a.#c#c#c#c#c#c#c#c#c.a",
+"a.cbbbcccbbbbcccbbc#.a",
+"a.#c#c#c#c#c#c#c#c#c.a",
+"a.ccc#ccc#ccc#ccc#cc.a",
+"a....................a",
+"aa...aaaaaaaaaaaa...aa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/raise.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/raise.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/raise.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,22 @@
+/* XPM */
+static char * raise_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000",
+"+ c #7F7F7F",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .. ",
+" ....+ ",
+" ......+ ",
+" ........+ ",
+" ..........+ ",
+" ............+ ",
+" ++++++++++++ ",
+" ",
+" ",
+" ",
+" "};
Added: packages/openev/branches/upstream/current/pics/recenter.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/recenter.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/recenter.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,281 @@
+/* XPM */
+static char *recenter[] = {
+/* width height num_colors chars_per_pixel */
+" 20 18 256 2",
+/* colors */
+"`` c None",
+"`. c #003163",
+"`# c #000000",
+"`a c #000000",
+"`b c #000000",
+"`c c #000000",
+"`d c #000000",
+"`e c #000000",
+"`f c #000000",
+"`g c #000000",
+"`h c #000000",
+"`i c #000000",
+"`j c #000000",
+"`k c #000000",
+"`l c #000000",
+"`m c #000000",
+"`n c #000000",
+"`o c #000000",
+"`p c #000000",
+"`q c #000000",
+"`r c #000000",
+"`s c #000000",
+"`t c #000000",
+"`u c #000000",
+"`v c #000000",
+"`w c #000000",
+"`x c #000000",
+"`y c #000000",
+"`z c #000000",
+"`A c #000000",
+"`B c #000000",
+"`C c #000000",
+"`D c #000000",
+"`E c #000000",
+"`F c #000000",
+"`G c #000000",
+"`H c #000000",
+"`I c #000000",
+"`J c #000000",
+"`K c #000000",
+"`L c #000000",
+"`M c #000000",
+"`N c #000000",
+"`O c #000000",
+"`P c #000000",
+"`Q c #000000",
+"`R c #000000",
+"`S c #000000",
+"`T c #000000",
+"`U c #000000",
+"`V c #000000",
+"`W c #000000",
+"`X c #000000",
+"`Y c #000000",
+"`Z c #000000",
+"`0 c #000000",
+"`1 c #000000",
+"`2 c #000000",
+"`3 c #000000",
+"`4 c #000000",
+"`5 c #000000",
+"`6 c #000000",
+"`7 c #000000",
+"`8 c #000000",
+".` c #000000",
+".. c #000000",
+".# c #000000",
+".a c #000000",
+".b c #000000",
+".c c #000000",
+".d c #000000",
+".e c #000000",
+".f c #000000",
+".g c #000000",
+".h c #000000",
+".i c #000000",
+".j c #000000",
+".k c #000000",
+".l c #000000",
+".m c #000000",
+".n c #000000",
+".o c #000000",
+".p c #000000",
+".q c #000000",
+".r c #000000",
+".s c #000000",
+".t c #000000",
+".u c #000000",
+".v c #000000",
+".w c #000000",
+".x c #000000",
+".y c #000000",
+".z c #000000",
+".A c #000000",
+".B c #000000",
+".C c #000000",
+".D c #000000",
+".E c #000000",
+".F c #000000",
+".G c #000000",
+".H c #000000",
+".I c #000000",
+".J c #000000",
+".K c #000000",
+".L c #000000",
+".M c #000000",
+".N c #000000",
+".O c #000000",
+".P c #000000",
+".Q c #000000",
+".R c #000000",
+".S c #000000",
+".T c #000000",
+".U c #000000",
+".V c #000000",
+".W c #000000",
+".X c #000000",
+".Y c #000000",
+".Z c #000000",
+".0 c #000000",
+".1 c #000000",
+".2 c #000000",
+".3 c #000000",
+".4 c #000000",
+".5 c #000000",
+".6 c #000000",
+".7 c #000000",
+".8 c #000000",
+"#` c #000000",
+"#. c #000000",
+"## c #000000",
+"#a c #000000",
+"#b c #000000",
+"#c c #000000",
+"#d c #000000",
+"#e c #000000",
+"#f c #000000",
+"#g c #000000",
+"#h c #000000",
+"#i c #000000",
+"#j c #000000",
+"#k c #000000",
+"#l c #000000",
+"#m c #000000",
+"#n c #000000",
+"#o c #000000",
+"#p c #000000",
+"#q c #000000",
+"#r c #000000",
+"#s c #000000",
+"#t c #000000",
+"#u c #000000",
+"#v c #000000",
+"#w c #000000",
+"#x c #000000",
+"#y c #000000",
+"#z c #000000",
+"#A c #000000",
+"#B c #000000",
+"#C c #000000",
+"#D c #000000",
+"#E c #000000",
+"#F c #000000",
+"#G c #000000",
+"#H c #000000",
+"#I c #000000",
+"#J c #000000",
+"#K c #000000",
+"#L c #000000",
+"#M c #000000",
+"#N c #000000",
+"#O c #000000",
+"#P c #000000",
+"#Q c #000000",
+"#R c #000000",
+"#S c #000000",
+"#T c #000000",
+"#U c #000000",
+"#V c #000000",
+"#W c #000000",
+"#X c #000000",
+"#Y c #000000",
+"#Z c #000000",
+"#0 c #000000",
+"#1 c #000000",
+"#2 c #000000",
+"#3 c #000000",
+"#4 c #000000",
+"#5 c #000000",
+"#6 c #000000",
+"#7 c #000000",
+"#8 c #000000",
+"a` c #000000",
+"a. c #000000",
+"a# c #000000",
+"aa c #000000",
+"ab c #000000",
+"ac c #000000",
+"ad c #000000",
+"ae c #000000",
+"af c #000000",
+"ag c #000000",
+"ah c #000000",
+"ai c #000000",
+"aj c #000000",
+"ak c #000000",
+"al c #000000",
+"am c #000000",
+"an c #000000",
+"ao c #000000",
+"ap c #000000",
+"aq c #000000",
+"ar c #000000",
+"as c #000000",
+"at c #000000",
+"au c #000000",
+"av c #000000",
+"aw c #000000",
+"ax c #000000",
+"ay c #000000",
+"az c #000000",
+"aA c #000000",
+"aB c #000000",
+"aC c #000000",
+"aD c #000000",
+"aE c #000000",
+"aF c #000000",
+"aG c #000000",
+"aH c #000000",
+"aI c #000000",
+"aJ c #000000",
+"aK c #000000",
+"aL c #000000",
+"aM c #000000",
+"aN c #000000",
+"aO c #000000",
+"aP c #000000",
+"aQ c #000000",
+"aR c #000000",
+"aS c #000000",
+"aT c #000000",
+"aU c #000000",
+"aV c #000000",
+"aW c #000000",
+"aX c #000000",
+"aY c #000000",
+"aZ c #000000",
+"a0 c #000000",
+"a1 c #000000",
+"a2 c #000000",
+"a3 c #000000",
+"a4 c #000000",
+"a5 c #000000",
+"a6 c #000000",
+"a7 c #000000",
+"a8 c #000000",
+/* pixels */
+"````````````````````````````````````````",
+"```````````````````.````````````````````",
+"```````````````````.````````````````````",
+"`````````````````.`.`.``````````````````",
+"`````````````````.`.`.``````````````````",
+"```````````````.`.`.`.`.````````````````",
+"```````````````````.````````````````````",
+"```````````.```````.```````.````````````",
+"```````.`.`.```````.```````.`.`.````````",
+"```.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.`.````",
+"```````.`.`.```````.```````.`.`.````````",
+"```````````.```````.```````.````````````",
+"```````````````````.````````````````````",
+"```````````````.`.`.`.`.````````````````",
+"`````````````````.`.`.``````````````````",
+"`````````````````.`.`.``````````````````",
+"```````````````````.````````````````````",
+"```````````````````.````````````````````"
+};
Added: packages/openev/branches/upstream/current/pics/refresh.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/refresh.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/refresh.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,30 @@
+/* XPM */
+static char *refresh[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 5 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ff0000",
+"c c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaa.aaaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaa.....aaaaaaaaa",
+"aaaaaaa.......aaaaaaaa",
+"aaaaaa.........aaaaaaa",
+"aaaaa..a.....a..aaaaaa",
+"aaaa..aaa...aaa..aaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaa...aaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/root.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/root.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/root.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,31 @@
+/* XPM */
+static char *linear[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaa.................aa",
+"aaa.###############.aa",
+"aaa.aaaaaaaaa.##aa#.aa",
+"aaa.aaaaaaa.##aaaa#.aa",
+"aaa.aaaaaa.#aaaaaa#.aa",
+"aaa.aaaaa.#aaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaaa.#aaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.aaa.#aaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.aa.#aaaaaaaaaa#.aa",
+"aaa.................aa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
+
+
Added: packages/openev/branches/upstream/current/pics/save.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/save.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/save.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,28 @@
+/* XPM */
+static char *save[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 3 1",
+/* colors */
+". c #000000",
+"# c #c0c0c0",
+"a c #0000ff",
+/* pixels */
+"######################",
+"######################",
+"####..............####",
+"####.a.########.#.####",
+"####.a.########...####",
+"####.a.########.a.####",
+"####.a.########.a.####",
+"####.a.########.a.####",
+"####.aa........aa.####",
+"####.aaaaaaaaaaaa.####",
+"####.aaaaaaaaaaaa.####",
+"####.aa.........a.####",
+"####.aa......##.a.####",
+"####.aa......##.a.####",
+"####.aa......##.a.####",
+"#####...........a.####",
+"######################",
+"######################"
+};
Added: packages/openev/branches/upstream/current/pics/seeall.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/seeall.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/seeall.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,27 @@
+/* XPM */
+static char *seeall[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 2 1",
+/* colors */
+". c #000000",
+"a c None",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"a....................a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a.a...aaaaaaaaaa...a.a",
+"a.a..aaaaaaaaaaaa..a.a",
+"a.a.a.aaaaaaaaaa.a.a.a",
+"a.aaaa.aaaaaaaa.aaaa.a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a.aaaa.aaaaaaaa.aaaa.a",
+"a.a.a.aaaaaaaaaa.a.a.a",
+"a.a..aaaaaaaaaaaa..a.a",
+"a.a...aaaaaaaaaa...a.a",
+"a.aaaaaaaaaaaaaaaaaa.a",
+"a....................a",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/sym_circle.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_circle.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_circle.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,21 @@
+/* XPM */
+static char * sym_circle_xpm[] = {
+"16 16 2 1",
+" c None",
+". c #0B76B9",
+" ........ ",
+" ... ... ",
+" .. .. ",
+" . . ",
+".. ..",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+".. ..",
+" . . ",
+" .. .. ",
+" ... ... ",
+" ........ "};
Added: packages/openev/branches/upstream/current/pics/sym_cross.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_cross.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_cross.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,21 @@
+/* XPM */
+static char * sym_cross_xpm[] = {
+"15 16 2 1",
+" c None",
+". c #0B76B9",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+"...............",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+" . ",
+" . "};
Added: packages/openev/branches/upstream/current/pics/sym_filled_circle.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_filled_circle.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_filled_circle.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,21 @@
+/* XPM */
+static char * sym_filled_circle_xpm[] = {
+"16 16 2 1",
+" c None",
+". c #0B76B9",
+" ........ ",
+" ............ ",
+" .............. ",
+" .............. ",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+" .............. ",
+" .............. ",
+" ............ ",
+" ........ "};
Added: packages/openev/branches/upstream/current/pics/sym_filled_square.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_filled_square.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_filled_square.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,19 @@
+/* XPM */
+static char * sym_filled_square_xpm[] = {
+"16 14 2 1",
+" c None",
+". c #0B76B9",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................",
+"................"};
Added: packages/openev/branches/upstream/current/pics/sym_filled_star.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_filled_star.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_filled_star.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * sym_filled_star_xpm[] = {
+"18 18 2 1",
+" c None",
+". c #0B76B9",
+" ",
+" .. ",
+" ... ",
+" .... ",
+" ..... ",
+" ...... ",
+" ...... ",
+" ................ ",
+" ................ ",
+" .............. ",
+" ........... ",
+" ............ ",
+" ............ ",
+" .............. ",
+" ..... ..... ",
+" .... .... ",
+" ... ... ",
+" "};
Added: packages/openev/branches/upstream/current/pics/sym_filled_triangle.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_filled_triangle.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_filled_triangle.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * sym_filled_triangle_xpm[] = {
+"18 18 2 1",
+" c None",
+". c #0B76B9",
+" ",
+" ... ",
+" .... ",
+" ..... ",
+" ...... ",
+" ....... ",
+" ........ ",
+" ......... ",
+" .......... ",
+" .......... ",
+" ............ ",
+" ............ ",
+" .............. ",
+" .............. ",
+" ................ ",
+" .................",
+"..................",
+" "};
Added: packages/openev/branches/upstream/current/pics/sym_square.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_square.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_square.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,19 @@
+/* XPM */
+static char * sym_square_xpm[] = {
+"16 14 2 1",
+" c None",
+". c #0B76B9",
+"................",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+". .",
+"................"};
Added: packages/openev/branches/upstream/current/pics/sym_star.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_star.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_star.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * sym_star_xpm[] = {
+"18 18 2 1",
+" c None",
+". c #0B76B9",
+" ",
+" .. ",
+" ... ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" ................ ",
+" .. . . .. ",
+" ... ... ",
+" .. ... ",
+" . .. .. . ",
+" . .. . ",
+" . ...... . ",
+" . .. ... . ",
+" .... .... ",
+" ... ... ",
+" "};
Added: packages/openev/branches/upstream/current/pics/sym_triangle.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_triangle.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_triangle.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * sym_triangle_xpm[] = {
+"18 18 2 1",
+" c None",
+". c #0B76B9",
+" ",
+" ... ",
+" .... ",
+" ..... ",
+" .. .. ",
+" .. ... ",
+" .. .. ",
+" .. ... ",
+" .. .. ",
+" .. .. ",
+" .. .. ",
+" .. .. ",
+" .. .. ",
+" .. .. ",
+" ... ... ",
+" .................",
+"..................",
+" "};
Added: packages/openev/branches/upstream/current/pics/sym_vertical.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_vertical.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_vertical.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,18 @@
+/* XPM */
+static char * sum_vertical2_xpm[] = {
+"2 13 2 1",
+" c None",
+". c #0B76B9",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" .",
+" ."};
Added: packages/openev/branches/upstream/current/pics/sym_x.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/sym_x.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/sym_x.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/* XPM */
+static char * sym_x_xpm[] = {
+"18 18 2 1",
+" c None",
+". c #0B76B9",
+" ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .. ",
+" .. ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" "};
Added: packages/openev/branches/upstream/current/pics/vexcel_logo.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/vexcel_logo.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/vexcel_logo.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,313 @@
+/* XPM */
+static char * vexcel_logo_xpm[] = {
+"234 53 257 2",
+" c None",
+". c #D6D6D6",
+"+ c #005495",
+"@ c #005595",
+"# c #AABBC8",
+"$ c #81C150",
+"% c #015695",
+"& c #015595",
+"* c #8AA8BF",
+"= c #035696",
+"- c #D0D2D4",
+"; c #B1C0CB",
+"> c #035796",
+", c #D5D5D5",
+"' c #C9CED2",
+") c #236AA0",
+"! c #2369A0",
+"~ c #0D5C99",
+"{ c #D3D4D5",
+"] c #D3D5D1",
+"^ c #B1CD9B",
+"/ c #0D5D99",
+"( c #256AA0",
+"_ c #ACBDC9",
+": c #D1D5CE",
+"< c #A1C981",
+"[ c #C4D2BA",
+"} c #9EB4C5",
+"| c #256BA0",
+"1 c #598BB0",
+"2 c #B9C5CD",
+"3 c #8CC462",
+"4 c #BACFAA",
+"5 c #BCC6CE",
+"6 c #AECC96",
+"7 c #84C255",
+"8 c #6B95B5",
+"9 c #CDD0D3",
+"0 c #22699F",
+"a c #CCD4C7",
+"b c #C2D1B6",
+"c c #6D97B6",
+"d c #85C257",
+"e c #C0C9CF",
+"f c #D4D6D3",
+"g c #B7CEA4",
+"h c #C0D0B3",
+"i c #A4C986",
+"j c #457EAA",
+"k c #CACFD2",
+"l c #96C671",
+"m c #80A2BC",
+"n c #91ACC1",
+"o c #D5D6D4",
+"p c #065897",
+"q c #8DA9C0",
+"r c #D1D3D4",
+"s c #D5D5D6",
+"t c #9EC87D",
+"u c #A8CB8E",
+"v c #C4CBD1",
+"w c #AFBECA",
+"x c #B2C0CB",
+"y c #5587AF",
+"z c #045796",
+"A c #286CA1",
+"B c #0A5B98",
+"C c #266CA0",
+"D c #C6CCD1",
+"E c #427CA9",
+"F c #12609B",
+"G c #3D7AA8",
+"H c #92C56B",
+"I c #A1B6C6",
+"J c #D5D6D5",
+"K c #94C66E",
+"L c #045896",
+"M c #B4CEA0",
+"N c #D6D6D5",
+"O c #D4D5D2",
+"P c #2C6FA3",
+"Q c #A4B8C7",
+"R c #CED1D3",
+"S c #CFD4CB",
+"T c #A8BAC8",
+"U c #90C568",
+"V c #82C150",
+"W c #A2C985",
+"X c #82C152",
+"Y c #7B9EBA",
+"Z c #C7D2BF",
+"` c #98B1C3",
+" . c #D3D5D2",
+".. c #A6CA8A",
+"+. c #AABCC9",
+"@. c #9AC777",
+"#. c #D2D5D0",
+"$. c #C8D3C0",
+"%. c #CED1D4",
+"&. c #3273A4",
+"*. c #C1C9D0",
+"=. c #1A649D",
+"-. c #4C83AC",
+";. c #B7CEA6",
+">. c #9EC87E",
+",. c #7199B7",
+"'. c #C6D2BC",
+"). c #AFCC98",
+"!. c #86C258",
+"~. c #D4D5D5",
+"{. c #A5CA88",
+"]. c #4980AB",
+"^. c #BDD0AE",
+"/. c #3C79A7",
+"(. c #91C569",
+"_. c #6793B4",
+":. c #98C774",
+"<. c #81C151",
+"[. c #7EA1BB",
+"}. c #095A98",
+"|. c #025696",
+"1. c #8AC35F",
+"2. c #A9BBC8",
+"3. c #A5CA89",
+"4. c #8EC464",
+"5. c #AACB91",
+"6. c #BFC8CF",
+"7. c #5E8EB2",
+"8. c #D2D3D5",
+"9. c #9BC778",
+"0. c #B8CFA7",
+"a. c #B5CEA3",
+"b. c #B7C3CD",
+"c. c #88A7BE",
+"d. c #95AFC2",
+"e. c #266BA0",
+"f. c #5487AE",
+"g. c #3474A5",
+"h. c #89C35D",
+"i. c #B3CD9F",
+"j. c #17629C",
+"k. c #94C66D",
+"l. c #105F9A",
+"m. c #A9CB90",
+"n. c #779CB9",
+"o. c #AABBC9",
+"p. c #BED0B0",
+"q. c #9BB2C4",
+"r. c #0E5E99",
+"s. c #8FC466",
+"t. c #025596",
+"u. c #B2CD9D",
+"v. c #1F679E",
+"w. c #2A6DA2",
+"x. c #D0D4CC",
+"y. c #93C56C",
+"z. c #B4C1CC",
+"A. c #6994B5",
+"B. c #CBD3C4",
+"C. c #ADCC95",
+"D. c #105E9A",
+"E. c #82C151",
+"F. c #3172A4",
+"G. c #83C153",
+"H. c #CCD0D3",
+"I. c #618FB2",
+"J. c #5386AE",
+"K. c #3776A6",
+"L. c #6491B3",
+"M. c #B1CD9C",
+"N. c #5287AE",
+"O. c #C5CCD1",
+"P. c #407BA8",
+"Q. c #87C259",
+"R. c #3977A6",
+"S. c #075997",
+"T. c #18639C",
+"U. c #6B95B6",
+"V. c #C0D1B3",
+"W. c #2F71A3",
+"X. c #9CB3C4",
+"Y. c #2B6FA2",
+"Z. c #D1D5CF",
+"`. c #14619B",
+" + c #6290B3",
+".+ c #AFBFCA",
+"++ c #D2D5CF",
+"@+ c #B5C2CC",
+"#+ c #085998",
+"$+ c #A4B7C7",
+"%+ c #5185AD",
+"&+ c #8AC35D",
+"*+ c #CDD4C7",
+"=+ c #CED4C9",
+"-+ c #C9D3C2",
+";+ c #CAD3C3",
+">+ c #3675A5",
+",+ c #0B5C98",
+"'+ c #C8D2BF",
+")+ c #BACFA9",
+"!+ c #A9BAC8",
+"~+ c #B9CFA8",
+"{+ c #AEBECA",
+"]+ c #A4CA87",
+"^+ c #8CC461",
+"/+ c #B3C1CB",
+"(+ c #115F9A",
+"_+ c #759BB9",
+":+ c #ABCB92",
+"<+ c #6F98B7",
+"[+ c #B5CEA1",
+"}+ c #5286AE",
+"|+ c #83C254",
+"1+ c #5387AE",
+"2+ c #B0CD9B",
+"3+ c #5689AF",
+"4+ c #C8CDD2",
+"5+ c #B6CEA3",
+"6+ c #8DC463",
+"7+ c #125F9B",
+"8+ c #ADBDCA",
+"9+ c #4780AB",
+"0+ c #1D669E",
+"a+ c #5B8CB1",
+"b+ c #4B81AC",
+"c+ c #83A4BD",
+"d+ c #9FC880",
+"e+ c #91C56A",
+"f+ c #C3D1B8",
+"g+ c #9BC87A",
+"h+ c #9CC87B",
+"i+ c #246AA0",
+"j+ c #246BA0",
+"k+ c #085A97",
+"l+ c #99C776",
+"m+ c #6893B5",
+"n+ c #81C050",
+"o+ c #B0BFCB",
+"p+ c #A7CA8C",
+"q+ c #5186AE",
+"r+ c #789DB9",
+"s+ c #3775A6",
+"t+ c #B0CD9A",
+"u+ c #4F84AD",
+"v+ c #86C256",
+"w+ c #97B0C3",
+"x+ c #8BA9BF",
+"y+ c #ACCB92",
+"z+ c #83C151",
+"A+ c #81C051",
+"B+ c #115E9A",
+"C+ c #739AB8",
+"D+ c #3071A4",
+"E+ c #1C659D",
+"F+ c #1C669D",
+"G+ c #BBCFAC",
+"H+ c #B4CEA1",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =+h g ;.)+O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'.H+i ..0.-+#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . S 4 ]+9.{.[+Z J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . *+;.W e+ at .5.-+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #.G+ at .Q.6+u $.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . J h < h.|+t ^.#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a i.k.$ h...'+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -+3.d $ &+M.: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . b t 7 $ 6+0.: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . '+W E.$ 1.).: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . ++:+7 $ $ i *+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . h H $ $ U ^.. . . . . . . . . . . . . . . w 2.# # +.r . . . . . . . . . . . . . . . . . . . . _ # # T b.. x # # # # # # # # # # # # # # # # # # # # # # o.9 . . v I 2.# # _ . . . . . . . . . . . . . . . . . e # # !+I 5 . . . . . . . . 8.e T q * n.8 Y * n w k . . . . . . . . . . { _ # # # # # # # # # # # # # # # # # # # # # # _ { . . . D # # # +.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . o t+X $ $ 9.a . . . . . . . . . . . . . . . . c+z > = L a+. . . . . . . . . . . . . . . . . . . Y z > = p n s A > > > = & & % & % % % % % % % % % % % & % % L # . . 6.].& % > p ].e . . . . . . . . . . . . . . n v.= & + R.w . . . . . /+c+3+Y.}.+ @ + + + @ @ + > `./.U.} %.. . . . . . ' D.> > > > % & & & % & & % & % & & % & % & & % / ' . . . q = > = S.+.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . < $ $ $ ..N . . . . . . . . . . . . . . . . . . 7.@ @ + @ n . . . . . . . . . . . . . . . . . T B + + + L.. r ) @ + @ + & % & & % & & % & % % & % & % % % & z # . . . s _+p + + @ E+X.. . . . . . . . . . . v N.@ + @ & L.- . . . . $+E #++ @ + + k+0 F.b+-.E Y.`.+ + + + + P * . . . . . ' B @ @ + + % & & & % & & & & % % & % & % & % % / ' . . . * + + + & 2.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . o ]+$ $ $ ]+. . . . . . . . . . . . . . . . . . . . D e.+ @ @ 0+5 . . . . . . . . . . . . . . . R P @ @ + F.9 . - ( + + @ E # # # # # # # # # # # # # # # # # # o.9 . . . . . } A + @ @ B _+~.. . . . . . . . } A @ @ + C X.. . . . *.3+= + @ + j+7.d.6.- ~.. . . { k } m+( + @ @ + 1+v . . . ' / + @ + y # # # # # # # # # # # # # # # # # # _ { . . . * @ + @ > # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . 2+$ $ $ K .. . . . . . . . . . . . . . . . . . . . . x / @ + @ P.. . . . . . . . . . . . . . . }++ @ + =.6.. . - | @ + @ 3+. . . . . . . . . . . . . . . . . . . . . . . . . . ' -.+ + + + G 6.. . . . . k _.t.+ @ @ a+' . . . . b.0 + + + ,+r+%.. . . . . . . . . . . . ' ++ + + @ F.k . . ' ~ + + + c . . . . . . . . . . . . . . . . . . . . . . . * @ @ @ > # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . '.7 $ $ d $.. . . . . . . . . . . . . . . . . . . . . . . c++ + @ @ n.. . . . . . . . . . . . . x++ + + % q.. . . - | @ + @ J.. . . . . . . . . . . . . . . . . . . . . . . . . . . . c.F + + @ 0+n . . . Q P + @ + 0+n . . . . . O.w.+ + + / I . . . . . . . . . . . . . . . . c + = ,+T.c.. . ' ~ + + @ 8 . . . . . . . . . . . . . . . . . . . . . . . * + @ + = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . < $ $ $ h+. . . . . . . . . . . . . . . . . . . . . . . . . f.+ @ @ k++.. . . . . . . . . . . x `.+ + @ 8 . . . . - | + + @ f.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . o+g.+ @ + z c D [.}.+ + @ ].5 . . . . . . 8 + @ + |.c.. . . . . . . . . . . . . . . . . . ` !+v R %.. . ' / @ + @ c . . . . . . . . . . . . . . . . . . . . . . . * + + @ > # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . ^+$ $ $ 6 . . . . . . . . . . . . . . . . . . . . . . . . . k ( + + @ W.H.. . . . . . . . . { W.+ + + P.. . . . . - | + + @ %+- - - - - - - - - - - - - - - - - r . . . . . . . . . . . . 8._.% + + @ =.+ + @ l.c.. . . . . . . { C @ + + A s . . . . . . . . . . . . . . . . . . . . . . . . . ' / @ @ @ _.- - - - - - - - - - - - - - - - - 8.. . . . . * @ @ @ = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . d $ $ $ u.. . . . . . . . . . . . . . . . . . . . . . . . . . ; D.+ + @ 1 . . . . . . . . . 7.@ + + 0 6.. . . . . - ( @ @ + ~ ) ) ! ! ) ) ) ) ! ) ) ) ! ! ) ! ! E r . . . . . . . . . . . . . } C + + + + @ -. at +. . . . . . . . *.}.@ @ @ }+. . . . . . . . . . . . . . . . . . . . . . . . . . ' ~ + @ @ F ) ) ) ! ) ! ! ! ! ) ! ! ! ) ! ! ) +. . . . . * + @ @ = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . Q.$ $ $ 3.. . . . . . . . . . . . . . . . . . . . . . . . . . . [.+ + @ = ` . . . . . . . d.@ @ + p I . . . . . . - ( @ @ + + + @ @ + @ @ + @ + @ + @ + @ @ + + =.- . . . . . . . . . . . . . ' j + + + + % N.v . . . . . . . . .+z + @ @ 7.. . . . . . . . . . . . . . . . . . . . . . . . . . ' ~ + + + + @ @ + + @ + @ @ + + + + + @ + + @ j . . . . . * + + @ = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . H V $ $ 6+] . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 + + + j.e . . . . . 2 T.@ + + ,.. . . . . . . - ( + @ + >+* * * * * * * * * * * * * * * * * ` ~.. . . . . . . . . . . . w+E++ + @ @ @ + + F+} . . . . . . . 4+B + + + %+. . . . . . . . . . . . . . . . . . . . . . . . . . ' ~ + @ + j * * * * * * * * * * * * * * * * * Q . . . . . * + + @ = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . C.$ $ $ $ p+. . . . . . . . . . . . . . . . . . . . . . . . . . . ' A + + + 9+. . . . s K.+ + + E . . . . . . . . - | + @ + 3+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . H.1 p + + + I.w+w.+ @ @ S._.R . . . . . { D++ @ @ e.s . . . . . . . . . . . . . . . . . . 8.9 . . . . . ' ~ + @ + ,.. . . . . . . . . . . . . . . . . . . . . . . * + + + = # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . Z.H $ $ $ $ a.. . . . . . . . . . . . . . . . . . . . . . . . . . . {+r.+ + + Y . . . c @ @ + | e . . . . . . . . - | + + @ 1+. . . . . . . . . . . . . . . . . . . . . . . . . . . . $+F.@ @ + 7+Y . . v ].@ @ @ + K.w . . . . . n.@ @ @ |.q . . . . . . . . . . . . . . . . . . q+=./.f.U.k . ' ~ + @ @ 8 . . . . . . . . . . . . . . . . . . . . . . . * + + + > # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . '.d $ $ $ <.).. . . . . . . . . . . . . . . . . . . . . . . . . . . [.+ @ + ~ b.. q.+ + @ = T . . . . . . . . . - ( @ + @ J.. . . . . . . . . . . . . . . . . . . . . . . . . . { <+L + + + &./+. . . . . m B + + + / * . . . . r K.+ + + (+x . . . . . . . . . . . . . . . . q t.+ @ + g.- . ' / + + @ 8 . . . . . . . . . . . . . . . . . . . . . . . * + + @ > # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . b h.$ $ $ $ >.a . . . . . . . . . . . . . . . . . . . . . . . . . . 1 @ + + &.w v.+ + + [.. . . . . . . . . . - ( @ + @ 3+. . . . . . . . . . . . . . . . . . . . . . . . . {+>++ @ @ = A.R . . . . . . . T &.@ @ @ @ u+v . . . 6.w.+ + @ j.Y r . . . . . . . . . . . . ' A.S.@ @ + F.v . . ' ~ @ + + c . . . . . . . . . . . . . . . . . . . . . . . * + + + = w . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . [ k.V $ $ $ 6+M ] . . . . . . . . . . . . . . . . . . . . . . . . 4+C + @ @ F @ + + j . . . . . . . . . . . - | + + @ j ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; z.{ . . . m F @ + + 0 w+. . . . . . . . . . H.3+|.@ + @ e.X.. . . 6./.@ + @ @ P C+I e - s . . . - *.Q ,.i++ @ @ @ j e . . . ' ~ @ @ @ 1 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 5 . . . * + + @ = q ; ; ; ; ; ; ; ; ; ; ; ; ; ; z.. . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . #.u G.$ $ $ $ y.^.o . . . . . . . . . . . . . . . . . . . . . . . x ~ + @ @ + @ A O.. . . . . . . . . . . - ) + + + + = = = = = > > = = = > = = > = > > = = l.' . 2 E @ + + + j D . . . . . . . . . . . . . n r.@ @ @ @ A.R . . . * A % @ + + @ #+0 g.-.-.s+( }.@ + + + = P * . . . . . ' }.+ @ @ % > = > > = > > = > > > > = > = = = > = G . . . * @ @ @ @ > > = > = > > = > > = > = = = D.. . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . b g+$ $ $ $ $ K u.S . . . . . . . . . . . . . . . . . . . . . . c+p = = > B++.. . . . . . . . . . . . - A > > = > % & % & & % % & % % % & % & & % % & & r.9 q 0 + > = (+m ~.. . . . . . . . . . . . . . . x /.L = t.@ G z.. . . - } c /.T.z @ + + @ + + @ + = F P.<+Q r . . . . . . ' l.> > > = & & & % & & % % % % % % & % & & & & & /.. . . q = > = > |.& & % % % % & % % & % & & & ~ . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . ;.l <.$ V $ $ ^+m.f+f . . . . . . . . . . . . . . . . . . . . _ # # # 2 . . . . . . . . . . . . . s ; # # # # # # # # # # # # # # # # # # # # # # # 8+{ _ Q # # # 5 . . . . . . . . . . . . . . . . . . - o.# # 2.I 2 . . . . . . . 9 @+} * * ,.8 m * d..+k . . . . . . . . . . { _ # # # # # # # # # # # # # # # # # # # # # # # b.. . . D # # # # # # # # # # # # # # # # # # # _ . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . J V.t 7 $ $ $ $ X k.).;+N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Z C.(.$ $ $ n+$ v+l 5.f+O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O ^.i 4.A+$ $ $ V E.U ..~+$. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] V.m.s.G.$ $ $ $ $ 7 s.3.~+*+f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'.M W 6+X $ $ $ $ $ d (.>.6 h S N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] f+).d+H d $ $ $ $ $ $ Q.l p+i.h B.] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . f *+p.5.l+1.|+$ $ $ $ $ $ 7 3 9.u 5+[ : f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ++Z G+M.3.l 1.X $ $ V $ $ $ Q.U @.]+6 0.[ =+O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . N #.Z 4 6 W @.(.Q.X $ $ $ $ $ $ 7 4.:.W C.a.p.f+B.: f . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . f Z.-+h a.:+< l 6+d E.$ $ $ $ $ $ $ G.4.l >.5.^ ;.b Z : ] O J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .: ;+f+p.;.i.y+]+t l U &+z+$ $ $ $ <.<.!.1.U K 9.t {.u 6 [+5+h b [ =+S : ] ] ] J . . . . . . . . . . . . . . . . . . . . o o o f : x.x.*+*+N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o ] : B.[ b ;.g ).m.m.< >.t @.k.y.K K 6+U (.H K H 4.:.:.:.d+]+{.{.{.6 ^ ^ ^ ^ ^ ^ ^ ^ M 4 4 4 4 )+^ g g g g u.M M m.a.J . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , , , , , , , , , , , , , , , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , , , , , , , . . . . . . . . . . . . . . . . , , , , , , , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};
Added: packages/openev/branches/upstream/current/pics/warning.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/warning.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/warning.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,53 @@
+/* XPM */
+static char *warning[] = {
+/* width height num_colors chars_per_pixel */
+" 27 43 2 1",
+/* colors */
+". c #000000",
+"# c None",
+/* pixels */
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########..##############",
+"##########..#.#############",
+"#########..#.#.############",
+"#########.#.#.#############",
+"#########..#.#.############",
+"#########.#.#.#############",
+"#########..#.#.############",
+"##########..#.#############",
+"##########.#.##############",
+"##########..#.#############",
+"##########.#.##############",
+"##########..#.#############",
+"##########.#.##############",
+"###########################",
+"###########################",
+"##########....#############",
+"##########.#.##############",
+"##########..#.#############",
+"##########.#.##############",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################",
+"###########################"
+};
+
Added: packages/openev/branches/upstream/current/pics/windowed.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/windowed.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/windowed.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,29 @@
+/* XPM */
+static char *windowed[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 4 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aa..................aa",
+"aaa.##############.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa................aaa",
+"aaa.##############.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aaa.aaaaaaaaaaaaa#.aaa",
+"aa..................aa",
+"a....................a",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/worldg.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/worldg.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/worldg.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,36 @@
+/* XPM */
+static char *world[] = {
+/* width height num_colors chars_per_pixel */
+" 27 23 6 1",
+/* colors */
+". c None",
+"# c None",
+"a c None",
+"b c #282828",
+"c c #ffffff",
+"d c #ffffff",
+/* pixels */
+"...........................",
+".##########################",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaddaaaabdcadaaaaaaa",
+".#aaaaaaccbcaabcccbbbbcaaaa",
+".#aaaaabcbbcaacccbbbbbbcaaa",
+".#aaaaccbbbbccccbbbbbbcccca",
+".#aaacccbbbcccccccbbbbbcccc",
+".#aaccccbbbccccbbbbbbbbcccc",
+".#aaccccbcccccbbbbbbbcbcccc",
+".#accccccbccccbbbbbcbcccbcc",
+".#acccccccbbbcccbbbccccbccc",
+".#acccccccbbbcccbbccccbbbcc",
+".#accccccccbbcccbbccccbbbbc",
+".#aacccccccbcacccbccccbcbcc",
+".#aacccccccbcaacccccacccccb",
+".#aaccccaccccaacccccaacccca",
+".#aaacccaacccaaccccaaacccca",
+".#aaacccaacccaaacccaaaaccaa",
+".#aaaaddaaaddaaaaddaaaadaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/worldrgb.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/worldrgb.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/worldrgb.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,36 @@
+/* XPM */
+static char *world[] = {
+/* width height num_colors chars_per_pixel */
+" 27 23 6 1",
+/* colors */
+". c None",
+"# c None",
+"a c None",
+"b c #00ff00",
+"c c #0000ff",
+"d c #ffffff",
+/* pixels */
+"...........................",
+".##########################",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaddaaaabdcadaaaaaaa",
+".#aaaaaaccbcaabcccbbbbcaaaa",
+".#aaaaabcbbcaacccbbbbbbcaaa",
+".#aaaaccbbbbccccbbbbbbcccca",
+".#aaacccbbbcccccccbbbbbcccc",
+".#aaccccbbbccccbbbbbbbbcccc",
+".#aaccccbcccccbbbbbbbcbcccc",
+".#accccccbccccbbbbbcbcccbcc",
+".#acccccccbbbcccbbbccccbccc",
+".#acccccccbbbcccbbccccbbbcc",
+".#accccccccbbcccbbccccbbbbc",
+".#aacccccccbcacccbccccbcbcc",
+".#aacccccccbcaacccccacccccb",
+".#aaccccaccccaacccccaacccca",
+".#aaacccaacccaaccccaaacccca",
+".#aaacccaacccaaacccaaaaccaa",
+".#aaaaddaaaddaaaaddaaaadaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa",
+".#aaaaaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/zoomin.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/zoomin.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/zoomin.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,30 @@
+/* XPM */
+static char *zoomin[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 5 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ff0000",
+"c c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaa...aaaaaaaaaaaa",
+"aaaaa..aaa..aaaaaaaaaa",
+"aaaa.aaabaaa.aaaaaaaaa",
+"aaaa.aaabaaa.aaaaaaaaa",
+"aaa.aaaabaaaa.aaaaaaaa",
+"aaa.abbbbbbba.aaaaaaaa",
+"aaa.aaaabaaaa.aaaaaaaa",
+"aaaa.aaabaaa..aaaaaaaa",
+"aaaa..aabaaa.aaaaaaaaa",
+"aaaaa..aaa....#aaaaaaa",
+"aaaaaaa....a...#aaaaaa",
+"aaaaaaaaaaaa#...#aaaaa",
+"aaaaaaaaaaaaa#...caaaa",
+"aaaaaaaaaaaaaa#.ccaaaa",
+"aaaaaaaaaaaaaaaccaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/zoomout.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/zoomout.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/zoomout.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,30 @@
+/* XPM */
+static char *zoomout[] = {
+/* width height num_colors chars_per_pixel */
+" 22 18 5 1",
+/* colors */
+". c #000000",
+"# c #808080",
+"a c None",
+"b c #ff0000",
+"c c #ffffff",
+/* pixels */
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa",
+"aaaaaaa...aaaaaaaaaaaa",
+"aaaaa..aaa..aaaaaaaaaa",
+"aaaa.aaaaaaa.aaaaaaaaa",
+"aaaa.aaaaaaa.aaaaaaaaa",
+"aaa.aaaaaaaaa.aaaaaaaa",
+"aaa.abbbbbbba.aaaaaaaa",
+"aaa.aaaaaaaaa.aaaaaaaa",
+"aaaa.aaaaaaa..aaaaaaaa",
+"aaaa..aaaaaa.aaaaaaaaa",
+"aaaaa..aaa....#aaaaaaa",
+"aaaaaaa....a...#aaaaaa",
+"aaaaaaaaaaaa#...#aaaaa",
+"aaaaaaaaaaaaa#...caaaa",
+"aaaaaaaaaaaaaa#.ccaaaa",
+"aaaaaaaaaaaaaaaccaaaaa",
+"aaaaaaaaaaaaaaaaaaaaaa"
+};
Added: packages/openev/branches/upstream/current/pics/zoomrect.xpm
===================================================================
--- packages/openev/branches/upstream/current/pics/zoomrect.xpm (rev 0)
+++ packages/openev/branches/upstream/current/pics/zoomrect.xpm 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,281 @@
+/* XPM */
+static char *zoomrect[] = {
+/* width height num_colors chars_per_pixel */
+" 20 18 256 2",
+/* colors */
+"`` c #033365",
+"`. c #002a55",
+"`# c #cdf1f1",
+"`a c #1f4a76",
+"`b c #bfd0de",
+"`c c #cdb5b5",
+"`d c #d8f4f4",
+"`e c #d4f0f2",
+"`f c #a5dde2",
+"`g c #a9b8d0",
+"`h c #acc9d0",
+"`i c #caedef",
+"`j c #a5cacd",
+"`k c #cbb2b3",
+"`l c #fbfefe",
+"`m c #032648",
+"`n c #b0cfd6",
+"`o c #b5afaf",
+"`p c #31587f",
+"`q c #25496e",
+"`r c #22476c",
+"`s c #274f78",
+"`t c #41668a",
+"`u c #89949f",
+"`v c #163a60",
+"`w c #a8c9d2",
+"`x c #a3c4cb",
+"`y c #003163",
+"`z c #2d4d6d",
+"`A c #003061",
+"`B c #123c68",
+"`C c #013264",
+"`D c #69747f",
+"`E c #002c5a",
+"`F c #41668b",
+"`G c #2d4f72",
+"`H c #adadad",
+"`I c #b3d2db",
+"`J c #ade9e9",
+"`K c #cc0000",
+"`L c None",
+"`M c #000000",
+"`N c #000000",
+"`O c #000000",
+"`P c #000000",
+"`Q c #000000",
+"`R c #000000",
+"`S c #000000",
+"`T c #000000",
+"`U c #000000",
+"`V c #000000",
+"`W c #000000",
+"`X c #000000",
+"`Y c #000000",
+"`Z c #000000",
+"`0 c #000000",
+"`1 c #000000",
+"`2 c #000000",
+"`3 c #000000",
+"`4 c #000000",
+"`5 c #000000",
+"`6 c #000000",
+"`7 c #000000",
+"`8 c #000000",
+".` c #000000",
+".. c #000000",
+".# c #000000",
+".a c #000000",
+".b c #000000",
+".c c #000000",
+".d c #000000",
+".e c #000000",
+".f c #000000",
+".g c #000000",
+".h c #000000",
+".i c #000000",
+".j c #000000",
+".k c #000000",
+".l c #000000",
+".m c #000000",
+".n c #000000",
+".o c #000000",
+".p c #000000",
+".q c #000000",
+".r c #000000",
+".s c #000000",
+".t c #000000",
+".u c #000000",
+".v c #000000",
+".w c #000000",
+".x c #000000",
+".y c #000000",
+".z c #000000",
+".A c #000000",
+".B c #000000",
+".C c #000000",
+".D c #000000",
+".E c #000000",
+".F c #000000",
+".G c #000000",
+".H c #000000",
+".I c #000000",
+".J c #000000",
+".K c #000000",
+".L c #000000",
+".M c #000000",
+".N c #000000",
+".O c #000000",
+".P c #000000",
+".Q c #000000",
+".R c #000000",
+".S c #000000",
+".T c #000000",
+".U c #000000",
+".V c #000000",
+".W c #000000",
+".X c #000000",
+".Y c #000000",
+".Z c #000000",
+".0 c #000000",
+".1 c #000000",
+".2 c #000000",
+".3 c #000000",
+".4 c #000000",
+".5 c #000000",
+".6 c #000000",
+".7 c #000000",
+".8 c #000000",
+"#` c #000000",
+"#. c #000000",
+"## c #000000",
+"#a c #000000",
+"#b c #000000",
+"#c c #000000",
+"#d c #000000",
+"#e c #000000",
+"#f c #000000",
+"#g c #000000",
+"#h c #000000",
+"#i c #000000",
+"#j c #000000",
+"#k c #000000",
+"#l c #000000",
+"#m c #000000",
+"#n c #000000",
+"#o c #000000",
+"#p c #000000",
+"#q c #000000",
+"#r c #000000",
+"#s c #000000",
+"#t c #000000",
+"#u c #000000",
+"#v c #000000",
+"#w c #000000",
+"#x c #000000",
+"#y c #000000",
+"#z c #000000",
+"#A c #000000",
+"#B c #000000",
+"#C c #000000",
+"#D c #000000",
+"#E c #000000",
+"#F c #000000",
+"#G c #000000",
+"#H c #000000",
+"#I c #000000",
+"#J c #000000",
+"#K c #000000",
+"#L c #000000",
+"#M c #000000",
+"#N c #000000",
+"#O c #000000",
+"#P c #000000",
+"#Q c #000000",
+"#R c #000000",
+"#S c #000000",
+"#T c #000000",
+"#U c #000000",
+"#V c #000000",
+"#W c #000000",
+"#X c #000000",
+"#Y c #000000",
+"#Z c #000000",
+"#0 c #000000",
+"#1 c #000000",
+"#2 c #000000",
+"#3 c #000000",
+"#4 c #000000",
+"#5 c #000000",
+"#6 c #000000",
+"#7 c #000000",
+"#8 c #000000",
+"a` c #000000",
+"a. c #000000",
+"a# c #000000",
+"aa c #000000",
+"ab c #000000",
+"ac c #000000",
+"ad c #000000",
+"ae c #000000",
+"af c #000000",
+"ag c #000000",
+"ah c #000000",
+"ai c #000000",
+"aj c #000000",
+"ak c #000000",
+"al c #000000",
+"am c #000000",
+"an c #000000",
+"ao c #000000",
+"ap c #000000",
+"aq c #000000",
+"ar c #000000",
+"as c #000000",
+"at c #000000",
+"au c #000000",
+"av c #000000",
+"aw c #000000",
+"ax c #000000",
+"ay c #000000",
+"az c #000000",
+"aA c #000000",
+"aB c #000000",
+"aC c #000000",
+"aD c #000000",
+"aE c #000000",
+"aF c #000000",
+"aG c #000000",
+"aH c #000000",
+"aI c #000000",
+"aJ c #000000",
+"aK c #000000",
+"aL c #000000",
+"aM c #000000",
+"aN c #000000",
+"aO c #000000",
+"aP c #000000",
+"aQ c #000000",
+"aR c #000000",
+"aS c #000000",
+"aT c #000000",
+"aU c #000000",
+"aV c #000000",
+"aW c #000000",
+"aX c #000000",
+"aY c #000000",
+"aZ c #000000",
+"a0 c #000000",
+"a1 c #000000",
+"a2 c #000000",
+"a3 c #000000",
+"a4 c #000000",
+"a5 c #000000",
+"a6 c #000000",
+"a7 c #000000",
+"a8 c #000000",
+/* pixels */
+"`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L",
+"`L`K`K`K`K`K`K`K`K`K`K`L`L`L`L`L`L`L`L`L",
+"`L`K`L`L`L`L`L`L`L`L`K`L`L`L`L`L`L`L`L`L",
+"`L`K`L`L`L`L`L`L`L`L`K`L`L`L`L`L`L`L`L`L",
+"`L`K`L`L`L`L`L`L`L`L`K`L`L`L`L`L`L`L`L`L",
+"`L`K`L`L`L`L`L`b```.`.```b`L`L`L`L`L`L`L",
+"`L`K`L`L`L`L`g`a`j`e`k`x`a`g`L`L`L`L`L`L",
+"`L`K`L`L`L`b`a`f`J`d`c`J`f`a`b`L`L`L`L`L",
+"`L`K`L`L`L```j`J`d`l`c`#`J`I```L`L`L`L`L",
+"`L`K`L`L`L`.`e`d`l`#`c`J`J`i`.`L`L`L`L`L",
+"`L`K`K`K`K`.`k`c`c`c`o`J`#`e`.`L`L`L`L`L",
+"`L`L`L`L`L```w`J`#`J`J`J`#`h```L`L`L`L`L",
+"`L`L`L`L`L`b`a`f`J`J`#`#`d`B`L`L`L`L`L`L",
+"`L`L`L`L`L`L`g`a`n`i`e`h`v`E`s`L`L`L`L`L",
+"`L`L`L`L`L`L`L`b```.`.```L`z`A`p`L`L`L`L",
+"`L`L`L`L`L`L`L`L`L`L`L`L`L`L`G`y`F`L`L`L",
+"`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`q`C`t`L`L",
+"`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`L`r`m`u`L"
+};
Added: packages/openev/branches/upstream/current/pymod/.cvsignore
===================================================================
--- packages/openev/branches/upstream/current/pymod/.cvsignore (rev 0)
+++ packages/openev/branches/upstream/current/pymod/.cvsignore 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,7 @@
+*.pyc
+Makefile
+*.dll
+*.exp
+*.lib
+*.pdb
+*.ilk
Added: packages/openev/branches/upstream/current/pymod/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/pymod/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/pymod/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,71 @@
+/.cvsignore/1.5/Thu Feb 15 16:37:38 2001//
+/Makefile.in/1.10/Tue Sep 28 19:44:17 2004//
+/_gtkmissing.def/1.1/Sun Apr 16 21:45:27 2000//
+/_gview.def/1.1/Sun Apr 16 21:45:27 2000//
+/filedlg.py/1.9/Mon Aug 16 16:47:24 2004//
+/generate.py/1.7/Tue Jul 26 18:26:24 2005//
+/gtkmissing.c/1.8/Thu Sep 30 21:12:07 2004//
+/gtkmissing.py/1.8/Wed Jan 22 19:54:36 2003//
+/gv.defs/1.87/Mon Sep 12 15:33:10 2005//
+/gv_ciet.c/1.12/Wed Jul 27 18:31:50 2005//
+/gvalg.py/1.7/Fri Nov 19 23:59:37 2004//
+/gvbitlayerlut.py/1.4/Mon Mar 19 21:57:14 2001//
+/gvclassification.py/1.30/Tue Jun 29 16:06:15 2004//
+/gvclassifydlg.py/1.31/Fri Aug 27 17:11:06 2004//
+/gvcommand.py/1.10/Fri Oct 15 13:25:26 2004//
+/gvconst.py/1.12/Wed Aug 6 17:09:14 2003//
+/gvcorecmds.py/1.6/Thu Jun 3 20:26:07 2004//
+/gvhtml.py/1.14/Thu Nov 4 14:32:33 2004//
+/gview.py/1.212/Mon Oct 17 19:19:15 2005//
+/gviewapp.py/1.29/Mon Oct 17 18:21:13 2005//
+/gvlabeledit.py/1.8/Tue Dec 10 15:49:11 2002//
+/gvlegenddlg.py/1.21/Tue Jan 20 19:45:51 2004//
+/gvmaptools.py/1.1/Wed Jan 7 20:41:48 2004//
+/gvmodule.c/1.120/Mon Oct 17 19:19:15 2005//
+/gvmodule_defs.c/1.57/Mon Sep 12 15:33:10 2005//
+/gvmodule_impl.c/1.67/Mon Sep 12 15:33:10 2005//
+/gvogrdlg.py/1.5/Tue Sep 9 15:18:46 2003//
+/gvogrfs.py/1.7/Thu May 8 16:19:39 2003//
+/gvogrfsgui.py/1.6/Mon Sep 17 15:27:03 2001//
+/gvplot.py/1.21/Thu Aug 18 19:56:15 2005//
+/gvpquerypropdlg.py/1.11/Wed Aug 23 14:32:10 2000//
+/gvprint.py/1.16/Sat Jul 24 14:35:04 2004//
+/gvrasterpropdlg.py/1.57/Mon Jun 27 19:37:24 2005//
+/gvsdsdlg.py/1.4/Tue Sep 9 15:18:46 2003//
+/gvselbrowser.py/1.4/Fri Nov 9 15:41:49 2001//
+/gvshell.py/1.5/Wed Jul 30 15:31:12 2003//
+/gvsignaler.py/1.6/Tue Jan 7 18:44:32 2003//
+/gvutils.py/1.29/Fri Oct 15 16:52:20 2004//
+/gvvectorpropdlg.py/1.23/Fri Feb 14 23:03:35 2003//
+/gvviewwindow.py/1.96/Thu Oct 13 21:21:51 2005//
+/ibrowse.py/1.3/Thu Feb 6 08:18:29 2003//
+/layerdlg.py/1.33/Tue Sep 9 15:18:46 2003//
+/makefile.vc/1.9/Wed Apr 21 10:09:38 2004//
+/mkgv.py/1.1/Wed Nov 24 21:06:55 1999//
+/nls.py/1.6/Wed Mar 16 18:57:04 2005//
+/oe_about.py/1.1/Sun Aug 7 18:22:57 2005//
+/oeattedit.py/1.9/Thu Feb 20 19:27:23 2003//
+/openev.py/1.46/Fri Jan 14 17:17:18 2005//
+/pathutils.py/1.1/Fri Jul 2 16:40:51 2004//
+/pgu.py/1.1/Mon Jul 10 19:58:51 2000/-ko/
+/pgucolor.py/1.12/Tue Sep 9 15:18:46 2003//
+/pgucolorsel.py/1.4/Wed May 2 03:30:38 2001/-ko/
+/pgucolourswatch.py/1.3/Tue Sep 9 15:18:46 2003//
+/pgucombo.py/1.7/Tue Nov 8 15:51:44 2005//
+/pguentry.py/1.1/Mon Jun 11 23:19:00 2001//
+/pgufilesel.py/1.7/Wed Sep 1 15:46:52 2004/-ko/
+/pgufont.py/1.4/Tue Jul 20 12:26:43 2004//
+/pgugrid.py/1.17/Mon Oct 17 14:32:28 2005//
+/pgumenu.py/1.3/Tue Aug 13 16:09:29 2002//
+/pguprogress.py/1.1/Mon Jul 10 19:58:51 2000/-ko/
+/pgushapesgrid.py/1.10/Sun Jul 27 04:58:44 2003//
+/pgutextarea.py/1.5/Fri Feb 14 17:59:14 2003//
+/pgutogglebutton.py/1.1/Tue Aug 13 16:07:17 2002//
+/pyshell.py/1.14/Tue Sep 9 15:18:46 2003//
+/scmexpr.py/1.2/Mon Mar 19 21:57:14 2001//
+/testmain.py/1.14/Fri Apr 7 00:49:56 2000//
+/toolexample.py/1.2/Fri Apr 5 19:06:52 2002//
+/toolfile_example.txt/1.2/Fri Apr 5 19:06:52 2002//
+/vecplot.py/1.7/Sun Jun 27 20:18:14 2004//
+/vrtutils.py/1.17/Thu Jul 7 21:36:06 2005//
+D
Added: packages/openev/branches/upstream/current/pymod/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/pymod/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/pymod/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/pymod
Added: packages/openev/branches/upstream/current/pymod/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/pymod/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/pymod/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/pymod/Makefile.in
===================================================================
--- packages/openev/branches/upstream/current/pymod/Makefile.in (rev 0)
+++ packages/openev/branches/upstream/current/pymod/Makefile.in 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,44 @@
+all: _gvmodule.so _gtkmissing.so
+
+CC = @CC@
+CXX = @CXX@
+
+OPTFLAGS = @OPTFLAGS@
+CFLAGS = $(OPTFLAGS) @C_WFLAGS@ -I.. @CFLAGS@ @PYTHON_INCLUDES@
+
+LIBS = @LDFLAGS@ @LIBS@
+
+PYLINK = @PYTHON_LINK@
+
+%.o : %.c
+ $(CC) $(CFLAGS) -c $<
+
+gvmodule.o: gvmodule.c gvmodule_impl.c gv_ciet.c
+
+_gvmodule.so: gvmodule.o ../libgv.a
+ $(CXX) -shared -o $@ $^ $(LIBS)
+
+_gtkmissing.so: gtkmissing.o
+ $(CXX) -shared -o $@ $^ $(LIBS)
+
+gvmodule_impl.c: gv.defs mkgv.py
+ python mkgv.py
+
+clean:
+ rm -f *.o gvmodule_*.c *.so *.pyc
+
+doc:
+ @if test \! -d html ; then \
+ mkdir html; \
+ else \
+ rm -f html/*; \
+ fi
+ pythondoc -f HTML4 -i -d html _gv gview gvbitlayerlut
+
+install-doc: doc
+ @if test -d ~/wwwgv/gv_python ; then \
+ cp html/* ~/wwwgv/gv_python; \
+ echo cp html/* ~/wwwgv/gv_python; \
+ else \
+ echo "~/wwwgv/gv_python doesn't exist ... install fails."; \
+ fi
Added: packages/openev/branches/upstream/current/pymod/_gtkmissing.def
===================================================================
--- packages/openev/branches/upstream/current/pymod/_gtkmissing.def (rev 0)
+++ packages/openev/branches/upstream/current/pymod/_gtkmissing.def 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+LIBRARY _gtkmissing
+VERSION 1.0
+EXPORTS
+ init_gtkmissing @1
Added: packages/openev/branches/upstream/current/pymod/_gview.def
===================================================================
--- packages/openev/branches/upstream/current/pymod/_gview.def (rev 0)
+++ packages/openev/branches/upstream/current/pymod/_gview.def 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+LIBRARY _gv
+VERSION 1.0
+EXPORTS
+ init_gv @1
Added: packages/openev/branches/upstream/current/pymod/filedlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/filedlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/filedlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,685 @@
+###############################################################################
+# $Id: filedlg.py,v 1.9 2004/08/16 16:47:24 pgs Exp $
+#
+# Project: CIET Map
+# Purpose: Multi-purpose file selection dialog
+# Author: Paul Spencer, spencer at dmsolutions.ca
+#
+# Developed by DM Solutions Group (www.dmsolutions.ca) for CIETcanada
+#
+###############################################################################
+# Copyright (c) 2000-2002, CIETcanada
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: filedlg.py,v $
+# Revision 1.9 2004/08/16 16:47:24 pgs
+# modified handling of filters to respect order in which they are specified when populating the dropdown list
+#
+# Revision 1.8 2004/07/20 12:22:18 pgs
+# added patch from Zak James for handling manual input of filenames correctly
+#
+# Revision 1.7 2003/09/13 22:09:41 pgs
+# changed add_with_viewport to add to prevent problem with many entries
+#
+# Revision 1.6 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.5 2003/04/03 21:56:34 pgs
+# added localization support
+#
+# Revision 1.4 2003/04/03 15:06:27 pgs
+# made filedlg safe if pygtkextra not installed
+#
+# Revision 1.3 2003/02/14 17:58:35 pgs
+# added ability to multi-select files
+#
+# Revision 1.2 2002/11/06 16:38:10 warmerda
+# minor fix to pref handling
+#
+# Revision 1.1 2002/11/06 16:05:51 pgs
+# ported from CIETmap
+#
+# Revision 1.38 2002/08/27 19:01:37 pspencer
+# made the filename widget type dependent on dialog type.
+#
+# Revision 1.37 2002/08/15 18:01:49 pspencer
+# changed prints for ciet_utils.debug_msg()
+#
+# Revision 1.36 2002/08/01 18:14:12 pspencer
+# updated copyright text
+#
+# Revision 1.35 2002/08/01 15:24:03 warmerda
+# added fallback if pref_manager not available
+#
+# Revision 1.34 2002/08/01 13:44:09 pspencer
+# put keypresses into the filename box
+#
+# Revision 1.33 2002/07/30 02:53:38 pspencer
+# modified to use the new CmTopmostWindow base class to prevent conflicts
+# with message boxes that fight to be on top
+#
+# Revision 1.32 2002/07/12 22:39:13 pspencer
+# added filters to file dialogs
+#
+# Revision 1.31 2001/10/02 00:02:24 pspencer
+# modified for new preference manager architecture
+#
+# Revision 1.30 2001/09/27 02:30:43 pspencer
+# changed Save to OK for FILE_SAVE
+#
+# Revision 1.29 2001/09/21 21:30:51 pspencer
+# changed DIRECTORY_SELECT mode to display OK instead of Open
+#
+# Revision 1.28 2001/08/29 20:27:49 pspencer
+# removed dependence on cmnormpath and modified directory listing
+# to not have '..' when at the root of a drive.
+#
+# Revision 1.27 2001/08/29 18:46:32 pspencer
+# use cmnormpath to avoid bug in ntpath.py
+#
+# Revision 1.26 2001/07/01 03:15:12 pspencer
+# misc bug fixes
+#
+# Revision 1.25 2001/06/06 02:51:56 pspencer
+# use pguentry
+#
+# Revision 1.24 2001/05/24 14:03:44 pspencer
+# added case-insensitive filtering
+#
+# Revision 1.23 2001/05/14 22:05:50 pspencer
+# added expanduser to file name expansion for linux users
+#
+# Revision 1.22 2001/05/08 23:15:15 pspencer
+# minor change to update gui before loading files to allow for slow network
+# connections.
+#
+# Revision 1.21 2001/05/05 17:35:26 pspencer
+# modifications to allow modal state to work properly under certain circumstances
+#
+# Revision 1.20 2001/04/13 18:50:17 pspencer
+# fixed bug in help topic
+#
+# Revision 1.19 2001/04/12 18:14:24 pspencer
+# implemented nls'd helpfiles and preferences.
+#
+# Revision 1.18 2001/03/23 02:18:18 pspencer
+# fixed conflicts from merging v_1_1_4
+#
+# Revision 1.17 2001/03/05 03:20:24 pspencer
+# fixed a bug in cwd not existing that was fixed earlier but got lost in a merge.
+#
+# Revision 1.16 2001/03/01 14:04:16 pspencer
+# fixed conflicts during merge of bug fixes from v_1_1_3
+#
+# Revision 1.15 2001/02/26 18:52:04 pspencer
+# fixed bug when gview working directory doesn't exist
+#
+# Revision 1.14 2001/02/23 17:12:52 pspencer
+# Merged bug fixes from v_1_1_2
+#
+# Revision 1.13.2.2 2001/02/28 18:11:43 pspencer
+# fixed a bug in the file dialog code (need to destroy it
+#
+# Revision 1.13.2.1 2001/02/23 02:12:49 pspencer
+# fixed cwd, made dialog 'stay' on top.
+#
+# Revision 1.13 2001/02/10 18:13:32 pspencer
+# added combo box for rfl and made filename editable. when a path
+# is entered, the dialog switches to that path.
+#
+# Revision 1.12 2001/02/08 17:41:44 pspencer
+# fixed (I hope) a bug in determining drive letters
+#
+# Revision 1.11 2001/01/29 15:26:14 pspencer
+# missing import fixed
+#
+# Revision 1.10 2001/01/24 18:54:07 warmerda
+# fixed FALSE and TRUE constants
+#
+# Revision 1.9 2001/01/22 19:48:54 fredrock
+# adjusted self.set_policy(as=FALSE, ag=FALSE, autos=TRUE)
+#
+# Revision 1.8 2001/01/20 20:00:53 pspencer
+# fixed directory sorting and added missing drive letters
+#
+# Revision 1.7 2001/01/17 03:08:21 pspencer
+# editorial change
+#
+# Revision 1.6 2000/10/20 16:23:08 pspencer
+# fixed bug in get_directory()
+#
+# Revision 1.5 2000/10/19 22:46:26 pspencer
+# Modified to use os module for os specific path separators. Removed
+# os.chdir() code so it no longer changes the working directory.
+#
+# Revision 1.4 2000/10/19 05:15:38 warmerda
+# fixed some DOS path specific issues
+#
+# Revision 1.3 2000/10/17 19:00:38 pspencer
+# made this a modal dialog
+#
+# Revision 1.2 2000/10/09 14:02:59 pspencer
+# added comments and regular expressions for filter matching.
+#
+# Revision 1.1 2000/10/08 17:17:55 pspencer
+# initial version
+#
+#
+
+import os
+import gtk
+from gtk import TRUE, FALSE
+from gvsignaler import Signaler
+import gview
+import string
+from pguentry import pguEntry
+try:
+ from pgucombo import pguCombo
+except:
+ pguCombo = gtk.GtkCombo
+
+#pguCombo = gtk.GtkCombo
+
+import gdal
+import nls
+import re
+import string
+
+"""
+This module contains a single class, FileDialog that presents a common interface
+to several directory/file operations.
+
+The class is initialized for file saving, file opening, or directory selection
+through the dialog_type parameter of __init__.
+
+FILE_OPEN -- allows the user to select an existing file
+
+FILE_SAVE -- allows the user to pick an existing file or type a new one
+
+DIRECTORY_SELECT -- allows the user to pick an existing directory
+
+Usage -- connect signals to FileDialog.ok_button and FileDialog.cancel_button
+ -- FileDialog.get_filename() returns the file name
+ -- FileDialog.get_directory() returns the directory
+ -- FileDialog.set_filter() sets a filter for file name that limits the
+ display of files in the file list.
+
+Filter specifications
+
+A file filter is specified as a text string containing the filter name and
+filter items. Filter items are separated by commas. The filter name and
+filter items are separated by a vertical bar |
+
+Multiple filters are separated by a vertical bar
+
+i.e. DBF (*.dbf)|*.dbf|REC (*.rec)|*.rec|All Files (*.*)|*.*
+"""
+
+#dialog_types
+FILE_OPEN = 0
+FILE_SAVE = 1
+DIRECTORY_SELECT = 2
+
+
+class FilterSpec:
+
+ """
+ implements a single filter
+ """
+
+ def __init__(self, filterspec):
+ """
+ Initialize the filter based on the spec string
+ """
+ #parse the filterspec
+ parts = filterspec.split("|" )
+ if len(parts) != 2:
+ gdal.Debug( "OpenEV", "an error occurred parsing the FilterSpec %s" % filterspec )
+ pass
+
+
+ self.name = parts[0].strip()
+ filters = parts[1].split( "," )
+
+ self.filters = []
+ for i in range(len(filters)):
+ re_filter = string.replace(string.strip(filters[i]), "\\", "\\\\")
+ re_filter = string.replace(re_filter, ".", "\.")
+ re_filter = string.replace(re_filter, "*", ".*?")
+ re_comp = re.compile(re_filter, re.I)
+ self.filters.append( re_comp )
+
+ def match(self, filename):
+ """
+ compare the filename to the filter spec and return None if not matched,
+ otherwise the result of the match is returned
+ """
+ for i in range(len(self.filters)):
+ result = self.filters[i].match( filename )
+ if result is not None:
+ return result
+ return None
+
+
+class FileDialog(gtk.GtkWindow, Signaler):
+ """FileDialog provides a multipurpose file selection dialog."""
+
+ def __init__(self, title=None, cwd=None, dialog_type=FILE_OPEN, filter=None, app=None, multiselect=0):
+ gtk.GtkWindow.__init__(self)
+
+ if dialog_type >= FILE_OPEN and dialog_type <= DIRECTORY_SELECT:
+ self.dialog_type = dialog_type
+ else:
+ self.dialog_type = FILE_OPEN
+
+ self.filter = None #current filter
+ self.filters = {} #active filter objects
+ self.filter_keys = [] #ordered list of the names of the filters
+
+ self.file_selection = []
+
+ self.multiselect = multiselect
+
+ self.set_border_width(5)
+ self.set_policy(as=gtk.FALSE, ag=gtk.FALSE, autos=gtk.TRUE)
+ self.drives = None
+
+ if title == None:
+ if dialog_type == FILE_OPEN:
+ title = nls.get('filedlg-title-open-file', 'Open File ...')
+ elif dialog_type == FILE_SAVE:
+ title = nls.get('filedlg-title-save-file', 'Save File ...')
+ elif dialog_type == DIRECTORY_SELECT:
+ title = nls.get('filedlg-title-select-directory', 'Select Directory ...')
+ self.set_title(title)
+
+ #setup the current working directory
+ if cwd is None or not os.path.exists(cwd):
+ cwd = gview.get_preference('working-directory')
+ if cwd is None:
+ cwd = os.getcwd()
+ self.cwd = cwd
+
+ #widgets
+ vbox = gtk.GtkVBox(spacing=5)
+ if dialog_type == FILE_OPEN or dialog_type == DIRECTORY_SELECT:
+ lbl = gtk.GtkLabel(nls.get('filedlg-label-open-from', 'Open From:'))
+ elif dialog_type == FILE_SAVE:
+ lbl = gtk.GtkLabel(nls.get('filedlg-label-save-in', 'Save In:'))
+ self.opt_menu = gtk.GtkOptionMenu()
+ self.opt_menu.set_menu(gtk.GtkMenu())
+ hbox = gtk.GtkHBox()
+ hbox.pack_start(lbl, expand=gtk.FALSE)
+ hbox.pack_start(self.opt_menu)
+ vbox.pack_start(hbox, expand = gtk.FALSE)
+
+ self.list_directory = gtk.GtkCList()
+ scr_directories = gtk.GtkScrolledWindow()
+ scr_directories.add(self.list_directory)
+ self.list_directory.connect('button-press-event', self.directory_selected_cb)
+
+ if dialog_type == DIRECTORY_SELECT:
+ self.list_files = None
+ vbox.pack_start(scr_directories)
+ else:
+ self.list_files = gtk.GtkCList()
+ if self.multiselect:
+ self.list_files.set_selection_mode( gtk.SELECTION_EXTENDED )
+ scr_files = gtk.GtkScrolledWindow()
+ scr_files.add(self.list_files)
+ self.list_files.connect('button-press-event', self.file_clicked_cb)
+ self.list_files.connect('select-row', self.file_selected_cb )
+ self.list_files.connect('unselect-row', self.file_unselected_cb )
+ pane = gtk.GtkHPaned()
+ scr_directories.set_usize(100, -1)
+ scr_files.set_usize(100, -1)
+ pane.add1(scr_directories)
+ pane.add2(scr_files)
+ pane.set_position(200)
+ vbox.pack_start(pane)
+
+ widget = None
+ if dialog_type == FILE_SAVE:
+ self.txt_filename = gtk.GtkEntry()
+ widget = self.txt_filename
+
+ elif dialog_type == FILE_OPEN:
+ combo = gtk.GtkCombo()
+ combo.set_value_in_list(gtk.FALSE, gtk.FALSE)
+ combo.disable_activate()
+ if app is not None:
+ rfl = app.get_rfl()
+ rfl.insert(0, '')
+ combo.set_popdown_strings( rfl )
+ self.txt_filename = combo.entry
+ widget = combo
+
+ if widget is not None:
+ table = gtk.GtkTable(rows=2, cols=2)
+ lbl = gtk.GtkLabel(nls.get('filedlg-label-file-name', 'File Name:'))
+ self.txt_filename.connect('focus-out-event', self.map_path_cb)
+ self.txt_filename.connect('key-press-event', self.map_path_cb)
+
+ table.attach(lbl, 0, 1, 0, 1)
+ table.attach(widget, 1, 2, 0, 1)
+ lbl = gtk.GtkLabel(nls.get('filedlg-label-filter-extension', 'Filter extension:'))
+ self.cmb_filter = pguCombo()
+ self.set_filter(filter)
+ self.cmb_filter.entry.connect('changed', self.filter_cb)
+ table.attach(lbl, 0, 1, 1, 2)
+ table.attach(self.cmb_filter, 1, 2, 1, 2)
+ vbox.pack_start(table, expand=gtk.FALSE)
+
+ if dialog_type == FILE_SAVE:
+ self.ok_button = gtk.GtkButton(nls.get('filedlg-button-ok', 'OK'))
+ elif dialog_type == FILE_OPEN:
+ self.ok_button = gtk.GtkButton(nls.get('filedlg-button-open', 'Open'))
+ elif dialog_type == DIRECTORY_SELECT:
+ self.ok_button = gtk.GtkButton(nls.get('filedlg-button-ok', 'OK'))
+
+ self.cancel_button = gtk.GtkButton(nls.get('filedlg-button-cancel', 'Cancel'))
+
+ self.ok_button.connect('clicked', self.remove_grab)
+ self.ok_button.connect('clicked', self.update_cwd)
+ self.cancel_button.connect('clicked', self.remove_grab)
+ btn_box = gtk.GtkHButtonBox()
+ btn_box.pack_start(self.ok_button)
+ btn_box.pack_start(self.cancel_button)
+ vbox.pack_start(btn_box, expand=gtk.FALSE)
+
+ self.add(vbox)
+ self.show_all()
+
+ #make modal
+ gtk.grab_add(self)
+
+
+ self.ok_button.set_flags(gtk.CAN_DEFAULT)
+ self.ok_button.grab_default()
+
+ self.set_usize(400, 400)
+ self.menu_update = gtk.FALSE
+
+ while gtk.events_pending():
+ gtk.mainiteration(FALSE)
+
+ self.refresh_directory()
+ self.connect('delete-event', self.quit)
+ self.ok_button.connect('clicked', self.quit)
+ self.cancel_button.connect('clicked', self.quit)
+ self.publish('quit')
+
+ self.add_events(gtk.GDK.KEY_PRESS_MASK)
+ self.connect('key-press-event', self.key_press_cb)
+
+ self.result = 'cancel'
+
+ def key_press_cb( self, widget, event ):
+ """
+ process key presses
+ """
+ #focus on cmdline and disable further processing of this signal
+ self.txt_filename.grab_focus()
+ return FALSE
+
+ def update_cwd(self, *args):
+ #gview.set_preference('working-directory', self.cwd)
+ pass
+
+ def remove_grab(self, widget, *args):
+ if widget == self.ok_button:
+ self.result = 'ok'
+ gtk.grab_remove(self)
+
+ def refresh_directory(self, *args):
+ """refresh the directory menu and cause a rebuild of the
+ file/directory lists"""
+ self.menu_update = gtk.TRUE
+ self.opt_menu.remove_menu()
+ paths = []
+ drive, head = os.path.splitdrive(self.cwd)
+ while head <> os.sep and head <> "":
+ paths.append(drive + head)
+ head, tail = os.path.split(head)
+
+ paths.append(drive + os.sep)
+
+ menu = gtk.GtkMenu()
+ for path in paths:
+ item = gtk.GtkMenuItem(path)
+ item.show()
+ item.connect('activate', self.directory_cb, path)
+ menu.append(item)
+
+ self.opt_menu.set_menu(menu)
+ self.opt_menu.set_history(len(paths))
+ self.refresh_files()
+ self.menu_update = gtk.FALSE
+
+ def map_path_cb(self, entry, event):
+ """user has entered a value into txt_filename. If it maps to
+ a path, change to it"""
+ if event.type == gtk.GDK.KEY_PRESS:
+ if event.keyval == gtk.GDK.Return:
+ path = os.path.normpath(os.path.join(self.cwd, entry.get_text()))
+ path = os.path.expanduser(path)
+ if os.path.isdir(path):
+ self.cwd = path
+ self.refresh_directory()
+ entry.set_text('')
+ else:
+ """for text entry deselect in list"""
+ if len(self.file_selection) > 0:
+ self.file_selection = []
+ self.refresh_directory()
+
+ elif event.type == gtk.GDK.FOCUS_CHANGE:
+ if os.path.isdir(entry.get_text()):
+ self.cwd = entry.get_text()
+ self.refresh_directory()
+ entry.set_text('')
+ elif os.path.isfile(entry.get_text()):
+ self.update_filename_box()
+
+
+
+ def directory_cb(self, widget, path, *args):
+ """called when the directory menu changes"""
+ if not self.menu_update:
+ self.cwd = os.path.normpath(path)
+ self.refresh_directory()
+
+ def refresh_files(self, *args):
+ """rebuild the file and directory lists. Use regular expressions to
+ filter."""
+ files = os.listdir(self.cwd)
+ files.sort(self.cmp_dir)
+ if self.list_files <> None:
+ self.list_files.freeze()
+ self.list_files.clear()
+ self.list_directory.freeze()
+ self.list_directory.clear()
+
+ drive, path = os.path.splitdrive( self.cwd )
+ if path != '\\':
+ self.list_directory.append([os.pardir])
+
+ for file in files:
+ file_path = os.path.join(self.cwd, file)
+ if os.path.isfile(file_path) and self.list_files <> None:
+ if self.filter <> None:
+ match = self.filter.match(file_path)
+ if match <> None:
+ #f, ext = os.path.splitext(file)
+ #if ext == self.filter:
+ self.list_files.append([file])
+ else:
+ self.list_files.append([file])
+ elif os.path.isdir(file_path):
+ self.list_directory.append([file])
+ # add drive letters
+ drives = self.get_drives()
+ for drive in drives:
+ self.list_directory.append([drive])
+
+ if self.list_files <> None:
+ self.list_files.thaw()
+ self.list_directory.thaw()
+
+ def file_clicked_cb(self, widget, event, *args):
+ """called when the user selects a file in the file list"""
+ if event.type == gtk.GDK._2BUTTON_PRESS:
+ self.ok_button.clicked()
+
+ def file_selected_cb(self, widget, row, col, event, *args):
+ """handle the user selecting a row"""
+ try:
+ idx = self.file_selection.index( row )
+ except:
+ self.file_selection.append( row )
+ self.update_filename_box()
+
+ def file_unselected_cb( self, widget, row, col, event, *args):
+ """handle the user unselecting a row"""
+ try:
+ self.file_selection.remove( row )
+ self.update_filename_box()
+ except:
+ pass
+
+ def update_filename_box( self ):
+ """update the contents of the filename box"""
+ filenames = ""
+ spc = ''
+ if len(self.file_selection) > 1:
+ quote='"'
+ else:
+ quote = ''
+ for row in self.file_selection:
+ filenames = filenames + spc + quote + "%s" % self.list_files.get_text( row, 0 ) + quote
+ spc = " "
+ self.txt_filename.set_text(filenames)
+
+ def directory_selected_cb(self, widget, event, *args):
+ """called when the user selects a directory in the directory list"""
+ if event.type <> gtk.GDK._2BUTTON_PRESS:
+ return
+ try:
+ row, col = widget.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ new_dir = widget.get_text(row, col)
+ self.cwd = os.path.normpath(os.path.join(self.cwd, new_dir))
+ self.refresh_directory()
+
+ def filter_cb(self, widget, *args):
+ """called when the filter changes"""
+ import string
+ filter = string.strip(widget.get_text())
+ if filter == '':
+ self.filter = FilterSpec( nls.get("filedlg-default-filter", "All Files (*.*)|*.*"))
+ else:
+ self.filter = self.filters[filter]
+ self.refresh_directory()
+
+ def set_filter(self, filter):
+ """programmatically set the filename filter"""
+
+ self.filters = {}
+ self.filter_keys = []
+ self.filter = None
+ #build the filters
+ if filter != None and len(filter) > 0:
+ filterSpecs = filter.split( "|" )
+ if len(filterSpecs) % 2 != 0:
+ gdal.Debug( "OpenEV", "invalid filter spec: %s" % filter )
+ pass
+ else:
+ for i in range(0, len(filterSpecs), 2):
+ spec = FilterSpec(filterSpecs[i] + "|" + filterSpecs[i+1])
+ self.filters[spec.name] = spec
+ self.filter_keys.append( spec.name )
+ else:
+ self.filters[nls.get("filedlg-default-filter", "All Files (*.*)|*.*")] = FilterSpec( nls.get("filedlg-default-filter", "All Files (*.*)|*.*") )
+
+ self.cmb_filter.set_popdown_strings( self.filter_keys )
+ self.filter = self.filters[self.cmb_filter.entry.get_text()]
+
+ def set_filename(self, filename):
+ """set the filename"""
+ self.txt_filename.set_text(filename)
+
+ def get_filename(self, *args):
+ """return the first filename"""
+ if self.dialog_type == FILE_OPEN:
+ if len(self.file_selection) > 0:
+ filename = self.list_files.get_text( self.file_selection[0], 0 )
+ elif len(self.txt_filename.get_text()) > 0:
+ filename = self.txt_filename.get_text()
+ else:
+ filename = ""
+ elif self.dialog_type == FILE_SAVE:
+ filename = self.txt_filename.get_text()
+ return os.path.join(self.get_directory(), filename)
+
+ def get_filenames(self, *args):
+ """return all the filenames as a list"""
+ filenames = []
+ for row in self.file_selection:
+ filename = self.list_files.get_text( row, 0 )
+ filenames.append( os.path.join(self.get_directory(), filename) )
+
+ return filenames
+
+ def get_directory(self, *args):
+ """return the directory"""
+ return self.cwd
+
+ def get_drives(self, *args):
+ if self.drives is None:
+ self.drives = []
+ for d in range(ord('c'), ord('z') + 1):
+ drive = chr(d) + ':' + os.sep
+ if os.path.exists(drive):
+ self.drives.append(drive)
+ return self.drives
+
+ def cmp_dir(self, a, b):
+ if string.lower(a) < string.lower(b):
+ return -1
+ elif string.lower(a) == string.lower(b):
+ return 0
+ else:
+ return 1
+
+ def quit(self, *args):
+ """close the dialog"""
+ self.remove_grab(None)
+ self.hide()
+ self.notify('quit')
+ return gtk.FALSE
+
+if __name__ == '__main__':
+ dlg = FileDialog(title='Testing', dialog_type=FILE_OPEN)
+ dlg.show()
+ dlg.subscribe('quit', gtk.mainquit)
+ gtk.mainloop()
Added: packages/openev/branches/upstream/current/pymod/generate.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/generate.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/generate.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,510 @@
+import os
+import string
+import scmexpr
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+# for fnmatchcase -- filename globbing
+import fnmatch
+
+TRUE = 1
+FALSE = 0
+
+funcDefTmpl = ' { "%s", _wrap_%s, 1 },\n'
+funcLeadTmpl = 'static PyObject *_wrap_%s(PyObject *self, PyObject *args) {\n'
+enumCodeTmpl = ''' if (PyGtkEnum_get_value(%s, %s, (gint *)&%s))
+ return NULL;\n'''
+flagCodeTmpl = ''' if (PyGtkFlag_get_value(%s, %s, (gint *)&%s))
+ return NULL;\n'''
+setVarTmpl = ''' if (py_%s)
+ %s = %s;\n'''
+getTypeTmpl = '''static PyObject *_wrap_%s(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":%s"))
+ return NULL;
+ return PyInt_FromLong(%s());
+}\n\n'''
+
+nullokTmpl = ''' if (PyGtk_Check(py_%s))
+ %s = %s(PyGtk_Get(py_%s));
+ else if (py_%s != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "%s argument must be a %s or None");
+ return NULL;
+ }\n'''
+
+nullokBoxedTmpl = ''' if (Py%s_Check(py_%s))
+ %s = %s(py_%s);
+ else if (py_%s != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "%s argument must be a %s or None");
+ return NULL;
+ }\n'''
+
+convSpecialCases = {
+ 'GtkCList': '_GTK_CLIST',
+ 'GtkCTree': '_GTK_CTREE',
+ 'GtkCTreePos': '_GTK_CTREE_POS',
+ 'GtkCTreeLineStyle': '_GTK_CTREE_LINE_STYLE',
+ 'GtkCTreeExpanderStyle': '_GTK_CTREE_EXPANDER_STYLE',
+ 'GtkCTreeExpansionStyle': '_GTK_CTREE_EXPANSION_STYLE',
+ 'GnomeRootWin': '_GNOME_ROOTWIN',
+ 'GnomeAppBar': '_GNOME_APPBAR',
+ 'GnomeDEntryEdit': '_GNOME_DENTRY_EDIT',
+}
+
+def toUpperStr(str):
+ """Converts a typename to the equivalent upercase and underscores
+ name. This is used to form the type conversion macros and enum/flag
+ name variables"""
+ if convSpecialCases.has_key(str):
+ return convSpecialCases[str]
+ ret = []
+ while str:
+ if len(str) > 1 and str[0] in string.uppercase and \
+ str[1] in string.lowercase:
+ ret.append("_" + str[:2])
+ str = str[2:]
+ elif len(str) > 3 and \
+ str[0] in string.lowercase and \
+ str[1] in 'HV' and \
+ str[2] in string.uppercase and \
+ str[3] in string.lowercase:
+ ret.append(str[0] + "_" + str[1:3])
+ str = str[3:]
+ elif len(str) > 2 and \
+ str[0] in string.lowercase and \
+ str[1] in string.uppercase and \
+ str[2] in string.uppercase:
+ ret.append(str[0] + "_" + str[1])
+ str = str[2:]
+ else:
+ ret.append(str[0])
+ str = str[1:]
+ return string.upper(string.join(ret, ''))
+
+def enumName(typename):
+ """create a GTK_TYPE_* name from the given type"""
+ part = toUpperStr(typename)
+ if len(part) > 4 and part[:4] == '_GTK':
+ return 'GTK_TYPE' + part[4:]
+ else:
+ return 'GTK_TYPE' + part
+
+def conversionMacro(typename):
+ """get the conversion macro for the given type"""
+ return toUpperStr(typename)[1:]
+
+# a dictionary of known enum types ...
+# the value is a cached copy of the GTK_TYPE name
+enums = {}
+# and flags ...
+flags = {}
+
+# a dictionary of objects ...
+# the values are the conversion macros
+objects = {}
+
+# the known boxed types
+boxed = {
+ 'GtkAccelGroup': ('PyGtkAccelGroup_Type', 'PyGtkAccelGroup_Get',
+ 'PyGtkAccelGroup_New'),
+ 'GtkStyle': ('PyGtkStyle_Type', 'PyGtkStyle_Get', 'PyGtkStyle_New'),
+ 'GdkFont': ('PyGdkFont_Type', 'PyGdkFont_Get', 'PyGdkFont_New'),
+ 'GdkColor': ('PyGdkColor_Type', 'PyGdkColor_Get', 'PyGdkColor_New'),
+ 'GdkEvent': ('PyGdkEvent_Type', 'PyGdkEvent_Get', 'PyGdkEvent_New'),
+ 'GdkWindow': ('PyGdkWindow_Type', 'PyGdkWindow_Get','PyGdkWindow_New'),
+ 'GdkPixmap': ('PyGdkWindow_Type', 'PyGdkWindow_Get','PyGdkWindow_New'),
+ 'GdkBitmap': ('PyGdkWindow_Type', 'PyGdkWindow_Get','PyGdkWindow_New'),
+ 'GdkDrawable':('PyGdkWindow_Type','PyGdkWindow_Get','PyGdkWindow_New'),
+ 'GdkGC': ('PyGdkGC_Type', 'PyGdkGC_Get', 'PyGdkGC_New'),
+ 'GdkColormap': ('PyGdkColormap_Type', 'PyGdkColormap_Get',
+ 'PyGdkColormap_New'),
+ 'GdkDragContext': ('PyGdkDragContext_Type', 'PyGdkDragContext_Get',
+ 'PyGdkDragContext_New'),
+ 'GtkSelectionData': ('PyGtkSelectionData_Type',
+ 'PyGtkSelectionData_Get',
+ 'PyGtkSelectionData_New'),
+ 'GdkAtom': ('PyGdkAtom_Type', 'PyGdkAtom_Get', 'PyGdkAtom_New'),
+ 'GdkCursor': ('PyGdkCursor_Type', 'PyGdkCursor_Get',
+ 'PyGdkCursor_New'),
+ 'GtkCTreeNode': ('PyGtkCTreeNode_Type', 'PyGtkCTreeNode_Get',
+ 'PyGtkCTreeNode_New'),
+}
+
+class VarDefs:
+ def __init__(self):
+ self.vars = {}
+ def add(self, type, name):
+ if self.vars.has_key(type):
+ self.vars[type] = self.vars[type] + (name,)
+ else:
+ self.vars[type] = (name,)
+ def __str__(self):
+ ret = []
+ for type in self.vars.keys():
+ ret.append(' ')
+ ret.append(type)
+ ret.append(' ')
+ ret.append(string.join(self.vars[type], ', '))
+ ret.append(';\n')
+ if ret: ret.append('\n')
+ return string.join(ret, '')
+
+class TypesParser(scmexpr.Parser):
+ """A parser that only parses definitions -- no output"""
+ def define_enum(self, name, *values):
+ if not enums.has_key(name):
+ enums[name] = enumName(name)
+ def define_flags(self, name, *values):
+ if not flags.has_key(name):
+ flags[name] = enumName(name)
+ def define_object(self, name, *args):
+ if not objects.has_key(name):
+ objects[name] = conversionMacro(name)
+ def define_boxed(self, name, reffunc=None, unreffunc=None, size=None):
+ if not boxed.has_key(name):
+ print "Warning --", name, "not supported"
+ def include(self, filename):
+ if filename[0] != '/':
+ # filename relative to file being parsed
+ afile = os.path.join(os.path.dirname(self.filename),
+ filename)
+ else:
+ afile = filename
+ if not os.path.exists(afile):
+ # fallback on PWD relative filename
+ afile = filename
+ #print "including file", afile
+ fp = open(afile)
+ self.startParsing(scmexpr.parse(fp))
+
+class FunctionDefsParser(TypesParser):
+ def __init__(self, input, prefix='gtkmodule', typeprefix=''):
+ # typeprefix is set to & if type structs are not pointers
+ TypesParser.__init__(self, input)
+ self.impl = open(prefix + '_impl.c', "w")
+ self.defs = open(prefix + '_defs.c', "w")
+ self.tp = typeprefix
+
+ def unknown(self, tup):
+ print "Unknown function:", (tup and tup[0] or "")
+
+ def declare_object(self, name, *args):
+ # Just parse - no output
+ TypesParser.define_object(self, name)
+
+ def define_object(self, name, parent=(), fields=()):
+ TypesParser.define_object(self, name)
+ get_type = string.lower(objects[name]) + '_get_type'
+ self.defs.write(funcDefTmpl % (get_type,get_type))
+ self.impl.write(getTypeTmpl % (get_type,get_type,get_type))
+
+ if fields and fields[0] == 'fields':
+ for retType, attrname in fields[1:]:
+ self.get_attr_func(name, retType, attrname)
+
+ def get_attr_func(self, name, retType, attrname):
+ impl = StringIO()
+ funcName = string.lower(objects[name]) + '_get_' + attrname
+ impl.write(funcLeadTmpl % (funcName,))
+ impl.write(' PyObject *obj;\n\n')
+ impl.write(' if (!PyArg_ParseTuple(args, "O!:')
+ impl.write(funcName)
+ impl.write('", ' + self.tp + 'PyGtk_Type, &obj))\n')
+ impl.write(' return NULL;\n')
+ funcCall = '%s(PyGtk_Get(obj))->%s' % (objects[name], attrname)
+ if self.decodeRet(impl, funcCall, retType):
+ return
+ impl.write('}\n\n')
+ # actually write the info to the output files
+ self.defs.write(funcDefTmpl % (funcName, funcName))
+ self.impl.write(impl.getvalue())
+
+ def define_func(self, name, retType, args):
+ # we write to a temp file, in case any errors occur ...
+ impl = StringIO()
+ impl.write(funcLeadTmpl % (name,))
+ varDefs = VarDefs()
+ parseStr = '' # PyArg_ParseTuple string
+ parseList = [] # args to PyArg_ParseTuple
+ argList = [] # args to actual function
+ extraCode = [] # any extra code (for enums, flags)
+ nullret = FALSE # return value could be null
+ if type(retType) == type(()) and len(retType) == 2 \
+ and retType[0] in objects.keys() \
+ and retType[1] == 'null-ok':
+ nullret = TRUE
+ retType = retType[0]
+ varDefs.add('GtkObject', '*retval')
+ if retType == 'string':
+ # this is needed so we can free result string
+ varDefs.add('char', '*ret')
+ varDefs.add('PyObject', '*py_ret')
+ if retType == 'const_string':
+ varDefs.add('const char', '*ret')
+ for arg in args:
+ argType = arg[0]
+ argName = arg[1]
+ # munge special names ...
+ if argName in ('default', 'if', 'then', 'else',
+ 'while', 'for', 'do', 'case', 'select'):
+ argName = '_' + argName
+ default = ''
+ nullok = FALSE
+ if len(arg) > 2:
+ for a in arg[2:]:
+ if type(a) == type(()) and a[0] == '=':
+ default = ' = ' + a[1]
+ if '|' not in parseStr:
+ parseStr = parseStr+'|'
+ elif type(a) == type(()) and \
+ a[0] == 'null-ok':
+ nullok = TRUE
+ if argType == 'string':
+ varDefs.add('char', '*' + argName + default)
+ if nullok:
+ parseStr = parseStr + 'z'
+ else:
+ parseStr = parseStr + 's'
+ parseList.append('&' + argName)
+ argList.append(argName)
+ elif argType == 'const_string':
+ varDefs.add('const char', '*' + argName + default)
+ if nullok:
+ parseStr = parseStr + 'z'
+ else:
+ parseStr = parseStr + 's'
+ parseList.append('&' + argName)
+ argList.append(argName)
+ elif argType in ('char', 'uchar'):
+ varDefs.add('char', argName + default)
+ parseStr = parseStr + 'c'
+ parseList.append('&' + argName)
+ argList.append(argName)
+ elif argType in ('bool', 'int', 'uint', 'long',
+ 'ulong', 'guint', 'GdkAtom'):
+ # pretend atoms are integers for input ...
+ varDefs.add('int', argName + default)
+ parseStr = parseStr + 'i'
+ parseList.append('&' + argName)
+ argList.append(argName)
+ elif argType in ('float', 'double'):
+ varDefs.add('double', argName + default)
+ parseStr = parseStr + 'd'
+ parseList.append('&' + argName)
+ argList.append(argName)
+ elif argType == 'progress_cb':
+ varDefs.add('PyProgressData', 'sProgressInfo = {NULL,NULL,-1}')
+ parseStr = parseStr + 'O'
+ parseList.append('&(sProgressInfo.psPyCallback)')
+ argList.append('PyProgressProxy')
+ elif argType == 'progress_data':
+ parseStr = parseStr + 'O'
+ parseList.append('&(sProgressInfo.psPyCallbackData)')
+ argList.append('&sProgressInfo')
+ elif argType == 'FILE':
+ varDefs.add('PyObject', '*' + argName+default)
+ parseStr = parseStr + 'O!'
+ parseList.append('&PyFile_Type')
+ parseList.append('&' + argName)
+ argList.append('PyFile_AsFile(' +
+ argName + ')')
+ elif argType in enums.keys():
+ varDefs.add(argType, argName + default)
+ if default:
+ varDefs.add('PyObject', '*py_' + \
+ argName + ' = NULL')
+ else:
+ varDefs.add('PyObject', '*py_'+argName)
+ parseStr = parseStr + 'O'
+ parseList.append('&py_' + argName)
+ argList.append(argName)
+ extraCode.append(enumCodeTmpl %
+ (enums[argType],
+ 'py_' + argName,
+ argName))
+ elif argType in flags.keys():
+ varDefs.add(argType, argName + default)
+ if default:
+ varDefs.add('PyObject', '*py_' + \
+ argName + ' = NULL')
+ else:
+ varDefs.add('PyObject', '*py_'+argName)
+ parseStr = parseStr + 'O'
+ parseList.append('&py_' + argName)
+ argList.append(argName)
+ extraCode.append(flagCodeTmpl %
+ (flags[argType],
+ 'py_' + argName,
+ argName))
+ elif argType in objects.keys():
+ if nullok:
+ parseStr = parseStr + 'O'
+ parseList.append('&py_' + argName)
+ varDefs.add('PyObject', '*py_' +
+ argName + ' = Py_None')
+ varDefs.add(argType, '*' + argName +
+ ' = NULL')
+ extraCode.append(nullokTmpl %
+ (argName, argName,
+ objects[argType],
+ argName, argName,
+ argName, argType))
+ argList.append(argName)
+ elif default:
+ parseStr = parseStr + 'O!'
+ parseList.append(self.tp +'PyGtk_Type')
+ varDefs.add('PyObject', '*py_' +
+ argName + ' = NULL')
+ varDefs.add(argType, '*' + argName +
+ default)
+ parseList.append('&py_' + argName)
+ extraCode.append(setVarTmpl %
+ (argName, argName,
+ objects[argType] +
+ '(PyGtk_Get(py_' +
+ argName + '))'))
+ argList.append(argName)
+ else:
+ parseStr = parseStr + 'O!'
+ parseList.append(self.tp +'PyGtk_Type')
+ varDefs.add('PyObject', '*' + argName)
+ parseList.append('&' + argName)
+ argList.append(objects[argType] +
+ '(PyGtk_Get(' +
+ argName + '))')
+ elif argType in boxed.keys():
+ tp, get, new = boxed[argType]
+ if nullok:
+ varDefs.add('PyObject', '*py_' +
+ argName + ' = Py_None')
+ varDefs.add(argType, '*' + argName +
+ ' = NULL')
+ parseStr = parseStr + 'O'
+ parseList.append('&py_' + argName)
+ extraCode.append(nullokBoxedTmpl %
+ (argType, argName,
+ argName, get,
+ argName, argName,
+ argName, argType))
+ argList.append(argName)
+ else:
+ varDefs.add('PyObject', '*' + argName)
+ parseStr = parseStr + 'O!'
+ parseList.append(self.tp + tp)
+ parseList.append('&' + argName)
+ argList.append(get + '('+argName+')')
+ else:
+ print "%s: unknown arg type '%s'" % (name,
+ argType)
+ return
+
+ impl.write(str(varDefs))
+ impl.write(' if (!PyArg_ParseTuple(args, "')
+ impl.write(parseStr)
+ impl.write(':')
+ impl.write(name)
+ impl.write('"')
+ if parseList:
+ impl.write(', ')
+ impl.write(string.join(parseList, ', '))
+ impl.write('))\n return NULL;\n')
+ impl.write(string.join(extraCode, ''))
+
+ funcCall = name + '(' + string.join(argList, ', ') + ')'
+ if self.decodeRet(impl, funcCall, retType, nullret):
+ return
+ impl.write('}\n\n')
+ # actually write the info to the output files
+ self.defs.write(funcDefTmpl % (name,name))
+ self.impl.write(impl.getvalue())
+
+ def decodeRet(self, impl, funcCall, retType, nullret):
+ if retType == 'none':
+ impl.write(' ')
+ impl.write(funcCall)
+ impl.write(';\n Py_INCREF(Py_None);\n return Py_None;\n')
+ elif retType == 'static_string':
+ impl.write(' return PyString_FromString(')
+ impl.write(funcCall)
+ impl.write(');\n')
+ elif retType == 'string':
+ impl.write(' ret = ')
+ impl.write(funcCall)
+ impl.write(';\n py_ret = PyString_FromString(ret);\n g_free(ret);\n return py_ret;\n')
+ elif retType == 'const_string':
+ impl.write(' ret = ')
+ impl.write(funcCall)
+ impl.write(';\n')
+ impl.write(' if( ret != NULL)\n')
+ impl.write(' return PyString_FromString(ret);\n')
+ impl.write(' else\n')
+ impl.write(' {\n')
+ impl.write(' Py_INCREF(Py_None);\n')
+ impl.write(' return Py_None;\n')
+ impl.write(' }\n')
+ elif retType in ('char', 'uchar'):
+ impl.write(' return PyString_fromStringAndSize(*(')
+ impl.write(funcCall)
+ impl.write('));\n')
+ elif retType in ('bool','int','uint','long','ulong','guint') \
+ or retType in enums.keys() or retType in flags.keys():
+ impl.write(' return PyInt_FromLong(')
+ impl.write(funcCall)
+ impl.write(');\n')
+ elif retType in ('float','double'):
+ impl.write(' return PyFloat_FromDouble(')
+ impl.write(funcCall)
+ impl.write(');\n')
+ elif retType in boxed.keys():
+ impl.write(' return ')
+ impl.write(boxed[retType][2])
+ impl.write('(')
+ impl.write(funcCall)
+ impl.write(');\n')
+ elif retType in objects.keys():
+ if nullret:
+ impl.write(' retval = (GtkObject *)')
+ impl.write(funcCall)
+ impl.write(';\n if (retval) return PyGtk_New(retval);\n Py_INCREF(Py_None);\n return Py_None;\n')
+ else:
+ impl.write(' return PyGtk_New((GtkObject *)')
+ impl.write(funcCall)
+ impl.write(');\n')
+ else:
+ print "unknown return type '%s'" % retType
+ return 1
+ return 0
+
+class FilteringParser(FunctionDefsParser):
+ """A refinement of FunctionDefsParser with some common filter types
+ built in"""
+ def __init__(self, input, prefix='gtkmodule', typeprefix=''):
+ FunctionDefsParser.__init__(self, input, prefix, typeprefix)
+ # hash lookups are pretty fast ...
+ self.excludeList = {}
+ self.excludeGlob = []
+ def filter(self, name):
+ if self.excludeList.has_key(name):
+ return 0
+ for glob in self.excludeGlob:
+ if fnmatch.fnmatchcase(name, glob):
+ return 0
+ return 1
+ def define_func(self, name, retType, args):
+ if self.filter(name):
+ FunctionDefsParser.define_func(self,name,retType,args)
+ else:
+ print "%s: filtered out" % (name)
+ def addExcludeFile(self, fname):
+ """Adds the function names from file fname to excludeList"""
+ lines = open(fname).readlines()
+ # remove \n from each line ...
+ lines = map(lambda x: x[:-1], lines)
+ # remove comments and blank lines ...
+ lines = filter(lambda x: x and x[0] != '#', lines)
+ for name in lines:
+ self.excludeList[name] = None
+ def addExcludeGlob(self, glob):
+ if glob not in self.excludeGlob:
+ self.excludeGlob.append(glob)
+
Added: packages/openev/branches/upstream/current/pymod/gtkmissing.c
===================================================================
--- packages/openev/branches/upstream/current/pymod/gtkmissing.c (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gtkmissing.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,268 @@
+/******************************************************************************
+ * $Id: gtkmissing.c,v 1.8 2004/09/30 21:12:07 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Hand generated python bindings for some Gtk functionality
+ * not addressed by pygtk.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gtkmissing.c,v $
+ * Revision 1.8 2004/09/30 21:12:07 warmerda
+ * added explicit ref() and unref() though we shouldn't generally need them
+ *
+ * Revision 1.7 2002/07/09 03:34:10 warmerda
+ * added window get/set position calls
+ *
+ * Revision 1.6 2001/07/03 23:25:51 warmerda
+ * added gtk_object_sink
+ *
+ * Revision 1.5 2000/06/23 13:00:41 warmerda
+ * added a few ref count related debugging functions
+ *
+ * Revision 1.4 2000/06/20 13:39:06 warmerda
+ * added standard headers
+ *
+ */
+
+#if defined(WIN32) || defined(_WIN32)
+# include <pygtk.h>
+#else
+# include <pygtk/pygtk.h>
+#endif
+
+/*
+ * Functions missing in the python gtk bindings (as of pygtk-0.6.3)
+ */
+
+static PyObject *
+_wrap_gtk_toolbar_append_element(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkWidget *widget = NULL, *icon = NULL;
+ char *text, *tooltip, *tip_private;
+ GtkWidget *ret;
+ PyObject *callback, *py_widget, *py_icon, *extra = NULL, *data;
+ int type;
+
+ if (!PyArg_ParseTuple(args, "O!iOzzzOO|O!:gtk_toolbar_append_item",
+ &PyGtk_Type, &t, &type, &py_widget,
+ &text, &tooltip, &tip_private,
+ &py_icon, &callback, &PyTuple_Type, &extra))
+ return NULL;
+ if (!PyCallable_Check(callback) && callback != Py_None) {
+ PyErr_SetString(PyExc_TypeError,"eighth argument not callable");
+ return NULL;
+ }
+ Py_INCREF(callback);
+ if (PyGtk_Check(py_widget))
+ widget = GTK_WIDGET(PyGtk_Get(py_widget));
+ else if (py_widget != Py_None)
+ {
+ PyErr_SetString(PyExc_TypeError, "arg 3 must be a widget or None");
+ return NULL;
+ }
+ if (PyGtk_Check(py_icon))
+ widget = GTK_WIDGET(PyGtk_Get(py_icon));
+ else if (py_icon != Py_None)
+ {
+ PyErr_SetString(PyExc_TypeError, "arg 7 must be a widget or None");
+ return NULL;
+ }
+ /* if you set sigfunc to NULL, no signal is connected, rather than
+ the default signal handler being used */
+ ret = gtk_toolbar_append_element(GTK_TOOLBAR(PyGtk_Get(t)), type,
+ widget, text, tooltip, tip_private,
+ icon, NULL, NULL);
+ if (callback != Py_None) {
+ if (extra)
+ Py_INCREF(extra);
+ else
+ extra = PyTuple_New(0);
+ data = Py_BuildValue("(OO)", callback, extra);
+ gtk_signal_connect_full(GTK_OBJECT(ret), "clicked", NULL,
+ PyGtk_CallbackMarshal, data,
+ PyGtk_DestroyNotify, FALSE, FALSE);
+ }
+ return PyGtk_New((GtkObject *)ret);
+}
+
+static PyObject *
+_wrap_gtk_object_deref_and_destroy(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkObject *object;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_object_deref_and_destroy",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ object = GTK_OBJECT(PyGtk_Get(t));
+ while( object->ref_count > 1 )
+ gtk_object_unref(object);
+
+ gtk_object_unref(object);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gtk_object_unref(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkObject *object;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_object_unref",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ object = GTK_OBJECT(PyGtk_Get(t));
+
+ gtk_object_unref(object);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gtk_object_ref(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkObject *object;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_object_ref",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ object = GTK_OBJECT(PyGtk_Get(t));
+
+ gtk_object_ref(object);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gtk_object_get_ref_count(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkObject *object;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_object_get_ref_count",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ object = GTK_OBJECT(PyGtk_Get(t));
+
+ return Py_BuildValue("i", object->ref_count );
+}
+
+static PyObject *
+_wrap_gtk_object_sink(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ GtkObject *object;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_object_get_ref_count",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ object = GTK_OBJECT(PyGtk_Get(t));
+ gtk_object_sink( object );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_py_object_get_ref_count(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+
+ if (!PyArg_ParseTuple(args, "O:py_object_get_ref_count",
+ &t))
+ return NULL;
+
+ return Py_BuildValue("i", t->ob_refcnt );
+}
+
+static PyObject *
+_wrap_gtk_window_move(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ int x, y;
+ GdkWindow *window;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gtk_window_move",
+ &PyGtk_Type, &t, &x, &y))
+ return NULL;
+
+ window = GTK_WIDGET(PyGtk_Get(t))->window;
+
+ gdk_window_move( window, x, y );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gtk_window_get_position(PyObject *self, PyObject *args)
+{
+ PyGtk_Object *t;
+ int x, y;
+ GdkWindow *window;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_window_get_position",
+ &PyGtk_Type, &t))
+ return NULL;
+
+ window = GTK_WIDGET(PyGtk_Get(t))->window;
+
+ gdk_window_get_position( window, &x, &y );
+
+ return Py_BuildValue("(ii)", x, y );
+}
+
+static PyMethodDef gtkmissing_methods[] =
+{
+ {"gtk_toolbar_append_element", _wrap_gtk_toolbar_append_element, 1},
+ {"gtk_object_deref_and_destroy", _wrap_gtk_object_deref_and_destroy, 1},
+ {"gtk_object_unref", _wrap_gtk_object_unref, 1},
+ {"gtk_object_ref", _wrap_gtk_object_ref, 1},
+ {"gtk_object_get_ref_count", _wrap_gtk_object_get_ref_count, 1},
+ {"gtk_object_sink", _wrap_gtk_object_sink, 1},
+ {"py_object_get_ref_count", _wrap_py_object_get_ref_count, 1},
+ {"gtk_window_move", _wrap_gtk_window_move, 1},
+ {"gtk_window_get_position", _wrap_gtk_window_get_position, 1},
+ {NULL, NULL, 0}
+};
+
+void
+init_gtkmissing(void)
+{
+ init_pygtk();
+
+ Py_InitModule("_gtkmissing", gtkmissing_methods);
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module _gtkmissing");
+}
Added: packages/openev/branches/upstream/current/pymod/gtkmissing.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gtkmissing.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gtkmissing.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,70 @@
+import gtk; _gtk = gtk; del gtk
+import _gtkmissing
+import _gv
+import pgu
+
+###############################################################################
+class GtkColorWell(_gtk.GtkButton):
+ get_type = _gv.gtk_color_well_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gtk_color_well_new('')
+ if self._o is None:
+ raise ValueError, "Failed to create GtkColorWell."
+
+ def set_d( self, r, g, b, a ):
+ _gv.gtk_color_well_set_d( self._o, r, g, b, a )
+
+ def set_i8( self, r, g, b, a ):
+ _gv.gtk_color_well_set_i8( self._o, r, g, b, a )
+
+ def set_i16( self, r, g, b, a ):
+ _gv.gtk_color_well_set_i16( self._o, r, g, b, a )
+
+ def set_use_alpha( self, use_alpha ):
+ _gv.gtk_color_well_set_use_alpha( self._o, use_alpha )
+
+ def set_continuous( self, update_continuous ):
+ _gv.gtk_color_well_set_continuous( self._o, update_continuous )
+
+ def set_title( self, title ):
+ _gv.gtk_color_well_set_title( self._o, title )
+
+ def get_d(self):
+ return _gv.gtk_color_well_get_d( self._o );
+
+ def get_color( self ):
+ return self.get_d()
+
+ def set_color( self, color ):
+ self.set_d( color[0], color[1], color[2], color[3] )
+
+
+
+pgu.gtk_register( "GtkColorWell", GtkColorWell )
+
+
+###############################################################################
+
+def toolbar_append_element(self, type, widget, text, tooltip, tp,
+ icon, callback, *extra):
+ if widget: widget = widget._o
+ if icon: icon = icon._o
+ return _gtk._obj2inst(_gtkmissing.gtk_toolbar_append_element(
+ self._o, type, widget, text, tooltip, tp, icon, callback, extra))
+
+_gtk.GtkToolbar.append_element = toolbar_append_element
+
+###############################################################################
+
+def gtk_window_get_position( self ):
+ return _gtkmissing.gtk_window_get_position( self._o )
+
+def gtk_window_move( self, x, y ):
+ return _gtkmissing.gtk_window_move( self._o, x, y )
+
+_gtk.GtkWindow.get_position = gtk_window_get_position
+_gtk.GtkWindow.window_move = gtk_window_move
+
+del toolbar_append_element
+
Added: packages/openev/branches/upstream/current/pymod/gv.defs
===================================================================
--- packages/openev/branches/upstream/current/pymod/gv.defs (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gv.defs 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1160 @@
+;; -*- Scheme -*-
+
+;; Declaration of some gtk types
+
+(declare-object GtkObject)
+(declare-object GtkWidget)
+(declare-object GtkData)
+(declare-object GtkGLArea)
+
+;; View Area
+
+(define-object GvViewArea (GtkGLArea))
+
+(define-func gv_view_area_new
+ (GtkWidget null-ok)
+ ())
+
+(define-func gv_view_area_get_width
+ int
+ ((GvViewArea view)))
+
+(define-func gv_view_area_get_height
+ int
+ ((GvViewArea view)))
+
+(define-func gv_view_area_add_layer
+ none
+ ((GvViewArea view)
+ (GtkObject layer)))
+
+(define-func gv_view_area_remove_layer
+ none
+ ((GvViewArea view)
+ (GtkObject layer)))
+
+(define-func gv_view_area_get_named_layer
+ (GtkObject null-ok)
+ ((GvViewArea view)
+ (const_string layer_name)))
+
+(define-func gv_view_area_active_layer
+ (GtkObject null-ok)
+ ((GvViewArea view)))
+
+(define-func gv_view_area_set_active_layer
+ none
+ ((GvViewArea area)
+ (GtkObject layer)))
+
+(define-func gv_view_area_swap_layers
+ none
+ ((GvViewArea area)
+ (int layer_a)
+ (int layer_b)))
+
+(define-func gv_view_area_zoom
+ none
+ ((GvViewArea area)
+ (double zoom)))
+
+(define-func gv_view_area_get_zoom
+ double
+ ((GvViewArea view)))
+
+(define-func gv_view_area_get_flip_x
+ int
+ ((GvViewArea area)))
+
+(define-func gv_view_area_get_flip_y
+ int
+ ((GvViewArea area)))
+
+(define-func gv_view_area_set_flip_xy
+ none
+ ((GvViewArea area)
+ (int flip_x)
+ (int flip_y)))
+
+(define-func gv_view_area_rotate
+ none
+ ((GvViewArea area)
+ (double angle)))
+
+(define-func gv_view_area_translate
+ none
+ ((GvViewArea area)
+ (double dx)
+ (double dy)))
+
+(define-func gv_view_area_set_translation
+ none
+ ((GvViewArea area)
+ (double x)
+ (double y)))
+
+(define-func gv_view_area_fit_extents
+ none
+ ((GvViewArea area)
+ (double llx)
+ (double llyy)
+ (double width)
+ (double height)))
+
+(define-func gv_view_area_fit_all_layers
+ none
+ ((GvViewArea area)))
+
+(define-func gv_view_area_set_projection
+ none
+ ((GvViewArea area)
+ (const_string proj_name)))
+
+(define-func gv_view_area_get_projection
+ const_string
+ ((GvViewArea area)))
+
+(define-func gv_view_area_copy_state
+ none
+ ((GvViewArea area)
+ (GvViewArea source)))
+
+(define-func gv_view_area_print_to_file
+ int
+ ((GvViewArea area)
+ (int width)
+ (int height)
+ (string filename)
+ (string format)
+ (int is_rgb)))
+
+(define-func gv_view_area_print_postscript_to_file
+ int
+ ((GvViewArea area)
+ (int width)
+ (int height)
+ (double ulx)
+ (double uly)
+ (double lrx)
+ (double lry)
+ (int is_rgb)
+ (string filename)))
+
+(define-func gv_view_area_page_setup
+ none
+ ())
+
+(define-func gv_view_area_print_to_windriver
+ int
+ ((GvViewArea area)
+ (int width)
+ (int height)
+ (double ulx)
+ (double uly)
+ (double lrx)
+ (double lry)
+ (int is_rgb)))
+
+(define-func gv_view_area_set_mode
+ none
+ ((GvViewArea area)
+ (int flag_3d)))
+
+(define-func gv_view_area_get_mode
+ int
+ ((GvViewArea area)))
+
+(define-func gv_view_area_height_scale
+ none
+ ((GvViewArea area)
+ (double scale)))
+
+(define-func gv_view_area_get_height_scale
+ double
+ ((GvViewArea area)))
+
+(define-func gv_view_area_queue_draw
+ none
+ ((GvViewArea area)))
+
+(define-func gv_view_area_get_raw
+ int
+ ((GvViewArea area)
+ (GtkObject ref_layer)))
+
+(define-func gv_view_area_set_raw
+ int
+ ((GvViewArea area)
+ (GtkObject ref_layer)
+ (int raw_enable)))
+
+(define-func gv_view_area_get_property
+ const_string
+ ((GvViewArea area)
+ (string name)))
+
+(define-func gv_view_area_set_property
+ none
+ ((GvViewArea area)
+ (const_string name)
+ (const_string value)))
+
+;gv_view_area_list_layers
+;gv_view_area_create_thumbnail
+
+;; GvData
+
+(define-object GvData (GtkData))
+
+(define-func gv_data_is_read_only
+ int
+ ((GvData data)))
+
+(define-func gv_data_set_read_only
+ none
+ ((GvData data)
+ (int read_only)))
+
+(define-func gv_data_get_name
+ const_string
+ ((GvData data)))
+
+(define-func gv_data_set_name
+ none
+ ((GvData data)
+ (string name)))
+
+(define-func gv_data_get_projection
+ const_string
+ ((GvData data)))
+
+(define-func gv_data_set_projection
+ none
+ ((GvData data)
+ (string projection)))
+
+(define-func gv_data_get_property
+ const_string
+ ((GvData data)
+ (string name)))
+
+(define-func gv_data_set_property
+ none
+ ((GvData data)
+ (const_string name)
+ (const_string value)))
+
+(define-func gv_data_freeze
+ none
+ ((GvData data)))
+
+(define-func gv_data_thaw
+ none
+ ((GvData data)))
+
+(define-func gv_data_get_parent
+ (GtkObject null-ok)
+ ((GvData data)))
+
+(define-func gv_data_registry_dump
+ none
+ ())
+
+;gv_data_changed
+
+;; GvRecords
+
+(define-object GvRecords (GvData))
+
+(define-func gv_records_new
+ GvData
+ ())
+
+(define-func gv_records_from_dbf
+ (GvData null-ok)
+ ((string filename)
+ (progress_cb cb)
+ (progress_data cb_data)))
+
+(define-func gv_records_from_rec
+ (GvData null-ok)
+ ((string filename)
+ (progress_cb cb)
+ (progress_data cb_data)))
+
+(define-func gv_records_create_records
+ int
+ ((GvRecords records)
+ (int new_records)))
+
+(define-func gv_records_num_records
+ int
+ ((GvRecords records)))
+
+(define-func gv_records_add_field
+ int
+ ((GvRecords records)
+ (const_string name)
+ (int rft)
+ (int width)
+ (int precision)))
+
+(define-func gv_records_set_raw_field_data
+ none
+ ((GvRecords records)
+ (int record_index)
+ (int field_index)
+ (const_string value (null-ok) (= "NULL"))))
+
+(define-func gv_records_get_raw_field_data
+ const_string
+ ((GvRecords records)
+ (int record_index)
+ (int field_index)))
+
+;; GvShapes
+
+(define-object GvShapes (GvData))
+
+(define-func gv_shapes_new
+ GvData
+ ())
+
+(define-func gv_shapes_from_shapefile
+ (GvData null-ok)
+ ((string filename)))
+
+(define-func gv_shapes_to_shapefile
+ int
+ ((string filename)
+ (GvData data)
+ (int shp_type)))
+
+(define-func gv_shapes_from_ogr
+ (GvData null-ok)
+ ((string filename)
+ (int layer)))
+
+(define-func gv_have_ogr_support
+ int
+ ())
+
+(define-func gv_shapes_num_shapes
+ int
+ ((GvShapes shapes)))
+
+(define-func gv_shapes_add_height
+ none
+ ((GvShapes shapes)
+ (GvData raster)
+ (double offset)
+ (double default_height)))
+
+(define-func gv_shape_get_count
+ int
+ ())
+
+;; GvPoints
+
+(define-object GvPoints (GvData))
+
+(define-func gv_points_new
+ GvData
+ ())
+
+(define-func gv_points_num_points
+ int
+ ((GvPoints points)))
+
+;; GvPolylines
+
+(define-object GvPolylines (GvData))
+
+(define-func gv_polylines_new
+ GvData
+ ())
+
+(define-func gv_polylines_num_lines
+ int
+ ((GvPolylines lines)))
+
+;; GvAreas
+
+(define-object GvAreas (GvData))
+
+(define-func gv_areas_new
+ GvData
+ ())
+
+(define-func gv_areas_num_areas
+ int
+ ((GvAreas areas)))
+
+;; GvLayer
+
+(define-object GvLayer (GvData))
+
+(define-func gv_layer_is_visible
+ int
+ ((GvLayer layer)))
+
+(define-func gv_layer_set_visible
+ none
+ ((GvLayer layer)
+ (int visible)))
+
+(define-func gv_layer_reproject
+ int
+ ((GvLayer layer)
+ (string projection)))
+
+(define-func gv_layer_get_view
+ GvViewArea
+ ((GvLayer layer)))
+
+;gv_layer_extents
+
+;; GvShapeLayer
+
+(define-object GvShapeLayer (GvLayer))
+
+(define-func gv_shape_layer_clear_selection
+ none
+ ((GvShapeLayer layer)))
+
+(define-func gv_shape_layer_select_all
+ none
+ ((GvShapeLayer layer)))
+
+(define-func gv_shape_layer_select_shape
+ none
+ ((GvShapeLayer layer)
+ (int shape_id)))
+
+(define-func gv_shape_layer_deselect_shape
+ none
+ ((GvShapeLayer layer)
+ (int shape_id)))
+
+(define-func gv_shape_layer_subselect_shape
+ none
+ ((GvShapeLayer layer)
+ (int shape_id)))
+
+(define-func gv_shape_layer_get_subselection
+ int
+ ((GvShapeLayer layer)))
+
+;; GvShapesLayer
+
+(define-object GvShapesLayer (GvShapeLayer))
+
+(define-func gv_shapes_layer_new
+ GtkObject
+ ((GvShapes shapes (null-ok) (= "NULL"))))
+
+(define-func gv_shapes_layer_get_symbol_manager
+ (GtkObject null-ok)
+ ((GvShapesLayer layer)
+ (int ok_to_create)))
+
+;; GvPointLayer
+
+(define-object GvPointLayer (GvShapeLayer))
+
+(define-func gv_point_layer_new
+ GtkObject
+ ((GvPoints points (null-ok) (= "NULL"))))
+
+;; GvLineLayer
+
+(define-object GvLineLayer (GvShapeLayer))
+
+(define-func gv_line_layer_new
+ GtkObject
+ ((GvPolylines lines (null-ok) (= "NULL"))))
+
+;; GvAreaLayer
+
+(define-object GvAreaLayer (GvShapeLayer))
+
+(define-func gv_area_layer_new
+ GtkObject
+ ((GvAreas areas (null-ok) (= "NULL"))))
+
+;; GvPqueryLayer
+
+(define-object GvPqueryLayer (GvShapesLayer))
+
+(define-func gv_pquery_layer_new
+ GtkObject
+ ((GvShapes shapes (null-ok) (= "NULL"))))
+
+;; IpGcpLayer
+
+(define-object IpGcpLayer (GvShapesLayer))
+
+(define-func ip_gcp_layer_new
+ GtkObject
+ ())
+
+;; AppCurLayer
+
+(define-object AppCurLayer (GvShapesLayer))
+
+(define-func app_cur_layer_new
+ GtkObject
+ ((GvShapes shapes (null-ok) (="NULL"))))
+
+;; GvSymbolManager
+
+(define-object GvSymbolManager (GtkObject))
+
+(define-func gv_get_symbol_manager
+ GvSymbolManager
+ ())
+
+(define-func gv_symbol_manager_eject_symbol
+ none
+ ((GvSymbolManager manager)
+ (const_string name)))
+
+(define-func gv_symbol_manager_has_symbol
+ int
+ ((GvSymbolManager manager)
+ (const_string name)))
+
+;; GvManager
+
+(define-object GvManager (GtkObject))
+
+(define-func gv_get_manager
+ GvManager
+ ())
+
+(define-func gv_manager_get_preference
+ const_string
+ ((GvManager manager)
+ (const_string name)))
+
+(define-func gv_manager_set_preference
+ none
+ ((GvManager manager)
+ (const_string name)
+ (const_string value)))
+
+(define-func gv_manager_get_busy
+ int
+ ((GvManager manager)))
+
+(define-func gv_manager_set_busy
+ none
+ ((GvManager manager)
+ (int busy)))
+
+(define-func gv_manager_dump
+ none
+ ((GvManager manager)))
+
+;; GvTool
+
+(define-object GvTool (GtkObject))
+
+(define-func gv_tool_activate
+ none
+ ((GvTool tool)
+ (GvViewArea view)))
+
+(define-func gv_tool_deactivate
+ none
+ ((GvTool tool)
+ (GvViewArea view)))
+
+(define-func gv_tool_get_view
+ (GvViewArea null-ok)
+ ((GvTool tool)))
+
+(define-func gv_tool_set_cursor
+ none
+ ((GvTool tool)
+ (int cursor_type)))
+
+;; GvSelectionTool
+
+(define-object GvSelectionTool (GvTool))
+
+(define-func gv_selection_tool_new
+ GvTool
+ ())
+
+(define-func gv_selection_tool_set_layer
+ none
+ ((GvSelectionTool tool)
+ (GvShapeLayer layer)))
+
+;; GvZoompanTool
+
+(define-object GvZoompanTool (GvTool))
+
+(define-func gv_zoompan_tool_new
+ GvTool
+ ())
+
+;; GvPointTool
+
+(define-object GvPointTool (GvTool))
+
+(define-func gv_point_tool_new
+ GvTool
+ ())
+
+(define-func gv_point_tool_set_layer
+ none
+ ((GvPointTool tool)
+ (GvShapeLayer layer)))
+
+(define-func gv_point_tool_set_named_layer
+ none
+ ((GvPointTool tool)
+ (string name)))
+
+;; GvLineTool
+
+(define-object GvLineTool (GvTool))
+
+(define-func gv_line_tool_new
+ GvTool
+ ())
+
+(define-func gv_line_tool_set_layer
+ none
+ ((GvLineTool tool)
+ (GvShapeLayer layer)))
+
+(define-func gv_line_tool_set_named_layer
+ none
+ ((GvLineTool tool)
+ (string name)))
+
+;; GvRectTool
+
+(define-object GvRectTool (GvTool))
+
+(define-func gv_rect_tool_new
+ GvTool
+ ())
+
+(define-func gv_rect_tool_set_layer
+ none
+ ((GvRectTool tool)
+ (GvShapeLayer layer)))
+
+(define-func gv_rect_tool_set_named_layer
+ none
+ ((GvRectTool tool)
+ (string name)))
+
+;; GvRotateTool
+
+(define-object GvRotateTool (GvTool))
+
+(define-func gv_rotate_tool_new
+ GvTool
+ ())
+
+(define-func gv_rotate_tool_set_layer
+ none
+ ((GvRotateTool tool)
+ (GvShapeLayer layer)))
+
+(define-func gv_rotate_tool_set_named_layer
+ none
+ ((GvRotateTool tool)
+ (string name)))
+
+;; GvAreaTool
+
+(define-object GvAreaTool (GvTool))
+
+(define-func gv_area_tool_new
+ GvTool
+ ())
+
+(define-func gv_area_tool_set_layer
+ none
+ ((GvAreaTool tool)
+ (GvShapeLayer layer)))
+
+(define-func gv_area_tool_set_named_layer
+ none
+ ((GvAreaTool tool)
+ (string name)))
+
+;; GvNodeTool
+
+(define-object GvNodeTool (GvTool))
+
+(define-func gv_node_tool_new
+ GvTool
+ ())
+
+(define-func gv_node_tool_set_layer
+ none
+ ((GvNodeTool tool)
+ (GvShapeLayer layer)))
+
+;; GvRoiTool
+
+(define-object GvRoiTool (GvTool))
+
+(define-func gv_roi_tool_new
+ GvTool
+ ())
+
+;gv_roi_tool_get_rect
+
+;gv_roi_tool_new_rect
+
+;; GvPoiTool
+
+(define-object GvPoiTool (GvTool))
+
+(define-func gv_poi_tool_new
+ GvTool
+ ())
+
+;; GvTrackTool
+
+(define-object GvTrackTool (GvTool))
+
+(define-func gv_track_tool_new
+ GvTool
+ ((GtkObject label)))
+
+;; GvToolbox
+
+(define-object GvToolbox (GvTool))
+
+(define-func gv_toolbox_new
+ GvTool
+ ())
+
+(define-func gv_toolbox_add_tool
+ none
+ ((GvToolbox toolbox)
+ (string name)
+ (GvTool tool)))
+
+(define-func gv_toolbox_activate_tool
+ none
+ ((GvToolbox toolbox)
+ (string name)))
+
+;; GvUndo
+
+(define-func gv_undo_register_data
+ none
+ ((GvData data)))
+
+(define-func gv_undo_pop
+ none
+ ())
+
+(define-func gv_undo_clear
+ none
+ ())
+
+(define-func gv_undo_can_undo
+ int
+ ())
+
+(define-func gv_undo_close
+ none
+ ())
+
+(define-func gv_undo_open
+ none
+ ())
+
+(define-func gv_undo_start_group
+ int
+ ())
+
+(define-func gv_undo_end_group
+ none
+ ((int group)))
+
+;; GvViewLink
+
+(define-object GvViewLink (GtkObject))
+
+(define-func gv_view_link_new
+ GtkObject
+ ())
+
+(define-func gv_view_link_register_view
+ none
+ ((GvViewLink link)
+ (GvViewArea view)))
+
+(define-func gv_view_link_remove_view
+ none
+ ((GvViewLink link)
+ (GvViewArea view)))
+
+(define-func gv_view_link_enable
+ none
+ ((GvViewLink link)))
+
+(define-func gv_view_link_disable
+ none
+ ((GvViewLink link)))
+
+(define-func gv_view_link_set_cursor_mode
+ none
+ ((GvViewLink link)
+ (int cursor_mode)))
+
+;; GvRaster
+
+(define-object GvRaster (GvData))
+
+(define-func gv_raster_flush_cache
+ none
+ ((GvRaster raster)
+ (int x_off)
+ (int y_off)
+ (int width)
+ (int height)))
+
+(define-func gv_raster_get_min
+ float
+ ((GvRaster raster)))
+
+(define-func gv_raster_get_max
+ float
+ ((GvRaster raster)))
+
+(define-func gv_raster_cache_get_max
+ int
+ ())
+
+(define-func gv_raster_cache_get_used
+ int
+ ())
+
+(define-func gv_raster_cache_set_max
+ none
+ ((int new_max)))
+
+(define-func gv_raster_set_poly_order_preference
+ none
+ ((GvRaster raster)
+ (int poly_order)))
+
+;gv_raster_new
+
+;; GvRasterLayer
+
+(define-object GvRasterLayer (GvLayer))
+
+(define-func gv_raster_layer_lut_color_wheel_new
+ int
+ ((GvRasterLayer layer)
+ (int h_type)
+ (float h_param)
+ (int s_type)
+ (float s_param)
+ (int v_type)
+ (float v_param)))
+
+(define-func gv_raster_layer_lut_color_wheel_new_ev
+ int
+ ((GvRasterLayer layer)
+ (int set_phase)
+ (int set_magnitude)))
+
+(define-func gv_raster_layer_lut_color_wheel_1d_new
+ int
+ ((GvRasterLayer layer)
+ (float s)
+ (float v)
+ (float offset)))
+
+(define-func gv_raster_layer_alpha_set
+ int
+ ((GvRasterLayer layer)
+ (int alpha_mode)
+ (float alpha_check_val)))
+
+(define-func gv_raster_layer_min_set
+ int
+ ((GvRasterLayer layer)
+ (int isource)
+ (float min)))
+
+(define-func gv_raster_layer_min_get
+ float
+ ((GvRasterLayer layer)
+ (int isource)))
+
+(define-func gv_raster_layer_max_set
+ int
+ ((GvRasterLayer layer)
+ (int isource)
+ (float max)))
+
+(define-func gv_raster_layer_max_get
+ float
+ ((GvRasterLayer layer)
+ (int isource)))
+
+(define-func gv_raster_layer_nodata_set
+ int
+ ((GvRasterLayer layer)
+ (int isource)
+ (float nodata_real)
+ (float nodata_imaginary)))
+
+(define-func gv_raster_layer_type_get
+ float
+ ((GvRasterLayer layer)
+ (int isource)))
+
+(define-func gv_raster_layer_get_const_value
+ int
+ ((GvRasterLayer layer)
+ (int isource)))
+
+(define-func gv_raster_layer_get_data
+ (GvRaster null-ok)
+ ((GvRasterLayer layer)
+ (int isource)))
+
+(define-func gv_raster_layer_get_mode
+ int
+ ((GvRasterLayer layer)))
+
+(define-func gv_raster_layer_texture_clamp_set
+ int
+ ((GvRasterLayer layer)
+ (int s_clamp)
+ (int t_clamp)))
+
+(define-func gv_raster_layer_zoom_set
+ int
+ ((GvRasterLayer layer)
+ (int max_mode)
+ (int min_mode)))
+
+(define-func gv_raster_layer_blend_mode_set
+ int
+ ((GvRasterLayer layer)
+ (int mode)
+ (int sfactor)
+ (int dfactor)))
+
+(define-func gv_raster_layer_lut_type_get
+ int
+ ((GvRasterLayer layer)))
+
+(define-func gv_raster_layer_add_height
+ none
+ ((GvRasterLayer layer)
+ (GvRaster height_raster)
+ (double default_height)))
+
+(define-func gv_raster_layer_clamp_height
+ none
+ ((GvRasterLayer layer)
+ (int bclamp_min)
+ (int bclamp_max)
+ (double min_height)
+ (double max_height)))
+
+(define-func gv_texture_cache_dump
+ none
+ ())
+
+(define-func gv_texture_cache_get_max
+ int
+ ())
+
+(define-func gv_texture_cache_get_used
+ int
+ ())
+
+(define-func gv_texture_cache_set_max
+ none
+ ((int new_max)))
+
+(define-func gv_build_skirt
+ GvLayer
+ ((GvRasterLayer raster)
+ (double base_z)))
+
+;; GtkColorWell
+
+(define-object GtkColorWell (GtkButton))
+
+(define-func gtk_color_well_new
+ GtkColorWell
+ ((string title)))
+
+(define-func gtk_color_well_set_d
+ none
+ ((GtkColorWell cwell)
+ (double r)
+ (double g)
+ (double b)
+ (double a)))
+
+(define-func gtk_color_well_set_i8
+ none
+ ((GtkColorWell cwell)
+ (int r)
+ (int g)
+ (int b)
+ (int a)))
+
+(define-func gtk_color_well_set_i16
+ none
+ ((GtkColorWell cwell)
+ (int r)
+ (int g)
+ (int b)
+ (int a)))
+
+(define-func gtk_color_well_set_use_alpha
+ none
+ ((GtkColorWell cwell)
+ (int use_alpha)))
+
+(define-func gtk_color_well_set_continuous
+ none
+ ((GtkColorWell cwell)
+ (int update_continuous)))
+
+(define-func gtk_color_well_set_title
+ none
+ ((GtkColorWell cwell)
+ (string title)))
+
+;; GvAutopanTool
+
+(define-object GvAutopanTool (GvTool))
+
+(define-func gv_autopan_tool_new
+ GvAutopanTool
+ ())
+
+(define-func gv_autopan_tool_play
+ int
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_pause
+ int
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_stop
+ int
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_set_speed
+ double
+ ((GvAutopanTool tool)
+ (double speed)))
+
+(define-func gv_autopan_tool_get_speed
+ double
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_set_location
+ int
+ ((GvAutopanTool tool)
+ (double x)
+ (double y)
+ (double z)))
+
+(define-func gv_autopan_tool_set_overlap
+ int
+ ((GvAutopanTool tool)
+ (double overlap)))
+
+(define-func gv_autopan_tool_get_overlap
+ double
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_set_block_x_size
+ int
+ ((GvAutopanTool tool)
+ (double block_x_size)
+ (int mode)))
+
+(define-func gv_autopan_tool_set_x_resolution
+ int
+ ((GvAutopanTool tool)
+ (double resolution)))
+
+(define-func gv_autopan_tool_set_standard_path
+ int
+ ((GvAutopanTool tool)
+ (int path_type)))
+
+(define-func gv_autopan_tool_set_lines_path
+ int
+ ((GvAutopanTool tool)
+ (GvShapes lines )))
+
+(define-func gv_autopan_tool_clear_trail
+ none
+ ((GvAutopanTool tool)))
+
+(define-func gv_autopan_tool_set_trail_color
+ int
+ ((GvAutopanTool tool)
+ (GvViewArea view)
+ (float red)
+ (float green)
+ (float blue)
+ (float alpha)))
+
+(define-func gv_autopan_tool_set_trail_mode
+ int
+ ((GvAutopanTool tool)
+ (GvViewArea view)
+ (int trail_mode)))
+
+(define-func gv_autopan_tool_set_trail_parameters
+ none
+ ((GvAutopanTool tool)
+ (GvRect overview_extents)
+ (int overview_width_pixels)))
+
+(define-func gv_autopan_tool_save_trail_tiles
+ int
+ ((GvAutopanTool tool)
+ (const_string basename)))
+
+(define-func gv_autopan_tool_load_trail_tiles
+ int
+ ((GvAutopanTool tool)
+ (const_string basename)
+ (int num_trail_tiles)))
+
+(define-func gv_autopan_tool_register_view
+ int
+ ((GvAutopanTool tool)
+ (GvViewArea view)
+ (int can_resize)
+ (int can_reposition)
+ (int trail_mode)))
+
+(define-func gv_autopan_tool_remove_view
+ int
+ ((GvAutopanTool tool)
+ (GvViewArea view)))
+
+
+
+
Added: packages/openev/branches/upstream/current/pymod/gv_ciet.c
===================================================================
--- packages/openev/branches/upstream/current/pymod/gv_ciet.c (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gv_ciet.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,985 @@
+/******************************************************************************
+ * $Id: gv_ciet.c,v 1.12 2005/07/27 18:31:50 warmerda Exp $
+ *
+ * Project: CIETmap
+ * Purpose: High performance function for collecting stratified
+ * sample data to accelerate the CIETmap TABLES command.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, CIETcanada
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gv_ciet.c,v $
+ * Revision 1.12 2005/07/27 18:31:50 warmerda
+ * fixed allocation handling for paszFieldNames
+ *
+ * Revision 1.11 2004/11/19 15:38:18 zjamesatdm
+ * added support for optional else clause to recode.
+ *
+ * Revision 1.10 2004/09/28 19:43:26 warmerda
+ * Avoid extra reference increment on PyDict objects in StratTreeToDict().
+ * Was causing a substantial leak as noted in:
+ * https://www.lan.dmsolutions.ca/bugzilla/show_bug.cgi?id=3033
+ *
+ * Revision 1.9 2004/08/23 21:29:36 pgs
+ * fixed memory allocation problem in gv_records_asdict
+ *
+ * Revision 1.8 2004/08/20 13:32:07 warmerda
+ * Removed some unused variables.
+ *
+ * Revision 1.7 2004/08/18 20:55:21 pgs
+ * added ability to return columns of data in a python dictionary
+ *
+ * Revision 1.6 2004/01/13 19:26:46 pgs
+ * fixed SortRecodings algorithim
+ *
+ * Revision 1.5 2003/08/23 04:02:39 warmerda
+ * added gv_records_recode
+ *
+ * Revision 1.4 2003/08/14 18:31:47 warmerda
+ * handle case of no data collected, support just 1 or 2 vars
+ *
+ * Revision 1.3 2003/08/11 20:06:33 warmerda
+ * added progress reporting
+ *
+ * Revision 1.2 2003/08/11 18:36:49 warmerda
+ * added integer type support
+ *
+ * Revision 1.1 2003/08/08 18:10:16 warmerda
+ * New
+ *
+ */
+
+typedef struct _StratNode {
+ int nNodeCount;
+ struct _StratNode *pasItemSubNode;
+ int *panItemCount;
+} StratNode;
+
+typedef struct {
+ int nFieldIndex;
+ int nValueCount;
+ double *padfValueList;
+ PyObject **papyValueList;
+ int *panValueIndex;
+ int *panValueCount;
+
+ int bLastVar;
+ int bIsInteger;
+} StratVarInfo;
+
+/************************************************************************/
+/* StratVarFindValue() */
+/* */
+/* Try to find the passed in value in the list of values */
+/* currently associated with the variable. We keep the values */
+/* in sorted order so we can do a binary search. If we find */
+/* it, just return the index (unsorted that is). */
+/************************************************************************/
+
+static int StratVarFindValue( StratVarInfo *psVar, double dfValue )
+
+{
+ int iStart, iEnd, iMiddle;
+
+/* -------------------------------------------------------------------- */
+/* Special case for the very common case of one or two values */
+/* in the list. */
+/* -------------------------------------------------------------------- */
+ if( psVar->nValueCount > 0 && dfValue == psVar->padfValueList[0] )
+ return psVar->panValueIndex[0];
+
+ else if( psVar->nValueCount > 1 && dfValue == psVar->padfValueList[1] )
+ return psVar->panValueIndex[1];
+
+/* -------------------------------------------------------------------- */
+/* Do a binary search on the list. */
+/* -------------------------------------------------------------------- */
+ iStart = 0;
+ iEnd = psVar->nValueCount - 1;
+ while( iEnd >= iStart )
+ {
+ iMiddle = (iEnd + iStart) / 2;
+ if( dfValue < psVar->padfValueList[iMiddle] )
+ iEnd = iMiddle - 1;
+ else if( dfValue > psVar->padfValueList[iMiddle] )
+ iStart = iMiddle + 1;
+ else
+ return psVar->panValueIndex[iMiddle];
+ }
+
+/* -------------------------------------------------------------------- */
+/* We didn't find the value. Add it to the end of the list. */
+/* -------------------------------------------------------------------- */
+ psVar->nValueCount++;
+
+ psVar->padfValueList = (double *)
+ VSIRealloc(psVar->padfValueList, sizeof(double) * psVar->nValueCount );
+ psVar->padfValueList[psVar->nValueCount-1] = dfValue;
+
+ psVar->panValueIndex = (int *)
+ VSIRealloc(psVar->panValueIndex, sizeof(int) * psVar->nValueCount );
+ psVar->panValueIndex[psVar->nValueCount-1] = psVar->nValueCount-1;
+
+ psVar->panValueCount = (int *)
+ VSIRealloc(psVar->panValueCount, sizeof(int) * psVar->nValueCount );
+ psVar->panValueCount[psVar->nValueCount-1] = 0;
+
+/* -------------------------------------------------------------------- */
+/* Now sort it into the correct location in order. */
+/* -------------------------------------------------------------------- */
+ for( iStart = psVar->nValueCount - 2; iStart >= 0; iStart-- )
+ {
+ if( psVar->padfValueList[iStart] > psVar->padfValueList[iStart+1] )
+ {
+ /* swap values */
+
+ dfValue = psVar->padfValueList[iStart];
+ psVar->padfValueList[iStart] = psVar->padfValueList[iStart+1];
+ psVar->padfValueList[iStart+1] = dfValue;
+
+ iMiddle = psVar->panValueIndex[iStart];
+ psVar->panValueIndex[iStart] = psVar->panValueIndex[iStart+1];
+ psVar->panValueIndex[iStart+1] = iMiddle;
+
+ /* note: the counts are in unsorted order */
+ }
+ else
+ break;
+ }
+
+ return psVar->nValueCount-1;
+}
+
+/************************************************************************/
+/* StratNodeAdd() */
+/* */
+/* Add the passed value to the counts in this node, and return */
+/* the subnode associated with the value. Extent the item list */
+/* if needed. */
+/************************************************************************/
+
+static StratNode *StratNodeAdd( StratNode *psNode, StratVarInfo *psVar,
+ double dfValue )
+
+{
+ int nItem = StratVarFindValue( psVar, dfValue );
+
+ psVar->panValueCount[nItem]++;
+
+/* -------------------------------------------------------------------- */
+/* Reallocate the list of items larger if we find that the new */
+/* item is higher than the available item list. */
+/* -------------------------------------------------------------------- */
+ if( nItem >= psNode->nNodeCount )
+ {
+ if( psVar->bLastVar )
+ {
+ psNode->panItemCount = (int *)
+ VSIRealloc(psNode->panItemCount,
+ sizeof(int) * psVar->nValueCount);
+ memset( psNode->panItemCount + psNode->nNodeCount,
+ 0, sizeof(int)*(psVar->nValueCount-psNode->nNodeCount) );
+ }
+ else
+ {
+ psNode->pasItemSubNode = (StratNode *)
+ VSIRealloc(psNode->pasItemSubNode,
+ sizeof(StratNode) * psVar->nValueCount);
+ memset( psNode->pasItemSubNode + psNode->nNodeCount,
+ 0,
+ sizeof(StratNode)*(psVar->nValueCount-psNode->nNodeCount));
+ }
+ psNode->nNodeCount = psVar->nValueCount;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Increment count (for last variable), or return appropriate */
+/* subnode. */
+/* -------------------------------------------------------------------- */
+ if( psVar->bLastVar )
+ {
+ psNode->panItemCount[nItem]++;
+ return NULL;
+ }
+ else
+ return psNode->pasItemSubNode + nItem;
+}
+
+/************************************************************************/
+/* StratTreeToDict() */
+/************************************************************************/
+
+PyObject *StratTreeToDict( StratNode *psNode, StratVarInfo *pasVarInfos )
+
+{
+ PyObject *psDict = NULL;
+ int i, bHaveItems = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Do we have any children? If not, we don't need to do */
+/* anything. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < psNode->nNodeCount && !bHaveItems; i++ )
+ {
+ if( pasVarInfos[0].bLastVar )
+ bHaveItems |= (psNode->panItemCount[i] != 0);
+ else
+ bHaveItems |= (psNode->pasItemSubNode[i].nNodeCount != 0);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Create a dictionary into which to stick subdictionaries, or */
+/* counts. */
+/* -------------------------------------------------------------------- */
+ if( bHaveItems )
+ {
+ psDict = PyDict_New();
+
+ for( i = 0; i < psNode->nNodeCount; i++ )
+ {
+ PyObject *pyValue = NULL;
+
+ if( pasVarInfos[0].bLastVar )
+ {
+ if( psNode->panItemCount[i] != 0 )
+ pyValue = Py_BuildValue( "i", psNode->panItemCount[i] );
+ }
+ else
+ {
+ if( psNode->pasItemSubNode[i].nNodeCount != 0 )
+ {
+ pyValue = StratTreeToDict( psNode->pasItemSubNode + i,
+ pasVarInfos + 1 );
+ }
+ }
+
+ if( pyValue )
+ {
+ PyDict_SetItem( psDict, pasVarInfos[0].papyValueList[i],
+ pyValue );
+ Py_DECREF( pyValue );
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Cleanup resources associated witht his node. */
+/* -------------------------------------------------------------------- */
+ CPLFree( psNode->panItemCount );
+ CPLFree( psNode->pasItemSubNode );
+
+ return psDict;
+}
+
+/************************************************************************/
+/* GvRecords.MultiStratifiedCollect() */
+/************************************************************************/
+
+static PyObject *
+_wrap_gv_records_MultiStratifiedCollect(PyObject *self, PyObject *args)
+{
+ PyObject *py_records, *pyResultTree;
+ PyObject *py_data_selection, *py_strat_vars;
+ PyObject *v1_keys=Py_None, *v2_keys=Py_None, *result;
+ char *var1 = NULL, *var2 = NULL;
+ GvRecords *records;
+ int nSelectionCount, *panSelectionList = NULL, i;
+ int nVarCount, iVar, bCancelled = FALSE;
+ StratVarInfo *pasVarInfo;
+ StratNode *psRoot = NULL;
+ double *padfRecValues;
+ PyProgressData sProgressInfo;
+
+ sProgressInfo.psPyCallback = NULL;
+ sProgressInfo.psPyCallbackData = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!O!ssO!OO:gv_records_MultiStratifiedCollect",
+ &PyGtk_Type, &py_records,
+ &PyList_Type, &py_data_selection,
+ &var1, &var2,
+ &PyList_Type, &py_strat_vars,
+ &(sProgressInfo.psPyCallback),
+ &(sProgressInfo.psPyCallbackData) ) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ /*
+ ** Initialize progress.
+ */
+ if( !PyProgressProxy( 0.0, "", &sProgressInfo ) )
+ return FALSE;
+
+ /*
+ ** Build the variable list. Var2 is manditory, var1 is optional.
+ */
+ nVarCount = PyList_Size( py_strat_vars ) + 1;
+ if( var1 != NULL && strlen(var1) > 0 )
+ nVarCount++;
+
+ pasVarInfo = (StratVarInfo *) VSICalloc(sizeof(StratVarInfo),nVarCount);
+ padfRecValues = (double *) VSICalloc(sizeof(double),nVarCount);
+
+ for( iVar = 0; iVar < nVarCount; iVar++ )
+ {
+ const char *pszVarName = NULL;
+ int iField;
+
+ if( iVar < nVarCount-2 )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(py_strat_vars,iVar), "s",
+ &pszVarName ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting variable name in strat_vars.");
+ return NULL;
+ }
+ }
+ else if( iVar == nVarCount - 2 )
+ {
+ pszVarName = var1;
+ }
+ else if( iVar == nVarCount - 1 )
+ {
+ pszVarName = var2;
+ pasVarInfo[iVar].bLastVar = TRUE;
+ }
+
+ for( iField = 0; iField < records->nFieldCount; iField++ )
+ {
+ if( EQUAL(pszVarName,records->papszFieldName[iField]) )
+ {
+ pasVarInfo[iVar].nFieldIndex = iField;
+ pasVarInfo[iVar].bIsInteger =
+ records->panFieldType[iField] == GV_RFT_INTEGER;
+ break;
+ }
+ }
+
+ if( iField == records->nFieldCount )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "unrecognised field name.");
+ return NULL;
+ }
+ }
+
+ /*
+ ** Build up the "selection" list.
+ */
+ nSelectionCount = PyList_Size( py_data_selection );
+ panSelectionList = (int *) CPLMalloc(sizeof(int) * nSelectionCount );
+
+ for( i = 0; i < nSelectionCount; i++ )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(py_data_selection,i), "i",
+ panSelectionList + i ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "problem extracting selection item.");
+ return NULL;
+ }
+ }
+
+ /*
+ ** Allocate a root node for the data collection "tree".
+ */
+
+ psRoot = (StratNode *) CPLCalloc(sizeof(StratNode),1);
+
+ /*
+ ** Process all records.
+ */
+
+ for( i = 0; i < nSelectionCount && !bCancelled; i++ )
+ {
+ int rec_index = panSelectionList[i];
+ StratNode *psNode = psRoot;
+
+ for( iVar = 0; iVar < nVarCount; iVar++ )
+ {
+ const char *pszRawFieldValue
+ = gv_records_get_raw_field_data( records, rec_index,
+ pasVarInfo[iVar].nFieldIndex);
+ if( pszRawFieldValue == NULL )
+ break;
+
+ if( pasVarInfo[iVar].bIsInteger )
+ padfRecValues[iVar] = atoi(pszRawFieldValue);
+ else
+ padfRecValues[iVar] = atof(pszRawFieldValue);
+ }
+
+ if( i % 100 == 0 )
+ {
+ if( !PyProgressProxy( i / (double) nSelectionCount,
+ "", &sProgressInfo ) )
+ bCancelled = TRUE;
+ }
+
+ /* skip records with nulls in a used variable. */
+ if( iVar < nVarCount )
+ continue;
+
+ for( iVar = 0; iVar < nVarCount; iVar++ )
+ {
+ psNode = StratNodeAdd( psNode, pasVarInfo + iVar,
+ padfRecValues[iVar] );
+ }
+ }
+
+ CPLFree( padfRecValues );
+ CPLFree( panSelectionList );
+
+ if( !bCancelled )
+ PyProgressProxy( 1.0, "", &sProgressInfo );
+
+ /*
+ ** Unsort the values list in the StratVarInfo's so that our indexes can
+ ** be used easily to get back to the variable values.
+ */
+ for( iVar = 0; iVar < nVarCount; iVar++ )
+ {
+ StratVarInfo *psVar = pasVarInfo + iVar;
+ int iValue;
+ double *padfNewValueList;
+
+ padfNewValueList = (double *)
+ CPLMalloc(sizeof(double) * psVar->nValueCount);
+
+ for( iValue = 0; iValue < psVar->nValueCount; iValue++ )
+ {
+ padfNewValueList[psVar->panValueIndex[iValue]] =
+ psVar->padfValueList[iValue];
+ }
+ CPLFree( psVar->padfValueList );
+ psVar->padfValueList = padfNewValueList;
+
+ CPLFree( psVar->panValueIndex );
+ psVar->panValueIndex = NULL;
+ }
+
+ /*
+ ** Create Python string reresentations of the values for use in the
+ ** final results dictionary.
+ */
+ for( iVar = 0; iVar < nVarCount; iVar++ )
+ {
+ StratVarInfo *psVar = pasVarInfo + iVar;
+ int iValue;
+
+ psVar->papyValueList = (PyObject **)
+ CPLMalloc(sizeof(PyObject *) * psVar->nValueCount);
+
+ for( iValue = 0; iValue < psVar->nValueCount; iValue++ )
+ {
+ if( psVar->bIsInteger )
+ {
+ psVar->papyValueList[iValue] =
+ Py_BuildValue( "i", (int) psVar->padfValueList[iValue] );
+ }
+ else
+ {
+ psVar->papyValueList[iValue] =
+ Py_BuildValue( "d", psVar->padfValueList[iValue] );
+ }
+ }
+ }
+
+ /*
+ ** Marshall the results into a tree of dictionaries. Wipe tree as
+ ** part of the process.
+ */
+
+ pyResultTree = StratTreeToDict( psRoot, pasVarInfo );
+ if( pyResultTree == NULL )
+ {
+ pyResultTree = Py_None;
+ Py_INCREF( Py_None );
+ }
+
+ /*
+ ** Create v1/v2_keys ... a dictionary with one entry for each value of
+ ** var1/var2 that occurs in the data.
+ */
+
+ for( iVar = nVarCount-1; iVar >= nVarCount-2 && iVar >= 0; iVar-- )
+ {
+ int iValue;
+ PyObject *key_dict = PyDict_New();
+
+ for( iValue = 0; iValue < pasVarInfo[iVar].nValueCount; iValue++ )
+ {
+ PyDict_SetItem( key_dict, pasVarInfo[iVar].papyValueList[iValue],
+ Py_None );
+ }
+
+ if( iVar == nVarCount-1 )
+ v2_keys = key_dict;
+ else
+ v1_keys = key_dict;
+ }
+
+ /*
+ ** Cleanup working structures.
+ */
+
+ /*
+ ** Prepare final result tuple.
+ */
+
+ result = Py_BuildValue( "(OOO)", v1_keys, v2_keys, pyResultTree );
+
+ if( v1_keys != Py_None )
+ {
+ Py_DECREF( v1_keys );
+ }
+ Py_DECREF( v2_keys );
+ Py_DECREF( pyResultTree );
+
+ if( bCancelled )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "User called processing.");
+ Py_DECREF( result );
+ return NULL;
+ }
+ else
+ {
+ return result;
+ }
+}
+
+typedef struct {
+ double dfMin;
+ double dfMax;
+ double dfReplacement;
+ int bReplaceNULL;
+} GvRecodeEntry;
+
+/************************************************************************/
+/* SortRecodings() */
+/* */
+/* Simple bubble sort of the recode table entries. */
+/************************************************************************/
+
+void SortRecodings( int nCount, GvRecodeEntry *pasRecodings )
+
+{
+ int i, j;
+
+ for( i = 0; i < nCount-1; i++ )
+ {
+ for( j = 0; j < nCount-1; j++ )
+ {
+ if( pasRecodings[j].dfMin > pasRecodings[j+1].dfMin )
+ {
+ GvRecodeEntry sTempEntry;
+
+ memcpy( &sTempEntry, pasRecodings+j, sizeof(sTempEntry) );
+ memcpy( pasRecodings+j, pasRecodings+j+1, sizeof(sTempEntry) );
+ memcpy( pasRecodings+j+1, &sTempEntry, sizeof(sTempEntry) );
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* FindRecoding() */
+/************************************************************************/
+
+GvRecodeEntry *FindRecoding( double dfValue,
+ int nCount, GvRecodeEntry *pasRecodings )
+
+{
+ int iStart, iEnd, iMiddle;
+
+ iStart = 0;
+ iEnd = nCount - 1;
+
+ //TODO: dump out here???
+
+ while( iEnd >= iStart )
+ {
+ iMiddle = (iStart+iEnd)/2;
+
+ if( pasRecodings[iMiddle].dfMin > dfValue )
+ iEnd = iMiddle - 1;
+ else if( pasRecodings[iMiddle].dfMax < dfValue )
+ iStart = iMiddle+1;
+ else if( pasRecodings[iMiddle].dfMin <= dfValue
+ && pasRecodings[iMiddle].dfMax >= dfValue )
+ return pasRecodings + iMiddle;
+ else
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/************************************************************************/
+/* gv_records_recode() */
+/************************************************************************/
+
+static PyObject *
+_wrap_gv_records_recode(PyObject *self, PyObject *args)
+{
+ PyObject *py_records, *py_single_mapping, *py_range_mapping;
+ GvRecords *records;
+ char *pszSrcVarName = NULL, *pszDstVarName = NULL;
+ int bCancelled = FALSE, i, nRecordCount;
+ int nRangeRecodeCount = 0, nSingleRecodeCount = 0;
+ int iSrcField, iDstField, nIgnored=0, nAltered=0, nUnchanged=0;
+ PyProgressData sProgressInfo;
+ GvRecodeEntry *pasSingleRecodings;
+ GvRecodeEntry *pasRangeRecodings;
+ PyObject *pyKey = NULL, *pyValue = NULL;
+ int bHaveNULLReplacement = FALSE;
+ GvRecodeEntry sNULLEntry;
+ int bElseClause = FALSE;
+ GvRecodeEntry sElseEntry;
+
+ sProgressInfo.psPyCallback = NULL;
+ sProgressInfo.psPyCallbackData = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!O!O!ssOO:gv_records_recode",
+ &PyGtk_Type, &py_records,
+ &PyDict_Type, &py_single_mapping,
+ &PyList_Type, &py_range_mapping,
+ &pszSrcVarName, &pszDstVarName,
+ &(sProgressInfo.psPyCallback),
+ &(sProgressInfo.psPyCallbackData) ) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ /*
+ ** Identify the source and destination field indexes.
+ */
+ iSrcField = -1;
+ iDstField = -1;
+ for( i = 0; i < records->nFieldCount; i++ )
+ {
+ if( EQUAL(pszSrcVarName,records->papszFieldName[i]) )
+ iSrcField = i;
+ if( EQUAL(pszDstVarName,records->papszFieldName[i]) )
+ iDstField = i;
+ }
+
+ if( iSrcField == -1 || iDstField == -1 )
+ {
+ PyErr_SetString( PyExc_ValueError, "RECODE variable not recognised." );
+ return NULL;
+ }
+
+ cos( 0.0 );
+
+ /*
+ ** Collect the single value mappings.
+ */
+ pasSingleRecodings =
+ g_new( GvRecodeEntry, PyDict_Size(py_single_mapping) );
+
+ nSingleRecodeCount = 0;
+ i = 0;
+ while( PyDict_Next( py_single_mapping, &i, &pyKey, &pyValue ) )
+ {
+ char *pszKey = NULL, *pszValue = NULL;
+
+ if( pyValue == Py_None )
+ {
+ pasSingleRecodings[nSingleRecodeCount].dfReplacement = 0.0;
+ pasSingleRecodings[nSingleRecodeCount].bReplaceNULL = TRUE;
+ }
+ else if( !PyArg_Parse( pyValue, "s", &pszValue ) )
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Single value is not numeric." );
+ return NULL;
+ }
+ else
+ {
+ pasSingleRecodings[nSingleRecodeCount].dfReplacement =
+ atof( pszValue );
+ pasSingleRecodings[nSingleRecodeCount].bReplaceNULL = FALSE;
+ }
+
+ if( pyKey == Py_None )
+ {
+ bHaveNULLReplacement = TRUE;
+ memcpy( &sNULLEntry,
+ pasSingleRecodings + nSingleRecodeCount,
+ sizeof(sNULLEntry) );
+ }
+ else if( !PyArg_Parse( pyKey, "s", &pszKey ) )
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Single value is not numeric." );
+ return NULL;
+ }
+ else if( EQUAL(pszKey,"None") || EQUAL(pszKey,"NULL") )
+ {
+ bHaveNULLReplacement = TRUE;
+ memcpy( &sNULLEntry,
+ pasSingleRecodings + nSingleRecodeCount,
+ sizeof(sNULLEntry) );
+ }
+ else if( EQUAL(pszKey,"ELSE") )
+ {
+ /*NULL is a special case*/
+ if( pyValue != Py_None )
+ {
+ sElseEntry.dfReplacement = atof( pszValue );
+ }
+ else
+ {
+ bHaveNULLReplacement = TRUE;
+ }
+
+ /*any value should be caught by else*/
+ sElseEntry.dfMin = 0 - HUGE_VAL;
+ sElseEntry.dfMax = HUGE_VAL;
+ memcpy( &sElseEntry,
+ pasSingleRecodings + nSingleRecodeCount,
+ sizeof(sElseEntry) );
+ bElseClause = TRUE;
+ }
+ else
+ {
+ pasSingleRecodings[nSingleRecodeCount].dfMin = atof(pszKey);
+ pasSingleRecodings[nSingleRecodeCount].dfMax = atof(pszKey);
+ nSingleRecodeCount++;
+ }
+ }
+
+ SortRecodings( nSingleRecodeCount, pasSingleRecodings );
+
+ /*
+ ** Collect range mappings.
+ */
+
+ nRangeRecodeCount = PyList_Size(py_range_mapping);
+ pasRangeRecodings = g_new( GvRecodeEntry, nRangeRecodeCount );
+
+ for( i = 0; i < nRangeRecodeCount; i++ )
+ {
+ char *pszReplacement=NULL;
+
+ if( !PyArg_Parse( PyList_GetItem( py_range_mapping, i ), "(ddz)",
+ &(pasRangeRecodings[i].dfMin),
+ &(pasRangeRecodings[i].dfMax),
+ &pszReplacement ) )
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Range value is not (min,max,result) tuple." );
+ return NULL;
+ }
+
+ if( pszReplacement == NULL )
+ {
+ pasRangeRecodings[i].dfReplacement = 0.0;
+ pasRangeRecodings[i].bReplaceNULL = TRUE;
+ }
+ else
+ {
+ pasRangeRecodings[i].dfReplacement = atof(pszReplacement);
+ pasRangeRecodings[i].bReplaceNULL = FALSE;
+ }
+ }
+
+ SortRecodings( nRangeRecodeCount, pasRangeRecodings );
+
+ /*
+ ** Initialize progress.
+ */
+ if( !PyProgressProxy( 0.0, "", &sProgressInfo ) )
+ return FALSE;
+
+ /*
+ ** Process all records (not just selected ones!).
+ */
+ nRecordCount = gv_records_num_records( records );
+ for( i = 0; i < nRecordCount && !bCancelled; i++ )
+ {
+ double dfValue;
+ GvRecodeEntry *psEntry;
+ const char *pszRawFieldValue =
+ gv_records_get_raw_field_data( records, i, iSrcField );
+
+ if( pszRawFieldValue == NULL )
+ {
+ if( bHaveNULLReplacement )
+ psEntry = &sNULLEntry;
+ else
+ psEntry = NULL;
+ }
+ else
+ {
+ dfValue = atof(pszRawFieldValue);
+
+ psEntry = FindRecoding( dfValue,
+ nSingleRecodeCount, pasSingleRecodings );
+ if( psEntry == NULL)
+ psEntry = FindRecoding( dfValue,
+ nRangeRecodeCount, pasRangeRecodings );
+
+ /*
+ if nothing else was applied, use the ELSE value after adding
+ the correct mapping
+ */
+ if (psEntry == NULL && bElseClause)
+ {
+ psEntry = &sElseEntry;
+ }
+ }
+
+
+ if( psEntry == NULL )
+ nUnchanged++;
+ else if( psEntry->bReplaceNULL )
+ {
+ gv_records_set_raw_field_data( records, i, iDstField, NULL );
+ nIgnored++;
+ }
+ else
+ {
+ char szReplaceText[200];
+
+ sprintf( szReplaceText, "%g", psEntry->dfReplacement );
+ gv_records_set_raw_field_data( records, i, iDstField,
+ szReplaceText);
+ nAltered++;
+ }
+
+ if( i % 100 == 0 )
+ {
+ if( !PyProgressProxy( i / (double) nRecordCount,
+ "", &sProgressInfo ) )
+ bCancelled = TRUE;
+ }
+ }
+
+ if( !bCancelled )
+ PyProgressProxy( 1.0, "", &sProgressInfo );
+
+ g_free( pasSingleRecodings );
+ g_free( pasRangeRecodings );
+
+ return Py_BuildValue( "(iii)", nUnchanged, nAltered, nIgnored );
+}
+
+
+
+/************************************************************************/
+/* gv_records_aslist() */
+/************************************************************************/
+
+static PyObject *
+_wrap_gv_records_asdict(PyObject *self, PyObject *args)
+{
+ PyObject *py_records, *py_fields;
+ GvRecords *records;
+ int i, j, nRecordCount, nFields, *panFields;
+ PyObject *py_dict = NULL, *py_list = NULL;
+ char ** paszFieldNames;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_records_asdict",
+ &PyGtk_Type, &py_records,
+ &PyList_Type, &py_fields ) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+
+ nFields = PyList_Size(py_fields);
+ paszFieldNames = (char **) calloc( nFields, sizeof( char * ) );
+ panFields = (int *)malloc( nFields * sizeof( int ) );
+ for( i = 0; i < nFields; i++ )
+ {
+ PyArg_Parse( PyList_GET_ITEM(py_fields,i), "s", &paszFieldNames[i] );
+ panFields[i] = -1;
+ for( j = 0; j < records->nFieldCount; j++ )
+ {
+ if( EQUAL(paszFieldNames[i],records->papszFieldName[j]) )
+ panFields[i] = j;
+ }
+ if( panFields[i] == -1)
+ {
+ PyErr_SetString( PyExc_ValueError, "ASDICT variable not recognised." );
+ return NULL;
+ }
+ }
+
+ nRecordCount = gv_records_num_records( records );
+ py_dict = PyDict_New();
+ for( i = 0; i < nFields; i++ )
+ {
+ PyDict_SetItem( py_dict, PyString_FromString(paszFieldNames[i]), PyList_New( nRecordCount ) );
+ }
+
+ /*
+ ** Process all records (not just selected ones!).
+ */
+
+ for( i = 0; i < nRecordCount; i++ )
+ {
+ for( j = 0; j < nFields; j++ )
+ {
+ const char *pszRawFieldValue =
+ gv_records_get_raw_field_data( records, i, panFields[j] );
+
+ py_list = PyDict_GetItem( py_dict, PyString_FromString(paszFieldNames[j]) );
+
+ if( pszRawFieldValue == NULL )
+ {
+ PyList_SetItem( py_list, i, Py_None );
+ }
+ else
+ {
+ switch( records->panFieldType[panFields[j]] )
+ {
+ case GV_RFT_INTEGER:
+ PyList_SetItem( py_list, i, Py_BuildValue( "i", atoi(pszRawFieldValue) ));
+ break;
+ case GV_RFT_FLOAT:
+ PyList_SetItem( py_list, i, Py_BuildValue( "d", atof(pszRawFieldValue) ));
+ break;
+ default:
+ PyList_SetItem( py_list, i, Py_BuildValue( "s", pszRawFieldValue));
+ }
+ }
+ //PyDict_SetItem( py_dict, PyString_FromString(paszFieldNames[j]), py_list );
+ }
+ }
+
+ free( panFields );
+ free( paszFieldNames );
+
+ return py_dict;
+}
Added: packages/openev/branches/upstream/current/pymod/gvalg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvalg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvalg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,142 @@
+###############################################################################
+# $Id: gvalg.py,v 1.7 2004/11/19 23:59:37 gmwalter Exp $
+#
+# Project: CIETMap/OpenEV
+# Purpose: Assorted algorithm python entry points.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Frank Warmerdam, warmerda at home.com
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvalg.py,v $
+# Revision 1.7 2004/11/19 23:59:37 gmwalter
+# Check in Aude's rasterization updates.
+#
+# Revision 1.6 2002/12/13 21:21:04 warmerda
+# Fixed docs.
+#
+# Revision 1.5 2002/12/13 21:13:33 warmerda
+# Added some user documentation.
+#
+# Revision 1.4 2001/04/22 17:34:21 pgs
+# changed wid_interpolate to take variable exponent for d
+#
+# Revision 1.3 2001/03/29 14:59:56 warmerda
+# added fill_short flag to control handling of slivers
+#
+# Revision 1.2 2000/09/15 15:13:14 warmerda
+# flush raster
+#
+# Revision 1.1 2000/09/15 01:44:12 warmerda
+# New
+#
+#
+
+import _gv
+
+"""
+Python wrappers for various algorithms.
+"""
+
+
+###############################################################################
+
+def rasterize_shapes( raster, shapes, burn_value, fill_short = 1 ):
+ """Rasterize GvShape polygons into a GvRaster.
+
+ A python list of GvShapes are burned into a GvRaster with a user supplied
+ "burn value". Only polygons are supported at this time. The polygon
+ coordinates must be in the same coordinate system as the GvRaster. The
+ polygons may have inner rings, or even multiple outer rings.
+
+ Example:
+ import gvalg, gview
+
+ polygons = gview.GvShapes( shapefilename = poly_filename )
+
+ rfile = gdal.GetDriverByName('GTiff').Create(filename,xsize,ysize,1)
+ rfile.SetGeoTransform( geotransform )
+ raster = gview.GvRaster( dataset = rfile )
+
+ gvalg.rasterize_shapes( raster, polygons, 255 )
+
+
+ raster -- a GvRaster with update access.
+ shapes -- A GvShapes or list object containing the list of shapes to
+ burn into the raster.
+ burn_value -- The value to be assigned to pixels under the polygons.
+ fill_short -- 1 to fill partial scanlines, or 0 to not do so.
+
+ NEW: fill_short = 2: same algorithm as above but with less bugs
+ fill_short = 3: a pixel is considered inside the shape if and only if its
+ centre is inside the shape.
+
+
+ Returns 0 on failure, or a non-zero value on success.
+ """
+
+ shapes_o = []
+ for shape in shapes:
+ shapes_o.append( shape._o )
+
+ ret = _gv.gv_raster_rasterize_shapes( raster._o, shapes_o, burn_value,
+ fill_short )
+ raster.get_band().FlushCache()
+ return ret
+
+###############################################################################
+
+def wid_interpolate( raster, points, exponent = 2.0, progress_cb=None, cb_data=None ):
+
+ """Weighted Inverse Distance Interpolation
+
+ This algorithm interpolates the pixel values of a GvRaster using a simple
+ inverse distance interpolator with an additional per point weighting
+ factor. The algorithm supports GDALProcessFunc style
+ progress reporting, and user termination support.
+
+ Note that the (x,y) values for the points must be in pixel/line coordinates
+ on the raster, not georeferenced coordinates. They may have subpixel
+ accuracy.
+
+ points -- a list of (x,y,value,weight) tuples where each tuple is
+ a point to interpolate.
+
+ raster -- the GvRaster representating the band to apply changes to.
+ The GvRaster must be in update mode.
+
+ exponent -- the exponent to apply to the distance calculate in the
+ weighting formula
+
+ progress_cb -- progress function, leave defaulted if no progress called
+ is needed.
+
+ cb_data -- a value to be passed into the progress_cb.
+
+ Returns a CPL error number on failure, or 0 on success. Note that
+ a user interrupt will result in CPLE_UserInterrupt being returned.
+ """
+
+ ret = _gv.WIDInterpolate( points, raster.get_band()._o,
+ exponent, progress_cb, cb_data )
+ raster.get_band().FlushCache()
+ return ret
+
+
+
Added: packages/openev/branches/upstream/current/pymod/gvbitlayerlut.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvbitlayerlut.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvbitlayerlut.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,73 @@
+
+class GvBitLayerLUT:
+ """Class for managing a LUT for display bitplane rasters.
+
+ This class keeps state for managing 8 colourized bitplanes, and
+ can produce an appropriate lut in string format, suitable for using
+ with GvRasterLayer.put_lut() when needed."""
+
+ def __init__(self):
+ """Initialize with eight distinct colours for bit planes."""
+ self.plane_color = [(0,0,0,0), (255,0,0,255), (0,255,0,255),
+ (0,0,255,255), (255,255,0,255), (255,0,255,255),
+ (0,255,255,255), (255,255,255,255)]
+ self.priority = [0, 1, 2, 3, 4, 5, 6, 7]
+
+ def set_color(self,plane,color):
+ """Set the color of one of the bit planes.
+
+ plane -- a bit plane number from 0 to 7.
+
+ color -- an RGBA tuple such as (255,0,0,255)"""
+ self.plane_color[plane] = color
+
+ def set_priority(self,priority,plane):
+ """Set what plane is drawn at a given priority level.
+
+ By default (after initialization) bit plane zero is
+ priority zero, through to bit plane seven being at
+ priority seven. To move bit plane 0 to top priority, and
+ move everything else down one it would be necessary to do
+ something like this example:
+
+ bit_lut.set_priority(7,0)
+ bit_lut.set_priority(6,7)
+ bit_lut.set_priority(5,6)
+ bit_lut.set_priority(4,5)
+ bit_lut.set_priority(3,4)
+ bit_lut.set_priority(2,3)
+ bit_lut.set_priority(1,2)
+ bit_lut.set_priority(0,1)
+
+ priority -- a priority level from 0 to 7
+
+ plane -- a plane from 0 to 7"""
+
+ self.priority[priority] = plane
+
+ def get_lut_as_string(self):
+ """Fetch a lut suitable for use with GvRasterLayer.lut_put()
+ representing the current bit plane configuration."""
+ lut = []
+ for i in range(256):
+ lut.append((0,0,0,0))
+
+ for ip in range(8):
+ plane = self.priority[ip]
+ bitvalue = 2 ** plane
+ for i in range(256):
+ if (i % (bitvalue*2)) >= bitvalue:
+ lut[i] = self.plane_color[plane]
+
+ lut_string = ''
+ for i in range(256):
+ rgba_tuple = lut[i]
+ lut_string = lut_string + \
+ (chr(rgba_tuple[0])+chr(rgba_tuple[1])+ \
+ chr(rgba_tuple[2])+chr(rgba_tuple[3]))
+ return lut_string
+
+if __name__ == '__main__':
+ x = GvBitLayerLUT()
+
+ print x.get_lut_as_string()
Added: packages/openev/branches/upstream/current/pymod/gvclassification.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvclassification.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvclassification.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1367 @@
+###############################################################################
+# $Id: gvclassification.py,v 1.30 2004/06/29 16:06:15 dem Exp $
+#
+# Project: CIETMap / OpenEV
+# Purpose: GvClassification class responsible for managing classification
+# related properties on a GvRasterLayer.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Frank Warmerdam <warmerda at home.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvclassification.py,v $
+# Revision 1.30 2004/06/29 16:06:15 dem
+# fixed a little bug in ranges serialization
+# (big numbers was truncated by '%s' (str) ; now use '%r' (repr) instead)
+#
+# Revision 1.29 2004/04/01 13:50:58 dem
+# CVS correction
+#
+# Revision 1.28 2004/04/01 13:24:25 dem
+# CVS problem (sorry)
+#
+# Revision 1.27 2004/04/01 10:30:48 dem
+# fixed bug in compute_rep when raw_value is out of
+# min/max range (< range[0][0] and > range[self.count - 1][1])
+# fixed a conversion warning
+# transmit rescale argument from update_layer to update_raster
+#
+# Revision 1.26 2003/12/28 15:46:19 warmerda
+# fixed up support for negatives
+#
+# Revision 1.25 2003/08/13 14:03:08 pgs
+# added code provided by Dan Puter for Std Dev and Quantile classification.
+#
+# Revision 1.24 2002/11/05 15:04:43 warmerda
+# added support for getting discrete values for rasters
+#
+# Revision 1.23 2002/11/05 03:40:49 warmerda
+# fixed syntax error in try statement
+#
+# Revision 1.22 2002/10/30 18:21:16 pgs
+# modiified computation of raw_value for vectors to skip shapes that don't have
+# the classification property set.
+#
+# Revision 1.21 2002/10/29 17:12:59 warmerda
+# use min_v and max_v for local vars to avoid optimized conflicts
+#
+# Revision 1.20 2002/10/28 15:01:28 warmerda
+# Improved handling for discrete integer classifications (int comparisons were
+# failing). Also report if more than 80 discrete classes are discovered as
+# only 80 will be proceessed.
+#
+# Revision 1.19 2002/09/10 21:17:05 warmerda
+# removed debugging statement
+#
+# Revision 1.18 2002/09/10 17:33:46 warmerda
+# default raw_value to 0.0 if get_property() fails on GvShape
+#
+# Revision 1.17 2002/09/10 15:44:18 pgs
+# fixed bug in remove_layer()
+#
+# Revision 1.16 2002/09/04 14:38:51 pgs
+# separate ranges with : to prevent problems with discrete classification on
+# strings with spaces.
+#
+# Revision 1.15 2002/08/27 19:13:35 pgs
+# extended default classification limits to 80 classes.
+#
+# Revision 1.14 2002/08/19 17:13:49 pgs
+# bug fixes related to discrete classifications
+#
+# Revision 1.13 2002/08/16 17:50:24 pgs
+# outline classified areas in a black pen
+#
+# Revision 1.12 2002/08/13 17:43:35 pgs
+# fixed raster classification and fixed legend for point layers
+#
+# Revision 1.11 2002/08/09 21:05:20 pgs
+# finished vector support
+#
+# Revision 1.10 2002/08/01 20:13:01 warmerda
+# partial implementation of vector layer support
+#
+# Revision 1.9 2001/05/07 14:01:33 warmerda
+# significant fixes to rescaling logic
+#
+# Revision 1.8 2001/04/09 19:42:43 pgs
+# added flag to add_raster to turn off auto-init on first raster
+#
+# Revision 1.7 2001/02/14 02:10:30 pgs
+# *** empty log message ***
+#
+# Revision 1.6 2000/10/09 14:01:21 pgs
+# added a default legend title in prepare_default()
+#
+# Revision 1.5 2000/10/02 20:55:39 pgs
+# fixed bug in remove_class.
+#
+# Revision 1.4 2000/09/29 04:29:47 warmerda
+# made default classification extend slightly outside min/max
+#
+# Revision 1.3 2000/09/27 14:35:27 warmerda
+# added auto update of legend, and classification serial numbers
+#
+# Revision 1.2 2000/09/27 13:38:18 warmerda
+# (pgs) added lots of access methods, prepare_default()
+#
+# Revision 1.1 2000/09/21 03:01:43 warmerda
+# New
+#
+#
+
+#
+# TODO: Add Sybmols
+#
+
+import gview
+import string
+import gdal
+import gvutils
+import Numeric
+
+###############################################################################
+#
+# Classification Type Handling
+#
+# A classification type dictates how the default classification for a given set
+# of layers is created. To support different types of classifications, you
+# add a new CLASSIFY_XXXXXX declaration using the next available number, update
+# CLASSIFY_LAST to the new maximum number, and then add an entry to the
+# classification_types dictionary that maps a name to the number and add code
+# to GvClassification.prepare_default() to handle the new type.
+#
+###############################################################################
+
+#classification types
+CLASSIFY_BASE = 0 #used for validation
+CLASSIFY_DISCRETE = 0
+CLASSIFY_EQUAL_INTERVAL = 1
+CLASSIFY_QUANTILE = 2
+CLASSIFY_NORM_SD = 3
+CLASSIFY_LAST = CLASSIFY_NORM_SD #used for validation
+
+#classification type dictionary
+classification_types = { 'Discrete Values' : CLASSIFY_DISCRETE,
+ 'Equal Interval' : CLASSIFY_EQUAL_INTERVAL,
+ 'Quantiles' : CLASSIFY_QUANTILE,
+ 'Normal Std Dev' : CLASSIFY_NORM_SD }
+
+class GvClassification:
+
+ """Manage layer classification scheme.
+
+ Holds information on a layer classification scheme, and
+ can be instantiated from, and serialized to, the properties of the
+ GvLayer. Currently supports GvRasterLayer and GvShapesLayer.
+ """
+
+ ###########################################################################
+ def __init__(self, layer=None, type=CLASSIFY_EQUAL_INTERVAL):
+ self.count = 0
+ self.name = []
+ self.desc = []
+ self.range = []
+ self.color = []
+ self.title = ''
+ self.layers = []
+ self.point_symbols = []
+ self.symbol_scales = []
+ self.set_type( type )
+
+ self.legend_dialog = None
+
+ if layer is not None:
+ self.add_layer( layer )
+
+ ###########################################################################
+ def dump( self, *args ):
+ print str(self)
+
+ ###########################################################################
+ def __str__(self):
+ s = ''
+ s = s + 'Classification Object:\n'
+ s = s + 'type: ' + str(self.type) + '\n'
+ s = s + 'Title: ' + self.title + '\n'
+ s = s + 'count: ' + str(self.count) + '\n'
+ for i in range(len(self.name)):
+ s = s + 'name: ' + self.name[i] + '\n'
+ s = s + 'desc: ' + self.desc[i] + '\n'
+ s = s + 'range: ' + str(self.range[i]) + '\n'
+ s = s + 'color: ' + str(self.color[i]) + '\n'
+ s = s + 'symbol: ' + str(self.point_symbols[i]) + '\n'
+ s = s + 'symbol scale: ' + str(self.symbol_scales[i]) + '\n'
+ return s
+
+ ###########################################################################
+ def add_raster(self, raster, init=1):
+ """Add a ranster layer to the list of layers managed by this
+ classification
+
+ DEPRECATED - use add_layer instead
+ """
+ print "GvClassification.add_raster() is deprecated, " + \
+ "use add_layer instead"
+ self.add_layer( raster, init )
+
+ ###########################################################################
+ def add_layer(self, layer, init = 1, property = None ):
+ """Add a layer to the list of layers managed by this
+ classification.
+
+ layer -- GvRasterLayer or GvShapesLayer to operate on.
+
+ init -- true (1) to initialize classification from this layer
+ -- false(0) to not initialize ...
+
+ property -- the property (attribute) from GvShapesLayers that should
+ be used as the value.
+
+ Initializes classification scheme from indicated layer, remembering
+ tied layer. If available the classification properties are read from
+ the GvLayer, otherwise a default classification scheme is prepared."""
+ if init:
+ self.deserialize( layer.get_properties() )
+
+ if property is not None:
+ self.set_classify_property( layer, property )
+
+ if self.get_classify_property( layer ) is None \
+ and issubclass(layer.__class__,gview.GvShapesLayer):
+ schema = layer.get_parent().get_schema()
+ if len(schema) > 0:
+ self.set_classify_property( layer, schema[0][0] )
+
+ self.layers.append( layer )
+
+ ###########################################################################
+ def remove_raster(self, raster):
+ """Remove a raster from the classification
+
+ DEPRECATED - use remove_layer instead
+ """
+ print "GvClassification.remove_raster() is deprecated, " + \
+ "use remove_layer instead"
+ self.remove_layer( raster )
+
+ ###########################################################################
+ def remove_layer( self, layer):
+ """Remove a layer from the classification
+
+ layer -- the GvLayer to remove.
+ """
+ for n in range(len(self.layers)):
+ if layer is self.layers[n]:
+ del self.layers[n]
+ break
+
+ ###########################################################################
+ def remove_all_layers(self):
+ """remove all layers currently being managed by this classification"""
+ self.layers = []
+
+ ###########################################################################
+ def set_classify_property( self, layer, property ):
+ """Set property (attribute field) to use for classification."""
+
+ if self.title == 'Legend: ' + str(self.get_classify_property( layer )):
+ self.title = 'Legend: ' + property
+ layer.set_property( 'Classification_Property', property )
+
+ ###########################################################################
+ def get_classify_property( self, layer ):
+ """Get property (attribute field) to use for classification."""
+
+ return layer.get_property( 'Classification_Property' )
+
+ ###########################################################################
+ def set_class(self, color, range_min, range_max=None,
+ name=None, desc=None, class_id=None,
+ symbol=None, symbol_scale=None ):
+ """Set class info
+
+ Create a new class, or reset the information for an existing class.
+ Note that set_class() calls do not cause
+
+ color -- the color value to use as an RGBA tuple with values between
+ 0.0 and 1.0.
+
+ range_min -- the minimum value in the pixel value range to be
+ considered part of this class.
+
+ range_max -- the maximum value in the pixel value range to be
+ considered part of this class. If None, the
+ range_min is used.
+
+ name -- the class name. If none is provided the class name will
+ be made up from the range.
+
+ desc -- the class description. If None is provided, an empty
+ string will be used.
+
+ class_id -- the class number to assign, if defaulted a new class will
+ be created after the largest existing class number. Zero
+ based.
+
+ symbol -- the symbol to assign to this class (for point layers)
+
+ symbol_scale -- the scale to draw the symbol at
+
+ Returns the class number assigned."""
+
+
+ if class_id is None:
+ class_id = self.count
+
+ if class_id+1 > self.count:
+ self.count = class_id+1
+ self.name.append('')
+ self.desc.append('')
+ self.color.append('')
+ self.range.append('')
+ self.point_symbols.append('')
+ self.symbol_scales.append('')
+
+ if desc is None:
+ desc = ''
+
+ if range_max is None:
+ range_max = range_min
+
+ try:
+ range_min = string.strip( range_min )
+ range_max = string.strip( range_max )
+ except:
+ pass
+
+ if name is None:
+ #name = 'class_%d' % class_id
+ name = string.strip(str(range_min))
+ if range_max != range_min and range_max != '':
+ name = name + ' - ' + string.strip(str(range_max))
+
+ if len(color) == 3:
+ (r,g,b) = color
+ color = (r,g,b,1.0)
+
+ if symbol_scale is None:
+ symbol_scale = 2.0
+
+ self.name[class_id] = name
+ self.desc[class_id] = desc
+ self.color[class_id] = color
+ self.range[class_id] = (range_min, range_max)
+ self.point_symbols[class_id] = symbol
+ self.symbol_scales[class_id] = symbol_scale
+
+ return class_id
+
+ ###########################################################################
+ def remove_class(self, class_id):
+ """Removes a class
+
+ class_id -- the index of the class to remove."""
+
+ if class_id >= 0 and class_id < self.count:
+ del self.name[class_id]
+ del self.desc[class_id]
+ del self.color[class_id]
+ del self.range[class_id]
+ del self.point_symbols[class_id]
+ del self.symbol_scales[class_id]
+ self.count = self.count - 1
+
+ ###########################################################################
+ def remove_all_classes(self):
+ """Removes all classification data"""
+
+ self.count = 0
+ self.name = []
+ self.desc = []
+ self.range = []
+ self.color = []
+ self.point_symbols = []
+ self.symbol_scales = []
+
+ ###########################################################################
+ def update_all_layers(self, rescale=1):
+ """Updates all GvLayers managed by this classification"""
+ self.order_classes()
+ cd = self.serialize()
+ for layer in self.layers:
+ self.update_layer(layer, cd, rescale )
+
+ ###########################################################################
+ def update_layer(self, layer, cd, rescale=1 ):
+ ###################################################################
+ # Update properties on the GvLayer with the new classification
+ # information.
+
+ self.update_layer_properties( layer, cd )
+
+ ###################################################################
+ # Do layer specific actions.
+
+ if issubclass(layer.__class__,gview.GvShapesLayer):
+ self.update_vector( layer )
+ elif issubclass(layer.__class__,gview.GvRasterLayer):
+ self.update_raster( layer, rescale )
+ else:
+ raise ValueError, 'Unsupported layer class in GvClassification'
+
+ ###########################################################################
+ def update_raster(self, raster, rescale=1):
+ """Updates GvRasterLayer color table.
+
+ Updates the color table on the GvRasterLayer based on the current
+ classification scheme. If rescale is non-zero the GvRaster's
+ scaling min and max may also be reset to better handle the given
+ data range.
+
+ Note that the GvRasterLayer will rescale data to the range 0-255, and
+ the color table is applied after this rescaling. The range values
+ in the GvClassification are in raw data pixel values, but the final
+ color table is not. If the total data ranges of the classes exceeds
+ 256 then there may be discretization in the generated color table.
+
+ The update_raster() call also causes the classification scheme to
+ be updated on the GvRasterLayer's property list.
+
+ raster -- the GvRasterLayer to update
+
+ rescale -- Set to 0 to disable possible changes to GvRaster scaling
+ min/max.
+ """
+
+ ###################################################################
+ # Compute scaling range
+
+ if self.count == 0:
+ overall_min = 0
+ overall_max = 255
+ else:
+ overall_min = self.range[0][0]
+ overall_max = self.range[0][1]
+
+ for class_id in range(self.count):
+ overall_min = min(self.range[class_id][0],overall_min)
+ overall_max = max(self.range[class_id][1],overall_max)
+
+ if overall_min < 0 or overall_max > 255 \
+ or raster.get_parent().get_band().DataType != gdal.GDT_Byte:
+ scale_min = overall_min
+ scale_max = overall_max
+ else:
+ scale_min = 0
+ scale_max = 255
+
+ if rescale == 0:
+ scale_min = raster.min_get(0)
+ scale_max = raster.max_get(0)
+ else:
+ raster.min_set(0,float(scale_min))
+ raster.max_set(0,float(scale_max))
+
+ ###################################################################
+ # Build color table
+
+ pct = ''
+ for iColor in range(256):
+ raw_value = (iColor/255.0) * (scale_max-scale_min) + scale_min
+
+ rep = self.compute_rep( raw_value )
+ color = rep[1]
+
+ pct = pct + (chr(int(255*color[0])) + chr(int(255*color[1]))
+ + chr(int(255*color[2])) + chr(int(255*color[3])))
+
+ raster.lut_put( pct )
+
+ ###########################################################################
+ def update_vector(self, vector, class_prop = None ):
+ """
+ Updates GvShapesLayer representation information.
+
+ vector -- the GvShapesLayer to operate on.
+ class_prop -- the property based on which to classify. If not
+ provided it will be fetched off the layer metadata.
+ """
+ if class_prop is None:
+ class_prop = self.get_classify_property( vector )
+
+
+ ###################################################################
+ # Set representations for all shapes.
+
+ shapes = vector.get_parent()
+ for shape in shapes:
+
+ try:
+ raw_value = shape.get_property( class_prop )
+ except:
+ continue
+
+ try:
+ raw_value = float(raw_value)
+ except:
+ pass
+
+ rep = self.compute_rep( raw_value )
+
+ color = rep[1]
+ ogrfs_color = '#%02x%02x%02x%02x' % (int(color[0] * 255.999),
+ int(color[1] * 255.999),
+ int(color[2] * 255.999),
+ int(color[3] * 255.999))
+
+ stype = shape.get_type()
+ if stype == gview.GVSHAPE_POINT:
+ ogrfs = 'SYMBOL(id:%s,c:%s,s:%s)' % (rep[0], ogrfs_color,
+ rep[2])
+ elif stype == gview.GVSHAPE_LINE:
+ ogrfs = 'PEN(c:%s)' % ogrfs_color
+ elif stype == gview.GVSHAPE_AREA:
+ ogrfs = 'BRUSH(fc:%s);PEN(c:#010101ff)' % ogrfs_color
+ shape.set_property( '_gv_ogrfs', ogrfs )
+
+ shapes.changed()
+
+ ###########################################################################
+ def compute_rep( self, raw_value ):
+
+ """
+ Compute representation corresponding to a input value.
+
+ raw_value -- the value to run through the classification.
+
+ Returns a list of property information with the following values:
+
+ [0] - symbol name
+ [1] - symbol color
+ [2] - symbol scale
+
+ """
+ rep = []
+ symbol = 'ogr-sym-0'
+ color = (0.0, 0.0, 0.0, 1.0)
+ scale = 2.0
+
+ # Try to produce a string corresponding to the raw value.
+ # Ensure that integer values are represented without any decimals
+ raw_string = string.strip(str(raw_value))
+ try:
+ num_value = float(raw_string)
+ if num_value == int(num_value):
+ raw_string = str(int(float(raw_string)))
+ except:
+ pass
+
+ if self.get_type() == CLASSIFY_DISCRETE:
+ for i in range(self.count):
+ if raw_string == string.strip(str(self.range[i][0])):
+ symbol = self.point_symbols[i]
+ color = self.color[i]
+ scale = self.symbol_scales[i]
+ break
+ else:
+ if raw_value < self.range[0][0]:
+ symbol = self.point_symbols[0]
+ color = self.color[0]
+ scale = self.symbol_scales[0]
+ elif raw_value > self.range[self.count - 1][1]:
+ symbol = self.point_symbols[self.count - 1]
+ color = self.color[self.count - 1]
+ scale = self.symbol_scales[self.count - 1]
+ else:
+ for i in range(self.count):
+ #if a value lies directly in the range, then use the value directly
+ if raw_value >= self.range[i][0] \
+ and raw_value <= self.range[i][1] \
+ or raw_value == self.range[i][0]:
+ symbol = self.point_symbols[i]
+ color = self.color[i]
+ scale = self.symbol_scales[i]
+ break
+
+ #this scales colors and scales for values that are between classes,
+ #but assigns the symbol name from the closest class (favouring the
+ #lower class
+ if i < self.count-1 \
+ and raw_value > self.range[i][1] \
+ and raw_value < self.range[i+1][0]:
+ try:
+ ratio = (raw_value-self.range[i][1]) \
+ / (self.range[i+1][0] - self.range[i][1])
+ except:
+ ratio = 0.5
+ c1 = self.color[i]
+ c2 = self.color[i+1]
+ s1 = self.symbol_scales[i]
+ s2 = self.symbol_scales[i+1]
+ if ratio > 0.5:
+ symbol = self.point_symbols[i+1]
+ else:
+ symbol = self.point_symbols[i]
+
+ color = (c1[0] * (1.0 - ratio) + c2[0] * ratio,
+ c1[1] * (1.0 - ratio) + c2[1] * ratio,
+ c1[2] * (1.0 - ratio) + c2[2] * ratio,
+ c1[3] * (1.0 - ratio) + c2[3] * ratio)
+
+ scale = s1 * (1.0 - ratio) + s2 * ratio
+
+ break
+
+ rep.append( symbol )
+ rep.append( color )
+ rep.append( scale )
+
+ return rep
+
+ ###########################################################################
+ # Update properties on the GvShapesLayer with the new classification
+ # information.
+ def update_layer_properties( self, layer, cd ):
+
+ od = layer.get_properties()
+ nd = {}
+
+ for key in od.keys():
+ if key[:6] != 'Class_':
+ nd[key] = od[key]
+
+ for key in cd.keys():
+ nd[key] = cd[key]
+
+ # manage a serial number for the class metadata version so the
+ # legend can more easily determine if it needs to react.
+ if od.has_key('Class_sn'):
+ nd['Class_sn'] = str(int(od['Class_sn'])+1)
+ else:
+ nd['Class_sn'] = '1'
+
+ layer.set_properties( nd )
+ layer.changed()
+
+ ###########################################################################
+ def swap_classes(self, class_id_1, class_id_2):
+ temp = self.name[class_id_1]
+ self.name[class_id_1] = self.name[class_id_2]
+ self.name[class_id_2] = temp
+
+ temp = self.desc[class_id_1]
+ self.desc[class_id_1] = self.desc[class_id_2]
+ self.desc[class_id_2] = temp
+
+ temp = self.color[class_id_1]
+ self.color[class_id_1] = self.color[class_id_2]
+ self.color[class_id_2] = temp
+
+ temp = self.range[class_id_1]
+ self.range[class_id_1] = self.range[class_id_2]
+ self.range[class_id_2] = temp
+
+ ###########################################################################
+ def order_classes(self):
+ """Reorder classes in order.
+
+ Reorder classes in ascending over of range_min. Modify range_max
+ values if necessary to avoid overlapping classes."""
+
+ for i in range(self.count):
+ for j in range(self.count-i-1):
+ if self.range[j][0] > self.range[j+1][0]:
+ self.swap_classes(j,j+1)
+
+ for i in range(self.count-1):
+ if self.range[i][1] > self.range[i+1][0]:
+ self.range[i] = (self.range[i][0], self.range[i+1][0])
+
+
+ ###########################################################################
+ def serialize(self):
+ cdict = {}
+ for class_id in range(self.count):
+
+ key = 'Class_%d_Name' % class_id
+ cdict[key] = self.name[class_id]
+
+ key = 'Class_%d_Desc' % class_id
+ cdict[key] = self.desc[class_id]
+
+ key = 'Class_%d_Color' % class_id
+ (r, g, b, a) = self.color[class_id]
+ r = int(max(0,min(255,r*255.0)))
+ g = int(max(0,min(255,g*255.0)))
+ b = int(max(0,min(255,b*255.0)))
+ a = int(max(0,min(255,a*255.0)))
+ cdict[key] = '#%02x%02x%02x%02x' % (r, g, b, a)
+
+ key = 'Class_%d_Range' % class_id
+ cdict[key] = '%r:%r' % self.range[class_id]
+
+ if self.point_symbols[class_id] is not None:
+ key = 'Class_%d_Symbol' % class_id
+ cdict[key] = self.point_symbols[class_id]
+
+ key = 'Class_%d_Scale' % class_id
+ cdict[key] = str(self.symbol_scales[class_id])
+
+ cdict['Classification_Title'] = self.title
+ cdict['Classification_Type'] = str(self.get_type())
+
+ return cdict
+
+ ###########################################################################
+ def deserialize(self, dict):
+
+ self.remove_all_classes()
+
+ self.title = dict.get('Classification_Title', '')
+ type = int(dict.get('Classification_Type', '1'))
+ self.set_type( type )
+
+ class_id = 0
+ while dict.has_key('Class_%d_Color' % class_id):
+
+ key = 'Class_%d_Name' % class_id
+ name = dict.get(key, '')
+
+ key = 'Class_%d_Desc' % class_id
+ desc = dict.get(key, '')
+
+ key = 'Class_%d_Color' % class_id
+ color_spec = dict.get(key, '#000000FF')
+
+ try:
+ color = ( string.atoi(color_spec[1:3],16) / 255.0,
+ string.atoi(color_spec[3:5],16) / 255.0,
+ string.atoi(color_spec[5:7],16) / 255.0,
+ string.atoi(color_spec[7:9],16) / 255.0 )
+ except:
+ color = ( 0.0, 0.0, 0.0, 1.0 )
+
+ key = 'Class_%d_Range' % class_id
+ range_spec = dict.get(key, '0 0')
+ try:
+ (range_min, range_max) = range_spec.split(':')
+ range_min = string.strip(range_min)
+ range_max = string.strip(range_max)
+ except:
+ range_min = range_spec
+ range_min = string.strip(range_min)
+ range_max = None
+ #allow ranges to be discrete string values
+ try:
+ range_min = float(range_min)
+ range_max = float(range_max)
+ except:
+ pass
+
+ key = 'Class_%d_Symbol' % class_id
+ try:
+ symbol = dict[key]
+ except:
+ symbol = None
+
+ key = 'Class_%d_Scale' % class_id
+ try:
+ scale = float(dict[key])
+ except:
+ scale = None
+
+ self.set_class( color, range_min, range_max, name, desc,
+ class_id, symbol, scale )
+
+ class_id = class_id + 1
+
+
+ ###########################################################################
+ def set_title(self, title):
+ """Set new title (for Legend)
+
+ title -- the new title for this classification"""
+
+ self.title = title
+
+ ###########################################################################
+ def get_title(self):
+ return self.title
+
+ ###########################################################################
+ def get_name(self, idx):
+ """return the name at the given index or None if the index is invalid"""
+ return self.get_value(self.name, idx)
+
+ ###########################################################################
+ def set_name(self, idx, name):
+ """set the name for the given index"""
+ self.set_value(self.name, idx, name)
+
+ ###########################################################################
+ def get_color(self, idx):
+ """return the color at the given index or None if the index is invalid"""
+ return self.get_value(self.color, idx)
+
+ ###########################################################################
+ def set_color(self, idx, color):
+ """set the color at the given index"""
+ if len(color) == 3:
+ (r,g,b) = color
+ color = (r,g,b,1.0)
+
+ self.set_value(self.color, idx, color)
+
+ ###########################################################################
+ def get_desc(self, idx):
+ """return the description at the given index or None if the index is invalid"""
+ return self.get_value(self.desc, idx)
+
+ ###########################################################################
+ def get_range(self, idx):
+ """return the range at the given index or None if the index is invalid"""
+ return self.get_value(self.range, idx)
+
+ ###########################################################################
+ def set_range(self, idx, range_min, range_max):
+ self.set_value(self.range, idx, (range_min, range_max))
+
+ ###########################################################################
+ def get_value(self, lst, idx):
+ """return the item at the given idx from the given list or None if
+ something is wrong"""
+ result = None
+ try:
+ result = lst[idx]
+ except:
+ pass
+ return result
+
+ ###########################################################################
+ def set_value(self, lst, idx, val):
+ """set the item at the given idx in the given list"""
+ try:
+ lst[idx] = val
+ except:
+ pass
+
+ ###########################################################################
+ def get_symbol(self, idx):
+ """return the range at the given index or None if the index is invalid
+ """
+ return self.get_value(self.point_symbols, idx)
+
+ ###########################################################################
+ def set_symbol(self, idx, symbol):
+ if symbol[0] == '"':
+ symbol = symbol[1:]
+ if symbol[-1] == '"':
+ symbol = symbol[:-1]
+ self.set_value(self.point_symbols, idx, symbol)
+
+ ###########################################################################
+ def get_scale(self, idx):
+ """return the range at the given index or None if the index is invalid
+ """
+ return self.get_value(self.symbol_scales, idx)
+
+ ###########################################################################
+ def set_scale(self, idx, scale):
+ self.set_value(self.symbol_scales, idx, scale)
+
+ ###########################################################################
+ def set_type(self, type):
+ """Set the classification type - affects prepare_default only
+ """
+ if type >= CLASSIFY_BASE and type <= CLASSIFY_LAST:
+ self.type = type
+ else:
+ print 'invalid classification type: ', type
+
+ ###########################################################################
+ def get_type(self):
+ """return the classification type
+ """
+ return self.type
+
+ ###########################################################################
+ def collect_range(self, layer, property = None ):
+ if issubclass(layer.__class__,gview.GvShapesLayer):
+ shapes = layer.get_parent()
+ min_v = None
+ max_v = None
+
+ for shape in shapes:
+ try:
+ value = float(shape.get_property( property ))
+ if min_v is None:
+ min_v = value
+ max_v = value
+ else:
+ if value < min_v:
+ min_v = value
+ if value > max_v:
+ max_v = value
+ except:
+ pass
+
+ return (min_v,max_v)
+
+ elif issubclass(layer.__class__,gview.GvRasterLayer):
+ #is there a better way to do this, or is it even necessary?
+ if layer.get_mode() == gview.RLM_RGBA:
+ return (min(layer.min_get(0),
+ layer.min_get(1),
+ layer.min_get(2)),
+ max(layer.max_get(0),
+ layer.max_get(1),
+ layer.max_get(2)))
+ else:
+ return (layer.min_get(0), layer.max_get(0))
+
+ else:
+ raise ValueError, 'unsupported layer type in collect_range'
+
+ ###########################################################################
+ def collect_unique(self, layer, property = None ):
+ """
+ Collect list of unique values occuring in a GvLayer.
+
+ The returned list is a dictionary with the keys being the unique
+ values found, and the values associated with the keys being the
+ occurance count for each value.
+
+ layer -- the GvLayer (GvRasterLayer or GvShapesLayer) to be queried
+ property -- for GvShapesLayer this is the property name to be scanned.
+ """
+
+ if issubclass(layer.__class__,gview.GvShapesLayer):
+ shapes = layer.get_parent()
+
+ val_count = {}
+ for shape in shapes:
+ try:
+ #value = float(shape.get_property( property ))
+ value = shape.get_property( property )
+ if value is not None:
+ if val_count.has_key( value ):
+ val_count[value] = val_count[value] + 1
+ else:
+ val_count[value] = 1
+ except:
+ pass
+
+ return val_count
+
+ elif issubclass(layer.__class__,gview.GvRasterLayer):
+
+ raster = layer.get_data()
+ datatype = raster.get_band().DataType
+
+ count = 65536
+ h_min = raster.get_min()
+ h_max = raster.get_max()
+ delta = h_max - h_min
+ if delta < 0.1:
+ delta = 0.1
+ h_min = h_min - delta*0.25
+ h_max = h_max + delta*0.25
+
+ is_int = 0
+
+ if datatype == gdal.GDT_Byte:
+ h_min = 0
+ h_max = 256
+ count = 256
+ is_int = 1
+ elif datatype == gdal.GDT_Int16:
+ h_min = -32768
+ h_max = 32767
+ count = 65536
+ is_int = 1
+ elif datatype == gdal.GDT_UInt16:
+ h_min = 0
+ h_max = 65536
+ count = 65536
+ is_int = 1
+
+ histogram = \
+ raster.get_band().GetHistogram( h_min, h_max,
+ buckets = count,
+ include_out_of_range = 0,
+ approx_ok = 0 )
+ delta = (h_max - h_min)/count
+ val_count = {}
+ for i in range(count):
+ if histogram[i] > 0:
+ if is_int:
+ value = h_min + i
+ else:
+ value = h_min + delta * i
+
+ val_count[value] = histogram[i]
+
+ return val_count
+
+ else:
+ raise ValueError, 'unsupported layer type in collect_unique'
+
+ ###########################################################################
+ def collect_values(self, layer, property = None ):
+ """
+ Collect the data values from a property field occuring in a GvLayer.
+
+ The returned list contains all values of the property field for shapes
+ that have a non-missing value for that field.
+
+ layer -- the GvLayer (GvRasterLayer or GvShapesLayer) to be queried
+ property -- for GvShapesLayer this is the property name to be scanned.
+ """
+ # Obtain the data values for a shapefile vector layer
+ if issubclass(layer.__class__,gview.GvShapesLayer):
+ shapes = layer.get_parent()
+
+ shpvals = []
+ for shape in shapes:
+ try:
+ value = float(shape.get_property( property ))
+ if value is not None:
+ shpvals.append(value)
+ except:
+ pass
+
+ return shpvals
+
+ # Obtain the data values for a raster layer
+ elif issubclass(layer.__class__,gview.GvRasterLayer):
+
+ raster = layer.get_data()
+ datatype = raster.get_band().DataType
+
+ count = 65536
+ h_min = raster.get_min()
+ h_max = raster.get_max()
+ delta = h_max - h_min
+ if delta < 0.1:
+ delta = 0.1
+ h_min = h_min - delta*0.25
+ h_max = h_max + delta*0.25
+
+ is_int = 0
+
+ if datatype == gdal.GDT_Byte:
+ h_min = 0
+ h_max = 256
+ count = 256
+ is_int = 1
+ elif datatype == gdal.GDT_Int16:
+ h_min = -32768
+ h_max = 32767
+ count = 65536
+ is_int = 1
+ elif datatype == gdal.GDT_UInt16:
+ h_min = 0
+ h_max = 65536
+ count = 65536
+ is_int = 1
+
+ histogram = \
+ raster.get_band().GetHistogram( h_min, h_max,
+ buckets = count,
+ include_out_of_range = 0,
+ approx_ok = 0 )
+ delta = (h_max - h_min)/count
+ rastvals = []
+ for i in range(count):
+ if histogram[i] > 0:
+ if is_int:
+ for j in range(histogram[i]):
+ rastvals.append((h_min + i))
+ else:
+ for j in range(histogram[i]):
+ rastvals.append((h_min + delta * i))
+ return rastvals
+
+ else:
+ raise ValueError, 'unsupported layer type in collect_unique'
+
+
+ ###########################################################################
+ def quantile(self,values,cats):
+ """
+ Determine the minimum and maximum values of the break points in a
+ quantile (equal proportions) classification.
+
+ The returned list contains two sublists:
+ [0] a list of the minimum values for each category
+ [1] a list of the maximum values for each category.
+
+ layer -- the GvLayer (GvRasterLayer or GvShapesLayer) to be queried
+ property -- for GvShapesLayer this is the property name to be scanned.
+ """
+
+ segl = len(values)/cats # Min number of obs in a category
+ lftout = len(values) - (segl*cats) # The "residual" obs needed to be assigned
+ catobs = cats*[segl] # initialize the number of observations per category var
+ # If there are unassigned obs, assign the needed number of "middle" categories
+ # one observation each until the number of assigned obs is equal to actual obs
+ if lftout > 0:
+ midcat = len(catobs)/2 # the "middle" category
+ catobs[midcat] = segl + 1 # up this category by one observation
+ # The following loop assigns the remaining obs around the middle category
+ for i in range(1,cats):
+ if Numeric.sum(catobs) < len(values):
+ catobs[midcat-i] = segl + 1
+ else:
+ break
+ if Numeric.sum(catobs) < len(values):
+ catobs[midcat+i] = segl + 1
+ else:
+ break
+ # Use the catobs variable as an index to figure out the location of the break
+ # points for the categories
+ valsort=Numeric.sort(Numeric.array(values)) # Sort the original data
+ maxind = [0]*cats # the maximum value of each break point
+ maxind = list(Numeric.cumsum(catobs) - 1)
+ # Based on the index, get the maximum value for each category
+ maxval = range(cats) # intialize the maxval variable
+ # The following for-loop assigns the top values using maxind
+ for i in range(cats):
+ maxval[i]=valsort[maxind[i]]
+ minval = range(cats) # initialize the bottom break points
+ minval[0] = min(values)
+ # The following for-loop assigns the other minimum value break points
+ for i in range(1,cats):
+ minval[i] = maxval[i-1]
+
+ outquant = [minval,maxval]
+ return outquant
+ ###########################################################################
+ def nstddev(self,values):
+ """
+ Determine the minimum and maximum values of the break points in a
+ classifier based on standard deviations from the mean. This implicitly
+ assumes a symmetric distribution
+
+ The returned list contains two sublists:
+ [0] a list of the minimum values for each category
+ [1] a list of the maximum values for each category
+ [2] the total number of categories as an integer.
+ [3] the labels to use in the legend
+
+ layer -- the GvLayer (GvRasterLayer or GvShapesLayer) to be queried
+ property -- for GvShapesLayer this is the property name to be scanned.
+ """
+
+ mnval = Numeric.sum(values)/len(values) # The mean
+ sdval = Numeric.sqrt(Numeric.sum(pow((Numeric.array(values)-mnval),2))/(len(values)-1))
+ # The SD
+ possds = int((max(values)-mnval)/sdval) # SDs above the mean
+ if (max(values)-mnval)/sdval > possds:
+ possds = possds + 1
+ negsds = int((mnval-min(values))/sdval) # SDs below the mean
+ if (mnval-min(values))/sdval > negsds:
+ negsds = negsds + 1
+
+ # Handling the maximum category values below the mean
+ maxblw = range(negsds)
+ blwlbl = range(negsds)
+ for i in range(negsds):
+ maxblw[((negsds-1)-i)] = mnval - (i*sdval)
+ blwlbl[((negsds-1)-i)] = "%i to %i standard deviations" % (-1*i, -1*(i+1))
+ # maxblw[(negsds-1)] = mnval - 0.0001
+
+ # Handling the maximum category values above the mean
+ maxabv = range(possds)
+ abvlbl = range(possds)
+ # maxabv[(possds-1)] = max(values)
+ # for i in range((possds-1)):
+ for i in range(possds):
+ maxabv[i] = mnval + ((i+1)*sdval)
+ abvlbl[i] = "%i to %i standard deviations" % (i, i+1)
+ # maxabv[0] = mnval + 0.0001
+
+ maxval = maxblw + [mnval] + maxabv # concatinate the below and above max values
+ meanlb = "Mean: %f" % mnval
+ labels = blwlbl + [meanlb] + abvlbl
+ minval = range((possds+negsds+1)) # initialize the category min values
+ minval[0] = min(values) - 0.0001
+ # The following for-loop assigns the other minimum value break points
+ for i in range(1,(possds+negsds+1)):
+ minval[i] = maxval[i-1]
+
+ # outnsd = [minval,maxval,2*numsds]
+ outnsd = [minval,maxval,(possds+negsds+1),labels]
+ return outnsd
+ ###########################################################################
+ def prepare_default(self, count=5):
+ """Prepare a default classification scheme.
+
+ count -- the number of classes to create by default (the actual number
+ may differ if creating a discrete classification)
+
+ If the layer is a GvShapesLayer and the classify property is not
+ numeric then the type will be changed to a discrete classication with
+ a maximum of 32 discrete values
+ """
+
+ if len(self.layers) == 0:
+ return
+
+ overall_min = None
+ overall_max = None
+ bUnique = 0
+ unique_vals = []
+ symbol = None
+ name = None
+
+ for layer in self.layers:
+ property = self.get_classify_property( layer )
+
+ if property is not None and \
+ issubclass( layer.__class__, gview.GvShapesLayer):
+ #determine the type of the
+ props = layer.get_parent().get_properties()
+ k = props.keys()[ props.values().index( property ) ]
+ try:
+ property_type = props[ "_field_type_%s" % k[12:] ]
+ except:
+ property_type = None
+ if layer.get_parent()[0].get_type() == gview.GVSHAPE_POINT:
+ symbol = 'ogr-sym-0'
+ if property_type == "string":
+ self.set_type( CLASSIFY_DISCRETE )
+ else:
+ property_type = None
+
+ if self.get_type() == CLASSIFY_DISCRETE:
+ vals = self.collect_unique( layer, property )
+ keys = vals.keys()
+ keys.sort()
+ unique_vals.extend( keys )
+ count = min( len(unique_vals), 80 )
+ if len(unique_vals) > 80:
+ gvutils.warning( '%d discrete values identified, but only the first 80 are being used' % len(unique_vals) )
+ else:
+ this_min, this_max = self.collect_range( layer, property )
+ if overall_min is None:
+ overall_min = this_min
+ overall_max = this_max
+ elif this_min is not None:
+ if this_min < overall_min:
+ overall_min = this_min
+ if this_max > overall_max:
+ overall_max = this_max
+
+ if count == 0:
+ print 'no values to classify on'
+ return
+
+ if overall_min is None and not self.get_type() == CLASSIFY_DISCRETE:
+ print 'overall_min still None in prepare_default()!'
+ return
+ elif self.get_type() == CLASSIFY_DISCRETE:
+ overall_min = 0
+ overall_max = count
+
+ epsilon = (overall_max-overall_min) * 0.002
+ overall_min = overall_min - epsilon
+ overall_max = overall_max + epsilon
+
+ # Below are calls to the classifiers that require the entire property field
+
+ if self.get_type() == CLASSIFY_QUANTILE:
+ svalues = self.collect_values( layer, property )
+ qminmax = self.quantile(svalues,count)
+
+ elif self.get_type() == CLASSIFY_NORM_SD:
+ svalues = self.collect_values( layer, property )
+ nsdminmax = self.nstddev(svalues)
+ count = nsdminmax[2]
+
+ input_incr = (overall_max - overall_min) / count
+ color_incr = float(1.0 / (count + 1))
+
+ for n in range(count):
+ if self.get_type() == CLASSIFY_EQUAL_INTERVAL:
+ range_min = round(overall_min + (input_incr * n), 4)
+ range_max = round(overall_min + (input_incr * (n + 1)), 4)
+ name = None
+ elif self.get_type() == CLASSIFY_QUANTILE:
+ range_min = round(qminmax[0][n], 4)
+ range_max = round(qminmax[1][n], 4)
+ name = None
+ elif self.get_type() == CLASSIFY_NORM_SD:
+ range_min = round(nsdminmax[0][n], 4)
+ range_max = round(nsdminmax[1][n], 4)
+ name = nsdminmax[3][n]
+ elif self.get_type() == CLASSIFY_DISCRETE:
+ try:
+ range_min = string.strip(unique_vals[n])
+ range_max = ''
+ except:
+ range_min = unique_vals[n]
+ range_max = unique_vals[n]
+ name = str(unique_vals[n])
+ c = float(color_incr * (n + 1))
+ self.set_class((c,c,c,1.0), range_min, range_max, name=name, symbol = symbol)
+
+ if property is not None:
+ self.set_title( 'Legend: ' + property )
+ else:
+ self.set_title('Legend')
+
+if __name__ == '__main__':
+
+ cs = GvClassification()
+
+ print cs.count
+
+ cs.set_class( (1.0, 0.0, 0.0, 1.0), 0 )
+ cs.set_class( (0.0, 1.0, 0.0, 1.0), 2 )
+ cs.set_class( (0.0, 0.0, 1.0, 1.0), 1, 3 )
+
+ cs.order_classes()
+
+ print cs.count
+
+ d = cs.serialize()
+
+ cs2 = GvClassification()
+ cs2.deserialize( d )
+
+ d = cs2.serialize()
+
+ for key in d.keys():
+ print key + " = " + d[key]
+
+
+ print '-------'
+
+ cs.remove_class(1)
+ print cs.count
+ cs.remove_class(1)
+ print cs.count
+ d = cs.serialize()
+ for key in d.keys():
+ print key + ' = ' + d[key]
+
+
+ #cs2.update_raster()
Added: packages/openev/branches/upstream/current/pymod/gvclassifydlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvclassifydlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvclassifydlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,962 @@
+###############################################################################
+# $Id: gvclassifydlg.py,v 1.31 2004/08/27 17:11:06 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: Raster classification dialogs
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvclassifydlg.py,v $
+# Revision 1.31 2004/08/27 17:11:06 pgs
+# updated logic for building the reclassify dialogs list of entries so it would be ordered correctly
+#
+# Revision 1.30 2004/08/27 16:46:41 pgs
+# change repr to str to avoid extra decimal places in values
+#
+# Revision 1.29 2004/07/23 16:57:23 pgs
+# restructure notifications when OK/Apply clicked
+#
+# Revision 1.28 2004/07/02 16:40:41 dem
+# - Implement project files portability
+# - last_strech restored in projects reloading
+# - add a "File/Save Project as..." menu
+#
+# Revision 1.27 2003/12/28 15:46:19 warmerda
+# fixed up support for negatives
+#
+# Revision 1.26 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.25 2002/11/05 14:17:04 warmerda
+# fixed set_class call in add_class_cb
+#
+# Revision 1.24 2002/10/30 17:35:14 pgs
+# added overwrite protection message when saving classifications.
+#
+# Revision 1.23 2002/09/04 14:40:29 pgs
+# space out range names
+#
+# Revision 1.22 2002/08/27 19:13:34 pgs
+# extended default classification limits to 80 classes.
+#
+# Revision 1.21 2002/08/19 17:13:49 pgs
+# bug fixes related to discrete classifications
+#
+# Revision 1.20 2002/08/13 17:43:32 pgs
+# fixed raster classification and fixed legend for point layers
+#
+# Revision 1.19 2002/08/09 21:05:20 pgs
+# finished vector support
+#
+# Revision 1.18 2002/08/01 20:12:44 warmerda
+# added vector layers, and the property selector - partly working
+#
+# Revision 1.17 2002/08/01 14:51:19 pgs
+# fixed default button, added support for file dialog filters and fixed bug in
+# adding new class
+#
+# Revision 1.16 2001/09/21 20:23:06 pgs
+# modified for new colorbutton.
+#
+# Revision 1.15 2001/07/01 03:01:52 pgs
+# fixed issue with ramp menu
+#
+# Revision 1.14 2001/06/11 23:17:19 pgs
+# modified to use pguEntry
+#
+# Revision 1.13 2001/05/25 16:26:27 pgs
+# close reclass dialog if required when closing classification dlg
+#
+# Revision 1.12 2001/05/24 14:02:58 pgs
+# removed ramps from reclass dialog
+#
+# Revision 1.11 2001/05/07 14:01:51 warmerda
+# allow rescaling
+#
+# Revision 1.10 2001/03/30 01:37:30 pgs
+# added ramp config file option
+#
+# Revision 1.9 2001/03/23 00:12:12 pgs
+# added exception handling to ramp code
+#
+# Revision 1.8 2001/03/21 05:26:06 warmerda
+# fix reset_cb() to avoid exception
+#
+# Revision 1.7 2001/02/14 02:11:25 pgs
+# modified for multiple raster layer support
+#
+# Revision 1.6 2000/10/17 18:59:36 pgs
+# modified load/save to use .leg extensions.
+#
+# Revision 1.5 2000/10/09 14:04:13 pgs
+# added support for loading and saving classification schemes.
+#
+# Revision 1.4 2000/10/03 00:28:42 pgs
+# fixed bug in delete_class callback.
+#
+# Revision 1.3 2000/10/02 20:56:58 pgs
+# enabled removal of classes, moved some stuff around in the UI.
+#
+# Revision 1.2 2000/09/28 22:43:19 pgs
+# modified to work with the new ColorRamp
+#
+# Revision 1.1 2000/09/27 14:34:41 warmerda
+# New
+#
+#
+
+import gview
+import gvutils
+import gtk
+import GDK
+from gvsignaler import Signaler
+from pgucolor import ColorSwatch, ColorButton, ColorDialog, ColorRamp
+from gvclassification import *
+from pguentry import pguEntry
+import gvogrfsgui
+from pgumenu import *
+import gdal #for CPLDebug
+
+from string import *
+
+"""gvclassifydlg.py module contains two classes related to raster classification.
+
+GvClassificationDlg is the main gui for modifying raster classifications.
+GvReclassifyDlg is a supplementary dialog for changing the number of classes in
+a classification scheme.
+
+This module also contains a number of supplementary utilties for working with ramps.
+
+
+TODO:
+
+ x find out how to modify the background color of a widget and use it in the column
+ headers
+
+ x determine when range values are valid/invalid. When invalid, set bg color of cell
+ to red or something.
+
+ x provide more buttons for doin' stuff.
+"""
+
+MIN_COLOR=0
+LOW_COLOR = 21845
+HI_COLOR = 65535
+MAX_COLOR = 65535
+
+def set_widget_background(widget, rgba_color):
+ style = widget.get_style().copy()
+ for i in range(1):
+ style.base[i] = gdk_from_rgba(widget, rgba_color)
+ style.bg[i] = style.base[i]
+ widget.set_style(style)
+
+def gdkcolor(widget, red=0, green=0, blue=0):
+ return widget.get_colormap().alloc(int(red), int(green), int(blue))
+ #return gtk.GdkColor(red, green, blue, 1)
+
+def gdk_from_rgba(widget, rgba_color):
+ r = rgba_color[0] * MAX_COLOR
+ g = rgba_color[1] * MAX_COLOR
+ b = rgba_color[2] * MAX_COLOR
+ return gdkcolor(widget, r, g, b)
+
+def rgba_from_gdk(gdk_color):
+ r = float(gdk_color.red) / MAX_COLOR
+ g = float(gdk_color.green) / MAX_COLOR
+ b = float(gdk_color.blue) / MAX_COLOR
+ return (r, g, b, 1.0)
+
+def rgba_tuple(red=0.0, green=0.0, blue=0.0, alpha=1.0):
+ return (red, green, blue, alpha)
+
+def load_ramps():
+ """reads in all the ramp files in the ramps directory and creates ramps for them"""
+ import os
+ import os.path
+ ramps = []
+ ramp_dir = gview.get_preference('ramp_directory')
+ if ramp_dir is None:
+ ramp_dir = os.path.join(gview.home_dir,'ramps')
+ if os.path.isdir(ramp_dir):
+ files = os.listdir(ramp_dir)
+ for file in files:
+ ramp_file = os.path.join(ramp_dir, file)
+ if os.path.isfile(ramp_file):
+ ramp = ColorRamp()
+ try:
+ ramp.deserialize(ramp_file)
+ ramps.append(ramp)
+ except:
+ print 'invalid ramp file %s' % ramp_file
+ else:
+ print 'no default ramp files in ', ramp_dir
+ return ramps
+
+def load_ramp_config_file():
+ """
+ Reads in ramp files specified in the ramp config file
+ in the ramps directory and creates ramps for them
+
+ This allows for ordering of the ramps in the config
+ file and for specifying separators
+ """
+ import os
+ import os.path
+ import string
+ ramps = []
+ ramp_dir = gview.get_preference('ramp_directory')
+ if ramp_dir is None:
+ ramp_dir = os.path.join(gview.home_dir,'ramps')
+ if os.path.isdir(ramp_dir):
+ config_path = os.path.join(ramp_dir, 'ramps.cfg')
+ if os.path.isfile(config_path):
+ #load config file and parse ramps ...
+ config = open(config_path)
+ lines = config.readlines()
+ for line in lines:
+ ramp_file = string.strip(line)
+ if ramp_file == '<separator>':
+ ramps.append(gtk.GtkHSeparator())
+ else:
+ ramp_file = os.path.join(ramp_dir, ramp_file)
+ if os.path.isfile(ramp_file):
+ ramp = ColorRamp()
+ try:
+ ramp.deserialize(ramp_file)
+ ramps.append(ramp)
+ ramp.show()
+ except:
+ print 'invalid ramp file %s' % ramp_file
+ else:
+ print 'not a file (%s)' % ramp_file
+ else:
+ print 'no ramps.cfg file, loading ramps directly'
+ return load_ramps()
+ else:
+ print 'no default ramp files in ', ramp_dir
+ return ramps
+
+class GvClassificationDlg(gtk.GtkWindow, Signaler):
+ """A dialog for modifying the classification scheme of a GvLayer."""
+
+ def __init__(self, classification):
+ """Initialize a GvClassificationDlg on a particular GvLayer"""
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Layer Classification')
+ self.set_usize(-1, 400)
+ self.connect('delete-event', self.close)
+ self.set_border_width(5)
+ self.color_buttons = []
+ self.sym_menus = []
+ self.scale_spinners = []
+ self.view_mgr = None
+ self.ranges = []
+ self.labels = []
+ self.reclassdlg = None
+ self.updating = FALSE
+ items = load_ramp_config_file()
+ self.ramp = None
+ if classification is None:
+ self.classification = GvClassification()
+ elif issubclass(classification.__class__, GvClassification):
+ self.classification = classification
+ else:
+ raise TypeError, 'GvClassificationDlg now requires a \
+ GvClassification instance'
+ if self.classification.count <= 0:
+ self.ramp = items[0]
+ self.classification.prepare_default()
+ #d = self.classification.serialize()
+ #main vertical box
+ vbox = gtk.GtkVBox(spacing=3)
+
+ save_box = gtk.GtkHButtonBox()
+ btn_save = gtk.GtkButton('Save ...')
+ btn_save.connect('clicked', self.save_cb)
+ btn_load = gtk.GtkButton('Load ...')
+ btn_load.connect('clicked', self.load_cb)
+ save_box.pack_start(btn_load)
+ save_box.pack_start(btn_save)
+
+ try:
+ import pgucombo
+ self.property_list = pgucombo.pguCombo()
+ except:
+ self.property_list = gtk.GtkCombo()
+
+ self.property_list.entry.connect('changed',self.property_select_cb)
+ self.update_property_list()
+
+ save_box.pack_start(self.property_list)
+ vbox.pack_start(save_box, expand=gtk.FALSE)
+
+ #classification frame
+ class_frame = gtk.GtkFrame()
+ frame_box = gtk.GtkVBox(spacing=3)
+
+ title_box = gtk.GtkHBox()
+ title_lbl = gtk.GtkLabel('Legend Title: ')
+ self.title_txt = gtk.GtkEntry()
+ self.title_txt.set_text(self.classification.get_title())
+ self.title_txt.connect('changed', self.title_changed_cb)
+
+ title_box.pack_start(title_lbl, expand=gtk.FALSE)
+ title_box.pack_start(self.title_txt)
+
+ frame_box.pack_start(title_box, expand=gtk.FALSE)
+ frame_box.set_border_width(5)
+
+ #classification list
+ class_box = gtk.GtkScrolledWindow()
+ self.class_list = gtk.GtkList()
+ self.class_list.connect( 'select-child', self.list_selected )
+ class_box.add_with_viewport(self.class_list)
+ frame_box.pack_start(class_box)
+ self.reset_classification_list()
+
+ class_frame.add(frame_box)
+ vbox.pack_start(class_frame)
+
+ ar_box = gtk.GtkHButtonBox()
+ add_btn = gtk.GtkButton('Add class')
+ add_btn.connect('clicked', self.add_class_cb)
+ classify_btn = gtk.GtkButton('reclassify ...')
+ classify_btn.connect('clicked', self.reclassify_cb)
+ reset_btn = gtk.GtkButton('Revert')
+ reset_btn.connect('clicked', self.reset_cb)
+ ar_box.pack_start(add_btn)
+ ar_box.pack_start(classify_btn)
+ ar_box.pack_start(reset_btn)
+ vbox.pack_start(ar_box, expand=gtk.FALSE)
+
+ #Color Ramp choices
+ ramp_table=gtk.GtkTable(rows=2, cols=2)
+ ramp_table.show()
+ ramp_lbl = gtk.GtkLabel('Color Ramps: ')
+ ramp_lbl.show()
+ ramp_table.attach(ramp_lbl, 0, 1, 0, 1)
+ ramp_opt = gtk.GtkOptionMenu()
+ ramp_opt.show()
+ self.ramp_menu = gtk.GtkMenu()
+ self.ramp_menu.show()
+ ramp_item=gtk.GtkMenuItem()
+ ramp_item.add(gtk.GtkHSeparator())
+ ramp_item.set_sensitive(gtk.FALSE)
+ ramp_item.show_all
+ self.ramp_menu.append(ramp_item)
+ for n in items:
+ ramp_item = gtk.GtkMenuItem()
+ ramp_item.add(n)
+ ramp_item.show_all()
+ if issubclass(n.__class__, ColorRamp):
+ ramp_item.connect('activate', self.ramp_cb, n)
+ else:
+ ramp_item.set_sensitive(gtk.FALSE)
+ self.ramp_menu.append(ramp_item)
+ ramp_opt.set_menu(self.ramp_menu)
+ ramp_opt.show()
+ ramp_opt.set_history(0)
+ ramp_table.attach(ramp_opt, 1, 2, 0, 1)
+ ramp_table.show_all()
+ vbox.pack_start(ramp_table, expand=gtk.FALSE)
+ #buttons
+ button_box = gtk.GtkHButtonBox()
+ #button_box.set_layout_default(gtk.BUTTONBOX_START)
+ self.ok_button = gtk.GtkButton('OK')
+ self.ok_button.connect('clicked', self.ok_cb)
+ self.apply_button = gtk.GtkButton('Apply')
+ self.apply_button.connect('clicked', self.apply_cb)
+ self.cancel_button = gtk.GtkButton('Cancel')
+ self.cancel_button.connect('clicked', self.cancel_cb)
+ button_box.pack_start(self.ok_button, expand=gtk.FALSE)
+ button_box.pack_start(self.apply_button, expand=gtk.FALSE)
+ button_box.pack_start(self.cancel_button, expand=gtk.FALSE)
+ vbox.pack_start(button_box, expand=gtk.FALSE)
+ vbox.show_all()
+ self.add(vbox)
+
+ #make ok_button a default button ? why isn't it working ?
+ self.ok_button.set_flags(gtk.CAN_DEFAULT)
+ self.ok_button.grab_default()
+ self.publish('classification-changed')
+
+ self.update_property_list()
+
+ def close(self, *args):
+ """close and destroy this dialog"""
+ self.hide()
+ self.destroy()
+ if self.reclassdlg is not None:
+ self.reclassdlg.destroy()
+ return gtk.TRUE
+
+ def ok_cb(self, *args):
+ """Close the dialog and notify listeners and the raster that the
+ classification has changed"""
+ #allowing the raster to be rescale screws things up!
+ self.classification.update_all_layers(rescale=1)
+ self.notify('classification-changed')
+ return self.close()
+
+ def apply_cb(self, *args):
+ """apply the current classification"""
+ self.notify('classification-changed')
+ self.classification.update_all_layers(rescale=1)
+
+ def cancel_cb(self, *args):
+ """close the classification dialog without doing anything
+ about the classification"""
+ return self.close()
+
+ def list_selected( self, *args ):
+ self.class_list.unselect_all()
+
+ def add_class_cb(self, *args):
+ """add a single class to the classification. Add it at the end
+ with the same value and color as the upper range value of the
+ last class. If there are no classes, use the entire range.
+ """
+ #first create the new class
+ cls = self.classification
+ if len(self.color_buttons) > 0:
+ color = self.color_buttons[len(self.color_buttons)-1].get_d()
+ print color
+ rng = cls.get_range(cls.count-1)
+ rng = (rng[1], rng[1])
+ symbol = cls.get_symbol( cls.count - 1 )
+ scale = cls.get_scale( cls.count - 1 )
+ else:
+ color = ( 0.0, 0.0, 0.0, 1.0 )
+ rng = cls.collect_range()
+ #for point layers only
+ if cls.layers[0].get_parent()[0].get_type() == gview.GVSHAPE_POINT:
+ symbol = '"ogr-sym-0"'
+ else:
+ symbol = None
+ scale = 1.0
+ n = cls.set_class(color = color,
+ range_min = rng[0],
+ range_max = rng[1],
+ symbol = symbol,
+ symbol_scale = scale)
+ self.insert_class( n )
+
+ def insert_class( self, class_id ):
+ """Create gui elements for the class_id and insert them
+ into the gui
+ """
+ cls = self.classification
+ self.color_buttons.insert(class_id, ColorButton(cls.get_color(class_id)))
+ self.color_buttons[class_id].connect('color-set',
+ self.color_button_cb, class_id)
+ symbol = cls.get_symbol( class_id )
+ if symbol is not None:
+ sym_menu = pguMenuFactory(MENU_FACTORY_OPTION_MENU)
+ entries = []
+ for i in range(len(gvogrfsgui.ogrfs_symbol_names)):
+ sym_name = gvogrfsgui.ogrfs_symbol_names[i]
+ sym_img = gvogrfsgui.ogrfs_symbols[sym_name][1]
+ a = '<image:' + sym_img + '>'
+ entries.append((a, None, self.symbol_change, class_id,
+ gvogrfsgui.ogrfs_symbols[sym_name][0]))
+ sym_menu.add_entries(entries)
+ sym_menu.set_usize(70, 30)
+ sym_menu.set_history(int(symbol[8:]))
+ self.sym_menus.insert( class_id, sym_menu )
+
+ scale = cls.get_scale( class_id )
+ adj = gtk.GtkAdjustment( value=scale, lower=0.0, upper=100.0,
+ step_incr=0.11, page_incr=1.0, page_size=1.0 )
+ scale_spin = gtk.GtkSpinButton(adj)
+ scale_spin.set_editable( TRUE )
+ adj.connect( 'value-changed', self.scale_change, class_id )
+ self.scale_spinners.insert( class_id, scale_spin )
+ else:
+ self.sym_menus.insert( class_id, None )
+ self.scale_spinners.insert( class_id, None )
+
+ self.ranges.insert(class_id, pguEntry())
+ rng = cls.get_range(class_id)
+ rng_txt = str( rng[0] )
+ if rng[1] != '' and cls.get_type() != CLASSIFY_DISCRETE:
+ rng_txt = rng_txt + "-" + str( rng[1] )
+ self.ranges[class_id].set_text(rng_txt)
+ self.ranges[class_id].connect('changed', self.range_changed_cb, class_id)
+ self.labels.insert(class_id, pguEntry())
+ self.labels[class_id].set_text(cls.get_name(class_id))
+ self.labels[class_id].connect('changed', self.label_changed_cb, class_id)
+ self.add_classification_item(self.color_buttons[class_id],
+ self.sym_menus[class_id],
+ self.scale_spinners[class_id],
+ self.ranges[class_id],
+ self.labels[class_id])
+ self.class_list.show_all()
+
+ def add_classification_item(self, clr, sym, scl, rng, lbl,
+ delete_button=gtk.TRUE):
+ """add a single row to the classification list. Optionally add a delete
+ button that will delete that row from the classification.
+ """
+ class_item = gtk.GtkListItem()
+ class_box = gtk.GtkHBox()
+ #explicitly size the first 5, let the last one fill the rest of the
+ #space.
+ clr.set_usize(70, -1)
+ if sym is not None:
+ sym.set_usize(70, -1)
+ if scl is not None:
+ scl.set_usize(70, -1)
+ rng.set_usize(130, -1)
+ lbl.set_usize(130, -1)
+ class_box.pack_start(clr, expand=gtk.FALSE, fill=gtk.FALSE)
+ if sym is not None:
+ class_box.pack_start(sym, expand=gtk.FALSE, fill=gtk.FALSE)
+ if scl is not None:
+ class_box.pack_start(scl, expand=gtk.FALSE, fill=gtk.FALSE)
+ class_box.pack_start(rng, expand=gtk.FALSE, fill=gtk.FALSE)
+ class_box.pack_start(lbl, expand=gtk.FALSE, fill=gtk.FALSE)
+ if delete_button:
+ del_btn = gtk.GtkButton('x')
+ del_btn.set_usize( 45, -1 )
+ del_btn.connect('clicked', self.delete_item, class_item)
+ class_box.pack_start(del_btn, expand=gtk.FALSE, fill=gtk.FALSE)
+ class_box.add( gtk.GtkLabel( '' ) )
+ class_item.add(class_box)
+ class_item.show()
+ self.class_list.add(class_item)
+
+ def reset_classification_list(self, *args):
+ """Set the contents of class_list to the classification
+ scheme in the classification object."""
+
+ #clear existing UI side items.
+ self.class_list.clear_items(0, -1)
+ del self.color_buttons, self.ranges, self.labels
+ self.color_buttons = []
+ self.ranges = []
+ self.labels = []
+
+ cls = self.classification
+ #prepare a default classification if one doesn't exist
+ if cls.count == 0:
+ cls.prepare_default(5)
+
+ symbol = cls.get_symbol( 0 )
+ #setup the column headers
+ class_item = gtk.GtkListItem()
+ set_widget_background(class_item, (1.0, 0.0, 0.0))
+ class_box = gtk.GtkHBox()
+ clr_frm = gtk.GtkFrame()
+ clr_frm.add(gtk.GtkLabel('Color'))
+ clr_frm.set_shadow_type(gtk.SHADOW_OUT)
+ if symbol is not None:
+ sym_frm = gtk.GtkFrame()
+ sym_frm.add( gtk.GtkLabel( 'Symbol' ))
+ sym_frm.set_shadow_type( gtk.SHADOW_OUT )
+
+ scale_frm = gtk.GtkFrame()
+ scale_frm.add( gtk.GtkLabel( 'Scale' ))
+ scale_frm.set_shadow_type( gtk.SHADOW_OUT )
+ else:
+ sym_frm = None
+ scale_frm = None
+ rng_frm = gtk.GtkFrame()
+ rng_frm.add(gtk.GtkLabel('Range'))
+ rng_frm.set_shadow_type(gtk.SHADOW_OUT)
+ lbl_frm = gtk.GtkFrame()
+ lbl_frm.add(gtk.GtkLabel('Label'))
+ lbl_frm.set_shadow_type(gtk.SHADOW_OUT)
+ self.add_classification_item(clr_frm, sym_frm, scale_frm, rng_frm,
+ lbl_frm, gtk.FALSE)
+
+ #for each class, create an entry in the list
+ for n in range(cls.count):
+ self.insert_class( n )
+
+ self.class_list.show_all()
+
+ if self.ramp is not None:
+ self.apply_ramp(self.ramp)
+
+ def reclassify_cb(self, *args):
+ """show the reclassify dlg"""
+ dlg = GvReclassifyDlg(ok_cb = self.reset_dlg_cb,
+ classify_type = self.classification.get_type())
+ self.reclassdlg = dlg
+ dlg.show()
+
+ def reset_dlg_cb(self, dlg, *args):
+ """reset the classification to the default"""
+ self.classification.set_type( dlg.classify_type )
+ self.classification.remove_all_classes()
+ self.classification.prepare_default(dlg.classes)
+ self.reset_classification_list()
+ self.reclassdlg = None
+
+ def reset_cb(self,*args):
+ """reset the classification to the default"""
+ self.classification.remove_all_classes()
+ self.classification.prepare_default(5)
+ self.reset_classification_list()
+
+ def delete_item(self, btn, item):
+ """Remove a class from the classification"""
+ n = self.class_list.child_position(item) - 1
+ self.classification.remove_class(n)
+ self.class_list.remove_items([item])
+ del self.color_buttons[n]
+ del self.ranges[n]
+ del self.labels[n]
+
+ def color_button_cb(self, widget, color, num, *args):
+ """Handle the user changing a color value"""
+ self.classification.set_color(num, widget.get_color())
+
+ def symbol_change( self, widget, index, symbol ):
+ self.classification.set_symbol( index, symbol )
+
+ def scale_change( self, widget, index ):
+ self.classification.set_scale( index, widget.value )
+
+ def range_changed_cb(self, widget, num):
+ """Handle the user changing a range value. This requires validation"""
+ print 'range_changed_cb'
+ #if self.updating: return
+ self.updating = TRUE
+ range_txt = strip(widget.get_text()) #remove whitespace
+ vals = split(range_txt, '-')
+ if range_txt == '':
+ #nothing entered
+ return
+ # lots of hackery here recognise various cases with negatives.
+ # Negatives come out of the split as an empty token.
+ if len(vals) == 4 and vals[0] == '' and vals[2] == '':
+ try:
+ low = -float(vals[1])
+ hi = -float(vals[3])
+ except:
+ low = '-' + vals[1]
+ hi = '-' + vals[3]
+ elif len(vals) == 3 and vals[0] == '':
+ try:
+ low = -float(vals[1])
+ hi = float(vals[2])
+ except:
+ low = '-' + vals[1]
+ hi = vals[2]
+
+ elif len(vals) == 3 and vals[1] == '':
+ try:
+ low = float(vals[0])
+ hi = -float(vals[2])
+ except:
+ low = vals[0]
+ hi = '-' + vals[2]
+
+ elif len(vals) == 2:
+ #two vals
+ try:
+ low = float(vals[0])
+ hi = float(vals[1])
+ except:
+ low = vals[0]
+ hi = vals[1]
+
+ elif len(vals) == 1:
+ #one val
+ try:
+ low = float(vals[0])
+ hi = float(vals[0])
+ except:
+ low = vals[0]
+ hi = vals[0]
+ else:
+ #too many values
+ return
+
+ try:
+ if int(low) == low:
+ low_txt = "%.0f" % low
+ else:
+ low_txt = "%s" % low
+ except:
+ low_txt = low
+
+ try:
+ if int(hi) == hi:
+ hi_txt = "%.0f" % hi
+ else:
+ hi_txt = "%s" % hi
+ except:
+ hi_txt = hi
+
+ r_low, r_hi = self.classification.get_range( num )
+ old_name = self.classification.get_name( num )
+
+ try:
+ if int(r_low) == r_low:
+ r_low_txt = "%.0f" % r_low
+ else:
+ r_low_txt = "%s" % r_low
+ except:
+ r_low_txt = r_low
+
+ try:
+ if int(r_hi) == r_hi:
+ r_hi_txt = "%.0f" % r_hi
+ else:
+ r_hi_txt = "%s" % r_hi
+ except:
+ r_hi_txt = r_hi
+
+ if r_hi_txt == "":
+ calc_name = r_low_txt
+ else:
+ calc_name = "%s - %s" % (r_low_txt, r_hi_txt)
+
+ print 'old rng is ', r_low, r_hi
+ print 'new rng is ', low, hi
+ print 'name is ', old_name
+ print 'calc is ', calc_name
+ if calc_name == old_name:
+ if hi_txt == "":
+ calc_name = low_txt
+ else:
+ calc_name = "%s - %s" % ( low_txt, hi_txt )
+ else:
+ calc_name = old_name
+ print 'new is ', calc_name
+ self.classification.set_range(num, low, hi)
+ self.labels[num].set_text( calc_name )
+ self.updating = FALSE
+
+ def label_changed_cb(self, widget, num):
+ """Handle the user changing the label."""
+ self.classification.set_name(num, widget.get_text())
+
+ def title_changed_cb(self, widget):
+ """Handle the user changing the title"""
+ self.classification.set_title(widget.get_text())
+
+ def ramp_cb(self, widget, ramp, *args):
+ if ramp is not None:
+ self.ramp = ramp
+ self.apply_ramp(ramp)
+ else:
+ #TODO: custom ramp creator here.
+ pass
+
+ def apply_ramp_cb(self, n, color):
+ self.classification.set_color(n, color)
+ self.color_buttons[n].set_color(color)
+
+ def apply_ramp(self, ramp, *args):
+ ramp.apply_ramp(self.apply_ramp_cb, self.classification.count)
+
+ def save_cb(self, *args):
+ import filedlg
+ dlg = filedlg.FileDialog(dialog_type=filedlg.FILE_SAVE, filter='Legend Files|*.leg')
+ dlg.ok_button.connect('clicked', self.save, dlg)
+ dlg.cancel_button.connect('clicked', dlg.hide)
+ dlg.show()
+
+ def save(self, widget, dlg, *args):
+ import pickle
+ import os
+ filename = dlg.get_filename()
+ path, ext = os.path.splitext(filename)
+ if not (ext == ".leg"):
+ gvutils.warning("filename extension changed to .leg")
+ ext = ".leg"
+ filename = path + ext
+ dlg.hide()
+ if os.path.exists( filename ):
+ warning_pix = os.path.join(gview.home_dir, 'pics', 'warning.xpm' )
+ win = gvutils._MessageBox( "Do you wish to overwrite the existing file?",
+ ( 'Yes', 'No', ), warning_pix, modal=TRUE)
+ win.set_title( 'File Exists' )
+ win.show()
+ gtk.mainloop()
+ if win.ret == 'No':
+ print 'not saving'
+ return
+ print 'saving'
+ file = open(filename, "w")
+ d = self.classification.serialize()
+ try:
+ pickle.dump(d, file)
+ except PicklingError:
+ gvutils.error('An error occurred saving the classification:\n' + filename)
+
+ def load_cb(self, *args):
+ import filedlg
+ dlg = filedlg.FileDialog(dialog_type=filedlg.FILE_OPEN, filter='Legend Files|*.leg')
+ dlg.ok_button.connect('clicked', self.load, dlg)
+ dlg.cancel_button.connect('clicked', dlg.hide)
+ dlg.show()
+
+ def load(self, widget, dlg, *args):
+ import pickle
+ filename = dlg.get_filename()
+ dlg.hide()
+ try:
+ file = open(filename, "r")
+ d = pickle.load(file)
+ self.classification.deserialize(d)
+ self.ramp = None
+ self.reset_classification_list()
+ self.title_txt.set_text(self.classification.get_title())
+ except:
+ gvutils.error('Error opening classification file:\n' + filename)
+
+ def property_select_cb(self, *args):
+ if len(self.classification.layers) == 0:
+ return
+
+ if self.property_updating:
+ return
+
+ layer = self.classification.layers[0]
+
+ if not issubclass(layer.__class__,gview.GvShapesLayer):
+ self.property_list.hide()
+ return
+
+ new_property = self.property_list.get_text()
+
+ self.classification.set_classify_property( layer, new_property )
+
+ self.classification.remove_all_classes()
+ self.classification.prepare_default(5)
+ self.reset_classification_list()
+ self.title_txt.set_text( self.classification.get_title() )
+ def update_property_list( self, *args ):
+ if len(self.classification.layers) == 0:
+ return
+
+ layer = self.classification.layers[0]
+
+ if not issubclass(layer.__class__,gview.GvShapesLayer):
+ self.property_list.hide()
+ return
+
+ self.property_list.show()
+
+ property = self.classification.get_classify_property( layer )
+ schema = layer.get_parent().get_schema()
+ fields = []
+ for field_def in schema:
+ fields.append( field_def[0] )
+
+ self.property_updating = 1
+ self.property_list.set_popdown_strings( tuple(fields) )
+ if property is not None:
+ self.property_list.select_string( property )
+ self.property_updating = 0
+
+class GvReclassifyDlg(gtk.GtkWindow):
+ """This dialog displays a re-classification dialog that allows
+ the user to specify the number of classes, and the type of classification
+ """
+ def __init__(self, ok_cb=None, cancel_cb=None, cb_data=None,
+ classify_type=CLASSIFY_EQUAL_INTERVAL):
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Classification')
+ self.user_ok_cb = ok_cb
+ self.user_cancel_cb = cancel_cb
+ self.user_cb_data = cb_data
+ self.classify_type = classify_type
+ self.set_border_width(6)
+ #main vertical box
+ vbox = gtk.GtkVBox(spacing=6)
+ type_box = gtk.GtkHBox(spacing=6)
+ type_box.pack_start(gtk.GtkLabel('Type:'), expand=gtk.FALSE)
+ opt_menu = gtk.GtkOptionMenu()
+ type_menu = gtk.GtkMenu()
+
+ #using classification_types dictionary from gvclassification
+ for i in range(len(classification_types)):
+ for type in classification_types.iteritems():
+ if type[1] == i:
+ item = gtk.GtkMenuItem( type[0] )
+ item.connect( 'activate', self.type_menu_cb, classification_types[type[0]] )
+ type_menu.append( item )
+
+ opt_menu.set_menu(type_menu)
+ opt_menu.set_history( classify_type )
+ opt_menu.resize_children()
+ type_box.pack_start(opt_menu)
+ vbox.pack_start(type_box, expand=gtk.FALSE)
+ #Number of classes
+ classes_box = gtk.GtkHBox(spacing=6)
+ classes_box.pack_start(gtk.GtkLabel('Number of classes:'))
+ adj = gtk.GtkAdjustment(5, 2, 80, 1, 5, 5, 0)
+ self.spinner = gtk.GtkSpinButton(adj)
+ self.spinner.set_snap_to_ticks(gtk.TRUE)
+ self.spinner.set_digits(0)
+ classes_box.pack_start(self.spinner)
+ vbox.pack_start(classes_box, expand=gtk.FALSE)
+ #add the ok and cancel buttons
+ button_box = gtk.GtkHButtonBox()
+ ok_button = gtk.GtkButton("OK")
+ ok_button.connect('clicked', self.ok_cb, cb_data)
+ cancel_button = gtk.GtkButton("Cancel")
+ cancel_button.connect('clicked', self.cancel_cb, cb_data)
+ button_box.pack_start(ok_button)
+ button_box.pack_start(cancel_button)
+ vbox.pack_start(button_box, expand=gtk.FALSE)
+ vbox.show_all()
+ self.add(vbox)
+ ok_button.set_flags(gtk.CAN_DEFAULT)
+ ok_button.grab_default()
+
+ def type_menu_cb(self, menu_item, classify_type):
+ self.classify_type = classify_type
+
+ def ok_cb(self, *args):
+ self.classes = self.spinner.get_value_as_int()
+ if self.user_ok_cb is not None:
+ self.user_ok_cb(self, self.user_cb_data)
+ self.hide()
+ self.destroy()
+
+ def cancel_cb(self, *args):
+ if self.user_cancel_cb is not None:
+ self.user_cancel_cb(self.user_cb_data, self)
+ self.hide()
+ self.destroy()
+
+if __name__ == '__main__':
+ gview.set_preference('ramp_directory', 'c:\\CIETmap\\ramps')
+ shapes = gview.GvShapes( shapefilename="c:/projects/dmsolutions/ciet/ciet_data/wcsite.shp" )
+ layer = gview.GvShapesLayer( shapes=shapes )
+ cls = GvClassification( layer )
+ dlg = GvClassificationDlg( cls )
+ dlg.apply_button.connect('clicked', cls.dump)
+ dlg.apply_button.connect('clicked', gtk.mainquit)
+
+ dlg.connect('delete-event', gtk.mainquit)
+ dlg.show()
+ gtk.mainloop()
Added: packages/openev/branches/upstream/current/pymod/gvcommand.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvcommand.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvcommand.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,717 @@
+###############################################################################
+# $Id: gvcommand.py,v 1.10 2004/10/15 13:25:26 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Base classes for Command Parsing.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvcommand.py,v $
+# Revision 1.10 2004/10/15 13:25:26 gmwalter
+# Fix bug that causes cietmap problems.
+#
+# Revision 1.9 2004/09/20 22:37:24 gmwalter
+# Fix bug in argument validation.
+#
+# Revision 1.8 2003/07/28 19:42:33 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.7 2002/08/06 16:07:18 warmerda
+# ensure failed validation stops execution
+#
+# Revision 1.6 2002/07/29 21:00:26 warmerda
+# substantially restructured introducing CommandContext
+#
+# Revision 1.5 2002/07/26 17:56:07 warmerda
+# added default value for arguments
+#
+# Revision 1.4 2002/07/24 14:50:15 warmerda
+# temporary hack for token_string
+#
+# Revision 1.3 2002/07/18 19:57:37 warmerda
+# fixed typo
+#
+# Revision 1.2 2002/07/18 19:44:17 warmerda
+# added commanding parsing function
+#
+# Revision 1.1 2002/07/18 17:38:03 warmerda
+# New
+#
+#
+
+import string
+
+###############################################################################
+class CommandBase:
+ """Base class for command objects.
+
+ Commands should have the following data members:
+
+ Name -- command name... the first keyword on any line that is this command.
+ Usage -- optional short usage message (eg. 'DEFINE {column_name} [FLOAT/STRING/INTEGER]')
+ HelpURL -- web url to help for this command. Suitable for use with gvhtml.
+ Args -- List of CommandArgDef objets defining the arguments to this command.
+ Group -- Textual token indicating the command group this command belongs
+ to.
+
+ A command must also implement the execute() method. The execute() method
+ can depend on the arg_tokens argument being a list of argument values,
+ with one entry for each entry in self.Args. Switch arguments will have
+ a logical TRUE/FALSE (nonzero/zero) value. Other arguments will be a
+ string (the token value) or None if the argument did not occur. Execute()
+ isn't called unless all automated validation passed.
+
+ """
+ def __init__(self):
+ pass
+
+ def execute( arg_tokens, line, interpreter ):
+ pass
+
+
+###############################################################################
+class ArgDef:
+
+ """
+Argument Attributes
+-------------------
+
+type:
+ - The type of the argument. Legal values are "string_word", "string_token",
+ "switch", "numeric" and "string_chunk". Details are later in docs.
+
+name:
+ - The name of the argument. Used as the key for argument values in the
+ dictionary of arguments passed into the Evaluate method.
+
+valid_list:
+ - A list of valid values for this argument. The list will be treated as
+ literal text to be case insensitively compared against the value when
+ checking if the argument is present/valid.
+
+required:
+ - 1 or 0 depending on whether the argument is required or not. Arguments
+ that are not required, and are not present will be passed with a None
+ value into the Execute method of the command.
+
+prompt:
+ - Text to be shown to the user when they are prompted for the value of
+ this argument. If not supplied the name of the argument will be shown
+ to the user as the prompt.
+
+prompt_func:
+ - A function to be called when prompt text is needed. The returned string
+ will be the prompt. Useful when the prompt will vary depending on the
+ current environment.
+
+parse_func:
+ - A function that should be called to parse text output of the input command
+ that is intended to be part of the argument. Normally None indicating
+ that default parsing logic should be used.
+
+validate_method:
+ - A function that should be called on the argument value to determine if it
+ is valid or not. The function should return None if valid, or a string
+ indicating the problem if it is not. It also receives the current
+ interpreter as a context, but shouldn't use it for input/output.
+
+read_token_method:
+ - A function that should be called on the input text to get the next token.
+ If not provided a built-in will be used based on the 'type'. The read
+ token method will receive as input an input text string, and a
+ CommandContext object. It should return a (token,remaining_text) tuple.
+
+process_token_method:
+- A function that should be called on the token to convert it to the
+ appropriate argument type (eg. evaluating a variable, converting
+ a string to a number). This gets called in parsing.
+
+default:
+ - The value that should be assigned to this argument if it isn't found on
+ the commandline. If not provided, None is assumed. Not applicable to
+ switch arguments.
+
+
+Argument Types
+--------------
+
+string_word:
+ - Normally a white space terminated chunk of text.
+ - Any mix of non-white space characters.
+ - If quoted it may contain white space, and the quotes will be dropped
+ from the processed value.
+
+string_token:
+ - a well formed token. Alpha-numeric, starting with a letter. May
+ include underscores but no other special characters. Used for variable
+ names, and so forth.
+
+switch:
+ - May appear at any point in the command (perhaps limit to all switches
+ preceeding non-switch arguments, but allow reordering of switches?)
+ - Must start with a '-' or '/'.
+ - Must have a valid_list with the set of possible values. eg ['-n','/n'].
+ - Currently can't take any arguments.
+
+multi_switch:
+ - Like switch, except that instead of returning 1 or zero, the argument
+ returned is the name used for the switch or None (useful for switches
+ which can take on one of a few values, but different behaviours are
+ needed for the different options- eg. /off or /on)
+
+list_type:
+ - Argument is one of a list of possible string values
+ - Must supply a list of valid options (valid_opts)
+
+numeric:
+ - value is numeric.
+ - min/max range values can be tested in validate.
+
+string_chunk:
+ - Similar to string_word, but an arbitrary terminator string can be
+ supplied. The terminator string may be None indicating all the remainder
+ of the command should be consumed.
+
+variable:
+ - A user variable, such as a numpy array.
+ - internally, both the variable's value and its name will be passed to
+ the command (as a list) so that in place modifications can be made
+ if need be.
+
+ """
+
+
+ def __init__(self, name = None, type = 'string_word', prompt = None,
+ prompt_func = None, required = 1, valid_list = None,
+ validate_method = None, default = None,
+ read_token_method = None, process_token_method = None, valid_opts=None ):
+ self.name = name
+ self.type = type
+ self.prompt = prompt
+ self.required = required
+ self.valid_list = valid_list
+ self.valid_opts = valid_opts
+ self.validate_method = validate_method
+ self.default = default
+
+ # Generate valid sequence for switches if not explicitly provided.
+ if self.type == 'switch' and valid_list is None:
+ self.valid_list = [ '-' + name, '/' + name ]
+
+ if self.type == 'list_type' and valid_opts is None:
+ raise AttributeError,'list type requires a list of valid string arguments (valid_opts)'
+
+ # Ensure "valid_list" entries are all forced into lower case for
+ # comparison purposes.
+
+ self.valid_list_lower = None
+ if self.valid_list is not None:
+ self.valid_list_lower = []
+ for item in self.valid_list:
+ self.valid_list_lower.append( string.lower(item) )
+
+ # Validate some requirements
+ if self.type not in [ 'string_word', 'string_token', 'switch','list_type',
+ 'multi_switch','numeric', 'string_chunk', 'variable']:
+ raise ValueError, 'Unsupported argument type: ' + self.type
+
+ # Provide token reader if not specified in args.
+ if read_token_method is not None:
+ self.read_token_method = read_token_method
+
+ elif type == 'string_word':
+ self.read_token_method = self.read_quotable_token
+
+ elif type == 'variable':
+ self.read_token_method = self.read_quotable_token
+
+ elif type == 'string_chunk':
+ self.read_token_method = self.read_remainder_token
+
+ else:
+ self.read_token_method = self.read_simple_token
+
+ # Processing method: in variable case, this evaluates the
+ # variable's value in the pyshell. In the simple case
+ # it does nothing (just returns the input)
+ if process_token_method is not None:
+ self.process_token_method = process_token_method
+
+ elif type == 'variable':
+ self.process_token_method = self.process_variable_token
+
+ elif type == 'numeric':
+ self.process_token_method = self.process_numeric_token
+
+ else:
+ self.process_token_method = self.process_simple_token
+
+
+ ###########################################################################
+ def validate(self, arg_text, command_context):
+ if self.validate_method is not None:
+ return self.validate_method( arg_text, command_context )
+
+ if self.valid_list_lower is not None:
+ lower_arg_text = string.lower(arg_text)
+ if lower_arg_text not in self.valid_list_lower:
+ return '%s: %s is not in the set of valid options.' % \
+ ( self.name, arg_text )
+ else:
+ return None
+
+ if self.type == 'numeric':
+ try:
+ string.atof( arg_text )
+ except ValueError:
+ return '%s: %s is not numeric.' % \
+ ( self.name, arg_text )
+
+ elif self.type == 'string_token':
+ # Must start with a letter
+ first_char='abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ later_char = first_char + '0123456789'
+ if len(arg_text) > 0:
+ if arg_text[0] not in first_char:
+ return '%s: %s is not a valid variable name.' % \
+ (self.name, arg_text)
+ for cchar in arg_text[1:]:
+ if cchar not in later_char:
+ return '%s: %s is not a valid variable name.' % \
+ (self.name, arg_text)
+
+
+ return None
+
+ ###########################################################################
+ def read_simple_token(self, line, cc ):
+ tokens = string.split(line,None,1)
+ if len(tokens) == 1:
+ return (tokens[0], '')
+ elif len(tokens) == 2:
+ return (tokens[0], tokens[1])
+ else:
+ return (None,'')
+
+ ###########################################################################
+ def read_quotable_token(self, line, cc ):
+ # Check for non-keyword quoted string
+ if len(line) < 1:
+ return (None,'')
+
+ if (line[0] == '"'):
+ tokens1 = string.split(line,'"',1)
+ tokens2 = string.split(tokens1[1],'"',1)
+ if len(tokens2) < 2:
+ interpreter.showText( 'Unmatched " in argument line ','error' )
+ return (None,'')
+ return (tokens2[0],tokens2[1])
+ elif (line[0] == "'"):
+ tokens1 = string.split(line,"'",1)
+ tokens2 = string.split(tokens1[1],"'",1)
+ if len(tokens2) < 2:
+ interpreter.showText( "Unmatched ' in argument line ",'error' )
+ return (None,'')
+ return (tokens2[0],tokens2[1])
+
+ # Check for keyword
+ tokens1=string.split(line,None,1)
+
+ if string.find(tokens1[0],'=') == -1:
+ # No keyword found- simple token
+ return self.read_simple_token( line, cc )
+ else:
+ # keyword found- check for quoted token
+ tokens2=string.split(tokens1[0],'=')
+ if tokens2[1][0] == '"':
+ # Keyword found. return quoted token with keyword
+ # to identify the argument in later parsing, but separated
+ # from remainder of line
+ tokens1 = string.split(line,'"',1)
+ tokens2 = string.split(tokens1[1],'"',1)
+ if len(tokens2) < 2:
+ interpreter.showText( 'Unmatched " in argument line ','error' )
+ return (None,'')
+ token = tokens1[0]+tokens2[0]
+ return (token,tokens2[1])
+ elif tokens2[1][0] == "'":
+ # Keyword found. return quoted token with keyword
+ # to identify the argument in later parsing, but separated
+ # from remainder of line
+ tokens1 = string.split(line,"'",1)
+ tokens2 = string.split(tokens1[1],"'",1)
+ if len(tokens2) < 2:
+ interpreter.showText( "Unmatched ' in argument line ",'error' )
+ return (None,'')
+ token = tokens1[0]+tokens2[0]
+ return (token,tokens2[1])
+ else:
+ return self.read_simple_token( line, cc )
+
+###############################################################################
+ def read_remainder_token(self, line, cc ):
+ return (line, '')
+
+###############################################################################
+ def process_variable_token(self, token, cc ):
+ # Convention for variables: argument consists of a
+ # list: (argument value, argument name). argument value
+ # is None if the token is not already present in the shell
+ # environment
+ # CURRENTLY ALL VARIABLE ARGUMENTS VALUES ARE PASSED AS STRINGS
+ # IF THEY ARE NOT SHELL VARIABLES (ie. '0.5' will be passed
+ # as '0.5', not atof('0.5')).
+ if cc.interpreter.locals.has_key(token):
+ return (cc.interpreter.locals[token],token)
+ else:
+ return(None,token)
+
+###############################################################################
+ def process_numeric_token(self, token, cc ):
+ return string.atof( token )
+
+###############################################################################
+ def process_simple_token(self, token, cc):
+ return token
+
+###############################################################################
+# The following is intended to document the methods a command interpreter
+# must implement. It isn't critical that custom command interpreters
+# derive from this class as long as they provide reasonable behaviour.
+#
+class CommandInterpreter:
+
+ def isInteractive():
+ """Is command interactive?
+
+ Returns non-zero if the command should be treated as interactive,
+ meaning that arguments can be prompted for, and usage help can be
+ provided.
+ """
+ pass
+
+ def showText( text, text_class ):
+ """
+ Show text to the user.
+
+ The text may be one or more lines. The class argument indicates
+ the purpose of the text, and may be used to differentiate fonts,
+ or even to direct output in different ways. The available values
+ for class are "result", "error", or "usage".
+
+ text -- the single, or multi line text to display.
+
+ text_class - the indicator of the purpose of the text.
+
+ No value is returned.
+ """
+ pass
+
+ def showPrompt( *args ):
+ """To be determined."""
+ pass
+
+###############################################################################
+# CommandContext
+#
+# Objects of this class capture the state of a command as it is parsed. It
+# allows customized parsing actions to be done taking into account the
+# arguments that come before, and it is responsible for command parsing.
+
+class CommandContext:
+
+ ###########################################################################
+ def __init__(self, line, command_dict = None, interpreter = None ):
+ self.interpreter = interpreter
+ self.command_dict = command_dict
+ self.line = line
+
+ self.text_remaining = line
+
+ # The following are set after a successful parse.
+ self.args = None
+ self.cmd_obj = None
+ self.parsed = 0
+ self.error = 0
+ self.args_parsed = 0
+
+
+ ###########################################################################
+ def parse_command_text(self):
+ tokens = string.split( self.line, None, 1 )
+
+ # Null input line is considered valid.
+ if len(tokens) == 0:
+ return ('', '')
+
+ if len(tokens) == 1:
+ return (string.lower(tokens[0]), '')
+ else:
+ return (string.lower(tokens[0]), tokens[1])
+
+ ###########################################################################
+ def parse_args(self):
+
+ self.parsed = 0
+ self.args_parsed = 0
+ self.args = []
+
+ # Next argument to try to parse (added to allow
+ # out-of-order keywords)
+ self.current_arg = 0
+ self.arg_is_parsed = []
+
+ for i in range(len(self.cmd_obj.Args)):
+ self.args.append( None )
+ self.arg_is_parsed.append(0)
+
+ while self.args_parsed < len(self.cmd_obj.Args):
+ if not self.parse_one_arg():
+ return 0
+
+ self.parsed = 1
+ return 1
+
+ ###########################################################################
+ def parse_one_arg(self):
+
+ #######################################################################
+ # Argument parsing logic:
+ # Maintain an argument "current_arg" to indicate which argument is
+ # currently being searched for. "current_arg" starts at 0 and goes
+ # up to len(self.cmd_obj.Args)-1 (number of args-1). Each time
+ # parse_one_arg is called, check if current_arg has been parsed yet.
+ # If it has, increment current_arg and continue. If not, read the
+ # next token as a quotable token and determine if the next argument
+ # is a switch or multi_switch (which may occur anywhere in the line)
+ # or an argument specified by keyword (which may also appear out-of-
+ # order). If the argument is found to be a switch/multi_switch or
+ # a later argument specified by keyword, reset arg to reflect the
+ # appropriate command argument. Set next_arg_index to current_arg,
+ # since current_arg still hasn't been found and we are parsing a
+ # later argument. Next, reread the token using the proper argument
+ # method (discard the quotable token results) and finish parsing the
+ # argument.
+
+ if self.arg_is_parsed[self.current_arg] == 1:
+ # argument has already been found and parsed by keyword
+ self.current_arg = self.current_arg + 1
+ return 1
+
+ # Index of next argument to search for
+ next_arg_index = self.current_arg + 1
+
+ arg = self.cmd_obj.Args[self.current_arg]
+ interpreter = self.interpreter
+
+ #######################################################################
+ # Before parsing using the current argument's method, check that
+ # the argument isn't a switch/multi-switch (which can occur anywhere)
+ # or designated by a keyword.
+ #
+ test_token, test_remainder = ArgDef.read_quotable_token(arg,self.text_remaining,self)
+
+ #######################################################################
+ # Has the token been assigned a keyword?
+
+ arg_keyword = None
+ if test_token is not None:
+ checknamed = string.split(test_token,'=',1)
+ if len(checknamed) == 2:
+ if arg.name != string.strip(checknamed[0]):
+ checknamed[0] = string.strip(checknamed[0])
+ # keyword doesn't match current argument name:
+ arg = None
+
+ # Next argument to search for should be the
+ # original again, but fill in the one that
+ # does match so its token isn't lost
+ next_arg_index = self.current_arg
+ for idx in range(len(self.cmd_obj.Args)):
+ new_arg=self.cmd_obj.Args[idx]
+ if new_arg.name == checknamed[0]:
+ arg = new_arg
+ self.current_arg = idx
+
+ if arg is None:
+ # If keyword not found, = may be part of current
+ # argument's value. Reset to original argument
+ # and try to parse
+ arg = self.cmd_obj.Args[self.current_arg]
+ next_arg_index = self.current_arg + 1
+ else:
+ arg_keyword=string.strip(checknamed[0])
+
+
+
+ elif (len(checknamed) == 1) and (len(test_token) > 1) and (test_token[0] in ['/','-']):
+ #######################################################################
+ # Check to make sure this isn't a switch or multi_switch argument
+ # rather than the token for the current argument. Check the command
+ # line argument list in order, stopping at the first switch or
+ # multi_switch variable that is compatible with the switch value
+ # and has not been parsed yet.
+
+ for idx in range(len(self.cmd_obj.Args)):
+ new_arg=self.cmd_obj.Args[idx]
+ if ((new_arg.type in ['switch','multi_switch']) and
+ (self.arg_is_parsed[idx] == 0)):
+ if test_token in new_arg.valid_list:
+ next_arg_index = self.current_arg
+ arg = new_arg
+ self.current_arg = idx
+
+
+ #######################################################################
+ # At this point, the correct argument should have been selected.
+ # Parse out a candidate token using the appropriate method for this
+ # argument.
+
+ if arg_keyword is None:
+ token, next_remainder = arg.read_token_method( self.text_remaining,
+ self )
+ else:
+ # Read token, leaving off keyword.
+ token, next_remainder = arg.read_token_method( self.text_remaining[len(arg_keyword)+1:],
+ self )
+
+ #######################################################################
+ # If this is not really a switch, reset the token
+ if ((arg.type == 'switch') and (token is not None) and
+ (token[0] not in ['/','-'])):
+ token = None
+
+ #######################################################################
+ # If we are out of tokens, ensure that the arg is optional.
+ if token is None:
+ if arg.required:
+ interpreter.showText( 'missing argument ' + arg.name,
+ 'error' )
+ return 0
+ elif arg.type == 'switch':
+ self.args[self.current_arg] = 0
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+ return 1
+ elif arg.type == 'multi_switch':
+ self.args[self.current_arg] = arg.default
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+ return 1
+ else:
+ self.args[self.current_arg] = arg.default
+ self.arg_is_parsed[self.current_arg]=1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+ return 1
+
+
+ #######################################################################
+ # Is this a legitimate token for this argment or was it skipped.
+
+
+ val_msg = arg.validate( token, self )
+
+ # Did we actually consume the token?
+ if val_msg is None:
+ self.text_remaining = next_remainder
+
+ else:
+ interpreter.showText( val_msg, 'error' )
+ return 0
+
+ # If argument type was variable, do required processing
+ token = arg.process_token_method(token, self)
+
+ # Report validation errors for required arguments.
+ if arg.type == 'switch':
+ self.args[self.current_arg] = val_msg is None
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+ elif arg.type == 'multi_switch':
+ self.args[self.current_arg] = token
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+
+ elif arg.type == 'list_type':
+ if token not in self.valid_opts:
+ txt=token+' is not a valid option. Valid options are:\n'
+ for copt in self.valid_opts:
+ txt=txt + str(copt) + ' '
+ interpreter.showText(txt,'error')
+ return 0
+ else:
+ self.args[self.current_arg] = token
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+
+ else:
+ self.args[self.current_arg] = token
+ self.arg_is_parsed[self.current_arg] = 1
+ self.current_arg = next_arg_index
+ self.args_parsed = self.args_parsed + 1
+
+ return 1
+
+ ###########################################################################
+ # Parse complete command. Returns 0 on failure, or non-zero on success.
+ def parse(self):
+ if self.interpreter is None:
+ raise ValueError, 'No interpreter set in CommandContext.parse()'
+
+ if self.command_dict is None:
+ raise ValueError, 'No command dictionary set in CommandContext.parse()'
+
+ #######################################################################
+ # Parse out the command and check for it in the command dictionary.
+
+ cmd, self.text_remaining = self.parse_command_text()
+
+ if not self.command_dict.has_key(cmd):
+ self.interpreter.showText( "Command '%s' not recognised." % cmd,
+ 'error' )
+ return 0
+
+ self.cmd_obj = self.command_dict[cmd]
+
+ #######################################################################
+ # Parse the arguments out.
+
+ self.error = 0
+ result = self.parse_args()
+
+ if self.error or result == 0:
+ return 0
+
+ return 1
+
+ ###########################################################################
+ def execute(self):
+ if not self.parsed and not self.parse():
+ return 0
+
+ return self.cmd_obj.execute( self.args, self, self.interpreter )
Added: packages/openev/branches/upstream/current/pymod/gvconst.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvconst.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvconst.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,206 @@
+###############################################################################
+# $Id: gvconst.py,v 1.12 2003/08/06 17:09:14 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Declaration of OpenEV constants
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvconst.py,v $
+# Revision 1.12 2003/08/06 17:09:14 warmerda
+# Added GLRA values
+#
+# Revision 1.11 2002/07/24 14:50:41 warmerda
+# added GVSHAPE_COLLECTION
+#
+# Revision 1.10 2001/08/14 17:03:24 warmerda
+# added standard deviation autoscaling support
+#
+# Revision 1.9 2000/07/31 21:17:23 srawlin
+# added change_info type constants for GvShapes and GvRaster
+#
+# Revision 1.8 2000/07/07 14:56:06 srawlin
+# added default LUT
+#
+# Revision 1.7 2000/06/23 12:58:36 warmerda
+# added GvRasterLayer modes
+#
+# Revision 1.6 2000/06/14 22:11:35 warmerda
+# Added real/imaginary support to color wheel
+#
+# Revision 1.5 2000/06/14 13:17:51 warmerda
+# added RL_LUT_ codes
+#
+# Revision 1.4 2000/06/13 22:19:49 srawlin
+# added 3D python bindings
+#
+# Revision 1.3 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+"""
+Constants for use in the GvRasterLayer functions
+
+Constants for texture_mode_set
+"""
+
+RL_TEXTURE_REPLACE = 0
+RL_TEXTURE_MODULATE = 1
+
+"""
+Constants for zoom_set
+
+Magnification / Minification
+"""
+
+RL_FILTER_BILINEAR = 0
+RL_FILTER_NEAREST = 1
+
+"""
+Minification only -- if we ever use mipmaps this is useful
+"""
+
+RL_FILTER_TRILINEAR = 2
+
+
+"""
+Preset modes for blend_mode_set
+"""
+
+RL_BLEND_OFF = 0
+RL_BLEND_FILTER = 1
+RL_BLEND_MULTIPLY = 2
+RL_BLEND_ADD = 3
+RL_BLEND_CUSTOM = 4
+
+"""
+Constants for custom blend modes
+These can go in both the source and destination modes
+"""
+
+RL_BLEND_FACT_ZERO = 0
+RL_BLEND_FACT_ONE = 1
+RL_BLEND_FACT_DST_COLOR = 2
+RL_BLEND_FACT_MIN_DST_COLOR = 3
+RL_BLEND_FACT_MIN_SRC_COLOR = 4
+RL_BLEND_FACT_SRC_ALPHA = 5
+RL_BLEND_FACT_MIN_SRC_ALPHA = 6
+
+"""
+Constants for alpha_mode_set
+"""
+
+RL_ALPHA_OFF = 0
+RL_ALPHA_NEVER = 1
+RL_ALPHA_ALWAYS = 2
+RL_ALPHA_LESSER = 3
+RL_ALPHA_LEQUAL = 4
+RL_ALPHA_EQUAL = 5
+RL_ALPHA_GEQUAL = 6
+RL_ALPHA_GREATER = 7
+RL_ALPHA_NEQUAL = 8
+
+"""
+Constants to set texture wrapping/clamping
+"""
+
+RL_TEXCOORD_CLAMP = 0
+RL_TEXCOORD_REPEAT = 1
+
+"""
+Constants to describe type of LUT attached to the RasterLayer
+"""
+
+RL_LUT_NONE = 0
+RL_LUT_1D = 1
+RL_LUT_2D = 2
+
+"""
+Constants for GvRasterLayer.lut_color_wheel_new() mode arguments.
+"""
+
+RL_LUT_MAGNITUDE = 0
+RL_LUT_PHASE_ANGLE = 1
+RL_LUT_SCALAR = 2
+RL_LUT_REAL = 3
+RL_LUT_IMAGINARY = 4
+
+"""
+GvRasterLayer modes
+"""
+
+RLM_AUTO = 0
+RLM_SINGLE = 1
+RLM_RGBA = 2
+RLM_COMPLEX = 3
+
+
+"""
+GvShape types.
+"""
+
+GVSHAPE_POINT = 1
+GVSHAPE_LINE = 2
+GVSHAPE_AREA = 3
+GVSHAPE_COLLECTION = 4
+
+
+"""
+GvRaster and GvShapes change_info types, from gvtypes.h
+"""
+GV_CHANGE_ADD = 0x001
+GV_CHANGE_REPLACE = 0x002
+GV_CHANGE_DELETE = 0x003
+
+"""
+GvView 2D = Orthonormal Projection
+ 3D = Perspective
+"""
+MODE_2D = 0
+MODE_3D = 1
+
+
+"""
+Default Rainbow Look Up Table, colour order (red, orange, yellow, green, cyan, blue, purple, red)
+"""
+STD_LUT = '\377\000\000\377\377\006\000\377\377\014\000\377\377\022\000\377\377\030\000\377\377\036\000\377\377$\000\377\377*\000\377\3770\000\377\3776\000\377\377<\000\377\377B\000\377\377H\000\377\377N\000\377\377T\000\377\377Z\000\377\377`\000\377\377f\000\377\377l\000\377\377r\000\377\377x\000\377\377~\000\377\377\204\000\377\377\212\000\377\377\220\000\377\377\226\000\377\377\234\000\377\377\242\000\377\377\250\000\377\377\256\000\377\377\264\000\377\377\272\000\377\377\300\000\377\377\306\000\377\377\314\000\377\377\322\000\377\377\330\000\377\377\336\000\377\377\344\000\377\377\352\000\377\377\360\000\377\377\366\000\377\377\374\000\377\373\377\000\377\365\377\000\377\357\377\000\377\351\377\000\377\343\377\000\377\335\377\000\377\327\377\000\377\321\377\000\377\313\377\000\377\305\377\000\377\277\377\000\377\271\377\000\377\263\377\000\377\255\377\000\377\247\377\000\377\241\377\000\377\233\377\000\377\225\377\000\377\217\377\000\377\211\377\000\377\203\377\000\377}\377\000\377w\377\000\377q\377\000\377k\377\000\377e\377\000\377_\377\000\377Y\377\000\377S\377\000\377M\377\000\377G\377\000\377A\377\000\377;\377\000\3775\377\000\377/\377\000\377)\377\000\377#\377\000\377\035\377\000\377\027\377\000\377\021\377\000\377\013\377\000\377\005\377\000\377\000\377\000\377\000\377\006\377\000\377\014\377\000\377\022\377\000\377\030\377\000\377\036\377\000\377$\377\000\377*\377\000\3770\377\000\3776\377\000\377<\377\000\377B\377\000\377H\377\000\377N\377\000\377T\377\000\377Z\377\000\377`\377\000\377f\377\000\377l\377\000\377r\377\000\377x\377\000\377~\377\000\377\204\377\000\377\212\377\000\377\220\377\000\377\226\377\000\377\234\377\000\377\242\377\000\377\250\377\000\377\256\377\000\377\264\377\000\377\272\377\000\377\300\377\000\377\306\377\000\377\314\377\000\377\322\377\000\377\330\377\000\377\336\377\000\377\344\377\000\377\352\377\000\377\360\377\000\377\366\377\000\377\374\377\000\373\377\377\000\365\377\377\000\357\377\377\000\351\377\377\000\343\377\377\000\335\377\377\000\327\377\377\000\321\377\377\000\313\377\377\000\305\377\377\000\277\377\377\000\271\377\377\000\263\377\377\000\255\377\377\000\247\377\377\000\241\377\377\000\233\377\377\000\225\377\377\000\217\377\377\000\211\377\377\000\203\377\377\000}\377\377\000w\377\377\000q\377\377\000k\377\377\000e\377\377\000_\377\377\000Y\377\377\000S\377\377\000M\377\377\000G\377\377\000A\377\377\000;\377\377\0005\377\377\000/\377\377\000)\377\377\000#\377\377\000\035\377\377\000\027\377\377\000\021\377\377\000\013\377\377\000\005\377\377\000\000\377\377\006\000\377\377\014\000\377\377\022\000\377\377\030\000\377\377\036\000\377\377$\000\377\377*\000\377\3770\000\377\3776\000\377\377<\000\377\377B\000\377\377H\000\377\377N\000\377\377T\000\377\377Z\000\377\377`\000\377\377f\000\377\377l\000\377\377r\000\377\377x\000\377\377~\000\377\377\204\000\377\377\212\000\377\377\220\000\377\377\226\000\377\377\234\000\377\377\242\000\377\377\250\000\377\377\256\000\377\377\264\000\377\377\272\000\377\377\300\000\377\377\306\000\377\377\314\000\377\377\322\000\377\377\330\000\377\377\336\000\377\377\344\000\377\377\352\000\377\377\360\000\377\377\366\000\377\377\374\000\377\377\377\000\373\377\377\000\365\377\377\000\357\377\377\000\351\377\377\000\343\377\377\000\335\377\377\000\327\377\377\000\321\377\377\000\313\377\377\000\305\377\377\000\277\377\377\000\271\377\377\000\263\377\377\000\255\377\377\000\247\377\377\000\241\377\377\000\233\377\377\000\225\377\377\000\217\377\377\000\211\377\377\000\203\377\377\000}\377\377\000w\377\377\000q\377\377\000k\377\377\000e\377\377\000_\377\377\000Y\377\377\000S\377\377\000M\377\377\000G\377\377\000A\377\377\000;\377\377\0005\377\377\000/\377\377\000)\377\377\000#\377\377\000\035\377\377\000\027\377\377\000\021\377\377\000\013\377\377\000\005\377\377\000\000\377'
+
+"""
+GvRaster autoscaling algorithms.
+"""
+
+ASAAutomatic = 0
+ASAPercentTailTrim = 1
+ASAStdDeviation = 2
+
+"""
+OGR Feature Style Anchor points for LABELs.
+"""
+
+GLRA_LOWER_LEFT = 1
+GLRA_LOWER_CENTER = 2
+GLRA_LOWER_RIGHT = 3
+GLRA_CENTER_LEFT = 4
+GLRA_CENTER_CENTER = 5
+GLRA_CENTER_RIGHT = 6
+GLRA_UPPER_LEFT = 7
+GLRA_UPPER_CENTER = 8
+GLRA_UPPER_RIGHT = 9
Added: packages/openev/branches/upstream/current/pymod/gvcorecmds.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvcorecmds.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvcorecmds.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1290 @@
+###############################################################################
+# $Id: gvcorecmds.py,v 1.6 2004/06/03 20:26:07 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Implementation of some sample OpenEV core commands.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvcorecmds.py,v $
+# Revision 1.6 2004/06/03 20:26:07 warmerda
+# added shell command
+#
+# Revision 1.5 2003/09/17 20:45:21 gmwalter
+# Get rid of python 2.3 deprecation warning.
+#
+# Revision 1.4 2003/07/28 19:42:33 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.3 2003/02/20 19:27:20 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.2 2003/02/03 18:38:07 warmerda
+# Added the ClearView command.
+#
+# Revision 1.1 2002/12/12 07:42:49 warmerda
+# New
+#
+#
+
+import gview
+import gvcommand
+
+
+###############################################################################
+# The Commands command.
+class GvCommandsCommand(gvcommand.CommandBase):
+
+ """
+ List all currently loaded commands and display their usage strings.
+
+ Parameters:
+ group- used to limit the commands listed to
+ those from a single group (eg. commands core
+ will display the usage strings of the commands
+ in group "core" only).
+
+ /v- verbose mode. Display full help for commands.
+
+ """
+
+ def __init__(self):
+ self.Name = 'commands'
+ self.Usage = 'commands [group] [-v]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'group', type = 'string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'v', type = 'switch', required=0 )
+ ]
+
+ def execute( self, args, line, interp ):
+ group=args[0]
+ verbose=args[1]
+
+ commands = gview.app.shell.get_commands()
+ interp.showText( '%-24s %s' % ('Command', 'Usage' ), 'result' )
+ interp.showText( '%-24s %s' % ('-------', '-----' ), 'result' )
+ for cmd in commands:
+ if group is None:
+ if verbose == 0:
+ interp.showText( '%-24s %s' % (cmd.Name, cmd.Usage),
+ 'result')
+ else:
+ txt=interp.get_command_help(cmd.Name,quiet=1)
+ if txt is None:
+ interp.showText(cmd.Name+':\nNo help available.\n',
+ 'result')
+ else:
+ interp.showText(cmd.Name+':\n'+txt+'\n','result')
+ else:
+ if (hasattr(cmd,'Group') and (cmd.Group == group)):
+ if verbose == 0:
+ interp.showText( '%-24s %s' % (cmd.Name, cmd.Usage),
+ 'result')
+ else:
+ txt=interp.get_command_help(cmd.Name,quiet=1)
+ if txt is None:
+ interp.showText(cmd.Name+
+ ':\nNo help available.\n','result')
+ else:
+ interp.showText(cmd.Name+':\n'+txt+'\n','result')
+
+ return 1
+
+###############################################################################
+# Functions command.
+
+class GvFunctionsCommand(gvcommand.CommandBase):
+ """
+ The functions command is used to list all currently
+ loaded functions, or to scan a python module for
+ functions (module need not be loaded in python
+ shell, but must be accessible within the python
+ path).
+
+ Parameters:
+
+ module- if a module name is specified, the module
+ will be scanned for functions, and a
+ list of the results will be displayed.
+ If no module name is specified, the
+ functions currently loaded in the
+ python shell will be displayed.
+
+ /v- verbose mode. Display full help for each function.
+
+ """
+
+ def __init__(self):
+ self.Name = 'functions'
+ self.Usage = 'functions [module] [-v]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'module', type = 'string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'v', type = 'switch', required=0 )
+ ]
+
+ def execute( self, args, line, interp ):
+ import string
+ import os
+ import Numeric
+
+ modname=args[0]
+ verbose = args[1]
+
+ local_dict = interp.locals
+ next_txt=''
+ if modname is not None:
+ # User has specified a module name
+ # to search for functions.
+
+ # to do: use the help in the
+ # helpfiles, but only if the module
+ # names match
+
+ if modname in local_dict.keys():
+ modinst=local_dict[modname]
+ modkeys=dir(local_dict[modname])
+ else:
+ try:
+ exec 'import '+modname
+ exec 'modinst='+modname
+ exec 'modkeys=dir('+modname+')'
+ except:
+ interp.showText('Unable to locate module '+modname+'.',
+ 'error')
+ return 0
+
+ # If particular module is specified,
+
+ keys_to_show = []
+ for ckey in modkeys:
+ ckey_type=None
+ exec 'ckey_type=type(modinst.'+ckey+')'
+ if (ckey_type == type(Register) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+ elif (ckey_type == type(Numeric.logical_and) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+ elif (ckey_type == type(hasattr) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+
+ interp.showText( 'Functions: '+modname , 'result' )
+ interp.showText(
+ '------------------------------------------------' , 'result' )
+ keys_to_show.sort()
+ if verbose == 0:
+ count=1
+ for ckey in keys_to_show:
+ # In non verbose mode, show 2 columns
+ if (count % 2) == 0:
+ next_txt=next_txt+'\t'+ckey
+ interp.showText(next_txt,'result')
+ next_txt=''
+ else:
+ next_txt=next_txt+'%-24s' % ckey
+ count=count+1
+ return 1
+
+ # Verbose mode
+ for ckey in keys_to_show:
+ # First, check to see if there is help for
+ # the function.
+
+ txt=interp.get_function_help(ckey,modname,quiet=1)
+ if txt is None:
+ txt=interp.get_builtin_help(ckey,modname,quiet=1)
+
+ interp.showText( '%s:\n\n%s' % (ckey, txt),'result')
+
+ return 1
+
+
+ interp.showText( 'Functions:' , 'result' )
+ interp.showText( '------------------------------------------------' ,
+ 'result' )
+ keys_to_show=[]
+ for ckey in local_dict.keys():
+ if (type(local_dict[ckey]) == type(Register) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+ elif (type(local_dict[ckey]) == type(Numeric.logical_and) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+ elif (type(local_dict[ckey]) == type(hasattr) and
+ ckey[0] != "_"):
+ keys_to_show.append(ckey)
+
+ keys_to_show.sort()
+ count=1
+ for ckey in keys_to_show:
+ if verbose == 1:
+ txt=interp.get_function_help(ckey,quiet=1)
+ if txt is None:
+ txt=interp.get_builtin_help(ckey,quiet=1)
+ if txt is None:
+ txt='No help available.'
+ interp.showText( '%s:\n%s' % (ckey, txt),'result')
+ else:
+ # In non verbose mode, show 2 columns
+ if (count % 2) == 0:
+ next_txt=next_txt+'\t'+ckey
+ interp.showText(next_txt,'result')
+ next_txt=''
+ else:
+ next_txt=next_txt+'%-24s' % ckey
+
+ count=count+1
+
+ return 1
+
+
+###############################################################################
+# NewView command.
+class GvNewViewCommand(gvcommand.CommandBase):
+ """
+ Create a new OpenEV view window.
+
+ Parameters:
+
+ title- title for the new view.
+
+ """
+
+ def __init__(self):
+ self.Name = 'newview'
+ self.Usage = 'newview [title]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'title', type = 'string_chunk',
+ required=0 )
+ ]
+
+ def execute( self, args, line, interp ):
+
+ title = args[0]
+
+ if title is None or title == '':
+ title = None
+
+ if gview.app.shell.standalone == 1:
+ gview.app.new_view(title,menufile='PyshellNewViewMenuFile.xml')
+ else:
+ gview.app.new_view( title )
+ return 1
+
+###############################################################################
+# ClearView command.
+class GvClearViewCommand(gvcommand.CommandBase):
+ """
+ Clear the active view.
+
+ The clearview command is used to clear the currently
+ active view. The currently active view is the one
+ selected in the layer dialog (Edit->Layers); usually,
+ it is the last view modified or clicked on.
+
+ """
+
+ def __init__(self):
+ self.Name = 'clearview'
+ self.Usage = 'clearview'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = []
+
+ def execute( self, args, line, interp ):
+
+ view = gview.app.sel_manager.get_active_view()
+
+ layer_list = view.list_layers()
+ while len(layer_list) > 0:
+ view.remove_layer( layer_list[0] )
+ layer_list = view.list_layers()
+
+ return 1
+
+###############################################################################
+# View3D Command
+class GvView3DCommand(gvcommand.CommandBase):
+ """
+ Display a 3D raster in the current OpenEV view.
+
+ Parameters:
+
+ demfile- file to use as for elevation values.
+
+ drapefile- file to use as drape. Defaults to demfile
+ if drapefile is not specified.
+
+ mesh_lod- mesh level of detail to use in sampling
+ demfile (numeric).
+
+ hscale- amount to scale demfile by to generate
+ elevation values (numeric).
+
+ """
+
+ def __init__(self):
+ self.Name = 'view3d'
+ self.Usage = 'view3d <demfile> [drapefile] [mesh_lod] [hscale]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'demfile', type = 'string_word',
+ required=1 ),
+ gvcommand.ArgDef( name = 'drapefile', type = 'string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'mesh_lod', type = 'numeric',
+ required=0 ),
+ gvcommand.ArgDef( name = 'hscale', type = 'numeric', required=0 )
+ ]
+
+ def execute( self, args, line, interp ):
+
+ dem_filename = args[0]
+ drape_filename = args[1]
+ if drape_filename is None:
+ drape_filename = dem_filename
+ if args[2] is None:
+ mesh_lod = None
+ else:
+ mesh_lod = int(args[2])
+ if args[3] is None:
+ hscale = None
+ else:
+ hscale = float(args[3])
+
+
+ view_win = gview.app.sel_manager.get_active_view_window()
+
+ view_win.view3d_action( dem_filename, drape_filename, mesh_lod, hscale)
+
+ return 1
+
+###############################################################################
+# Help Command
+
+class GvHelpCommand(gvcommand.CommandBase):
+ """
+ Print help for a function or command.
+
+ The help command is used to print the help for a function
+ or command and/or to launch the help graphical user interface
+ (GUI). The help GUI displays help for currently loaded commands
+ and functions, and may display help on other functions
+ and commands if additional help files have been registered.
+
+ The procedure followed by the help GUI to locate information
+ is the following:
+
+ 1) Look for a function or command of the requested name in
+ the registered help file text, searching first commands,
+ then functions. If the function or command is loaded
+ locally, try to determine the function or command's
+ parent module by searching the function/command's attributes.
+ If text is found and the module name specified in
+ the file matches the function or command's parent
+ module, this text will be displayed. If the command or
+ function's parent module cannot be found from a search
+ of the function/command's attributes, the text will be
+ displayed anyway.
+
+ 2) If no suitable registered help is found but cf_name is
+ recognized as a loaded command, print the command's usage
+ string and group.
+
+ 3) If no registered help is found but cf_name is recognized
+ as a function, print the function's __doc__ string.
+
+ Note that the help GUI takes a "snapshot" of the shell at
+ the time it is launched. If you load new functions or
+ commands and want to view help on them, relaunch the GUI
+ or use the command line help.
+
+ Parameters:
+
+ cf_name- command or function name.
+
+ /g- launch the help GUI.
+
+ """
+
+ def __init__(self):
+ self.Name = 'help'
+ self.Usage = 'help [cf_name] [-g]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'cf_name', type = 'string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'g', type = 'switch', required=0 )
+ ]
+
+ def execute(self, args, line, interp):
+ cf_name = args[0]
+ gui_switch=args[1]
+
+ import Numeric
+
+ if ((cf_name is None) and (gui_switch == 0)):
+ print interp.get_command_help('help')
+ return 1
+
+
+ if gui_switch == 1:
+ # user requested GUI help
+ import pyshell
+ helpwin=pyshell.PyshellHelpDialog()
+ if cf_name is not None:
+ if cf_name in helpwin.total_cmd_keys:
+ txt=interp.get_command_help(cf_name)
+ if cf_name in helpwin.loaded_cmd_keys:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+' (command)\n\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (command)\n\nNo help available.'
+
+ else:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+\
+ ' (command- not loaded)\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (command- not loaded)\n\nNo help available.'
+ elif cf_name in helpwin.total_func_keys:
+ txt=interp.get_function_help(cf_name)
+ if cf_name in helpwin.loaded_func_keys:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+\
+ ' (function)\n\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (function)\n\nNo help available.'
+
+ else:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+\
+ ' (function- not loaded)\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (function- not loaded)\n\nNo help available.'
+ elif cf_name in helpwin.total_builtin_keys:
+ txt=interp.get_builtin_help(cf_name)
+ if cf_name in helpwin.loaded_builtin_keys:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+\
+ ' (built-in function)\n\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (built-in function)\n\nNo help available.'
+
+ else:
+ if txt is not None:
+ txt='\t\t\t'+cf_name+\
+ ' (built-in function- not loaded)\n'+txt
+ else:
+ txt='\t\t\t'+cf_name+\
+ ' (built-in function- not loaded)\n\nNo help available.'
+
+ else:
+ txt=cf_name+\
+ ' not recognized as a command or function.\nNo help available'
+
+ helpwin.update_text(txt)
+
+ return 1
+
+ # GUI not requested
+ if interp.cmdlist.has_key(cf_name):
+ interp.showText('Command '+cf_name+':','report')
+ txt=interp.get_command_help(cf_name)
+ if txt is None:
+ txt='No help available.\n'
+ interp.showText(txt,'report')
+ elif (interp.locals.has_key(cf_name) and
+ (type(interp.locals[cf_name]) == type(Register))):
+ interp.showText('Function '+cf_name+':','report')
+ txt=interp.get_function_help(cf_name)
+ if txt is None:
+ txt='No help available.\n'
+ interp.showText(txt,'report')
+ elif (interp.locals.has_key(cf_name) and
+ (type(interp.locals[cf_name]) == type(Numeric.cos))):
+ interp.showText('ufunc '+cf_name+':','report')
+ txt=interp.get_function_help(cf_name)
+ if txt is None:
+ txt='No help available.\n'
+ interp.showText(txt,'report')
+ elif (interp.locals.has_key(cf_name) and
+ (type(interp.locals[cf_name]) == type(hasattr))):
+ interp.showText('Built-in function '+cf_name+':','report')
+ txt=interp.get_builtin_help(cf_name)
+ if txt is None:
+ txt='No help available.\n'
+ interp.showText(txt,'report')
+ elif interp.get_command_help(cf_name) is not None:
+ # command isn't loaded, but is registered
+ interp.showText('Command '+cf_name+': (not loaded)','report')
+ txt=interp.get_command_help(cf_name)
+ interp.showText(txt,'report')
+ elif interp.get_function_help(cf_name) is not None:
+ # command isn't loaded, but is registered
+ interp.showText('Function '+cf_name+': (not loaded)','report')
+ txt=interp.get_function_help(cf_name)
+ interp.showText(txt,'report')
+ elif interp.get_builtin_help(cf_name) is not None:
+ # command isn't loaded, but is registered
+ interp.showText('Built-in function '+cf_name+': (not loaded)',
+ 'report')
+ txt=interp.get_function_help(cf_name)
+ interp.showText(str(txt),'report')
+
+ else:
+ interp.showText('No help found for '+cf_name+'.','report')
+
+ return 1
+
+###############################################################################
+# GvLocalsCommand(gvcommand.CommandBase):
+class GvLocalsCommand(gvcommand.CommandBase):
+ """
+ List local variables and functions loaded/created by the user.
+
+ Parameters:
+
+ type- type of object to list. eg. locals array
+ will list all Numeric python arrays currently
+ in the environment. type may also be a
+ comma separated list of variable types to
+ display. If type is not specified, all
+ variables/functions loaded by the user will
+ be listed.
+
+ """
+
+ def __init__(self):
+ self.Name='locals'
+ self.Usage = 'locals [type]'
+
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'type', type = 'string_chunk')
+ ]
+
+ def execute(self, args, line, interp):
+ searchtypes=args[0]
+ import gvshell
+
+ if ((searchtypes is not None) and (len(searchtypes) > 0)):
+ import string
+ typelist=string.split(searchtypes,',')
+ txtlst=gvshell.local_vars_list(interp.locals,typelist)
+ else:
+ txtlst=gvshell.local_vars_list(interp.locals)
+
+ for txt in txtlst:
+ interp.showText(txt,'result')
+
+ return 1
+
+###############################################################################
+# execute a series of pyshell lines (commands or functions) from a text file
+#
+# NOTE: This is really a placeholder- the interpreter should intercept macro
+# command lines at the top level and deal with them there because this
+# particular command could not be implemented using the GvCommand
+# structure (it would have resulted in nested interpreter "push" calls,
+# which lead to infinite loops because of buffer clearing issues). The
+# SOLE purpose of putting this placeholder here is so that the various
+# help functions will treat the macro command as a regular command
+# (macro should look like any other command to the user).
+#
+class GvMacroCommand(gvcommand.CommandBase):
+ """
+ Run a sequence of python statements and commands from a file.
+
+ The macro command will look for macro_file in the
+ following locations, using the first one it finds:
+
+ 1) macro_file
+ 2) OPENEV_MACRO_PATH/macro_file
+ 3) OPENEVHOME/macros/macro_file
+ 4) OPENEV_HOME/macros/macro_file
+
+ where OPENEV_MACRO_PATH, OPENEVHOME, and OPENEV_HOME
+ are environment variables. OPENEV_MACRO_PATH may
+ contain multiple search directories separated by
+ semi-colons (;).
+
+ Parameters:
+
+ macro_file- name of the macro text file to run.
+ OpenEV macros are text files and must
+ start with the line:
+ # openev macro
+
+ """
+
+ def __init__(self):
+ self.Name = 'macro'
+ self.Usage = 'macro <macro_file>'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'macro_file', type = 'string_word',
+ required=1 )
+ ]
+
+ def execute(self, args, line, interp):
+ interp.showText('In macro placeholder command- should not be here!',
+ 'error')
+ return 1
+
+
+############################################################
+# Store commands to a file
+
+class GvJournalCommand(gvcommand.CommandBase):
+ """
+ Store statements entered at the command line to a text file.
+
+ Parameters:
+
+ filename- file to store text in (required the first
+ time the journal command is entered in a
+ given session).
+
+ mode- whether to turn journaling on (/on) or off (/off).
+ Defaults to /on.
+
+ umode- whether to append to filename (/a) or overwrite
+ it (/w). Defaults to /a.
+
+ """
+
+ def __init__(self):
+ self.Name = 'journal'
+ self.Usage = "journal <filename> [mode] [umode]"
+
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'filename', type = 'string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'mode', type ='multi_switch', required=0,
+ valid_list=['-off','-on','/off','/on'] ),
+ gvcommand.ArgDef( name = 'umode', type = 'multi_switch',
+ required=0,
+ valid_list=['/w','-w','/a','-a'])
+ ]
+
+ def execute(self, args, line, interp):
+ fname = args[0]
+ state=args[1]
+ mode=args[2]
+
+ # If journal file was open before,
+ # close it.
+
+ if interp.journal_fh is not None:
+ interp.journal_fh.close()
+ interp.journal_fh = None
+
+ if (state is not None) and (state in ['-off','/off']):
+ return 1
+
+ if ((fname is not None) and (len(fname) == 0) and
+ (interp.journal_fname is None)):
+ fname = SelectFile("Journal File")
+
+ if (fname is not None) and (len(fname) > 0):
+ interp.journal_fname=fname
+
+ if interp.journal_fname is not None:
+ if ((mode is not None) and ((mode == 'w') or
+ (mode == '/w') or (mode == '-w'))):
+ interp.journal_fh=open(interp.journal_fname,'w')
+ interp.showText('overwriting '+interp.journal_fname,'result')
+ else:
+ interp.journal_fh=open(interp.journal_fname,'a')
+ interp.showText('appending to '+interp.journal_fname, 'result')
+
+ return 1
+ else:
+ interp.showText(
+ 'Unable to launch journaling- no filename specified','error')
+ return 0
+
+
+#############################################################################
+# import a group of commands
+class GvLoadextCommand(gvcommand.CommandBase):
+ """
+ Load a command extension module.
+
+ The loadext command is used to load an extension
+ module of OpenEV commands. This is similar
+ to the import keyword for pure python code.
+
+ """
+
+ def __init__(self):
+ self.Name = 'loadext'
+ self.Usage = 'loadext <extension_name>'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'extension_name', type = 'string_word',
+ required=1 )
+ ]
+
+ def execute(self, args, line, interp):
+
+ # Get the module name
+ module_name = args[0]
+
+ # Get the current python shell
+ import gview
+
+ exec "import " + module_name
+ exec "reload(" + module_name + ")"
+ exec module_name + '.Register(gview.app.shell)'
+
+ return 1
+
+############################################################
+# Get the currently active raster or vector file and load up the relevant part
+
+class GvGetCommand(gvcommand.CommandBase):
+ """
+ Get data from the active OpenEV view/layer.
+
+ The get command is used to grab data from the currently
+ active OpenEV view/layer and place it in variable
+ <varname> in the python shell. If the /s option
+ is specified, the data grabbed will be screenshot-style;
+ otherwise, data will be retrieved from the underlying
+ raster or shapes object.
+
+ If the view's active layer is a raster and a region of
+ interest (ROI) is drawn and /s is not specified, data will
+ only be extracted from the ROI. The ROI extracted is
+ always a rectangle, so if the view is in georeferenced
+ display mode, the corners will be reprojected to
+ the raster's pixel/line space and a rectangle will
+ be chosen to encompass the full area specified
+ by the ROI plus extra on the edges to make it
+ rectangular. ROI's are ignored if /s is specified.
+
+ If the view's active layer is a shapes layer
+ and shapes are selected, only those shapes will be
+ extracted.
+
+ In all cases, it is a COPY of the data that is
+ extracted; the original will be unchanged by changes
+ to varname.
+
+ Note that the /s option may not always work- some
+ OpenGL drivers give flakey results.
+
+ Parameters:
+
+ varname- name of python shell variable to extract
+ data to (will overwrite any existing
+ variable by that name).
+
+ /s- screenshot mode switch (off by default).
+
+ """
+
+ def __init__(self):
+ self.Name = 'get'
+ self.Usage = 'get <varname> [/s]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'varname', type = 'string_token',
+ required=1 ),
+ gvcommand.ArgDef( name = 's', type = 'switch', required=0 )
+ ]
+
+ def execute(self, args, line, interp):
+
+ import gvutils
+ import gview
+ import gdalnumeric
+
+ clayer = gview.app.sel_manager.get_active_layer()
+ if clayer is None:
+ interp.showText('No layer is currently active!','error')
+ return 0
+
+
+ try:
+ roi=gview.app.toolbar.get_roi()
+ except:
+ roi=None
+
+ # /s argument is 1 if user requested screenshot, 0
+ # if the underlying data was requested (default).
+ # NOTE: roi is ignored for screenshot option
+ is_ss=args[1]
+ shell_vars={}
+
+ if is_ss == 1:
+ cview=gview.app.sel_manager.get_active_view()
+ if roi is not None:
+ txt='Warning- ROI is ignored for screenshot-style get.\n'+\
+ 'Grabbing whole view area.\n'
+ interp.showText(txt,'error')
+
+ # Note: for now, assume colour mode to start with (since
+ # even single band images may have luts applied), and
+ # if all three bands are identical in the end (greyscale
+ # equivalent), return 1.
+
+ err=cview.print_to_file(cview.get_width(),cview.get_height(),
+ '_temp.tif','GTiff',1)
+
+ import os
+
+ if err != 0:
+ interp.showText(
+ 'Error grabbing screenshot- unable to generate temporary file.\n',
+ 'error')
+ os.unlink('_temp.tif')
+ return 0
+
+ try:
+ import Numeric
+ new_arr=gdalnumeric.LoadFile('_temp.tif')
+ if ((max(Numeric.ravel(Numeric.fabs(new_arr[0,:,:] - new_arr[1,:,:])))
+ == 0) and
+ (max(Numeric.ravel(Numeric.fabs(new_arr[2,:,:] - new_arr[1,:,:])))
+ == 0)):
+ shp=Numeric.shape(new_arr)
+ new_arr=Numeric.reshape(new_arr[0,:,:],(shp[1],shp[2]))
+ except:
+ interp.showText(
+ 'Error grabbing screenshot- unable to load temporary file.\n',
+ 'error')
+ os.unlink('_temp.tif')
+ return 0
+
+ shell_vars[args[0]]=new_arr
+ os.unlink('_temp.tif')
+
+ return(1,shell_vars)
+
+ if gvutils.is_of_class(clayer.__class__,'GvRasterLayer'):
+ ds=clayer.get_parent().get_dataset()
+
+ if roi is None:
+ shell_vars[args[0]]=gdalnumeric.DatasetReadAsArray(ds)
+ return (1,shell_vars)
+ else:
+ # Here, need to check if georeferencing is on or not and
+ # convert to pixel/line coordinates if it is on.
+ cview=gview.app.sel_manager.get_active_view()
+ if (cview.get_raw(clayer) == 0):
+ # view is georeferenced- convert corners
+ [pixel,line] = clayer.view_to_pixel(roi[0],roi[1])
+ [pixel2,line2] = clayer.view_to_pixel(roi[0]+roi[2],
+ roi[1]+roi[3])
+ [pixel3,line3] = clayer.view_to_pixel(roi[0],
+ roi[1]+roi[3])
+ [pixel4,line4] = clayer.view_to_pixel(roi[0]+roi[2],
+ roi[1])
+
+ # Get pixel-space rectangle (offsets of 1 ensure that
+ # only pixels fully enclosed by the roi are included-
+ # int casting will round floating point pixel/line
+ # values down)
+ max_pix = int(max(pixel,pixel2,pixel3,pixel4))
+ min_pix = int(min(pixel,pixel2,pixel3,pixel4))+1
+ max_line = int(max(line,line2,line3,line4))
+ min_line = int(min(line,line2,line3,line4))+1
+
+ # in pixel/line space, selected region is a parallelogram
+ # but not necessarily a rectangle. Choose a rectangle
+ # that fully encloses the parallelogram
+ roi = (min_pix,min_line,max_pix-min_pix,max_line-min_line)
+
+
+ shell_vars={}
+ shell_vars[args[0]]=gdalnumeric.DatasetReadAsArray(ds,roi[0],
+ roi[1],roi[2],roi[3])
+ return (1,shell_vars)
+ elif gvutils.is_of_class(clayer.__class__,'GvShapesLayer'):
+ shps=clayer.get_parent()
+ selected = clayer.get_selected()
+
+ if len(selected) == 0:
+ newshps = gview.GvShapes()
+ for item in shps.get_schema():
+ newshps.add_field(item[0],item[1],item[2],item[3])
+ for shp in shps:
+ if shp is not None:
+ newshps.append(shp.copy())
+
+ shell_vars={}
+ shell_vars[args[0]]=newshps
+ return (1,shell_vars)
+ else:
+ newshps = gview.GvShapes()
+ for item in shps.get_schema():
+ newshps.add_field(item[0],item[1],item[2],item[3])
+ for idx in selected:
+ newshps.append(shps[idx].copy())
+ shell_vars={}
+ shell_vars[args[0]]=newshps
+ return (1,shell_vars)
+ else:
+ interp.showText(
+ 'Active layer is not a raster or recognized vector layer!',
+ 'error')
+ return 0
+
+######################################################################
+#
+# Display a variable in a view
+#
+class GvShowCommand(gvcommand.CommandBase):
+ """
+ Display a variable in an OpenEV view.
+
+ The show command displays variable varname in an
+ OpenEV view.
+
+ Parameters:
+
+ varname- python shell variable to display. Must
+ be either a 1-D, 2-D, or 3-D Numeric python
+ array or a GvShapes variable.
+
+ /nocopy- switch to indicate that the original
+ data must be displayed rather than a
+ copy. Later changes made to varname will
+ be reflected in the view when the
+ refresh button is pressed; and
+ changes made through the view will
+ be reflected in varname (eg. shapes
+ deletion). Off by default.
+
+ /o- switch to indicate that varname should be
+ displayed in the current view rather than
+ in a new view.
+
+ """
+
+ def __init__(self):
+ self.Name = 'show'
+ self.Usage = 'show <varname> [/nocopy] [/o]'
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'varname', type = 'variable',
+ required=1 ),
+ gvcommand.ArgDef( name = 'nocopy', type = 'switch', required=0 ),
+ gvcommand.ArgDef( name = 'o', type = 'switch', required=0 )
+ ]
+
+ def execute(self, args, line, interp):
+ import gdalnumeric
+ import gview
+
+ data=args[0][0]
+ dataname=args[0][1]
+ if data is None:
+ interp.showText('No input variable supplied','error')
+ return 0
+
+ ncswitch=args[1]
+ vswitch=args[2]
+
+
+ if vswitch == 0:
+ import gview
+ win = gview.app.new_view()
+ if gview.app.shell.standalone == 1:
+ item = win.menuf.find('File/Exit')
+ if item is not None:
+ item.hide()
+ item = win.menuf.find('File/New View')
+ if item is not None:
+ item.hide()
+ item = win.menuf.find('File/Save Project')
+ if item is not None:
+ item.hide()
+
+ import Numeric
+ if type(data) == type(Numeric.zeros([1,1])):
+ if ncswitch == 0:
+ # By default, display a copy of the
+ # data rather than the original
+ import copy
+ if len(Numeric.shape(data)) == 1:
+ # reshape 1x1 arrays so they can be
+ # displayed.
+ newdata=Numeric.reshape(data,(1,Numeric.shape(data)[0]))
+ else:
+ newdata=copy.deepcopy(data)
+ else:
+ if len(Numeric.shape(data)) == 1:
+ txt='Vectors for display must have dimensions Nx1 or 1xN,\n'
+ txt=txt+'not N. Either reshape the array, or turn off the nocopy\nswitch '
+ txt=txt+'so that show is permitted to reshape it for you.'
+ interp.showText(txt,'error')
+ return 0
+
+ newdata=data
+
+ try:
+ # Only array data should get to here
+ array_name = gdalnumeric.GetArrayFilename(newdata)
+ ds = gview.manager.get_dataset( array_name )
+ #if prototype_name is not None:
+ # prototype_ds = gdal.Open( prototype_name )
+ # gdalnumeric.CopyDatasetInfo( prototype_ds, ds )
+
+ gview.app.file_open_by_name( array_name )
+ return 1
+ except:
+ interp.showText('Unable to open array.','error')
+ return 0
+
+ elif type(data) == type(gview.GvShapes()):
+
+ cview = gview.app.sel_manager.get_active_view_window()
+ cview.make_active()
+
+ # Get an okay layer name
+ layer_list = cview.viewarea.list_layers()
+ layer_map = {}
+ for clayer in layer_list:
+ layer_map[clayer.get_name()]=clayer
+ counter = 0
+
+ name = dataname
+ while layer_map.has_key(name):
+ counter = counter + 1
+ name = dataname + '_'+str(counter)
+
+ if ncswitch == 0:
+ newdata=gview.GvShapes()
+ for item in data.get_schema():
+ newdata.add_field(item[0],item[1],item[2],item[3])
+ for shp in data:
+ if shp is not None:
+ newdata.append(shp.copy())
+ else:
+ newdata=data
+
+ newdata.set_name(name)
+ gview.undo_register(newdata)
+ layer = gview.GvShapesLayer(newdata)
+ cview.viewarea.add_layer(layer)
+ return 1
+ else:
+ interp.showText('Unable to recognize input data type.','error')
+ return 0
+
+#######################################################################
+#
+# Save a variable to file
+#
+class GvSaveCommand(gvcommand.CommandBase):
+ """
+ Save a python shell variable to a file.
+
+ The save command saves python shell variable varname
+ to file filename.
+
+ Parameters:
+
+ varname- python shell variable to save. Must be
+ either a Numeric python array or a
+ GvShapes object.
+
+ filename- filename to save varname to.
+
+ format- Only for varnames of Numeric python array
+ type. Raster file format to use in save.
+ Must be a GDAL write-supported format.
+
+ dataset- Only for varnames of Numeric python array
+ type. Dataset to copy metadata from in
+ saving.
+
+ """
+
+ def __init__(self):
+ self.Name = 'save'
+ self.Usage = 'save <varname> <filename> [format] [dataset]'
+
+ self.HelpURL = ''
+ self.Group = 'core'
+ self.Args = [
+ gvcommand.ArgDef( name = 'varname', type = 'variable',
+ required=1 ),
+ gvcommand.ArgDef( name = 'filename', type = 'string_word',
+ required=1 ),
+ gvcommand.ArgDef( name = 'format', type='string_word',
+ required=0 ),
+ gvcommand.ArgDef( name = 'dataset', type = 'variable',
+ required=0 )
+ ]
+
+ def execute(self, args, line, interp):
+ import gdalnumeric
+ import gview
+
+ data=args[0][0]
+ dataname=args[0][1]
+ fname = args[1]
+ fmt = args[2]
+ dataset=args[3]
+ if dataset is not None:
+ dataset=dataset[0]
+
+ if data is None:
+ interp.showText('No input variable supplied','error')
+ return 0
+
+ import Numeric
+ if type(data) == type(Numeric.zeros([1,1])):
+
+ # Only array data should get to here
+ if ((fmt is None) or (len(fmt) == 0)):
+ fmt = 'GTiff'
+
+ try:
+ gdalnumeric.SaveArray(data,fname,fmt,dataset)
+ return 1
+ except ValueError:
+ txt = fmt + ' format not available. Available formats are:\n'
+ import gdal
+ for cDriver in gdal.GetDriverList():
+ txt = txt + cDriver.ShortName + ' '
+ interp.showText(txt,'error')
+
+ else:
+ try:
+ if fmt is not None:
+ txt='Warning: format option is only available for rasters.\n'
+ txt=txt+' '+fname+\
+ ' will be saved in shapefile format.'
+ interp.showText(txt,'error')
+
+ if data.save_to(fname) == 0:
+ interp.showText('Unable to save '+\
+ dataname+' to file '+fname,'error')
+ return 0
+
+ return 1
+ except:
+ interp.showText('Unable to save '+\
+ dataname+' to file '+fname,'error')
+
+
+###############################################################################
+# The Shell command.
+class GvShellCommand(gvcommand.CommandBase):
+ """
+ Execute a shell command.
+
+ The shell command executes the rest of the line as an external
+ operating system command (ie. via a DOS or unix shell). Output
+ is redirected to the Python shell window.
+
+ Note that the parent process is effectively blocked till the
+ subcommand terminates.
+
+ """
+
+ def __init__(self):
+ self.Name = 'shell'
+ self.Usage = 'shell <operating system command>'
+ self.HelpURL = ''
+ self.Group = 'core'
+
+ self.Args = [
+ gvcommand.ArgDef( name = 'os_command', type = 'string_chunk' )
+ ]
+
+ def execute( self, args, line, anal_win ):
+
+ import os
+ #os.system( args[0] )
+
+ out_fd = os.popen( args[0], 'r' )
+ result = out_fd.read()
+ print result
+
+ return 1
+
+
+def RegisterHelp( target ):
+ # If the gvcorecmd_help.txt file
+ # is present, register it.
+ import os
+ bpath,junk=os.path.split(__file__)
+ hfname=os.path.join(bpath,'gvcorecmds_help.txt')
+ if os.path.isfile(hfname):
+ target.add_helpfile(hfname)
+
+def Register( target ):
+
+ target.add_command( GvCommandsCommand() )
+ target.add_command( GvFunctionsCommand() )
+ target.add_command( GvHelpCommand() )
+ target.add_command( GvView3DCommand() )
+ target.add_command( GvNewViewCommand() )
+ target.add_command( GvClearViewCommand() )
+ target.add_command( GvLoadextCommand() )
+ target.add_command( GvMacroCommand() )
+ target.add_command( GvJournalCommand() )
+ target.add_command( GvLocalsCommand() )
+ target.add_command( GvGetCommand() )
+ target.add_command( GvShellCommand() )
+ target.add_command( GvShowCommand() )
+ target.add_command( GvSaveCommand() )
+
+ RegisterHelp( target )
+
+
+
Added: packages/openev/branches/upstream/current/pymod/gvhtml.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvhtml.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvhtml.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,164 @@
+###############################################################################
+# $Id: gvhtml.py,v 1.14 2004/11/04 14:32:33 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Methods for displaying HTML documentation.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvhtml.py,v $
+# Revision 1.14 2004/11/04 14:32:33 gmwalter
+# Avoid some of the problems with anchors.
+#
+# Revision 1.13 2004/03/12 21:01:00 gmwalter
+# Add image flip key sequences, avoid help
+# popping up when horizontal flip sequence
+# entered.
+#
+# Revision 1.12 2003/12/06 17:47:45 gmwalter
+# Try using webbrowser module before giving up on finding a browser.
+#
+# Revision 1.11 2003/01/24 15:44:32 warmerda
+# browse command may be None if browser not found
+#
+# Revision 1.10 2002/04/17 14:43:06 warmerda
+# use gvutils.FindExecutable()
+#
+# Revision 1.9 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.8 2000/10/19 03:22:15 warmerda
+# Fixed to avoid launching two browsers on NT. Report
+# error if no browser found on unix.
+#
+# Revision 1.7 2000/08/14 18:53:57 warmerda
+# add space to command just before use
+#
+# Revision 1.6 2000/08/11 16:00:51 warmerda
+# added %s substitution and preference support
+#
+# Revision 1.5 2000/08/10 15:58:46 warmerda
+# added set_help_topic support
+#
+# Revision 1.4 2000/06/13 15:16:20 warmerda
+# Added gnome-help-browser, though it doesn't seem to understand http.
+#
+# Revision 1.3 2000/06/09 02:41:41 warmerda
+# use gv_launch_url
+#
+# Revision 1.2 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+import gview
+import os
+import os.path
+import string
+import _gv
+import gtk
+import GDK
+import gview
+import gvutils
+
+def GetBrowseCommand():
+ if gview.get_preference('html_browser'):
+ return gview.get_preference('html_browser')
+
+ # On NT we don't try to find executables, so that we will default
+ # to using gv_launch_url().
+ if os.name == "nt":
+ return ''
+
+ exe_names = ['netscape', 'mozilla', 'mosaic', 'gnome-help-browser' ]
+ for name in exe_names:
+ full_path = gvutils.FindExecutable(name)
+ if (full_path is not None) and (full_path != ''):
+ return full_path
+
+ return ''
+
+def SetBrowseCommand(command):
+ global html_browse_command
+ html_browse_command = command
+ gview.set_preference('html_browser', command)
+
+
+def LaunchHTML( page_name ):
+ """Display indicated HTML page.
+
+ If the passed name is not an absolute path name, nor has an http: prefix,
+ it will be massaged to point into the GView html help tree."""
+
+ if not os.path.isabs(page_name) and page_name[:5] != 'http:':
+ page_name = os.path.abspath( \
+ os.path.join(gview.home_dir,'html',page_name) )
+
+ global html_browse_command
+
+ if page_name[:5] != 'http:':
+ page_name = 'file://'+page_name
+
+ if html_browse_command == '':
+ html_browse_command = GetBrowseCommand()
+
+ if os.name == "nt" and html_browse_command == '':
+ try:
+ import webbrowser
+ webbrowser.open(page_name)
+ except:
+ _gv.gv_launch_url( page_name )
+
+ return
+
+ if html_browse_command == '' or html_browse_command is None:
+ try:
+ import webbrowser
+ webbrowser.open(page_name)
+ except:
+ gvutils.warning( 'Unable to display HTML online help, browser not configured.' )
+ return
+
+ if string.find(html_browse_command,"%s") > -1:
+ full_command = string.replace(html_browse_command,"%s",page_name)+" &"
+ else:
+ full_command = html_browse_command + ' ' + page_name + ' &'
+
+ os.system( full_command )
+
+def f1_help_cb( item, event, topic, *args ):
+ if (event.keyval == GDK.F1) and not (event.state & GDK.CONTROL_MASK):
+ LaunchHTML( topic )
+
+def set_help_topic( object, topic ):
+ """Set a help topic for a widget.
+
+ The help topic (an html file) is launched if the user hits F1 over the
+ widget.
+
+ topic -- topic name, such as 'edittools.html', suitable for use
+ with the LaunchHTML() function."""
+
+ object.connect( "key_press_event", f1_help_cb, topic )
+
+html_browse_command = ''
+
+
+
Added: packages/openev/branches/upstream/current/pymod/gview.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gview.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gview.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4727 @@
+###############################################################################
+# $Id: gview.py,v 1.212 2005/10/17 19:19:15 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Shadow classes for OpenEV C to Python bindings
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gview.py,v $
+# Revision 1.212 2005/10/17 19:19:15 gmwalter
+# Wrap gvshape delete_ring function.
+#
+# Revision 1.211 2005/09/12 15:33:10 gmwalter
+# Update autopan tool for line paths.
+#
+# Revision 1.210 2005/07/06 18:16:47 gmwalter
+# Set translation directly in opening projects
+# (using relative translations was causing
+# problems in some applications when view
+# translation wasn't 0,0 to start with).
+#
+# Revision 1.209 2005/04/06 14:08:46 gmwalter
+# Bring gvdata freeze/thaw functions up to Python level.
+#
+# Revision 1.208 2005/02/22 13:22:38 gmwalter
+# Add autopan tool.
+#
+# Revision 1.207 2005/01/17 18:37:51 gmwalter
+# Add ability to reset tool cursor type.
+#
+# Revision 1.206 2005/01/14 16:51:51 gmwalter
+# Checked in Aude's gv_shapes_add_shape_last function
+# (allows shapes to be added without repeating
+# indices if others have been deleted).
+#
+# Revision 1.205 2005/01/14 15:30:16 warmerda
+# Added flip flag access, and save/restore in project file
+#
+# Revision 1.204 2005/01/04 18:50:31 gmwalter
+# Checked in Aude's new gvshape function changes.
+#
+# Revision 1.203 2004/09/30 21:10:51 warmerda
+# added sink() in lots of appropriate places
+#
+# Revision 1.202 2004/08/20 13:58:30 warmerda
+# GvPqueryLayer: GvShapes in constructor, serialize/deserialize support
+#
+# Revision 1.201 2004/08/18 17:27:50 warmerda
+# Don't blow a gasket if the histogram is empty in
+# GvRasterLayer.equalize().
+#
+# Revision 1.200 2004/07/02 16:40:51 dem
+# - Implement project files portability
+# - last_strech restored in projects reloading
+# - add a "File/Save Project as..." menu
+#
+# Revision 1.199 2004/06/23 14:35:06 gmwalter
+# Added support for multi-band complex imagery.
+#
+# Revision 1.198 2004/04/21 14:44:29 andrey_kiselev
+# Fixed problem with reading NODATA value from the project file.
+#
+# Revision 1.197 2004/04/13 15:07:13 gmwalter
+# Fix raster layer set_source so that it
+# gets min/max values from raster rather
+# than uninitialized sources in itself.
+#
+# Revision 1.196 2004/02/27 14:17:05 warmerda
+# applied fix to preserve no-data value when stretching
+#
+# Revision 1.195 2004/02/18 16:59:51 andrey_kiselev
+# Determine real mix/max values in GvRasterLayer.set_source().
+#
+# Revision 1.194 2004/02/12 22:36:07 gmwalter
+# Add functions for easily creating a line from three
+# lists of nodes (x,y,z), avoiding python-level for
+# loop.
+#
+# Revision 1.193 2004/02/10 15:49:59 andrey_kiselev
+# Added GvManager.add_dataset method.
+#
+# Revision 1.192 2004/01/22 20:54:58 andrey_kiselev
+# New methods in GvRasterLayer class: nodata_get(), nodata_set(), type_get().
+# get_nodata() method now deprecated (though, it does the same as nodata_get).
+#
+# Revision 1.191 2003/10/03 13:58:58 gmwalter
+# Avoid deprecation warning.
+#
+# Revision 1.190 2003/09/16 15:43:12 gmwalter
+# Add single selection mode to select tool, checked in developer tutorials.
+#
+# Revision 1.189 2003/09/12 18:32:32 pgs
+# modified get_preference to return default, added set_default_preferences
+#
+# Revision 1.188 2003/09/11 20:00:32 gmwalter
+# Add ability to specify a preferred polynomial order for warping a raster,
+# and add "safe mode" (only used if ATLANTIS_BUILD is defined).
+#
+# Revision 1.187 2003/09/02 17:27:11 warmerda
+# Added GvSymbolManager support on the GvShapesLayer.
+# Added has_symbol() and get_names() methods on symbol manager.
+# Added serialize/deserialize support for symbol manager.
+#
+# Revision 1.186 2003/08/29 20:53:51 warmerda
+# use C GvShape xml serialize/deserialize version
+#
+# Revision 1.185 2003/08/26 17:36:03 warmerda
+# added recode()
+#
+# Revision 1.184 2003/08/20 20:02:32 warmerda
+# Added collection support to GvShape.
+# Fixed integer type support in GvRecords.add_field().
+#
+# Revision 1.183 2003/08/14 19:07:27 warmerda
+# added MultiStratifiedCollect()method on GvRecords
+#
+# Revision 1.182 2003/08/11 15:34:34 warmerda
+# don't save nodata attribute for raster layer sources if not set
+#
+# Revision 1.181 2003/08/06 22:25:15 warmerda
+# added progress monitor to gv_records load/save funcs
+#
+# Revision 1.180 2003/08/06 17:10:20 warmerda
+# added selection option to GvRecords.save_to_dbf()
+#
+# Revision 1.179 2003/08/05 16:21:58 warmerda
+# fleshed out GvRecords implementation
+#
+# Revision 1.178 2003/06/25 17:08:57 warmerda
+# added rotate tool
+#
+# Revision 1.177 2003/05/23 16:18:17 warmerda
+# added GvRecords for CIETMap
+#
+# Revision 1.176 2003/04/13 04:24:05 warmerda
+# dont flake out on none shapes when serializing
+#
+# Revision 1.175 2003/04/08 11:59:47 andrey_kiselev
+# Added save_vector_symbol() wrapper for gv_symbol_manager_save_vector_symbol().
+#
+# Revision 1.174 2003/04/02 15:47:00 pgs
+# added wrapper for gv_format_point_query
+#
+# Revision 1.173 2003/03/07 17:03:03 gmwalter
+# Move last_complex_lut property setting down to c-level, fix magphase indeterminate
+# phase colour setting.
+#
+# Revision 1.172 2003/02/28 16:50:28 warmerda
+# Added GvSymbolManager support
+#
+# Revision 1.171 2003/02/20 19:27:20 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.170 2002/10/30 21:26:47 warmerda
+# Paul added pick_shape
+#
+# Revision 1.169 2002/09/11 20:40:50 warmerda
+# fixed so that 3d views can be saved
+#
+# Revision 1.168 2002/09/10 21:17:46 warmerda
+# change strstr() to str() in 3d view stuff
+#
+# Revision 1.167 2002/09/10 13:27:28 warmerda
+# added get_height_scale method
+#
+# Revision 1.166 2002/08/01 22:01:05 warmerda
+# removed debug print
+#
+# Revision 1.165 2002/08/01 20:11:45 warmerda
+# minor changes for vector capable classifications
+#
+# Revision 1.164 2002/08/01 14:53:17 pgs
+# removed superfluous XMLFind in gvviewarea initialize_from_xml
+#
+# Revision 1.163 2002/07/25 15:49:14 warmerda
+# fix int overflow problem with equalize()
+#
+# Revision 1.162 2002/07/24 20:33:22 warmerda
+# added gv_shape_get_property
+#
+# Revision 1.161 2002/07/24 14:49:33 warmerda
+# added one-field option to get_schema
+#
+# Revision 1.160 2002/07/23 16:39:50 pgs
+# minor bug fix in gvshapeslayer serialize
+#
+# Revision 1.159 2002/07/18 19:43:53 warmerda
+# added gv_shapes_get_typed_properties
+#
+# Revision 1.158 2002/07/18 19:35:16 pgs
+# added GvShapes.save_to_dbf()
+#
+# Revision 1.157 2002/07/18 17:46:42 warmerda
+# Added get_layout() on GvShapes
+#
+# Revision 1.156 2002/07/16 14:51:30 warmerda
+# serialize all shapes if there is no _filename
+#
+# Revision 1.155 2002/07/16 14:31:23 warmerda
+# removed serialization of selection, made stuff Python 2.0 compatible
+#
+# Revision 1.154 2002/07/16 14:17:31 warmerda
+# added support for getting background color
+#
+# Revision 1.153 2002/07/15 20:27:12 pgs
+# added XML serialization support for GvShapesLayer and ancestors\nand added restoration of raster layer classifications
+#
+# Revision 1.152 2002/07/12 12:46:05 warmerda
+# expanded tabs
+#
+# Revision 1.151 2002/07/08 19:46:03 warmerda
+# added project save/load capability
+#
+# Revision 1.150 2002/07/07 21:06:14 warmerda
+# preliminary addition of project saving
+#
+# Revision 1.149 2002/06/27 15:43:51 warmerda
+# added preliminary serialize() support
+#
+# Revision 1.148 2002/04/12 14:40:37 gmwalter
+# Removed the gvmesh rescale function (not needed because of view area
+# rescaling).
+#
+# Revision 1.146 2002/03/07 18:31:56 warmerda
+# added preliminary gv_shape_clip_to_rect() implementation
+#
+# Revision 1.145 2002/03/07 02:31:56 warmerda
+# added default_height to add_height functions
+#
+# Revision 1.144 2002/03/04 16:00:09 warmerda
+# fixed autoscaling with equalization
+#
+# Revision 1.143 2002/02/28 18:52:22 gmwalter
+# Added a point-of-interest tool similar to the region-of-interest
+# tool (allows a user to select a temporary point without having to add a
+# new layer). Added a mechanism to allow some customization of openev
+# via a textfile defining external modules.
+#
+# Revision 1.142 2002/01/18 05:48:13 warmerda
+# added GvShapes.get_extents() method in python
+#
+# Revision 1.141 2001/12/11 17:51:13 warmerda
+# fixed GvRasterLayer.autoscale() to call self.autoscale_view() when appr.
+#
+# Revision 1.140 2001/12/11 15:12:03 gmwalter
+# Increased default cache sizes for openev, updated mkdist to
+# copy files under their original rather than linked names.
+#
+# Revision 1.139 2001/12/08 04:49:39 warmerda
+# added point in polygon test
+#
+# Revision 1.138 2001/11/28 19:21:33 warmerda
+# Added set_gcps(), and get_gcps() on GvRaster.
+# Added info on geotransform-changed signal on GvRaster.
+#
+# Revision 1.137 2001/10/17 16:25:58 warmerda
+# added support for appling complex luts
+#
+# Revision 1.136 2001/10/16 18:51:18 warmerda
+# added raster layer histogram, autoscale, and various enhancements
+#
+# Revision 1.135 2001/10/02 20:30:06 warmerda
+# update code for establishing .openev file to work on win98
+#
+# Revision 1.134 2001/08/14 17:03:24 warmerda
+# added standard deviation autoscaling support
+#
+# Revision 1.133 2001/08/08 17:46:52 warmerda
+# added GvShape reference counting support
+#
+# Revision 1.132 2001/08/08 02:59:04 warmerda
+# added gv_data_registry_dump()
+#
+# Revision 1.131 2001/08/07 18:40:45 warmerda
+# fixed get_view() for unset views on GvTool
+#
+# Revision 1.130 2001/07/24 21:21:45 warmerda
+# added EV style phase colormap
+#
+# Revision 1.129 2001/07/24 02:59:25 warmerda
+# added force_load method on GvRaster
+#
+# Revision 1.128 2001/07/24 02:21:54 warmerda
+# added 8bit phase averaging
+#
+# Revision 1.127 2001/07/16 15:04:41 warmerda
+# added get_height and build_skirt on GvRasterLayer
+#
+
+import gtk; _gtk = gtk; del gtk
+import _gtkmissing
+import _gv
+import gvutils
+import os.path, sys
+import os
+import string
+import pgu
+import gdal
+from gvconst import *
+from gdalconst import *
+import pathutils
+
+"""
+Classes for viewing and interacting with geographic image and vector data.
+"""
+
+###############################################################################
+# A few notes on gview.py
+#
+# obj2inst():
+#
+# The GtkObject derived OpenEV classes are automatically registered with
+# the gtk name2cls mechanism by some startup code at the bottom of this
+# module (search for name2cls). Basically any class in this module starting
+# with Gv is assumed to:
+# - Be derived from GtkObject
+# - Have a get_type attributes which is the _gv get type method.
+#
+# Based on this, the _gtk._obj2inst() method can be used to create a
+# Python shadow class for any of the raw object handles (_o). It will
+# create the correct type based on the name to class translation and the
+# name returned by the get_type attribute.
+#
+# Note that two obj2inst() calls with one GtkObject will result in two
+# Python shadow objects for the same underlying GtkObject.
+###############################################################################
+
+SMAverage = 0
+SMSample = 1
+SMAverage8bitPhase = 2
+
+###############################################################################
+class GvViewArea(_gtk.GtkDrawingArea):
+ """Gtk geographic view area.
+
+ Signals:
+
+ gldraw -- This signal is emitted after all layers have drawn themselves
+ but before the result is displayed to the user. It provides a hook
+ whereby application code can do additional drawing.
+
+ active-changed -- This signal is emitted after the active layer has been
+ modified, or when a layer is added or removed from the view. It can be
+ used to update tools that depend on the active layer.
+
+ view-state-changed -- This signal is emitted after the view state changes.
+ This includes flipping, zooming and roaming. It does not include mouse
+ position changes.
+
+ Note that the GvViewArea is a GtkWidget, and application code may attach
+ callbacks to the motion-notify-event, button-press-event, key-press-event
+ and other similar events. The map_pointer() method should be used
+ to translate raw GtkWidget coordinates to georeferenced positions.
+ """
+
+ get_type = _gv.gv_view_area_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_view_area_new()
+ if self._o is None:
+ raise ValueError, "Failed to create GvViewArea, is OpenGL working?"
+
+ def serialize(self, filename=None ):
+ tree = [gdal.CXT_Element, 'GvViewArea']
+
+ tree.append( [CXT_Attribute, 'Mode',
+ [CXT_Text, str(self.get_mode())]] )
+ tree.append( [CXT_Attribute, 'Raw',
+ [CXT_Text, str(self.get_raw())]] )
+
+ translation = self.get_translation()
+ tree.append( [CXT_Element, 'Translation',
+ [CXT_Attribute, 'x',
+ [CXT_Text, str(translation[0])]],
+ [CXT_Attribute, 'y',
+ [CXT_Text, str(translation[1])]]] )
+
+ tree.append( [CXT_Element, 'Zoom',
+ [CXT_Text, str(self.get_zoom())]] )
+ tree.append( [CXT_Element, 'FlipX',
+ [CXT_Text, str(self.get_flip_x())]] )
+ tree.append( [CXT_Element, 'FlipY',
+ [CXT_Text, str(self.get_flip_y())]] )
+
+ projection = self.get_projection()
+ if projection is not None and len(projection) > 0:
+ tree.append( [CXT_Element, 'Projection',
+ [CXT_Text, str(self.get_projection())]] )
+
+ background = self.get_background_color()
+ tree.append( [CXT_Element, 'Background',
+ [CXT_Attribute, 'red',
+ [CXT_Text, str(background[0])]],
+ [CXT_Attribute, 'green',
+ [CXT_Text, str(background[1])]],
+ [CXT_Attribute, 'blue',
+ [CXT_Text, str(background[2])]],
+ [CXT_Attribute, 'alpha',
+ [CXT_Text, str(background[3])]]] )
+
+ if self.get_mode() == MODE_3D:
+ eye_pos = self.get_eye_pos()
+ tree.append( [CXT_Element, 'EyePos',
+ [CXT_Attribute, 'x',
+ [CXT_Text, str(eye_pos[0])]],
+ [CXT_Attribute, 'y',
+ [CXT_Text, str(eye_pos[1])]],
+ [CXT_Attribute, 'z',
+ [CXT_Text, str(eye_pos[2])]]] )
+ eye_dir = self.get_eye_dir()
+ tree.append( [CXT_Element, 'EyeDir',
+ [CXT_Attribute, 'x',
+ [CXT_Text, str(eye_dir[0])]],
+ [CXT_Attribute, 'y',
+ [CXT_Text, str(eye_dir[1])]],
+ [CXT_Attribute, 'z',
+ [CXT_Text, str(eye_dir[2])]]] )
+ height_scale = self.get_height_scale()
+ tree.append( [CXT_Element, 'HeightScale',
+ [CXT_Text, str(height_scale)]] )
+
+ layer_tree = [CXT_Element, 'Layers']
+ tree.append( layer_tree )
+
+ layers = self.list_layers()
+ for layer in layers:
+ layer_tree.append( layer.serialize( filename=filename ) )
+
+ return tree
+
+ def initialize_from_xml( self, tree, filename=None ):
+ self.set_property( '_supress_realize_auto_fit', 'on' )
+
+ layer_trees = gvutils.XMLFind( tree, 'Layers')
+ if layer_trees is not None:
+ for layer_tree in layer_trees[2:]:
+ layer = gvutils.XMLInstantiate( layer_tree, self, filename=filename )
+ if layer is not None:
+ self.add_layer( layer )
+ self.set_active_layer( layer )
+ else:
+ print 'Failed to instantiate layer:', layer_tree
+
+ tr = gvutils.XMLFind( tree, 'Translation')
+ if tr is not None:
+ x = float(gvutils.XMLFindValue( tr, 'x', '0.0'))
+ y = float(gvutils.XMLFindValue( tr, 'y', '0.0'))
+ self.set_translation(x,y)
+
+ zm = float(gvutils.XMLFindValue( tree, 'Zoom',
+ str(self.get_zoom()) ))
+ self.zoom( zm - self.get_zoom() )
+
+ flip_x = int(gvutils.XMLFindValue( tree, 'FlipX','1'))
+ flip_y = int(gvutils.XMLFindValue( tree, 'FlipY','1'))
+ self.set_flip_xy( flip_x, flip_y )
+
+ bg = gvutils.XMLFind( tree, 'Background')
+ if bg is not None:
+ self.set_background_color(
+ (float(gvutils.XMLFindValue( bg, 'red', '0.0')),
+ float(gvutils.XMLFindValue( bg, 'green', '0.0')),
+ float(gvutils.XMLFindValue( bg, 'blue', '0.0')),
+ float(gvutils.XMLFindValue( bg, 'alpha', '1.0'))) )
+
+ eye_pos_xml = gvutils.XMLFind( tree, 'EyePos' )
+ if eye_pos_xml is not None:
+ eye_pos = (float(gvutils.XMLFindValue( eye_pos_xml, 'x', '0.0')),
+ float(gvutils.XMLFindValue( eye_pos_xml, 'y', '0.0')),
+ float(gvutils.XMLFindValue( eye_pos_xml, 'z', '1.0')))
+ eye_dir_xml = gvutils.XMLFind( tree, 'EyeDir' )
+ eye_dir = (float(gvutils.XMLFindValue( eye_dir_xml, 'x', '0.0')),
+ float(gvutils.XMLFindValue( eye_dir_xml, 'y', '0.0')),
+ float(gvutils.XMLFindValue( eye_dir_xml, 'z', '-1.0')))
+ self.set_3d_view( eye_pos, eye_dir )
+
+ self.height_scale(
+ float(gvutils.XMLFindValue( tree, 'HeightScale', '1.0' )) )
+
+ self.set_mode( MODE_3D )
+
+ def get_width(self):
+ """Return width of area in pixels."""
+ return _gv.gv_view_area_get_width(self._o)
+
+ def get_height(self):
+ """Return height of area in pixels."""
+ return _gv.gv_view_area_get_height(self._o)
+
+ def add_layer(self, layer):
+ """Add a new layer to the view window.
+
+ Arguments
+
+ layer -- abc A GvLayer derived object to add to the view."""
+ _gv.gv_view_area_add_layer(self._o, layer._o)
+
+ def remove_layer(self, layer):
+ """Remove a layer from view window.
+
+ Arguments
+
+ layer -- the layer to remove"""
+ _gv.gv_view_area_remove_layer(self._o, layer._o)
+
+ def get_named_layer(self, name):
+ """Fetch the named layer from this view
+
+ Returns None if no such layer exists on the view."""
+
+ _o = _gv.gv_view_area_get_named_layer(self._o,name)
+ if _o is not None: return _gtk._obj2inst(_o)
+ return _o
+
+ def active_layer(self):
+ """Fetch the active layer for this view"""
+ _o = _gv.gv_view_area_active_layer(self._o)
+ if _o: return _gtk._obj2inst(_o)
+ return _o
+
+ def set_active_layer(self, layer):
+ """Set the active layer for this view.
+
+ It is an error to make a layer active if it has not already
+ been added to the view.
+
+ Arguments
+
+ layer -- GvLayer to make active."""
+
+ _gv.gv_view_area_set_active_layer(self._o, layer._o)
+
+ def list_layers(self):
+ """Fetch list of layers attached to this view."""
+ l = _gv.gv_view_area_list_layers(self._o)
+ return map(_gtk._obj2inst, l)
+
+ def swap_layers(self, layer_a, layer_b):
+ """Swap two layers in the display order stack.
+
+ Arguments
+
+ layer_a -- Integer index (within list_layers result) of first layer.
+
+ layer_b -- Integer index (within list_layers result) of second layer.
+ """
+ _gv.gv_view_area_swap_layers(self._o, layer_a, layer_b)
+
+ def create_thumbnail(self, layer, w, h):
+ """Return area thumbnail as a GdkWindow.
+
+ Arguments
+
+ layer -- the GvLayer to render into the thumbnail.
+
+ w -- Width in pixels of thumbnail.
+
+ h -- Height in pixel of thumbnail."""
+ return _gv.gv_view_area_create_thumbnail(self._o, layer._o, w, h)
+
+ def zoom(self, zoom):
+ """Zoom in or out.
+
+ Note that the zoom value is log base 2 of the linear zoom factor.
+ So to zoom in by a factor of 2, you would pass 1. To zoom in by
+ a factor of 8 you would pass 3. To zoom out by a factor of eight
+ you would pass -8.
+
+ zoom -- the value to add to the current zoom factor."""
+ _gv.gv_view_area_zoom(self._o,zoom)
+
+ def get_zoom(self):
+ """Get zoom value.
+
+ Note that the zoom value is log base 2 of the linear zoom factor.
+ So a zoom value of 1 means the view is zoomed in by a factor of 2.
+ Similarly, a value of 3 means zoomed in by a factor of 8. Negative
+ values indicate zoomed out.
+ """
+
+ return _gv.gv_view_area_get_zoom(self._o)
+
+ def rotate(self, angle):
+ """Rotate view about center.
+
+ angle -- the angle to rotate about the center by in degrees. Positive
+ is causes view contents to rotate counter-clockwise."""
+ _gv.gv_view_area_rotate(self._o,angle)
+
+ def translate(self, dx, dy):
+ """Translate view by dx and dy.
+
+ dx -- the amount to translate along the x axis in georeferenced units
+ dy -- the amount to translate along the y axis in georeferenced units """
+ _gv.gv_view_area_translate(self._o,dx,dy)
+
+ def set_translation(self, x, y):
+ """Set view center translation.
+
+ The translation values are in georeferenced coordinates, and to
+ put the value (1000,2000) at the view center a translation of
+ (-1000,-2000) is needed.
+
+ x -- the X (easting) value for view center translation.
+ y -- the Y (northing) value for view center translation."""
+ _gv.gv_view_area_set_translation(self._o,x,y)
+
+ def get_translation(self):
+ """Get view center translation.
+
+ The translation values are in georeferenced coordinates, and to
+ put the value (1000,2000) at the view center a translation of
+ (-1000,-2000) would be returned. The value is returned as an
+ (x,y) tuple."""
+
+ return _gv.gv_view_area_get_translation(self._o)
+
+ def get_flip_x( self ):
+ """Fetch X flip flag.
+
+ Normally 1, but will be -1 if an X flip (mirroring) has been applied.
+ """
+ return _gv.gv_view_area_get_flip_x(self._o)
+
+ def get_flip_y( self ):
+ """Fetch Y flip flag.
+
+ Normally 1, but will be -1 if a Y flip (mirroring) has been applied.
+ """
+ return _gv.gv_view_area_get_flip_y(self._o)
+
+ def set_flip_xy( self, flip_x, flip_y ):
+ """Set x/y flip flags.
+
+ flip_x -- x mirroring flag, 1 or -1.
+ flip_y -- x mirroring flag, 1 or -1.
+
+ A value of 1 is unflipped, and -1 is flipped (mirrored).
+ """
+ _gv.gv_view_area_set_flip_xy( self._o, flip_x, flip_y )
+
+ def copy_state(self, src_view):
+ """Copy the view state of another view.
+
+ This includes translation, rotation, and zoom factor.
+
+ src_view -- the GvViewArea to copy the state from."""
+ _gv.gv_view_area_copy_state(self._o,src_view)
+
+ def map_location(self, xy):
+ """ Translates a point from the current view projection (line/pixel or lat/long)
+ to georeferenced coordinates. Useful for a go to function that permits the
+ user to enter a coordinate, then use set_translation() with the mapped location.
+
+ returns a (x,y) tuple in georeferenced coordinates
+
+ xy -- (x,y) tuple in current view coordinates"""
+
+ return _gv.gv_view_area_map_location(self._o, xy)
+
+ def get_pointer(self):
+ """Fetch current pointer position.
+
+ The pointer value is returned as an (X,Y) tuple in georeferenced
+ coordinates."""
+ return _gv.gv_view_area_get_pointer(self._o)
+
+ def map_pointer(self, xy):
+ """Translate position to georef coords.
+
+ Translates a pixel/line position into map (georeferenced) coordinates
+ within the view. The pixel/line coordinates might come from a raw
+ GdkEvent, for instance.
+
+ Returns an (x,y) tuple in georeferenced coordinates.
+
+ xy -- (x,y) tuple in GvViewArea pixel coordinates"""
+ return _gv.gv_view_area_map_pointer(self._o, xy)
+
+ def inverse_map_pointer(self, xy):
+ """Translate position from georef coords.
+
+ Translates a map (georeferenced) position into pixel/line coordinates
+ within the GvViewArea on screen.
+
+ Returns an (x,y) tuple in pixel/line coordinates.
+
+ xy -- (x,y) tuple in georeferenced coordinates"""
+ return _gv.gv_view_area_inverse_map_pointer(self._o, xy)
+
+ def get_volume(self):
+ """Fetch volume of layers in view.
+
+ Returns the world volume of all layers attached to a view (not just
+ what can be currently seen). The volume is returned as an
+ (xmin, xmax, ymin, ymax, zmin, zmax) tuple. In case of failure a
+ dummy cube of (0,1000,0,1000,0,1000) is returned.
+
+ NOTE: At this time the zmin/zmax are not computed, and are always
+ the default 0,1000 values.
+ """
+
+ return _gv.gv_view_area_get_volume(self._o)
+
+ def get_extents(self):
+ """Fetch extents of view window.
+
+ The extents are returned as an (xmin,ymin,xmax,ymax) tuple
+ in georeferenced coordinates."""
+ return _gv.gv_view_area_get_extents(self._o)
+
+ def fit_extents(self,llx, lly, width, height):
+ """Fit view window to region.
+
+ The position and size of the window are in georeferenced coordinates.
+ The translation, zoom and rotation are updated to fit the entire
+ desired box. If the aspect ratio of the box is different than the
+ window, then the window will display the region centered, with
+ extra area viewed in one dimension. The rotation is always set to
+ zero by this call.
+
+ llx -- X (easting) position of the lower left corner.
+ lly -- Y (northing) position of the lower left corner.
+ width -- Width of view region.
+ height -- Height of view region."""
+ _gv.gv_view_area_fit_extents(self._o, llx, lly, width, height)
+
+ def fit_all_layers(self):
+ """Fit view window to extents of all layers
+
+ This sets the 2D and 3D views to the default. In 2D the default
+ sets the view to the minimum extents that will display all layers.
+ In 3D a default view is set which approximately shows all the data
+ in a reasonable way. Note that both the 2D and 3D views are set
+ regardless of the current mode.
+ """
+ _gv.gv_view_area_fit_all_layers(self._o)
+
+ def get_projection(self):
+ """Return view coordinate system.
+
+ The coordinate system is returned in OGC WKT format, and will
+ likely be an empty string if there is no coordinate system."""
+ return _gv.gv_view_area_get_projection( self._o )
+
+ def set_projection(self, proj):
+ """Set the coordinate system of the view.
+
+ Currently the only time the coordinate system can be modified
+ is when there are no layers attached. When raster layers are added
+ to the view, they will attempt to reproject themselves to match the
+ view if possible. Vector layers do not currently do this.
+
+ proj -- new coordinate system in OGC WKT."""
+ _gv.gv_view_area_set_projection( self._o, proj )
+
+ def set_background_color(self, color):
+ """Set the background color of the view.
+
+ color -- an RGBA tuple with the color value (scaled 0.0 to 1.0).
+ For reasonable operation alpha should always be 1.0.
+ """
+ _gv.gv_view_area_set_background_color( self._o, color )
+
+ def get_background_color(self):
+ """Get the background color of the view.
+
+ Returns the background color as an RGBA tuple with the color
+ values scaled 0.0 to 1.0.
+ """
+ return _gv.gv_view_area_get_background_color( self._o )
+
+ def print_to_file(self, width, height, filename, format='GTiff',
+ is_rgb = 1):
+ """Print view (at indicated resolution) to raster file.
+
+ width -- the desired raster width at which to render the image.
+ height -- the desired raster height at which to render the image.
+ filename -- the name of the file to write to.
+ format -- the GDAL format to use (defaults to 'GTiff').
+ is_rgb -- non-zero for RGB output or zero for greyscale output.
+
+ If the aspect ratio of width:height is not the same as the
+ aspect ratio of the view, the extents will be extended in one
+ direction to ensure the entire view data is visible.
+
+ This method return 0 on success or non-zero on failure."""
+
+ return _gv.gv_view_area_print_to_file(self._o, width, height,
+ filename, format, is_rgb)
+
+ def print_postscript_to_file(self, width, height,
+ ulx, uly, lrx, lry,
+ is_rgb, filename):
+ """Print view (at indicated resolution) to PostScript file.
+
+ width -- the desired raster width at which to render the image.
+ height -- the desired raster height at which to render the image.
+ ulx -- the upper left corner of the image print area in inches
+ uly -- the upper left corner of the image print area in inches
+ lrx -- the lower right corner of the image print area in inches
+ lry -- the lower right corner of the image print area in inches
+ is_rgb -- non-zero for RGB output or zero for greyscale output.
+ filename -- the name of the file to write to.
+
+ If the aspect ratio of width:height is not the same as the
+ aspect ratio of the view, the extents will be extended in one
+ direction to ensure the entire view data is visible.
+
+ This method return 0 on success or non-zero on failure."""
+
+ return _gv.gv_view_area_print_postscript_to_file(
+ self._o, width, height, ulx, uly, lrx, lry,
+ is_rgb, filename)
+
+ def page_setup(self):
+ _gv.gv_view_area_page_setup()
+
+ def print_to_windriver(self, width, height,
+ ulx, uly, lrx, lry,
+ is_rgb = 1):
+ """Print view to Windows Print Driver
+
+ width -- the desired raster width at which to render the image.
+ height -- the desired raster height at which to render the image.
+ ulx -- the upper left corner of the image print area in inches
+ uly -- the upper left corner of the image print area in inches
+ lrx -- the lower right corner of the image print area in inches
+ lry -- the lower right corner of the image print area in inches
+ is_rgb -- non-zero for RGB output or zero for greyscale output.
+
+ If the aspect ratio of width:height is not the same as the
+ aspect ratio of the view, the extents will be extended in one
+ direction to ensure the entire view data is visible.
+
+ This method return 0 on success or non-zero on failure."""
+
+ return _gv.gv_view_area_print_to_windriver(self._o, width, height,
+ ulx, uly, lrx, lry, is_rgb)
+
+ def get_mode(self):
+ """Get 2D/3D Mode
+
+ Returns either gview.MODE_2D or gview.MODE_3D depending on the
+ current mode of the view."""
+
+ return _gv.gv_view_area_get_mode(self._o)
+
+ def set_mode(self, flag_3D=MODE_2D):
+ """Set 2D/3D view mode.
+
+ Set the view mode to either 2D orthonormal projection or
+ 3D perspective projection.
+
+ flag_3D -- Either gview.MODE_2D or gview.MODE_3D"""
+
+ _gv.gv_view_area_set_mode(self._o, flag_3D)
+
+ def set_3d_view(self, eye_pos, eye_dir ):
+ """Set 3D view.
+
+ Set the 3D view position, and direction.
+
+ eye_pos -- (x,y,z) tuple indicating the eye position in georeferenced
+ coordinates.
+
+ eye_dir -- (x,y,z) tuple indicating the direction of view. (0,0,-1)
+ is straight down
+ """
+
+ _gv.gv_view_area_set_3d_view( self._o, eye_pos, eye_dir )
+
+ def set_3d_view_look_at(self, eye_pos, eye_look_at ):
+ """Set 3D view.
+
+ Set the 3D view position, and direction.
+
+ eye_pos -- (x,y,z) tuple indicating the eye position in georeferenced
+ coordinates.
+
+ eye_look_at -- (x,y) tuple indicating the position in the z-plane to
+ look at.
+ """
+
+ _gv.gv_view_area_set_3d_view_look_at( self._o, eye_pos, eye_look_at)
+
+ def get_eye_pos(self):
+ """Fetch 3D eye position
+
+ The 3D eye position is returned as an (x,y,z) tuple."""
+
+ return _gv.gv_view_area_get_eye_pos(self._o)
+
+ def get_eye_dir(self):
+ """Fetch 3D eye direction
+
+ The 3D eye direction is returned as an (x,y,z) tuple."""
+
+ return _gv.gv_view_area_get_eye_dir(self._o)
+
+ def get_look_at_pos(self):
+ """Fetch georeference location in z-plane that eye is looking
+
+ Location is returned as an (x,y) tuple, or None if looking above z-plane"""
+ return _gv.gv_view_area_get_look_at_pos(self._o)
+
+ def height_scale(self, scale=1.0):
+ """Set height scaling factor.
+
+ Has no effect unless in 3D mode. A scale value of 2.0 will exaggerate
+ all elevations by a factor of 2 relative to horizontal (georeferenced)
+ coordinates.
+
+ scale -- scale factor (originally 1.0)
+ """
+ _gv.gv_view_area_height_scale(self._o, scale)
+
+ def get_height_scale(self):
+ return _gv.gv_view_area_get_height_scale(self._o)
+
+ def queue_draw( self ):
+ """Force queuing of a redraw.
+
+ This method should not normally be needed, as a redraw should be
+ triggered any time something changes that would require a redraw.
+ """
+ _gv.gv_view_area_queue_draw( self._o )
+
+ def get_fontnames( self ):
+ """Get list of available fontnames.
+
+ Returns a Python list of font name strings suitable for using with
+ LABEL() tools on this view area. Generally the same for all views.
+ """
+ return _gv.gv_view_area_get_fontnames( self._o )
+
+ def get_raw( self, ref_layer = None ):
+ """Check if in Raw Mode
+
+ This returns true if the view is in raw mode relative to the identified
+ raster layer. Raw mode is active if the coordinate system of the
+ display is the raw pixel/line coordinates of the indicated raster.
+
+ ref_layer -- a GvRasterLayer to check against. If ref_layer is None,
+ always returns 0.
+ """
+
+ if ref_layer is None:
+ return 0
+ else:
+ return _gv.gv_view_area_get_raw( self._o, ref_layer._o )
+
+ def set_raw( self, ref_layer, raw_enable ):
+ """Set Raw Mode Enable
+
+ Force the layer to be in raw mode (raw_enable=TRUE) or in georeferenced
+ mode (raw_enable=FALSE) relative to the indicated raster layer. If
+ this requires a change, the coordinate system, and view extents of
+ the view will be altered, and the mesh of the underlying raster will
+ also be altered.
+
+ ref_layer -- a GvRasterLayer to check against.
+ raw_enable -- TRUE to set raw mode or FALSE for georeferenced mode.
+
+ A value of zero is returned if this operation is successful, or a
+ value of non-zero on failure.
+ """
+ if ref_layer is None:
+ return 1
+
+ return _gv.gv_view_area_set_raw( self._o, ref_layer._o, raw_enable )
+
+ def get_property(self,name):
+ """Get a GvViewArea property.
+
+ name -- the key or name of the property being set. Should be a
+ well behaved token (no spaces, equal signs, or colons).
+
+ NOTE: Returns None if property does not exist."""
+
+ return _gv.gv_view_area_get_property(self._o,name)
+
+ def set_property(self,name,value):
+ """Set a GvViewArea property.
+
+ name -- the key or name of the property being set. Should be a
+ well behaved token (no spaces, equal signs, or colons).
+
+ value -- the value to be assigned. Any text is acceptable."""
+
+ return _gv.gv_view_area_set_property(self._o,name,value)
+
+ def format_point_query( self, x, y ):
+ """Format a point as text
+
+ x - the x coordinate to format
+ y - the y coordinate to format
+
+ TODO: provide information on formatting using preferences
+ to control output.
+ """
+
+ return _gv.gv_format_point_query( self._o, x, y )
+
+###############################################################################
+def GvShapeFromXML( tree, parent, filename=None ):
+ """
+ construct a gvshape object from an xml tree
+ """
+
+ _obj = _gv.gv_shape_from_xml( tree )
+ return GvShape( _obj = _obj )
+
+class GvShape:
+ """Vector feature class for GvShapes/GvShapesLayer
+
+ The following properties have special interpretation for a GvShape.
+ Note that modifying these properties does not automatically trigger a
+ display-change signal ... please call display_change() manually.
+
+ _gv_color -- RGBA value used for point, line, or area edge color.
+
+ _gv_fill_color -- RGBA value used for area fill color.
+
+ Note that similar (names differ) color properties can also be set on the
+ GvShapesLayer. Setting these properties on a particular shape overrides
+ any layer drawing styles for that shape.
+
+ """
+
+ def __init__(self, _obj=None,type=GVSHAPE_POINT):
+ if _obj is None:
+ _obj = _gv.gv_shape_new(type)
+
+ _gv.gv_shape_ref( _obj )
+ self.__dict__['_o'] = _obj
+
+ def __del__(self):
+ if self.__dict__['_o'] is not None:
+ _gv.gv_shape_unref( self.__dict__['_o'] )
+ self.__dict__['_o'] = None
+
+ def copy(self):
+ """Make a copy of a shape"""
+
+ copy = _gv.gv_shape_copy( self._o )
+ if copy is None:
+ return None
+
+ return GvShape( _obj=copy )
+
+ def __getattr__(self,attr):
+ if self.__dict__.has_key(attr):
+ return self.__dict__[attr]
+
+ value = _gv.gv_shape_get_property( self._o, attr )
+ if value is None:
+ raise AttributeError, attr
+ else:
+ return value
+
+ def __delattr__(self,attr):
+ if self.__dict__.has_key(attr):
+ del self.__dict__[attr]
+
+ properties = self.get_properties()
+ if not properties.has_key(attr):
+ raise AttributeError, attr
+ else:
+ del properties[attr]
+ self.set_properties(properties)
+
+ def __setattr__(self,attr,value):
+ if attr == '_o':
+ self.__dict__['_o'] = value
+ else:
+ self.set_property(attr,value)
+
+ def __str__(self):
+ result = ''
+ properties = self.get_properties()
+ for key in properties.keys():
+ result = result + key + '=' + properties[key] + '\n'
+
+ result = result + self.geometry_to_wkt() + '\n'
+
+ return result
+
+ def serialize( self, base = None ):
+ """serialize this object in a format suitable for XML representation.
+ """
+ if base is not None:
+ raise ValueError, 'GvShape.serialize() doesnt allow base'
+
+ return _gv.gv_shape_to_xml( self._o )
+
+ def geometry_to_wkt(self):
+ t = self.get_type()
+ fmt = '%f %f %f'
+ geom = ''
+ if t == GVSHAPE_POINT:
+ geom = ('POINT ('+fmt+')') % self.get_node()
+ elif t == GVSHAPE_LINE:
+ geom = 'LINESTRING ('
+ for node in range(self.get_nodes()):
+ if node > 0:
+ geom = geom + ','
+ term = fmt % self.get_node(node)
+ geom = geom + term
+ geom = geom + ')'
+ elif t == GVSHAPE_AREA:
+ geom = 'POLYGON ('
+ for ring in range(self.get_rings()):
+ if ring > 0:
+ geom = geom + ','
+ geom = geom + '('
+ for node in range(self.get_nodes()):
+ if node > 0:
+ geom = geom + ','
+ term = fmt % self.get_node(node)
+ geom = geom + term
+ geom = geom + ')'
+ geom = geom + ')'
+ return geom
+
+ def destroy(self):
+ """Destroy shape.
+
+ The GvShape is not a GtkObject, and doesn't employ the same
+ reference counting mechanisms to ensure destruction when no longer
+ referenced. It is the applications responsibility to destroy
+ GvShape's with an explicit call to the GvShape.destroy() method
+ when appropriate."""
+ if self.__dict__['_o'] is not None:
+ _gv.gv_shape_unref(self.__dict__['_o'])
+ self.__dict__['_o'] = None
+
+ def get_properties(self):
+ """Get GvShape properties (attributes) as a dictionary.
+
+ The properties are returned as a Python dictionary. Note that
+ changes to this dictionary are not applied back to the GvShape."""
+ return _gv.gv_shape_get_properties(self.__dict__['_o'])
+
+ def get_typed_properties(self, prop_list):
+ return _gv.gv_shape_get_typed_properties(self.__dict__['_o'],prop_list)
+
+ def get_property(self,property_name, default_value=None):
+ """Get the value of a property.
+
+ Fetches the value of a single property on the shape. Roughly
+ equivelent to shape_obj.get_properties()[property_name] or
+ shape_obj.property_name but if the property does not exist
+ get_property() returns a default value instead of throwing an
+ exception.
+
+ property_name -- the name of the property (attribute field) to fetch.
+ default_value -- the value to return if the property does not exist,
+ defaults to None.
+
+ Returns the property value (always a string) or the default value."""
+
+ value = _gv.gv_shape_get_property( self._o, property_name )
+ if value is None:
+ return default_value
+ else:
+ return value
+
+ def set_property(self,name,value):
+ """Set a GvShape property.
+
+ name -- the key or name of the property being set. Should be a
+ well behaved token (no spaces, equal signs, or colons).
+
+ value -- the value to be assigned. Any text is acceptable."""
+
+ return _gv.gv_shape_set_property(self._o,name,value)
+
+ def set_properties(self,properties):
+ """Set a GvShape properties.
+
+ Clear all existing properties, and assign the new set passed in.
+
+ properties -- a python dictionary with the keys being property names,
+ and the result is the property value"""
+
+ return _gv.gv_shape_set_properties(self._o,properties)
+
+ def get_node(self,node=0,ring=0):
+ """Fetch a node (point) as a tuple.
+
+ node -- the node within the selected ring to return. Defaults to zero.
+ ring -- the ring containing the desired node. Defaults to zero.
+
+ The node is returned as an (x,y,z) tuple. None is returned if the
+ requested node is out of range."""
+ return _gv.gv_shape_get_node(self._o,node,ring)
+
+ def set_node(self,x,y,z=0,node=0,ring=0):
+ """Set a node.
+
+ x -- the x value to assign.
+ y -- the y value to assign.
+ z -- the z value to assign.
+ node -- the node to set.
+ ring -- the ring containing the node to set.
+
+ Note that the node and ring will be created if not already in
+ existance."""
+ return _gv.gv_shape_set_node(self._o,x,y,z,node,ring)
+
+ def add_node(self,x,y,z=0,ring=0):
+ """Add a node.
+
+ x -- the x value to assign.
+ y -- the y value to assign.
+ z -- the z value to assign.
+ ring -- the ring containing the node to set.
+
+ Note that the ring will be created if not already in
+ existance. The index of the newly created node is returned. """
+ return _gv.gv_shape_add_node(self._o,x,y,z,ring)
+
+ def get_nodes(self,ring=0):
+ """Get number of nodes.
+
+ ring -- the ring to check. Defaults to zero.
+
+ Note that the returned number of nodes will be zero for non-existent
+ rings."""
+ return _gv.gv_shape_get_nodes(self._o,ring)
+
+ def get_rings(self):
+ """Get number of rings.
+ """
+ return _gv.gv_shape_get_rings(self._o)
+
+ def get_type(self):
+ """Get shape type.
+
+ The returned integer will match one of gview.GVSHAPE_POINT,
+ gview.GVSHAPE_LINE, gview.GVSHAPE_AREA or gview.GVSHAPE_COLLECTION."""
+ return _gv.gv_shape_get_type(self._o)
+
+ def delete_ring(self, ring):
+ """Delete a ring
+
+ ring -- the ring to delete."""
+ return _gv.gv_shape_delete_ring(self._o,ring)
+
+ def point_in_polygon(self, x, y ):
+ """Check if point in this area.
+
+ x -- the x component of the location to check.
+ y -- the y component of the location to check.
+
+ Returns a non-zero value if the point (x,y) is inside this
+ shapes area. Returns zero if not, or if the current shape is not
+ an area."""
+ return _gv.gv_shape_point_in_polygon( self._o, x, y )
+
+ def distance_from_polygon(self, x, y ):
+ """Compute shortest distance between point and outline of polygon
+
+ x -- the x component of the location to check.
+ y -- the y component of the location to check.
+
+ Returns the distance as a double."""
+ return _gv.gv_shape_distance_from_polygon( self._o, x, y )
+
+ def clip_to_rect(self, x, y, width, height ):
+ """Clip shape to a rectangle.
+
+ x -- the minimum x of the clip rectangle.
+ y -- the minimum y of the clip rectangle.
+ width -- the width of the clip rectangle.
+ height -- the height of the clip rectangle.
+
+ Creates a new GvShape which is clipped to the indicated rectangle.
+ If the shape does not intersect the rectangle None is returned. If
+ it is entirely contained within the rectangle a copy is returned.
+ Otherwise a copy of the shape with clipped geometry is created and
+ returned. Clipping will generally not work well for complex polygons
+ with holes due to an incomplete implementation of the clipping
+ algorithm. This will be fixed at some point in the future as needed.
+ """
+
+ result = _gv.gv_shape_clip_to_rect( self._o, x, y, width, height )
+ if result is None:
+ return None
+ else:
+ return GvShape( _obj=result )
+
+ def add_shape( self, shape ):
+ _gv.gv_shape_add_shape( self._o, shape._o )
+
+ def get_shape( self, shape_index ):
+ return _gv.gv_shape_get_shape( self._o, shape_index )
+
+ def collection_get_count( self ):
+ return _gv.gv_shape_collection_get_count( self._o )
+
+def gv_shape_get_count():
+ return _gv.gv_shape_get_count()
+
+def gv_shape_line_from_nodes(xlist,ylist,zlist):
+ """ Create a new line shape from three lists
+ of nodes.
+ Inputs: xlist- x coordinates
+ ylist- y coordinates
+ zlist- z coordinates
+ xlist, ylist, and zlist must be the same
+ length.
+ """
+ # cast so that tuples and numeric arrays are
+ # accepted
+ if type(xlist) != type([1]):
+ xlist=list(xlist)
+ if type(ylist) != type([1]):
+ ylist=list(ylist)
+ if type(zlist) != type([1]):
+ zlist=list(zlist)
+ obj=_gv.gv_shape_line_from_nodelists(xlist,ylist,zlist)
+ if obj is None:
+ return None
+ else:
+ return GvShape(_obj=obj,type=GVSHAPE_LINE)
+
+def gv_shapes_lines_for_vecplot(xlist,ylist,zlist,oklist):
+ """ Create a new line shape from three lists
+ of nodes.
+ Inputs: xlist- x coordinates
+ ylist- y coordinates
+ zlist- z coordinates
+ oklist- whether or not the coordinate
+ should be included
+ xlist, ylist, zlist, and oklist must be the same
+ length.
+ """
+ if type(xlist) != type([1]):
+ xlist=list(xlist)
+ if type(ylist) != type([1]):
+ ylist=list(ylist)
+ if type(zlist) != type([1]):
+ zlist=list(zlist)
+ if type(oklist) != type([1]):
+ oklist=list(oklist)
+ obj=_gv.gv_shapes_lines_for_vecplot(xlist,ylist,zlist,oklist)
+ if obj is None:
+ return None
+ else:
+ return GvShapes(_obj=obj)
+
+
+###############################################################################
+class GvData(_gtk.GtkData):
+ """Base class for various raster and vector data containers.
+
+ All GvDatas have a name string, common undo semantics, and changing/changed
+ event notication semantics.
+
+ Signals:
+
+ changing -- Indicates that the underlying data is going to be changed.
+ This will trigger capture of an undo memento if undo is enabled for
+ this object.
+
+ changed -- Indicates that the underlying data has changed.
+
+ Note that the change_info for changing and changed varies depending on
+ the particular type of object. In particular, GvRaster can carry the
+ modified region, and shape containing objects can have a list of shapes.
+ """
+
+ get_type = _gv.gv_data_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+
+ def serialize( self, base = None, filename=None ):
+ """serialize this object in a format suitable for XML representation.
+ """
+
+ if base is None:
+ base = [gdal.CXT_Element, 'GvData']
+
+ base.append( [gdal.CXT_Attribute, 'read_only',
+ [gdal.CXT_Text, str(self.is_read_only())]] )
+ base.append( [gdal.CXT_Attribute, 'name',
+ [gdal.CXT_Text, str(self.get_name())]] )
+ projection = self.get_projection()
+ if projection is not None and len(projection) > 0:
+ base.append( [gdal.CXT_Element, 'Projection',
+ [gdal.CXT_Text, self.get_projection()]] )
+
+ props = self.get_properties()
+
+ for key in props.keys():
+ if key == '_gv_add_height_portable_path':
+ continue
+ v = props[key]
+ if key == '_gv_add_height_filename' and os.path.exists( v ):
+ base.append( [gdal.CXT_Element, 'Property',
+ [gdal.CXT_Attribute, 'name',
+ [gdal.CXT_Text,
+ '_gv_add_height_portable_path']],
+ [gdal.CXT_Text, pathutils.PortablePath( v, ref_path = filename ).serialize()]] )
+ base.append( [gdal.CXT_Element, 'Property',
+ [gdal.CXT_Attribute, 'name', [gdal.CXT_Text, key]],
+ [gdal.CXT_Text, v]] )
+ return base
+
+ def sink( self ):
+ _gtkmissing.gtk_object_sink( self._o )
+
+ def initialize_from_xml( self, tree, filename=None ):
+ """Initialize this instance's properties from the XML tree
+
+ Restores name, read_only, projection and all Property instances
+ """
+ self.set_name( gvutils.XMLFindValue( tree, 'name', self.get_name() ) )
+ self.set_read_only(int(gvutils.XMLFindValue(tree, 'read_only',
+ str(self.is_read_only()))))
+ projection = gvutils.XMLFindValue( tree, 'projection',
+ self.get_projection() )
+ if projection is not None:
+ self.set_projection( projection )
+
+ for subtree in tree[2:]:
+ if subtree[1] == 'Property':
+ name = gvutils.XMLFindValue( subtree, 'name' )
+ if name is not None:
+ value = gvutils.XMLFindValue( subtree, '', '' )
+ self.set_property(name, value)
+
+ def get_name(self):
+ """Fetch the name of this GvData."""
+ return _gv.gv_data_get_name(self._o)
+
+ def set_name(self, name):
+ """Set the name of this GvData."""
+ _gv.gv_data_set_name(self._o, name)
+
+ def is_read_only(self):
+ """Fetch the read_only flag."""
+ return _gv.gv_data_is_read_only(self._o)
+
+ def set_read_only(self, read_only):
+ """Set the read_only flag of this GvData."""
+ _gv.gv_data_set_read_only(self._o, read_only)
+
+ def changed(self):
+ """Emit GvData changed signal.
+
+ Send a notification that this data has changed, with a NULL
+ change_info value."""
+ _gv.gv_data_changed(self._o)
+
+ def get_parent(self):
+ """Fetch parent GvData object.
+
+ This is typically used to get the underlying GvData on which
+ a GvLayer (which is also a GvData) depends."""
+
+ _o_parent = _gv.gv_data_get_parent(self._o)
+ if _o_parent is None:
+ return None
+ else:
+ return _gtk._obj2inst(_o_parent)
+
+ def get_projection(self):
+ """Fetch projection, if any.
+
+ The projection is normally expressed in OpenGIS Well Known Text
+ format or an empty string if no value is available."""
+
+ return _gv.gv_data_get_projection(self._o)
+
+ def set_projection(self, projection):
+ """Set the projection.
+
+ This method won't actually modify the data geometry, only the
+ interpretation of the geometry."""
+ _gv.gv_data_set_projection(self._o, projection)
+
+ def get_properties(self):
+ """Get GvData properties (attributes) as a dictionary.
+
+ The properties are returned as a Python dictionary. Note that
+ changes to this dictionary are not applied back to the GvData."""
+ return _gv.gv_data_get_properties(self._o)
+
+ def get_property(self,name):
+ """Get a GvData property.
+
+ name -- the key or name of the property being set. Should be a
+ well behaved token (no spaces, equal signs, or colons).
+
+ NOTE: Returns None if property does not exist."""
+
+ return _gv.gv_data_get_property(self._o,name)
+
+ def set_properties( self, properties ):
+ """Set GvData properties
+
+ Clear all existing properties, and assign the new set passed in.
+
+ properties -- a python dictionary with the keys being property names,
+ and the result is the property value"""
+
+ return _gv.gv_data_set_properties( self._o, properties )
+
+ def set_property(self,name,value):
+ """Set a GvData property.
+
+ name -- the key or name of the property being set. Should be a
+ well behaved token (no spaces, equal signs, or colons).
+
+ value -- the value to be assigned. Any text is acceptable."""
+
+ return _gv.gv_data_set_property(self._o,name,value)
+
+ def freeze(self):
+ """Freeze a GvData object so that changes are not propagated
+ until thawed"""
+ return _gv.gv_data_freeze(self._o)
+
+ def thaw(self):
+ """Thaw a frozen GvData object"""
+ return _gv.gv_data_thaw(self._o)
+
+def gv_data_registry_dump():
+ _gv.gv_data_registry_dump()
+
+
+###############################################################################
+class GvRecord:
+
+ def __init__(self, records, rec_index ):
+ self.records = records
+ self.rec_index = rec_index
+
+ def get_properties( self ):
+ return self.records.get_rec_properties( self.rec_index )
+
+ def get_typed_properties( self ):
+ return self.records.get_rec_typed_properties( self.rec_index )
+
+ def get_property( self, property_name, default_value = None ):
+ properties = self.records.get_rec_properties( self.rec_index )
+ if properties.has_key( property_name ):
+ return properties[property_name]
+ else:
+ return default_value
+
+ def set_property(self,name,value):
+ field_index = self.records.fieldname_to_index( name )
+ self.records.set_rec_property( self.rec_index, field_index, value )
+
+ def set_properties(self,properties):
+ pass
+
+
+###############################################################################
+class GvRecords(GvData):
+ get_type = _gv.gv_records_get_type
+ def __init__(self, name=None, _obj=None, filename=None,
+ progress_cb = None, cb_data = None ):
+ if _obj:
+ self._o = _obj
+ self.sink()
+ return
+
+ if filename is not None:
+ if gvutils.is_shapefile(filename):
+ self._o = _gv.gv_records_from_dbf( filename, progress_cb, cb_data )
+ else:
+ self._o = _gv.gv_records_from_rec( filename, progress_cb, cb_data )
+
+ if self._o is None:
+ raise ValueError, 'Reading %s failed.' % filename
+
+ self.sink()
+ if name is not None:
+ self.set_name(name)
+ else:
+ self.set_name(filename)
+
+ # default to all fields.
+ self.set_used_properties(None)
+ return
+
+ self._o = _gv.gv_records_new()
+ if name: self.set_name(name)
+
+ def __len__(self):
+ """Return number of shapes in container."""
+ return _gv.gv_records_num_records(self._o)
+
+ def __getitem__(self, rec_index):
+ if rec_index < 0 or rec_index >= _gv.gv_records_num_records(self._o):
+ raise IndexError
+ else:
+ return GvRecord( self, rec_index )
+
+ def __setitem__(self, index, shape):
+ pass
+
+ def create_records( self, count = 1 ):
+ return _gv.gv_records_create_records( self._o, count )
+
+ def fieldname_to_index( self, field_name, schema = None ):
+ if schema is None:
+ schema = self.get_schema()
+ for i in range(len(schema)):
+ if schema[i][0] == field_name:
+ return i
+
+ field_name = string.lower(field_name)
+ for i in range(len(schema)):
+ if string.lower(schema[i][0]) == field_name:
+ return i
+
+ return -1
+
+ def set_used_properties( self, property_list ):
+ schema = self.get_schema()
+ index_list = []
+ if property_list is not None:
+ for i in range(len(property_list)):
+ item = property_list[i]
+ i_fld = self.fieldname_to_index( item )
+ if i_fld == -1:
+ raise ValueError, 'Unknown field name:' + item
+ index_list.append( i_fld )
+ else:
+ index_list = range(len(schema))
+
+ _gv.gv_records_set_used_properties( self._o, index_list )
+
+
+ def get_rec_typed_properties( self, record_index ):
+ return _gv.gv_records_get_typed_properties( self._o, record_index )
+
+ def get_rec_properties( self, record_index ):
+ return _gv.gv_records_get_properties( self._o, record_index )
+
+ def get_rec_property( self, record_index, field_index ):
+ return _gv.gv_records_get_raw_field_data( self._o, record_index,
+ field_index )
+
+ def set_rec_property( self, record_index, field_index, value ):
+ if value is not None:
+ value = str(value)
+
+ return _gv.gv_records_set_raw_field_data( self._o, record_index,
+ field_index, value )
+
+ def get_schema( self, fieldname = None ):
+ prop = self.get_properties()
+
+ schema = []
+ cur_field = 1
+ key_name = '_field_name_' + str(cur_field)
+
+ while prop.has_key(key_name):
+ name = prop['_field_name_'+str(cur_field)]
+
+ if fieldname is not None \
+ and string.lower(name) != string.lower(fieldname):
+ cur_field = cur_field + 1
+ key_name = '_field_name_' + str(cur_field)
+ continue
+
+ type = prop['_field_type_'+str(cur_field)]
+ width = int(prop['_field_width_'+str(cur_field)])
+ try:
+ precision = int(prop['_field_precision_'+str(cur_field)])
+ except:
+ precision = 0
+
+ field_schema = (name, type, width, precision)
+
+ if fieldname is not None:
+ return field_schema
+
+ schema.append( field_schema )
+
+ cur_field = cur_field + 1
+ key_name = '_field_name_' + str(cur_field)
+
+ if fieldname is not None:
+ return None
+ else:
+ return schema
+
+ def get_layout( self ):
+ pass
+
+ def add_field( self, name, type = 'string', width = 0, precision = 0 ):
+
+ """Add field to schema.
+
+ This function will define a new field in the schema for this
+ container. The schema is stored in the GvShapes properties, and it
+ used by selected functions such as the save_to() method to define
+ the schema of output GIS files.
+
+ Note that adding a field to the schema does not cause it to be
+ added to all the individual GvShape objects in the container.
+ However, the save_to() method will assume a default value for
+ shapes missing some of the fields from the schema, so this is generally
+ not an issue.
+
+ name -- the name of the field. The application is expected to ensure
+ this is unique within the layer.
+
+ type -- the type of the field. Must be one of 'integer', 'float', or
+ 'string'.
+
+ width -- the field width. May be zero to indicated variable width.
+
+ precision -- the number of decimal places to be preserved. Should be
+ zero for non-float field types.
+
+ The field number of the newly created field is returned."""
+
+ if precision != 0 and type != 'float':
+ raise ValueError, 'Non-zero precision on '+type+' field '+name+' in GvShapes.add_field()'
+
+ rft = None
+
+ # GV_RFT_FLOAT
+ if type == 'float':
+ rft = 2
+
+ # GV_RFT_STRING
+ if type == 'string':
+ rft = 3
+
+ # GV_RFT_INTEGER
+ if type == 'integer':
+ rft = 1
+
+ if rft is None:
+ raise ValueError, 'Illegal field type "'+type+'" in GvRecords.add_field(), should be float, integer or string.'
+
+ return _gv.gv_records_add_field(self._o, name, rft, width, precision )
+
+ def save_to_dbf(self, filename, selection = [],
+ progress_cb = None, cb_data = None ):
+ """Save records attributes to a DBF file.
+
+ filename -- name of the file to save to
+
+ selection -- list of shape indexes to write, default for all.
+ """
+
+ return _gv.gv_records_to_dbf( self._o, filename, selection,
+ progress_cb, cb_data )
+
+ def MultiStratifiedCollect( self, selection, var1, var2, strat_vars = [],
+ progress_cb = None, progress_data = None ):
+ return _gv.gv_records_MultiStratifiedCollect( self._o, selection,
+ var1, var2, strat_vars,
+ progress_cb,
+ progress_data )
+
+ def recode( self, single_mapping, range_mapping, srcvar, dstvar = None,
+ progress_cb = None, progress_data = None ):
+
+ if dstvar is None:
+ dstvar = srcvar
+
+ return _gv.gv_records_recode( self._o, single_mapping, range_mapping,
+ srcvar, dstvar,
+ progress_cb, progress_data )
+
+###############################################################################
+def GvShapesFromXML( node, parent, filename=None ):
+ """construct a gvshapes object from an xml tree.
+
+ node is the current node to instantiate from
+ parent is the parent object that wants to instantiate
+ this GvShapes object.
+
+ will return the new GvShapes instance or None if something went
+ horribly wrong.
+ """
+
+ shapes = GvShapes()
+
+ #restore properties
+ shapes.initialize_from_xml( node, filename=filename )
+
+ #restore shapes
+ shape_tree = gvutils.XMLFind(node, 'Shapes')
+ for subtree in shape_tree[2:]:
+ shape = gvutils.XMLInstantiate( subtree, parent, filename=filename )
+ if shape is None:
+ print 'shape is None'
+ elif shape._o is None:
+ print 'shape._o is None'
+ else:
+ shapes.append(shape)
+
+ return shapes
+
+class GvShapes(GvData):
+ """A GvData of points, lines and areas (GvShapes).
+
+ This layer can be treated as a list object, where each value is
+ a GvShape.
+
+ Notes on updating Shapes:
+
+ In order to generate proper undo information, and to ensure proper
+ generation of data changing and changed events, it is illegal for
+ applications to change the geometry of attributes of GvShape objects
+ that are members of a GvShapes container. If you want to change some
+ aspect of a shape, it is necessary to copy it, modify the copy, and then
+ apply the copy back to the GvShapes.
+
+ eg.
+ shape = shapes[45].copy()
+ shape.set_property( "abc", "def" )
+ shapes[45] = shape
+
+ """
+
+ get_type = _gv.gv_shapes_get_type
+ def __init__(self, name=None, _obj=None, shapefilename=None):
+ """Create a GvShapes
+
+ name -- name to assign to GvShapes, defaults to None.
+ shapefilename -- name of ESRI shapefile to create from, or None
+ (default) to create an empty container.
+ """
+ if _obj:
+ self._o = _obj
+ self.sink()
+ return
+
+ if shapefilename:
+ self._o = _gv.gv_shapes_from_shapefile(shapefilename)
+ self.sink()
+ return
+
+ self._o = _gv.gv_shapes_new()
+ if name: self.set_name(name)
+ self.sink()
+
+ def __len__(self):
+ """Return number of shapes in container."""
+ return _gv.gv_shapes_num_shapes(self._o)
+
+ def __getitem__(self, index):
+ """Return an individual shape by index"""
+ shp_o = _gv.gv_shapes_get_shape(self._o, index)
+ if shp_o is not None:
+ return GvShape(_obj=shp_o)
+ else:
+ if index < 0 or index >= _gv.gv_shapes_num_shapes(self._o):
+ raise IndexError
+ else:
+ return None;
+
+ def __setitem__(self, index, shape):
+ """Overwrite a shape by index
+
+ Note that this actually deletes the old shape, and the new shape
+ will hereafter be referenced in the layer. Only freestanding GvShape
+ objects (not assigned to any existing GvShapes) should be assigned in
+ this manner, and they will thereafter be owned by the GvShapes."""
+
+ _gv.gv_shapes_replace_shapes(self._o, [index,], [shape._o,])
+
+ def __delitem__(self, index):
+ """Delete an individual shape by index"""
+
+ _gv.gv_shapes_delete_shapes(self._o, [index,])
+
+ def serialize( self, base = None, filename = None ):
+ """serialize this object in a format suitable for XML representation.
+ """
+ if base is None:
+ base = [gdal.CXT_Element, 'GvShapes']
+
+ GvData.serialize( self, base, filename=filename )
+
+ shapes = [gdal.CXT_Element, 'Shapes' ]
+ for i in range(len(self)):
+ if self[i] is not None:
+ shapes.append(self[i].serialize( ))
+ base.append( shapes )
+
+ return base
+
+ def append(self, shape):
+ """Add GvShape to GvShapes. If there is an empty space in GvShapes
+ (i.e. a shape has been deleted), place the new shape in it.
+
+ shape -- GvShape to add.
+
+ Returns the id of the newly added shape."""
+ return _gv.gv_shapes_add_shape(self._o, shape._o)
+
+ def append_last(self, shape):
+ """Add GvShape to GvShapes always at the end of list.
+
+ shape -- GvShape to add.
+
+ Returns the id of the newly added shape."""
+ return _gv.gv_shapes_add_shape_last(self._o, shape._o)
+
+ def get_extents(self):
+ """Fetch bounds extents of shapes.
+
+ The extents are returned as an (xmin,ymin,xsize,ysize) tuple."""
+ return _gv.gv_shapes_get_extents(self._o)
+
+ def delete_shapes(self, shapes):
+ """Delete a list of shapes
+
+ shapes -- a list of integer shape indexes to delete
+
+ Note the underlying GvShape objects are destroyed in addition to
+ them being removed from the container."""
+
+ _gv.gv_shapes_delete_shapes(self._o, shapes)
+
+ def save_to(self, filename, type = 0):
+ """Save layer to ESRI Shapefile
+
+ Shapefiles can only hold a single geometric type. By default this
+ method will select a type based on the geometry of the first feature
+ (GvShape) written, but it can be overridden with the type argument.
+ The possible values are listed as SHPT_ codes in shapefil.h.
+
+ filename -- name of file to save to (extension will be automatically
+ supplied)
+ type -- One of the shapefile type codes, or zero to try and auto
+ detect the type of file to create. Zero is the default."""
+
+ return _gv.gv_shapes_to_shapefile( filename, self._o, type )
+
+ def save_to_dbf(self, filename):
+ """Save shape attributes to a DBF file.
+
+ filename -- name of the file to save to
+ """
+
+ return _gv.gv_shapes_to_dbf( filename, self._o )
+
+ def get_change_info(self, c_object):
+ """Used to convert a PyCObject as returned from a changed/changing
+ signal to a python tuple.
+
+ Takes a PyCObject and returns the equivalent python object.
+
+ (change_type, num_shapes, (shape_ids))
+ where change_type is defined in gvconst.py
+ num_shapes is an integer
+ shape_ids is a list of shape IDs"""
+
+ return _gv.gv_shapes_get_change_info(c_object)
+
+ def add_height( self, raster, offset=0.0, default_height = 0.0 ):
+ """Set vertex heights from raster DEM.
+
+ Sets the Z component of each vertex to the value sampled from
+ the raster, and then adds the offset. Values off the DEM, or
+ in _nodata_ areas of the DEM are set to 0.0. Old z coordinates
+ are always lost.
+
+ The offset is normally used to boost the vectors up a bit over any
+ raster layers so they remain visible. Usually a value on the order
+ of 1/3 the size of a pixel is sufficient.
+
+ raster -- a GvRaster from which to sample elevations, should be in
+ a compatible coordinate system to the shapes.
+ offset -- optional offset to apply to the vertices. """
+
+ # Actually add the height.
+ _gv.gv_shapes_add_height( self._o, raster._o, offset, default_height )
+
+ def get_schema( self, fieldname = None ):
+ """Fetch attribute schema.
+
+ When read from GIS data sources such as shapefiles or OGR supported
+ GIS formats, there will be a schema associated with a GvShapes
+ grouping. The schema is the definition of the list of attributes
+ shared by all shapes in the container. This information is stored
+ in the properties of the GvShapes. This method extracts the schema
+ information in a more easily used form for Python.
+
+ The returned schema will contain a list of tuples, with one tuple
+ per attribute in the schema. The tuples wille each contain four
+ elements.
+
+ - name: the name of the field.
+ - type: the type of the field. One of 'integer', 'float' or 'string'.
+ - width: the width normally used for displaying the field, and
+ limiting storage capacity in some formats (ie. shapefiles)
+ - precision: the number of decimal places preserved. For non
+ floating point values this is normally 0.
+
+ Optionally, a single fieldname can be given as an argument and only
+ schema tuple for that field will be returned (or None if it does not
+ exist).
+
+ """
+ prop = self.get_properties()
+
+ schema = []
+ cur_field = 1
+ key_name = '_field_name_' + str(cur_field)
+
+ while prop.has_key(key_name):
+ name = prop['_field_name_'+str(cur_field)]
+
+ if fieldname is not None \
+ and string.lower(name) != string.lower(fieldname):
+ cur_field = cur_field + 1
+ key_name = '_field_name_' + str(cur_field)
+ continue
+
+ type = prop['_field_type_'+str(cur_field)]
+ width = int(prop['_field_width_'+str(cur_field)])
+ try:
+ precision = int(prop['_field_precision_'+str(cur_field)])
+ except:
+ precision = 0
+
+ field_schema = (name, type, width, precision)
+
+ if fieldname is not None:
+ return field_schema
+
+ schema.append( field_schema )
+
+ cur_field = cur_field + 1
+ key_name = '_field_name_' + str(cur_field)
+
+ if fieldname is not None:
+ return None
+ else:
+ return schema
+
+ def get_layout( self ):
+ """Get tabular layout information.
+
+ This returns a list of field names, and their suggested width. The
+ list of field names is based on the results of get_schema(), so
+ any fields not listed in the schema will be missed. The width
+ returned for each field is the maximum of the field title, and all
+ the field values occuring in all shapes.
+
+ The return result is a list of (field_name, width) tuples in the
+ same order as in the schema.
+ """
+
+ schema = self.get_schema()
+ name_list = []
+ width_list = []
+ for item in schema:
+ name_list.append( item[0] )
+ width_list.append( len(item[0]) )
+
+ field_count = len(name_list)
+
+ for rec in self:
+
+ props = rec.get_properties()
+
+ for i_field in range(field_count):
+ try:
+ l = len(props[name_list[i_field]])
+ if l > width_list[i_field]:
+ width_list[i_field] = l
+ except:
+ pass
+
+ result = []
+ for i_field in range(field_count):
+ result.append( (name_list[i_field], width_list[i_field]) )
+
+ return result
+
+ def add_field( self, name, type = 'string', width = 0, precision = 0 ):
+
+ """Add field to schema.
+
+ This function will define a new field in the schema for this
+ container. The schema is stored in the GvShapes properties, and it
+ used by selected functions such as the save_to() method to define
+ the schema of output GIS files.
+
+ Note that adding a field to the schema does not cause it to be
+ added to all the individual GvShape objects in the container.
+ However, the save_to() method will assume a default value for
+ shapes missing some of the fields from the schema, so this is generally
+ not an issue.
+
+ name -- the name of the field. The application is expected to ensure
+ this is unique within the layer.
+
+ type -- the type of the field. Must be one of 'integer', 'float', or
+ 'string'.
+
+ width -- the field width. May be zero to indicated variable width.
+
+ precision -- the number of decimal places to be preserved. Should be
+ zero for non-float field types.
+
+ The field number of the newly created field is returned."""
+
+ if type != 'float' and type != 'integer' and type != 'string':
+ raise ValueError, 'Illegal field type "'+type+'" in GvShapes.add_field(), should be float, integer or string.'
+
+ if precision != 0 and type != 'float':
+ raise ValueError, 'Non-zero precision on '+type+' field '+name+' in GvShapes.add_field()'
+
+ cur_schema = self.get_schema()
+ new_entry = len(cur_schema) + 1
+
+ self.set_property( '_field_name_'+str(new_entry), name )
+ self.set_property( '_field_type_'+str(new_entry), type )
+ self.set_property( '_field_width_'+str(new_entry), str(width) )
+ self.set_property( '_field_precision_'+str(new_entry), str(precision))
+
+ return new_entry
+
+
+
+###############################################################################
+class GvPoints(GvData):
+ get_type = _gv.gv_points_get_type
+ def __init__(self, name=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_points_new()
+ if name: self.set_name(name)
+ def __len__(self):
+ return _gv.gv_points_num_points(self._o)
+ def __getitem__(self, index):
+ return _gv.gv_points_get_point(self._o, index)
+ def append(self, point):
+ return _gv.gv_points_new_point(self._o, point)
+
+###############################################################################
+class GvPolylines(GvData):
+ get_type = _gv.gv_polylines_get_type
+ def __init__(self, name=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_polylines_new()
+ if name: self.set_name(name)
+ def __len__(self):
+ return _gv.gv_polylines_num_lines(self._o)
+ def __getitem__(self, index):
+ return _gv.gv_polylines_get_line(self._o, index)
+ def append(self, line):
+ return _gv.gv_polylines_new_line(self._o, line)
+
+###############################################################################
+class GvAreas(GvData):
+ get_type = _gv.gv_areas_get_type
+ def __init__(self, name=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_areas_new()
+ if name: self.set_name(name)
+ def __len__(self):
+ return _gv.gv_areas_num_areas(self._o)
+ def __getitem__(self, index):
+ return _gv.gv_areas_get_area(self._o, index)
+ def append(self, area):
+ return _gv.gv_areas_new_area(self._o, area)
+
+###############################################################################
+
+def GvRasterFromXML( node, parent, filename=None ):
+ band = int(gvutils.XMLFindValue(node,"band","1"))
+ portable_path = gvutils.XMLFindValue( node, 'portable_path' )
+ if portable_path is not None:
+ f = pathutils.PortablePathFromXML( portable_path ).local_path( ref_path = filename )
+ else:
+ for child in node[2:]:
+ if child[0] == gdal.CXT_Text:
+ f = child[1]
+
+ ds = manager.get_dataset( f )
+ raster = manager.get_dataset_raster( ds, band )
+ return raster
+
+class GvRaster(GvData):
+ """Raster data object
+
+ Signals:
+
+ geotransform-changed -- generated when the geotransform (whether
+ affine or the polynomials based on gcps) changes. Primarily used
+ by the GvRasterLayer to ensure updates to mesh and display.
+ """
+
+ get_type = _gv.gv_raster_get_type
+ def __init__(self, filename=None, dataset=None, _obj=None,
+ sample=SMSample, real=1 ):
+ """Create new raster.
+
+ All the arguments of this method are optional, and can be passed
+ as keywords.
+
+ filename -- name of the file to open. It must be suitable for use
+ with gdal.Open().
+
+ dataset -- a gdal.Dataset object as returned by gdal.Open(). May
+ be used as an alternative to filename.
+
+ sample -- Method to use to compute reduced levels of detail. Either
+ gview.SMAverage (2x2 average) or gview.SMSample (decimation).
+
+ real -- The band from the raster file to use as the band.
+
+ """
+ if _obj: self._o = _obj; return
+ if (filename is None) and (dataset is None):
+ raise ValueError, "expecting filename or dataset handle"
+
+ if not (dataset is None):
+ dataset_raw = dataset._o
+ else:
+ dataset_raw = None
+
+ self._o = _gv.gv_raster_new(filename = filename, sample = sample,
+ real = real, dataset = dataset_raw)
+ self.sink()
+
+ def flush_cache(self,x_off=0,y_off=0,width=0,height=0):
+ """Flush data cache.
+
+ This will cause the data caches of GDAL, and this GvRaster to be
+ cleared out. If this is being done to trigger reload, and redisplay
+ of modified data on disk, then a changed signal should be emitted on
+ the GvRaster instead. This will trigger a flush automatically, and
+ also invalidate displays, forcing them to be rerendered.
+
+ x_off -- x origin of area to be flushed.
+ y_off -- y origin of area to be flushed.
+ width -- width of area to be flushed (zero for whole image).
+ height -- height of area to be flushed (zero for whole image).
+ """
+ _gv.gv_raster_flush_cache(self._o,x_off,y_off,width,height)
+
+ def get_sample(self, x, y):
+ """Fetch sample value from raster.
+
+ This function will fetch the real, or complex data value at the
+ given location (in raster pixel/line coordinates). If the result
+ is real a single number is returned. It it is complex a (real
+ imaginary) tuple is returned. If the requested point is outside
+ the raster, or if the call fails for some other reason a None is
+ returned.
+
+ x -- x offset from top left corner of pixel to fetch.
+ y -- y offset from top left corner of pixel to fetch."""
+
+ return _gv.gv_raster_get_sample(self._o, x, y)
+
+ def georef_to_pixel(self, x, y ):
+ """Translate georeferenced coordinates to pixel/line.
+
+ x -- X (easting or longitude) in raster layer georeferencing system.
+ y -- Y (northing or latitude) in raster layer georeferencing system.
+
+ Returns a (pixel,line) coordinate tuple on the raster."""
+
+ return _gv.gv_raster_georef_to_pixel(self._o, x, y)
+
+ def cursor_link_georef_to_pixel(self, x, y ):
+ """Translate cursor/link georeferenced coordinates to pixel/line.
+
+ x -- X (easting or longitude) in raster layer georeferencing system.
+ y -- Y (northing or latitude) in raster layer georeferencing system.
+
+ Returns a (pixel,line) coordinate tuple on the raster."""
+
+ return _gv.gv_raster_georef_to_pixelCL(self._o, x, y)
+
+ def pixel_to_georef(self, x, y ):
+ """Translate pixel/line to georeferenced coordinate.
+
+ x -- pixel on raster layer (0.0 is left side of leftmost pixel)
+ y -- line on raster layer (0.0 is top side of topmost pixel)
+
+ Returns an (x,y) coordinate tuple in the raster georeferencing
+ system."""
+
+ return _gv.gv_raster_pixel_to_georef(self._o, x, y)
+
+ def cursor_link_pixel_to_georef(self, x, y ):
+ """Translate pixel/line to cursor/link georeferenced coordinate.
+
+ x -- pixel on raster layer (0.0 is left side of leftmost pixel)
+ y -- line on raster layer (0.0 is top side of topmost pixel)
+
+ Returns an (x,y) coordinate tuple in the raster georeferencing
+ system defined for the cursor and link mechanism (defaults
+ to the standard pixel_to_georef if no separate gcps have
+ been defined for the cursor/link)."""
+
+ return _gv.gv_raster_pixel_to_georefCL(self._o, x, y)
+
+ def data_changing(self, x_off, y_off, width, height):
+ """Send GvData changing signal with a raster rectangle.
+
+ This signal indicates that a region of the raster is about to change,
+ and will trigger capture of an undo memento of the region if
+ undo is enabled.
+
+ x_off -- pixel offset to top left corner of change region.
+ y_off -- line offset to top left corner of change region.
+ width -- width of window that is changing.
+ height -- width of window that is changing."""
+ _gv.gv_raster_data_changing(self._o, x_off, y_off, width, height )
+
+ def data_changed(self, x_off, y_off, width, height):
+ """Send GvData changed signal with a raster rectangle.
+
+ This signal indicates that a region of the raster has just changed,
+ and will trigger invalidation of any buffered data from the
+ source file, and rereading for display.
+
+ x_off -- pixel offset to top left corner of change region.
+ y_off -- line offset to top left corner of change region.
+ width -- width of window that is changed.
+ height -- width of window that is changed."""
+ _gv.gv_raster_data_changed(self._o, x_off, y_off, width, height )
+
+ def get_change_info(self, c_object):
+ """Used to convert a PyCObject as returned from a changed/changing
+ signal to a python tuple.
+
+ Returns an equivalent python tuple object to a GvRasterChangeInfo
+ structure as returned by a display_changed signal.
+
+ Returns (change_type, x_off, y_off, width, height)
+ where change_type is defined in gvconst.py and the rest are integers.
+ """
+ return _gv.gv_raster_get_change_info(c_object)
+
+ def get_band_number(self):
+ band = self.get_band()
+ dataset = self.get_dataset()
+ for iband in range(dataset.RasterCount):
+ test_band = dataset.GetRasterBand(iband+1)
+ if test_band._o == band._o:
+ return iband+1
+ return -1
+
+ def get_band(self):
+ """Get GDAL raster band
+
+ Fetch the band associated with the GvRaster as a
+ gdal.RasterBand object.
+ """
+
+ band_swigptr = _gv.gv_raster_get_gdal_band(self._o)
+ if band_swigptr is None:
+ return None
+
+ return gdal.Band(_obj=band_swigptr);
+
+ def get_dataset(self):
+ """Get GDAL raster dataset
+
+ Fetch the dataset associated with the GvRaster as a
+ gdal.Dataset object.
+ """
+
+ band_swigptr = _gv.gv_raster_get_gdal_dataset(self._o)
+ if band_swigptr is None:
+ return None
+
+ return gdal.Dataset(_obj=band_swigptr);
+
+ def autoscale(self, alg = ASAAutomatic, alg_param = -1.0, assign = 0):
+ """Force autoscaling to be recomputed.
+
+ alg -- Algorithm to use (see below)
+ alg_param -- the parameter to the algorithm, or -1.0 to get
+ default parameter value (possibly from preferences).
+ assign -- 1 to assign min/max to GvRaster or 0 to just return it.
+
+ This method will force recomputation of scaling min/max values
+ based on a sample of the data. The algorithms collect roughly 10000
+ sample points approximately at random. Any recognised no data values
+ are removed from the sample set.
+
+ The first algorithm option is ASAPercentTailTrim, in which case
+ the parameter is the percentage of the tail to exclude (0.02 for
+ 2%).
+
+ The second algorithm option is ASAStdDeviation in which case
+ the min/max values are based on the selected number of standard
+ deviations below and above the mean of the sample. The parameter
+ value might be 1.25 to use 1.25 standard deviations on each side of
+ the mean as the min/max values.
+
+ The algorithm value ASAAutomatic can also be passed (the default)
+ to determine the preferred algorithm from application preferences.
+
+ If the autoscale() fails (for instance due to an IO error, or if all
+ the sample data is the nodata value) the method will throw an
+ exception otherwise a (min,max) tuple is returned.
+
+ """
+ return _gv.gv_raster_autoscale(self._o, alg, alg_param, assign)
+
+ def get_min(self):
+ """Get the minimum for default scaling
+
+ See the autoscale() method for information on this is established."""
+ return _gv.gv_raster_get_min(self._o)
+
+ def get_max(self):
+ """Get the maximum for default scaling
+
+ See the autoscale() method for information on this is established."""
+ return _gv.gv_raster_get_max(self._o)
+
+ def force_load(self):
+ """Force loading all full res data.
+
+ All full res data for this GvRaster is forceably loaded, though
+ normal cache expiration rules apply so earlier tiles may already
+ be discarded as later tiles are fetched. This is a blocking
+ operation and should be use with care. It's main purpose is to
+ provide speculative "preloading" of smallish files to provide smooth
+ animation effects."""
+
+ _gv.gv_raster_force_load( self._o )
+
+ def get_gcps(self):
+ gcp_tuple_list = _gv.gv_raster_get_gcps(self._o)
+
+ gcp_list = []
+ for gcp_tuple in gcp_tuple_list:
+ gcp = gdal.GCP()
+ gcp.Id = gcp_tuple[0]
+ gcp.Info = gcp_tuple[1]
+ gcp.GCPPixel = gcp_tuple[2]
+ gcp.GCPLine = gcp_tuple[3]
+ gcp.GCPX = gcp_tuple[4]
+ gcp.GCPY = gcp_tuple[5]
+ gcp.GCPZ = gcp_tuple[6]
+ gcp_list.append(gcp)
+
+ return gcp_list
+
+ def get_cursor_link_gcps(self):
+ gcp_tuple_list = _gv.gv_raster_get_gcpsCL(self._o)
+
+ gcp_list = []
+ for gcp_tuple in gcp_tuple_list:
+ gcp = gdal.GCP()
+ gcp.Id = gcp_tuple[0]
+ gcp.Info = gcp_tuple[1]
+ gcp.GCPPixel = gcp_tuple[2]
+ gcp.GCPLine = gcp_tuple[3]
+ gcp.GCPX = gcp_tuple[4]
+ gcp.GCPY = gcp_tuple[5]
+ gcp.GCPZ = gcp_tuple[6]
+ gcp_list.append(gcp)
+
+ return gcp_list
+
+ def set_gcps(self, gcp_list ):
+ tuple_list = []
+ for gcp in gcp_list:
+ tuple_list.append( (gcp.Id, gcp.Info, gcp.GCPPixel, gcp.GCPLine,
+ gcp.GCPX, gcp.GCPY, gcp.GCPZ) )
+
+ return _gv.gv_raster_set_gcps( self._o, tuple_list )
+
+ def set_cursor_link_gcps(self, gcp_list, poly_order=1 ):
+ tuple_list = []
+ for gcp in gcp_list:
+ tuple_list.append( (gcp.Id, gcp.Info, gcp.GCPPixel, gcp.GCPLine,
+ gcp.GCPX, gcp.GCPY, gcp.GCPZ) )
+
+ return _gv.gv_raster_set_gcpsCL( self._o, tuple_list, poly_order )
+
+ def set_poly_order_preference(self, poly_order):
+ # Set preferred polynomial order for this raster (for use in
+ # display). This is only used if it is appropriate for
+ # the current number of gcp's (ground control points).
+ # If order is <1 or >3 it will be reset to fall within this
+ # range.
+ _gv.gv_raster_set_poly_order_preference(self._o, poly_order)
+
+#def GvLayerFromXML( node, parent, filename=None ):
+# band = int(gvutils.XMLFindValue(node,"band","1"))
+# for child in node[2:]:
+# if child[0] == gdal.CXT_Text:
+# filename = child[1]
+
+# ds = manager.get_dataset( filename )
+# raster = manager.get_dataset_raster( ds, band )
+# return raster
+
+###############################################################################
+class GvLayer(GvData):
+ """Base class for display layers.
+
+ Signals:
+
+ setup -- called when the layer is being setup. Internal use.
+
+ teardown -- called when the layer is being destroyed. Internal use.
+
+ draw -- called after normal drawing is complete on the layer. Gives tools
+ an opportunity to draw layer specific overlays.
+
+ get-extents -- called to fetch extents of layer. Takes a GvRect as an
+ argument (not clear to me why this is a signal).
+
+ display-change -- called to indicate a display property (colour,
+ interpolation method, etc) of this layer has changed. Triggers redraw.
+ """
+
+ get_type = _gv.gv_layer_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+
+ def serialize( self, base = None, filename=None ):
+ if base is None:
+ base = [gdal.CXT_Element, 'GvLayer']
+
+ base.append( [gdal.CXT_Attribute, 'visible',
+ [gdal.CXT_Text, str(self.is_visible())]] )
+
+ GvData.serialize( self, base, filename=filename )
+
+ return base
+
+ def initialize_from_xml( self, tree, filename=None ):
+ """restore object properties from XML tree
+ """
+ GvData.initialize_from_xml( self, tree, filename=filename )
+ self.set_visible( int(gvutils.XMLFindValue( tree, 'visible',
+ str(self.is_visible()))))
+
+ def is_visible(self):
+ """Check if layer is visible.
+
+ Returns a non-zero value if the layer is currently visible.
+ """
+ return _gv.gv_layer_is_visible(self._o)
+
+ def set_visible(self, visible):
+ """Set layer visibility.
+
+ visible -- 0 for invisible, and non-zero for visible.
+ """
+ _gv.gv_layer_set_visible(self._o, visible)
+
+ def extents(self):
+ """Return extents of layer.
+
+ The extents are returned as a tuple (xmin,ymin,width,height)."""
+ return _gv.gv_layer_extents(self._o)
+
+ def reproject(self, projection):
+ """Attempt to change view projection.
+
+ projection -- the projection string in OpenGIS Well Known Text format.
+
+ Currently this only works for rasters, but eventually it will
+ modify the display projection of any kind of GvLayer.
+
+ Returns 0 on failure, or non-zero on success."""
+ return _gv.gv_layer_reproject(self._o, projection)
+
+ def launch_properties(self):
+ """Launch a properties panel for this layer.
+
+ Returns the dialog object, or None if none can be created."""
+ return None
+
+ def display_change(self):
+ """Send a display property notification."""
+ _gv.gv_layer_display_change(self._o)
+
+ def get_view(self):
+ """Fetch the GvViewArea this layer is on."""
+
+ _o_view = _gv.gv_layer_get_view( self._o )
+ if _o_view is None:
+ return None
+ else:
+ return _gtk._obj2inst(_o_view)
+
+ def classify(self):
+ from gvclassification import GvClassification
+ from gvclassifydlg import GvClassificationDlg
+
+ classification = GvClassification(self)
+ classifyier = GvClassificationDlg(classification)
+ classifyier.show()
+
+ def show_legend(self):
+ from gvclassification import GvClassification
+ import gvlegenddlg
+
+ cls = GvClassification(self)
+ if cls.count > 0:
+ gvlegenddlg.show_legend( self )
+
+ def refresh( self ):
+ """Refresh from view of layer as required by layer type."""
+ pass
+
+###############################################################################
+class GvShapeLayer(GvLayer):
+ """Display layer of vector shape objects.
+
+ Signals:
+
+ selection-changed -- This signal is emitted when the selection for the
+ layer has changed (including clearing the selection). Use get_selected()
+ to get the current selection list.
+
+ subselection-changed -- This signal is emitted when the subselection
+ (the focus shape within the current selection) changes. Note that a
+ subselection-changed signal is usually generated on selection changes,
+ as well as subselection changes.
+
+ This class has many other signals, but they are mostly for internal
+ implementation of selection, editing and so forth.
+
+ """
+ get_type = _gv.gv_shape_layer_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+
+ def serialize(self, base, filename=None ):
+ """serialize this object in a format suitable for XML representation.
+
+ Adds properties for the current selection
+ """
+
+ if base is None:
+ base = [gdal.CXT_Element, 'GvShapeLayer']
+
+ GvLayer.serialize( self, base, filename=filename )
+
+ def initialize_from_xml( self, tree, filename=None ):
+ """initialize this object from the XML tree
+ """
+
+ GvLayer.initialize_from_xml( self, tree, filename=filename )
+
+ def set_color(self, color):
+ """Set the drawing color.
+
+ This method is deprecated.
+ """
+ _gv.gv_shape_layer_set_color(self._o, color)
+
+ def pick_shape( self, view, x, y ):
+ """
+ """
+ return _gv.gv_shape_layer_pick_shape( self._o, view._o, x, y )
+
+ def get_selected(self):
+ """Get list of currently selected objects.
+
+ The list of shape id's is returned as a list.
+ """
+ return _gv.gv_shape_layer_get_selected(self._o)
+
+ def get_subselected(self):
+ """Get current subselection.
+
+ Returns the shape id of the current subselection. The subselection
+ is the one shape out the current set of selected shapes that has
+ special focus of attention from the user. The return value will be
+ -1 if there is no subselection ... generally because there is no
+ selection."""
+
+ return _gv.gv_shape_layer_get_subselection(self._o)
+
+ def subselect_shape(self, shape_id):
+ """Change the subselection.
+
+ shape_id -- the new subselection. This may be -1, otherwise it must
+ be in the current selected shape set.
+ """
+ _gv.gv_shape_layer_subselect_shape( self._o, shape_id )
+
+ def clear_selection(self):
+ """Clear selection
+
+ Clear the current shape selection for this layer, sending a
+ selection-changed signal if there was anything selected."""
+
+ _gv.gv_shape_layer_clear_selection(self._o)
+
+ def select_all(self):
+ """Select all shapes in layer
+
+ All shapes in the layer are marked as selected, and if this is a
+ change, a selection-changed signal is sent."""
+
+ _gv.gv_shape_layer_select_all(self._o)
+
+ def select_shape(self,shape_id):
+ """Add a shape to selection
+
+ Adds the indicated shape to the current selection, triggering a
+ selection-changed signal if that shape wasn't previously selected.
+ The existing selection should be cleared explicitly with
+ clear_selection() if you only want the new shape select.
+
+ Nothing will happen if the shape is already selected.
+
+ shape_id -- the id (index) of the shape to be selected."""
+
+ _gv.gv_shape_layer_select_shape(self._o,shape_id)
+
+ def deselect_shape(self,shape_id):
+ """Remove shape from selection
+
+ Removes the indicated shape from the current selection, triggering a
+ selection-changed signal if that shape was previously selected.
+
+ shape_id -- the id (index) of the shape to be deselected."""
+
+ _gv.gv_shape_layer_deselect_shape(self._o, shape_id)
+
+ def set_selection_mode(self,mode=0,clear=1):
+ """Set selection mode
+
+ mode=0: multiple selection (default)
+ mode=1: single selection
+
+ clear=0: do not clear existing selections before changing mode
+ clear=1: clear existing selections before changing mode (default)
+
+ """
+ if clear == 1:
+ self.clear_selection()
+ self.display_change()
+
+ if mode == 1:
+ self.set_property("selection_mode","single")
+ else:
+ self.set_property("selection_mode","multiple")
+
+
+###############################################################################
+def GvShapesLayerFromXML( base, parent, filename=None ):
+ """Create a GvShapesLayer from an XML tree
+
+ Look for a GvShapes tree and use it to build the GvShapes object if
+ possible. Otherwise, look for the _filename propery and use it. If
+ neither is found, the layer will not have any shapes.
+
+ Returns a new GvShapesLayer or None if it failed
+ """
+ shape_tree = gvutils.XMLFind( base, 'GvShapes' )
+ if shape_tree is not None:
+ shapes = gvutils.XMLInstantiate( shape_tree, None, filename=filename )
+ else:
+ portable_path = gvutils.XMLFindValue( base, 'portable_path' )
+ if portable_path is not None:
+ shapefilename = pathutils.PortablePathFromXML( portable_path ).local_path( ref_path = filename )
+ else:
+ shapefilename = gvutils.XMLFindValue( base, "_filename" )
+ if shapefilename is None:
+ shapes = None
+ if shapefilename is not None:
+ shapes = GvShapes( shapefilename = shapefilename )
+
+ layer = GvShapesLayer( shapes = shapes )
+
+ if layer is not None:
+ layer.initialize_from_xml( base, filename=filename )
+
+ return layer
+
+class GvShapesLayer(GvShapeLayer):
+ """Vector Display Layer
+
+ The following properties have special interpretation for a GvShapesLayer.
+ Note that modifying these properties does not automatically trigger a
+ display-change signal ... please call display_change() manually.
+
+ _point_color -- RGBA value used for point color.
+
+ _point_size -- Size of point cross hairs in screen pixels.
+
+ _line_color -- RGBA value used for line color.
+
+ _area_edge_color -- RGBA value used for area edge drawing. Set alpha to
+ zero to skip drawing edges.
+
+ _area_fill_color -- RGBA value used for area filling. Set alpha to zero
+ to skip drawing fill.
+
+ Note that the above property values can also be set on individual
+ shapes to override drawing style on a per-shape basis.
+ """
+ get_type = _gv.gv_shapes_layer_get_type
+
+ def __init__(self, shapes=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if shapes != None: shapes = shapes._o
+ self._o = _gv.gv_shapes_layer_new(shapes)
+ self.sink()
+
+ def serialize( self, base = None, filename=None ):
+ """Create a representation of this object suitable for XMLing.
+ """
+ if base is None:
+ base = [gdal.CXT_Element, "GvShapesLayer"]
+
+ layer_props = self.get_properties()
+ shapes = self.get_parent()
+ if shapes is not None:
+ shape_props = shapes.get_properties()
+ if (layer_props.has_key('_serialize_shapes') and \
+ layer_props['_serialize_shapes'] == '1') \
+ or not shape_props.has_key('_filename'):
+ base.append( shapes.serialize( filename=filename ) )
+ elif shape_props.has_key('_filename'):
+ v = shape_props['_filename']
+ if os.path.exists( v ):
+ base.append( [gdal.CXT_Attribute, 'portable_path',
+ [gdal.CXT_Text, pathutils.PortablePath( v, ref_path = filename ).serialize()]] )
+ base.append( [gdal.CXT_Attribute, '_filename',
+ [gdal.CXT_Text, v]] )
+
+ # Do we have a symbol manager?
+
+ sm = self.get_symbol_manager(0)
+ if sm is not None:
+ base.append( sm.serialize() )
+
+ #serialize the base class properties (all the way to GvData)
+ GvShapeLayer.serialize( self, base, filename=filename )
+
+ return base
+
+ def launch_properties(self):
+ import gvvectorpropdlg
+ return gvvectorpropdlg.LaunchVectorPropDialog( self )
+
+ def get_symbol_manager( self, ok_to_create = 0 ):
+ _sm = _gv.gv_shapes_layer_get_symbol_manager( self._o, ok_to_create )
+ if _sm is None:
+ return None
+ else:
+ return GvSymbolManager( _obj = _sm )
+
+ def initialize_from_xml( self, tree, filename=None ):
+ """initialize this object from the XML tree
+ """
+
+ # Initialize GvSymbolManager.
+
+ sm_xml = gvutils.XMLFind( tree, 'GvSymbolManager' )
+ if sm_xml is not None:
+ sm = self.get_symbol_manager( 1 )
+ sm.initialize_from_xml( sm_xml, filename=filename )
+
+ GvShapeLayer.initialize_from_xml( self, tree, filename=filename )
+
+###############################################################################
+class GvPointLayer(GvShapeLayer):
+ get_type = _gv.gv_point_layer_get_type
+ def __init__(self, points=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if points != None: points = points._o
+ self._o = _gv.gv_point_layer_new(points)
+
+###############################################################################
+class GvLineLayer(GvShapeLayer):
+ get_type = _gv.gv_line_layer_get_type
+ def __init__(self, plines=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if plines != None: plines = plines._o
+ self._o = _gv.gv_line_layer_new(plines)
+
+###############################################################################
+class GvAreaLayer(GvShapeLayer):
+ get_type = _gv.gv_area_layer_get_type
+ def __init__(self, areas=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if areas != None: areas = areas._o
+ self._o = _gv.gv_area_layer_new(areas)
+
+###############################################################################
+def GvPqueryLayerFromXML( base, parent, filename=None ):
+ shape_tree = gvutils.XMLFind( base, 'GvShapes' )
+ if shape_tree is not None:
+ shapes = gvutils.XMLInstantiate( shape_tree, None, filename=filename )
+ else:
+ portable_path = gvutils.XMLFindValue( base, 'portable_path' )
+ if portable_path is not None:
+ shapefilename = pathutils.PortablePathFromXML( portable_path ).local_path( ref_path = filename )
+ else:
+ shapefilename = gvutils.XMLFindValue( base, "_filename" )
+ if shapefilename is None:
+ shapes = None
+ if shapefilename is not None:
+ shapes = GvShapes( shapefilename = shapefilename )
+
+ layer = GvPqueryLayer( shapes = shapes )
+
+ if layer is not None:
+ layer.initialize_from_xml( base, filename=filename )
+
+ return layer
+
+class GvPqueryLayer(GvShapesLayer):
+ """Point Query Layer
+
+ This layer is intended to only hold points, but this isn't strictly
+ enforced. For each point in this layer, coordinate and/or raster
+ values are displayed beside the point.
+
+ The following properties have special interpretation for a GvPqueryLayer.
+ Note that modifying these properties does not automatically trigger a
+ display-change signal ... please call display_change() manually.
+
+ _point_color -- RGBA value used for point and text color.
+
+ _point_size -- Size of point cross hairs in screen pixels
+
+ _pixel_mode -- One of "off" or "on" indicating if pixel raster values
+ should be displayed for each query point.
+
+ _coordinate_mode -- One of "off", "raster", "georef", or "latlong"
+ indicating what coordinate system the coordinates should be displayed in
+ (or skipped for off).
+
+ Note that the above property values can also be set on individual
+ shapes to override drawing style on a per-shape basis.
+ """
+ get_type = _gv.gv_pquery_layer_get_type
+ def __init__(self, shapes=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if shapes != None: shapes = shapes._o
+ self._o = _gv.gv_pquery_layer_new( shapes )
+ self.sink()
+
+ def launch_properties(self):
+ import gvpquerypropdlg
+ return gvpquerypropdlg.LaunchPQueryPropDialog( self )
+
+ def serialize( self, base = None, filename=None ):
+ """Create a representation of this object suitable for XMLing.
+ """
+ if base is None:
+ base = [gdal.CXT_Element, "GvPqueryLayer"]
+
+ #serialize the base class properties
+ GvShapesLayer.serialize( self, base, filename=filename )
+
+ return base
+
+###############################################################################
+class IpGcpLayer(GvShapesLayer):
+ get_type = _gv.ip_gcp_layer_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.ip_gcp_layer_new()
+ self.sink()
+
+###############################################################################
+class AppCurLayer(GvShapesLayer):
+ get_type = _gv.app_cur_layer_get_type
+ def __init__(self, _obj=None, shapes=None):
+ if _obj: self._o = _obj; return
+ if shapes is not None:
+ shapes = shapes._o
+ self._o = _gv.app_cur_layer_new(shapes)
+ self.sink()
+
+###############################################################################
+def GvRasterLayerFromXML( node, parent, filename=None ):
+ prototype_node = gvutils.XMLFind( node, 'Prototype' )
+ if prototype_node is not None:
+ prototype_data = GvRasterFromXML( prototype_node, None,
+ filename=filename )
+ else:
+ prototype_data = None
+
+ rl_mode = int(gvutils.XMLFindValue( node, 'mode', str(RLM_AUTO) ))
+ mesh_lod = gvutils.XMLFindValue( node, 'mesh_lod', '0' )
+
+ layer = GvRasterLayer( raster = prototype_data, rl_mode = rl_mode,
+ creation_properties = [('mesh_lod',mesh_lod)] )
+ layer.initialize_from_xml( node, filename=filename )
+
+ sources_min_max = []
+ for child in node[2:]:
+ if child[0] == gdal.CXT_Element and child[1] == 'Source':
+ raster = GvRasterFromXML( child, None, filename=filename )
+ isource = int(gvutils.XMLFindValue(child,"index","0"))
+ min = float(gvutils.XMLFindValue(child,"min","0"))
+ max = float(gvutils.XMLFindValue(child,"max","0"))
+ sources_min_max.append([min, max])
+ const_value = int(gvutils.XMLFindValue(child,"const_value","0"))
+ nodata = gvutils.XMLFindValue( child, "nodata", None )
+ nodata = eval(gvutils.XMLFindValue(child, "nodata", "None"))
+
+ layer.set_source( isource, raster, min = min, max = max,
+ const_value = const_value, nodata = nodata )
+ else:
+ raster = None
+
+ stretch = layer.get_property( 'last_stretch' )
+ if stretch is not None:
+ exec 'func = layer.' + stretch + '()'
+
+ # Warning !!! stretch functions generally reset min/max with autoscale for
+ # each source, so we have to reset them to the good values...
+ for i in range(layer.sources):
+ layer.min_set( i, sources_min_max[i][0] )
+ layer.max_set( i, sources_min_max[i][1] )
+
+ # Set classification?
+
+ from gvclassification import GvClassification
+ cls = GvClassification( layer )
+ if cls.count > 0:
+ cls.update_all_layers()
+
+ # Set elevations?
+ f = layer.get_property( '_gv_add_height_portable_path' )
+ if f is None:
+ f = layer.get_property( '_gv_add_height_filename' )
+ else:
+ f = pathutils.PortablePathFromXML( f ).local_path( ref_path = filename )
+ if f is not None:
+ ds = manager.get_dataset( f )
+ dem_raster = manager.get_dataset_raster(
+ ds, int(layer.get_property( '_gv_add_height_band' )) )
+ layer.add_height( dem_raster,
+ float(layer.get_property( '_gv_add_height_default')))
+
+ return layer
+
+class GvRasterLayer(GvLayer):
+ get_type = _gv.gv_raster_layer_get_type
+ def __init__(self, raster=None, creation_properties=None, _obj=None,
+ rl_mode = RLM_AUTO ):
+ """Create a raster layer.
+
+ raster -- the primary GvRaster to which this layer is tied. It
+ will be the GvData parent of this layer, and will be used to establish
+ georeferencing, and other information. Internally this is known
+ as the ``prototype-data''.
+
+ creation-properties -- A list of (name, value) tuples with special
+ creation options. Currently the only supported one is ('raw','yes')
+ to avoid using affine or gcp based georeferencing information from
+ the GvRaster.
+
+ rl_mode -- One of the RLM modes (documented in get_mode()), or
+ gview.RLM_AUTO meaning the layer type should be deduced from the
+ passed GvRaster (the default).
+ """
+ if _obj:
+ self._o = _obj
+ else:
+ if raster is None:
+ raise ValueError, "expecting GvRaster instance"
+ if creation_properties is None:
+ self._o = _gv.gv_raster_layer_new(raster._o, rl_mode)
+ else:
+ self._o = _gv.gv_raster_layer_new(raster._o, rl_mode,
+ creation_properties)
+
+ self.sink()
+
+ # Note: we don't want to include alpha in self.sources as it should
+ # not be enhanced.
+ if self.get_mode() == RLM_SINGLE:
+ self.sources = 1
+ elif self.get_mode() == RLM_COMPLEX:
+ self.sources = 1
+ else:
+ self.sources = 3
+
+ def serialize(self, layer = None, filename=None ):
+ if layer is None:
+ layer = [gdal.CXT_Element, 'GvRasterLayer']
+
+ layer.append( [CXT_Attribute, 'mode',
+ [CXT_Text, str(self.get_mode())]] )
+
+ layer.append( [CXT_Attribute, 'mesh_lod',
+ [CXT_Text, str(self.get_mesh_lod())]] )
+
+ GvLayer.serialize( self, layer, filename=filename )
+
+ source_count = self.sources
+ prototype_raster = None
+ for isource in range(source_count):
+ if prototype_raster is None:
+ raster = self.get_data(isource)
+ if raster is not None:
+ prototype_raster = raster
+
+ if prototype_raster is not None:
+ v = raster.get_dataset().GetDescription()
+ proto = [gdal.CXT_Element, 'Prototype',
+ [gdal.CXT_Attribute, 'band',
+ [gdal.CXT_Text, str(raster.get_band_number())]]]
+ if os.path.exists( v ):
+ proto.append( [gdal.CXT_Attribute, 'portable_path',
+ [gdal.CXT_Text, pathutils.PortablePath( v, ref_path=filename ).serialize()]] )
+ proto.append( [gdal.CXT_Text, v] )
+ layer.append( proto )
+
+ # Note that self.sources isn't necessary all the sources.
+ for isource in range(source_count):
+ src = [gdal.CXT_Element, 'Source',
+ [gdal.CXT_Attribute, 'index',
+ [gdal.CXT_Text, str(isource)]],
+ [gdal.CXT_Attribute, 'min',
+ [gdal.CXT_Text, str(self.min_get(isource))]],
+ [gdal.CXT_Attribute, 'max',
+ [gdal.CXT_Text, str(self.max_get(isource))]]
+ ]
+
+ if self.nodata_get(isource) != -100000000.0:
+ src.append( [gdal.CXT_Attribute, 'nodata',
+ [gdal.CXT_Text, str(self.nodata_get(isource))]] )
+
+ raster = self.get_data(isource)
+ if raster is None:
+ src.append( [gdal.CXT_Attribute, 'constant',
+ [gdal.CXT_Text, str(self.get_const_value(isource))]] )
+ else:
+ src.append( [gdal.CXT_Attribute, 'band',
+ [gdal.CXT_Text, str(raster.get_band_number())]] )
+ v = raster.get_dataset().GetDescription()
+ if os.path.exists( v ):
+ src.append( [gdal.CXT_Attribute, 'portable_path',
+ [gdal.CXT_Text, pathutils.PortablePath( v, ref_path=filename ).serialize()]] )
+ src.append( [gdal.CXT_Text, v] )
+
+ layer.append( src )
+
+ return layer
+
+ def view_to_pixel(self, x, y ):
+ """Translate view coordinates to pixel/line.
+
+ x -- X (easting or longitude) in view georeferencing system.
+ y -- Y (northing or latitude) in view georeferencing system.
+
+ Returns a (pixel,line) coordinate tuple on the raster."""
+
+ return _gv.gv_raster_layer_view_to_pixel(self._o, x, y)
+
+ def pixel_to_view(self, x, y ):
+ """Translate pixel/line to view coordinate.
+
+ x -- pixel on raster layer (0.0 is left side of leftmost pixel)
+ y -- line on raster layer (0.0 is top side of topmost pixel)
+
+ Returns an (x,y) coordinate tuple in the view georeferencing
+ system."""
+
+ return _gv.gv_raster_layer_pixel_to_view(self._o, x, y)
+
+ def get_mode(self):
+ """Fetch the GvRasterLayer display mode.
+
+ It will be one of gview.RLM_SINGLE (greyscale or pseudocolored
+ raster band), gview.RLM_RGBA (RGBA composite from individual GvRaster
+ bands), or gview.RLM_COMPLEX (complex GvRaster pseudocolored with 2D
+ lookup table)."""
+ return _gv.gv_raster_layer_get_mode(self._o);
+
+ def get_mesh_lod(self):
+ return _gv.gv_raster_layer_get_mesh_lod(self._o)
+
+ def get_data(self, isource=0):
+ """Fetch the GvRaster for a source.
+
+ Note that gview.RLM_SINGLE mode has one source (isource=0),
+ gview.RLM_COMPLEX has one source, and gview.RLM_RGBA has four (red,
+ green, blue and alpha). Any source may be None indicating that
+ that source will use the constant value (see get_const_value()).
+
+ isource -- the source index (from 0 to 3).
+
+ """
+
+ data = _gv.gv_raster_layer_get_data(self._o, isource)
+ if data is not None:
+ return _gtk._obj2inst(data)
+ else:
+ return None
+
+ def source_get_lut(self, isource=0):
+ """Fetch the lut for a source
+
+ This fetches the pre-compositing lut applied to a source. It
+ will be None (if there isn't any in effect), or a String of 256
+ values between 0 and 255. Source lut's can only be set with
+ GvRasterLayer.set_source().
+
+ isource -- the source to fetch from."""
+ return _gv.gv_raster_layer_source_get_lut(self._o, isource);
+
+ def get_nodata(self, isource):
+ """Fetch NODATA value. DEPRECATED: use nodata_get()."""
+ return _gv.gv_raster_layer_get_nodata( self._o, isource )
+
+ def set_source(self, isource, data, min=None, max=None, const_value=0,
+ lut=None, nodata=None):
+ """Set a data source
+
+ Sets all the configuration information for one of the data sources
+ of a layer. This method will trigger a display-change signal if
+ any values are altered.
+
+ isource -- the source index (from 0 to 3)
+
+ data -- a GvRaster, or None if the source should be constant valued.
+
+ min -- the minimum value to use for scaling this raster to the
+ range 0-255. If min and max are defaulted they will be extracted
+ from the raster.
+
+ max -- the maximum value to use for scaling this raster to the
+ range 0-255. If min and max are defaulted they will be extracted
+ from the raster.
+
+ const_value -- Constant value to use in place of data if data is None.
+
+ lut -- Pre-compositing lookup table or None. If passed it must be
+ a string of exactly 256 characters mapping input values to output
+ values in the range 0-255.
+ """
+
+ if data is None:
+ data_o = None
+ else:
+ data_o = data._o
+
+ if (min is None) and (data is not None):
+ min = data.get_min()
+
+ if (max is None) and (data is not None):
+ max = data.get_max()
+
+ if( self.get_property("_scale_lock") is not None and
+ self.get_property("_scale_lock") == "locked" ) :
+
+ if( self.get_property("_scale_limits") is not None ) :
+ min, max = map \
+ ( string.atof,
+ string.split(self.get_property("_scale_limits"))
+ )
+
+ return _gv.gv_raster_layer_set_source(self._o, isource, data_o,
+ min, max, const_value, lut,
+ nodata )
+
+ def alpha_set(self, alpha_mode, alpha_check_val):
+ return _gv.gv_raster_layer_alpha_set(self._o, alpha_mode, alpha_check_val)
+
+ def alpha_get(self):
+ return _gv.gv_raster_layer_alpha_get( self._o )
+
+ def min_set(self,isource,min):
+ """Set the scaling minimum.
+
+ This will trigger a redraw via the display-change signal if it
+ changes the scaling value.
+
+ isource -- the source index (from 0 to 3).
+ min -- new minimum value for scaling.
+ """
+ return _gv.gv_raster_layer_min_set(self._o, isource, min )
+
+ def min_get(self,isource):
+ """Fetch the scaling minimum."""
+ return _gv.gv_raster_layer_min_get(self._o,isource)
+
+ def max_set(self,isource,max):
+ """Set the scaling maximum.
+
+ This will trigger a redraw via the display-change signal if it
+ changes the scaling value.
+
+ isource -- the source index (from 0 to 3).
+ max -- new maximum value for scaling.
+ """
+ return _gv.gv_raster_layer_max_set(self._o, isource, max)
+
+ def max_get(self,isource):
+ """Fetch the scaling maximum."""
+ return _gv.gv_raster_layer_max_get(self._o,isource)
+
+ def nodata_set(self,isource,real,imaginary):
+ """Set the NODATA value.
+
+ This will trigger a redraw via the display-change signal if it
+ changes the NODATA value.
+
+ isource -- the source index (from 0 to 3).
+ nodata -- new nodata value.
+ """
+ return _gv.gv_raster_layer_nodata_set(self._o,isource,real,imaginary)
+
+ def nodata_get(self,isource):
+ """Fetch the NODATA value."""
+ return _gv.gv_raster_layer_nodata_get(self._o,isource)
+
+ def type_get(self,isource):
+ """Fetch GDAL type of the raster object."""
+ return _gv.gv_raster_layer_type_get(self._o,isource)
+
+ def get_const_value(self,isource):
+ """Fetch source constant value"""
+ return _gv.gv_raster_layer_get_const_value(self._o,isource)
+
+ def zoom_set(self,mag_mode,min_mode):
+ """Set interpolation method
+
+ I believe mag_mode sets the interpolation mode when zooming in past
+ 1:1 on a texture, and min_mode is the interpolation mode used for
+ downsampling from the texture, but I am not sure. Both default to
+ bilinear, and are normally changed together.
+
+ mag_mode -- One of gview.RL_FILTER_BILINEAR or gview.RL_FILTER_NEAREST.
+ min_mode -- One of gview.RL_FILTER_BILINEAR or gview.RL_FILTER_NEAREST.
+ """
+ return _gv.gv_raster_layer_zoom_set( self._o, mag_mode, min_mode )
+
+ def zoom_get(self):
+ """Fetch zoom mode
+
+ Returns the mag_mode, and min_mode interploation modes as a tuple.
+ See also: zoom_set()"""
+
+ return _gv.gv_raster_layer_zoom_get(self._o)
+
+ def texture_clamp_set(self,s_mode,t_mode):
+ return _gv.gv_raster_layer_texture_clamp_set(self._o, mag_mode, min_mode )
+
+ def texture_mode_set(self,texture_mode,color):
+ """Set the texture mode.
+
+ The default mode is replace in which case the fragment color is
+ ignored. In modulate mode the raster is modulated with the
+ provided fragment color.
+
+ texture_mode -- gview.RL_TEXTURE_REPLACE or gview.GL_TEXTURE_MODULATE
+ color -- fragment color as an RGBA tuple."""
+ return _gv.gv_raster_layer_texture_mode_set(self._o, texture_mode,
+ color )
+
+ def texture_mode_get(self):
+ return _gv.gv_raster_layer_texture_mode_get(self._o)
+
+ def blend_mode_set(self,mode,sfactor=0,dfactor=0):
+ """Set blend mode
+
+ mode -- 0=off, non-0=on
+ sfactor -- ...
+ dfactor -- ..."""
+
+ return _gv.gv_raster_layer_blend_mode_set(self._o, mode, sfactor, dfactor )
+
+ def blend_mode_get(self):
+ return _gv.gv_raster_layer_blend_mode_get(self._o)
+
+ def lut_put(self,lut=None):
+ """Set the lut.
+
+ This method will reset the compositing lut on a rasterlayer. The lut
+ should be a string of 1024 bytes for a 1D LUT and 262144 bytes (as a
+ String) for a 2D LUT. The array should be stored in "RGBARGBA..."
+ format.
+
+ 2D LUTs should only be applied to layers in RLM_COMPLEX mode, and
+ 1D LUTs should only be applied to layers in RLM_SINGLE mode. It is
+ an error to apply luts in any other case.
+
+ lut -- the lut to set, stored as a string. None may be used to
+ clear the lut.
+ """
+ return _gv.gv_raster_layer_lut_put(self._o, lut)
+
+ def lut_get(self, rgba_complex=0):
+ """Fetch the lut.
+
+ The returned lut will be a string of 1024 bytes if 1D, or 262144 bytes
+ if the lut is 2D. The data is stored in "RGBARGBA..." format.
+
+ The rgba_complex variable is used to determine whether the
+ real or complex lut should be returned in the rgba case (this
+ mode supports both real and complex data). Use 0 for real
+ (default for backwards compatibility), 1 for complex. This
+ variable was added in case complex and real data are mixed within
+ a given RGBA layer, to allow access to either lut. If mixed
+ real/complex data are never going to be permitted, or if real
+ data within an RGBA layer never has an associated lut, rgba_complex
+ should probably be removed again and the type of lut returned should
+ be based on whether the first source of the layer contains real or
+ complex data.
+ """
+ return _gv.gv_raster_layer_lut_get(self._o, rgba_complex)
+
+ def lut_type_get(self):
+ """Fetch the LUT type.
+
+ Returns one of RL_LUT_NONE, RL_LUT_1D, or RL_LUT_2D (defined in
+ gvconst.py)."""
+ return _gv.gv_raster_layer_lut_type_get( self._o )
+
+ def lut_color_wheel_new(self,h_mode,h_param,s_mode,s_param,v_mode,v_param):
+ """Generate 2D LUT
+
+ Returns a lut suitable for applying to a RLM_COMPLEX layer with the
+ lut_put() method. See gvrasterpropdlg.py for an example of use of
+ this method.
+
+ h_mode -- one of the RL_LUT_* values indicating the source of the hue
+ component of the HLS color.
+
+ h_param -- if h_mode is RL_LUT_SCALAR this should be the constant hue
+ value between 0.0 and 1.0.
+
+ s_mode -- one of the RL_LUT_* values indicating the source of the
+ saturation component of the HLS color.
+
+ s_param -- if s_mode is RL_LUT_SCALAR this should be the constant
+ saturation value between 0.0 and 1.0.
+
+ v_mode -- one of the RL_LUT_* values indicating the source of the value
+ component of the HLS color.
+
+ v_param -- if v_mode is RL_LUT_SCALAR this should be the constant value
+ value between 0.0 and 1.0.
+ """
+ return _gv.gv_raster_layer_lut_color_wheel_new(self._o,h_mode,h_param,
+ s_mode,s_param,
+ v_mode,v_param)
+
+ def lut_color_wheel_new_ev(self,set_phase=1, set_magnitude=1):
+ """Generate 2D LUT
+
+ Applies a lut suitable for an RLM_COMPLEX layer with the
+ lut_put() method. See gvrasterpropdlg.py for an example of use of
+ this method. This method is similar to lut_color_wheel_new()
+ but is simplified and computes the 2D LUT based on looking up
+ within a standard phase color table (from EV) and using magnitude
+ to modulate the color.
+
+ set_phase -- One if varying phase is to be used to lookup the color
+ in a color table, or zero to use a fixed color of white.
+
+ set_magnitude -- One if magnitude is to be used to modify the
+ intensity of the selected color, or zero to use a constant magnitude
+ factor of 1.0.
+
+ """
+ return _gv.gv_raster_layer_lut_color_wheel_new_ev(self._o,
+ set_phase,
+ set_magnitude)
+
+ def lut_color_wheel_1d_new( self, s=1.0, v=1.0, offset=0.0 ):
+ return _gv.gv_raster_layer_lut_color_wheel_1d_new( self._o,s,v,offset)
+
+ def autoscale_view(self, alg = ASAAutomatic, alg_param = -1.0, isource=0 ):
+ """Force autoscaling to be recomputed.
+
+ alg -- Algorithm to use (see below)
+ alg_param -- the parameter to the algorithm, or -1.0 to get
+ default parameter value (possibly from preferences).
+ isource -- the GvRaster to get scaling for
+
+ This method will compute of scaling min/max values based on a sample
+ of the data in the current view for the selected source raster. The
+ algorithm information is the same as GvRaster.autoscale().
+
+ If the autoscale_view() method fails (for instance due to an IO error,
+ or if all the sample data is the nodata value) the method will throw an
+ exception otherwise a (min,max) tuple is returned.
+
+ """
+ return _gv.gv_raster_layer_autoscale_view(self._o, alg, alg_param,
+ isource)
+
+ def autoscale( self, alg = ASAAutomatic, alg_param = -1.0, isource=0,
+ viewonly = 0):
+ if viewonly == 0:
+ raster = self.get_data(isource)
+ if raster is None:
+ return (self.min_get(isource), self.max_get(isource))
+ else:
+ return raster.autoscale(alg, alg_param)
+
+ else:
+ try:
+ return self.autoscale_view(alg, alg_param, isource)
+ except:
+ return (self.min_get(isource), self.max_get(isource))
+
+ def histogram_view(self, isource = 0, scale_min = 0.0, scale_max = 255.0,
+ hist_size = 256 ):
+ """Compute histogram of viewed pixels.
+
+ isource -- the GvRaster to collect histogram from.
+ scale_min -- the min value to use when scaling to histogram buckets.
+ scale_max -- the max value to use when scaling to histogram buckets.
+ hist_size -- the number of histogram buckets to divide the range into.
+
+ This method will attempt to collect all the pixels in the current
+ view into a histogram. Note that all pixels values are read only from
+ the GvRaster cache (for speed), so missing tiles or tiles only
+ available at reduced levels of detail will be underrepresented.
+
+ In 2D the sampling identification of raster pixels should be exact
+ for unrotated and unwarped images, otherwise it will be based on the
+ bounding rectangle and so will include some extra pixels outside the
+ view. In 3D all tiles which appear to intersect the view will be
+ sampled, so potentially many pixels outside the view will be included
+ in the histogram.
+
+ The function returns a list object with histogram entry counts of
+ size hist_size, or an exception in the case of failure.
+
+ """
+ return _gv.gv_raster_layer_histogram_view(self._o, isource,
+ scale_min, scale_max,
+ hist_size )
+
+ def launch_properties(self):
+ import gvrasterpropdlg
+ return gvrasterpropdlg.LaunchRasterPropDialog( self )
+
+ def add_height(self, height_raster, default_height = 0.0):
+ """ Adds height to raster layer for 3D effect.
+
+ Georeferrencing information will be used to place height_raster
+ with respect to layer.
+
+ height_raster -- a GvRaster containing elevation information in a
+ compatible georeferencing system with this raster layer."""
+
+ # Actually add the height.
+
+ _gv.gv_raster_layer_add_height(self._o, height_raster._o,
+ default_height)
+
+ # In order to be able to reconstitute with elevation data,
+ # we need to store information about where the elevation came from.
+
+ self.set_property( '_gv_add_height_filename',
+ height_raster.get_dataset().GetDescription() )
+ self.set_property( '_gv_add_height_band',
+ str(height_raster.get_band_number()) )
+ self.set_property( '_gv_add_height_default',
+ str(default_height) )
+
+ def clamp_height(self, bclamp_min=0, bclamp_max=0,
+ min_height=-30000.0,max_height=30000.0):
+ """ Sets lower mesh height bound to min_height if bclamp_min is 1.
+ Sets upper mesh height bound to max_height if bclamp_max is 1. """
+
+ _gv.gv_raster_layer_clamp_height(self._o, bclamp_min, bclamp_max,
+ min_height, max_height)
+
+ def complex_lut(self, method='magnitude'):
+
+ # This property is set at c-level now.
+ #self.set_property( 'last_complex_lut', method )
+
+ # Magnitude
+ if method == 'magnitude':
+ self.lut_color_wheel_new_ev( 0, 1 )
+
+ # Phase
+ elif method == 'phase':
+ self.lut_color_wheel_new_ev( 1, 0 )
+
+ # Magnitude and Phase
+ elif method == 'magphase':
+ self.lut_color_wheel_new_ev( 1, 1 )
+
+ # Real
+ elif method == 'real':
+ self.lut_color_wheel_new( RL_LUT_SCALAR, -1,
+ RL_LUT_SCALAR, 0.75,
+ RL_LUT_REAL, 1 )
+
+ # Imaginary
+ elif method == 'imaginary':
+ self.lut_color_wheel_new( RL_LUT_SCALAR, -1,
+ RL_LUT_SCALAR, 0.75,
+ RL_LUT_IMAGINARY, 1 )
+
+ def equalize(self, viewonly = 0):
+ """Compute a histogram equalized source LUT, and apply.
+
+ This method is not meaningful for RLM_COMPLEX layers, and will
+ be ignored."""
+
+ for isrc in range(self.sources):
+ raster = self.get_data(isrc)
+ if raster is None:
+ continue
+
+ (smin, smax) = self.autoscale(viewonly=viewonly,isource=isrc)
+
+ if viewonly == 0:
+ gdal_band = raster.get_band()
+ histogram = gdal_band.GetHistogram(smin, smax, approx_ok = 1)
+ else:
+ try:
+ histogram = self.histogram_view(isrc, smin, smax, 256 )
+ except:
+ # normally this means we are "off" the raster.
+ continue
+
+ cum_hist = []
+ total = 0
+ for bucket in histogram:
+ cum_hist.append(total + bucket/2)
+ total = total + bucket
+
+ if total == 0:
+ total = 1
+ gdal.Debug( 'OpenEV',
+ 'Histogram total is zero in GvRasterLayer.equalize()' )
+
+ lut = ''
+ for i in range(256):
+ value = (cum_hist[i] * 256L) / total
+ if value < 0 :
+ value = 0
+ elif value >= 255:
+ value = 255
+ lut = lut + chr(value)
+
+ self.set_source(isrc, raster, smin, smax,
+ self.get_const_value(isrc), lut,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'equalize' )
+
+ def linear( self, viewonly = 0 ):
+
+ for isrc in range(self.sources):
+ (smin, smax) = self.autoscale( isource=isrc, viewonly = viewonly )
+
+ self.set_source(isrc, self.get_data(isrc), smin, smax,
+ self.get_const_value(isrc), None,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'linear' )
+
+ def none_lut( self, viewonly = 0 ):
+
+ for isrc in range(self.sources):
+ raster = self.get_data(isrc)
+ if raster is None:
+ continue
+
+ if raster.get_band().DataType == gdal.GDT_Byte:
+ (smin, smax) = (0.0, 255.0)
+ else:
+ (smin, smax) = self.autoscale( isource = isrc,
+ viewonly = viewonly )
+
+ self.set_source(isrc, self.get_data(isrc), smin, smax,
+ self.get_const_value(isrc), None,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'none_lut' )
+
+ def log( self, viewonly = 0 ):
+
+ import math
+
+ lut = ''
+ for i in range(256):
+ value = int((255 * (math.log(1.0+i) / math.log(256.0)))+0.5)
+ if value < 0 :
+ value = 0
+ elif value >= 255:
+ value = 255
+ lut = lut + chr(value)
+
+ for isrc in range(self.sources):
+ (smin, smax) = self.autoscale( isource=isrc, viewonly = viewonly )
+ self.set_source(isrc, self.get_data(isrc), smin, smax,
+ self.get_const_value(isrc), lut,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'log' )
+
+ def root( self, viewonly = 0 ):
+
+ import math
+
+ lut = ''
+ for i in range(256):
+ value = 255 * math.sqrt(i/255.0)
+ if value < 0 :
+ value = 0
+ elif value >= 255:
+ value = 255
+ lut = lut + chr(value)
+
+ for isrc in range(self.sources):
+ (smin, smax) = self.autoscale( isource=isrc, viewonly = viewonly )
+
+ self.set_source(isrc, self.get_data(isrc), smin, smax,
+ self.get_const_value(isrc), lut,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'root' )
+
+ def square( self, viewonly = 0 ):
+
+ import math
+
+ lut = ''
+ for i in range(256):
+ value = 255 * math.pow(i/255.0,2.0)
+ if value < 0 :
+ value = 0
+ elif value >= 255:
+ value = 255
+ lut = lut + chr(value)
+
+ for isrc in range(self.sources):
+ (smin, smax) = self.autoscale( isource=isrc, viewonly = viewonly )
+
+ self.set_source(isrc, self.get_data(isrc), smin, smax,
+ self.get_const_value(isrc), lut,
+ self.nodata_get(isrc))
+
+ self.set_property( 'last_stretch', 'square' )
+
+ def window_restretch(self):
+
+ # Re-apply the last stretch operation.
+ if self.get_property( 'last_stretch' ) != None:
+ func_name = 'self.'+ self.get_property('last_stretch')
+ else:
+ func_name = 'self.'+ 'linear'
+
+ exec 'func = ' + func_name in locals()
+
+ func( viewonly = 1 )
+
+ def get_height( self, x, y ):
+ """Fetch 3D mesh height at location
+
+ Returns the elevation as extracted from the mesh used for 3D
+ display at the indicated georeferenced location on this raster
+ layer. If the request fails for some reason (such as being off
+ the raster) an exception is generated.
+
+ x -- Georeferenced X location to sample at.
+ y -- Georeferenced Y location to sample at.
+ """
+ return _gv.gv_raster_layer_get_height( self._o, x, y )
+
+ def build_skirt( self, base_height = 0.0 ):
+ """Build a skirt around the edges of layer.
+
+ The skirt is basically edges dropping down from the edge of the
+ raster to some base height. The skirt generation knows about nodata
+ regions, and will also build skirts on their edges. The skirt is
+ coloured according to the location on the raster it is dropped from.
+
+ base_height -- elevation to which the skirt drops, defaults to 0.0.
+
+ The returned skirt is a GvLayer (currently a GvShapesLayer).
+ """
+ layer_o = _gv.gv_build_skirt( self._o, base_height )
+ if layer_o is not None:
+ return GvLayer( layer_o )
+ else:
+ return None
+
+ def refresh( self ):
+ """Refresh raster data from disk."""
+ for isource in range(4):
+ raster = self.get_data(isource)
+ if raster is not None:
+ raster.changed()
+
+###############################################################################
+class GvTool(_gtk.GtkObject):
+ get_type = _gv.gv_tool_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+
+ def activate(self, view):
+ _gv.gv_tool_activate(self._o, view._o)
+
+ def deactivate(self, view):
+ _gv.gv_tool_deactivate(self._o, view._o)
+
+ def get_view(self):
+ v_o = _gv.gv_tool_get_view(self._o)
+ if v_o is None:
+ return None
+ else:
+ return GvViewArea(_obj=v_o)
+
+ def set_boundary(self, boundary):
+ """Set constraint rectangle.
+
+ boundary -- boundary is a tuple in the form (column,row,width,height)
+ """
+ return _gv.gv_tool_set_boundary(self._o, boundary)
+
+ def set_cursor(self, cursor_type):
+ """ Set the tool's associated cursor.
+
+ cursor_type -- an integer (one of the standard GDK cursor types)
+ """
+ return _gv.gv_tool_set_cursor(self._o, cursor_type)
+
+
+###############################################################################
+class GvSelectionTool(GvTool):
+ get_type = _gv.gv_selection_tool_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_selection_tool_new()
+ def set_layer(self, layer):
+ _gv.gv_selection_tool_set_layer(self._o, layer._o)
+
+###############################################################################
+class GvZoompanTool(GvTool):
+ get_type = _gv.gv_zoompan_tool_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_zoompan_tool_new()
+
+###############################################################################
+class GvPointTool(GvTool):
+ get_type = _gv.gv_point_tool_get_type
+ def __init__(self, layer=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_point_tool_new()
+ if layer: self.set_named_layer(layer)
+ def set_layer(self, layer):
+ _gv.gv_point_tool_set_layer(self._o, layer._o)
+ def set_named_layer(self, name):
+ _gv.gv_point_tool_set_named_layer(self._o, name)
+
+###############################################################################
+class GvLineTool(GvTool):
+ get_type = _gv.gv_line_tool_get_type
+ def __init__(self, layer=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_line_tool_new()
+ if layer: self.set_named_layer(layer)
+ def set_layer(self, layer):
+ _gv.gv_line_tool_set_layer(self._o, layer._o)
+ def set_named_layer(self, name):
+ _gv.gv_line_tool_set_named_layer(self._o, name)
+
+###############################################################################
+class GvRectTool(GvTool):
+ get_type = _gv.gv_rect_tool_get_type
+ def __init__(self, layer=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_rect_tool_new()
+ if layer: self.set_named_layer(layer)
+ def set_layer(self, layer):
+ _gv.gv_rect_tool_set_layer(self._o, layer._o)
+ def set_named_layer(self, name):
+ _gv.gv_rect_tool_set_named_layer(self._o, name)
+
+###############################################################################
+class GvRotateTool(GvTool):
+ get_type = _gv.gv_rotate_tool_get_type
+ def __init__(self, layer=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_rotate_tool_new()
+ if layer: self.set_named_layer(layer)
+ def set_layer(self, layer):
+ _gv.gv_rotate_tool_set_layer(self._o, layer._o)
+ def set_named_layer(self, name):
+ _gv.gv_rotate_tool_set_named_layer(self._o, name)
+
+###############################################################################
+class GvAreaTool(GvTool):
+ get_type = _gv.gv_area_tool_get_type
+ def __init__(self, layer=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_area_tool_new()
+ if layer: self.set_named_layer(layer)
+ def set_layer(self, layer):
+ _gv.gv_area_tool_set_layer(self._o, layer._o)
+ def set_named_layer(self, name):
+ _gv.gv_area_tool_set_named_layer(self._o, name)
+
+###############################################################################
+class GvNodeTool(GvTool):
+ get_type = _gv.gv_node_tool_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_node_tool_new()
+ def set_layer(self, layer):
+ _gv.gv_node_tool_set_layer(self._o, layer._o)
+
+###############################################################################
+class GvRoiTool(GvTool):
+ """Region of Interest Selection Tool
+
+ Signals:
+
+ roi-changing -- generated when the ROI is being rubber-banded and
+ coordinates are changing
+
+ roi-changed -- generated when the ROI has been changed and not currently
+ being modified.
+ """
+
+ get_type = _gv.gv_roi_tool_get_type
+ def __init__(self, boundary=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_roi_tool_new()
+ if boundary: self.set_boundary(boundary)
+ def get_rect(self):
+ """ Returns the current ROI """
+ return _gv.gv_roi_tool_get_rect(self._o)
+ def append(self, rect):
+ """ Creates an ROI.
+
+ rect -- a tuple (column, row, width, height)
+ """
+ return _gv.gv_roi_tool_new_rect(self._o, rect)
+
+###############################################################################
+class GvPoiTool(GvTool):
+ """Point of Interest Selection Tool
+
+ Signals:
+
+ poi-changed -- generated when the POI has been changed.
+ """
+
+ get_type = _gv.gv_poi_tool_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_poi_tool_new()
+
+ def get_point(self):
+ """ Returns the current POI """
+ return _gv.gv_poi_tool_get_point(self._o)
+
+ def set_point(self, point):
+ """ Sets the current POI.
+
+ point -- a tuple (column, row)
+ """
+ return _gv.gv_poi_tool_new_point(self._o, point)
+
+###############################################################################
+class GvTrackTool(GvTool):
+ get_type = _gv.gv_track_tool_get_type
+ def __init__(self, label=None, _obj=None):
+ if _obj: self._o = _obj; return
+ if label is None:
+ raise ValueError, "expecting GtkLabel instance"
+ self._o = _gv.gv_track_tool_new(label._o)
+
+###############################################################################
+class GvToolbox(GvTool):
+ get_type = _gv.gv_toolbox_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_toolbox_new()
+ def add_tool(self, name, tool):
+ _gv.gv_toolbox_add_tool(self._o, name, tool._o)
+ def activate_tool(self, name):
+ _gv.gv_toolbox_activate_tool(self._o, name)
+
+
+###############################################################################
+class GvAutopanTool(GvTool):
+ """Autopan Tool
+
+ Signals:
+
+ """
+
+ get_type = _gv.gv_autopan_tool_get_type
+ def __init__(self, boundary=None, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_autopan_tool_new()
+ if boundary: self.set_boundary(boundary)
+
+ def set_extents(self, rect):
+ """ Sets the panning extents.
+
+ rect -- a tuple (column, row, width, height)
+ """
+ return _gv.gv_autopan_tool_new_rect(self._o, rect)
+
+ def get_extents(self):
+ """ Gets the panning extents.
+ Returns a tuple (column, row, width, height)
+ """
+ return _gv.gv_autopan_tool_get_rect(self._o)
+
+ def play(self):
+ """ Start panning. """
+ return _gv.gv_autopan_tool_play(self._o)
+
+ def pause(self):
+ """ Pause panning. Regions remain drawn in secondary views."""
+ return _gv.gv_autopan_tool_pause(self._o)
+
+ def stop(self):
+ """ Stop panning. Regions do not remain drawn in secondary views."""
+ return _gv.gv_autopan_tool_stop(self._o)
+
+ def set_speed(self, speed):
+ """ Set the relative speed (a value between -1 and 1: -1
+ for maximum speed backwards; 1 for maximum speed
+ forwards).
+ """
+ return _gv.gv_autopan_tool_set_speed(self._o, speed)
+
+ def get_speed(self):
+ """ Returns the current speed setting. """
+
+ return _gv.gv_autopan_tool_get_speed(self._o)
+
+ def set_overlap(self, overlap):
+ """ Set block overlap perpendicular to panning direction
+ (a value between 0 and 1).
+ """
+ return _gv.gv_autopan_tool_set_overlap(self._o, overlap)
+
+ def get_overlap(self):
+ """ Returns the current overlap setting. """
+ return _gv.gv_autopan_tool_get_overlap(self._o)
+
+ def set_block_x_size(self, xsize, mode):
+ """ Set size of high-resolution block.
+ Inputs:
+ xsize- width of block, as a fraction of the
+ full panning region width if mode == 0
+ (in this case 0 < xsize < 1), or in
+ view coordinates if mode == 1.
+ mode- block size setting mode.
+ """
+ return _gv.gv_autopan_tool_set_block_x_size(self._o, xsize, mode)
+
+ def set_x_resolution(self, resolution):
+ """ Set the resolution of the zoomed extents:
+ Inputs:
+ resolution- view resolution
+ """
+ return _gv.gv_autopan_tool_set_x_resolution(self._o, resolution)
+
+ def set_standard_path(self, path_type):
+ """ Set the standard path to follow in panning:
+ Inputs:
+ path_type- an integer (0-4, currently)
+
+ 0- start top left, go right, down, left, down,...
+ 1- start bottom left, go right, up, left, up,...
+ 2- start top right, go left, down, right, down,...
+ 3- start bottom right, go left, up, left, up,...
+ 4- start top left, go right, jump down and back
+ to the left edge, go right,...
+ """
+ return _gv.gv_autopan_tool_set_standard_path(self._o, path_type)
+
+ def set_lines_path(self, lines):
+ """ Sets the path to follow based on a GvShapes object
+ that contains line shapes.
+ """
+ return _gv.gv_autopan_tool_set_lines_path(self._o, lines._o)
+
+ def set_location(self, x, y):
+ """ Set the current location within the panning
+ extents (snaps to nearest computed location).
+ """
+ # z is in case we ever do anything with 3d panning, but
+ # for now only 2d has been considered.
+ return _gv.gv_autopan_tool_set_location(self._o,x,y,0)
+
+ def get_location(self):
+ """ Get the current location within the panning extents.
+ Raises an error if there is no current location.
+ """
+ return _gv.gv_autopan_tool_get_location(self._o)
+
+ def get_state(self):
+ """ Gets the current settings of the following autopan
+ tool parameters (returned as a tuple):
+
+ play_flag: 0- stopped, 1- playing, 2- paused
+
+ path_type: 0- starts top left, goes right, down, left...
+ 1- starts bottom left, goes right, up, left...
+ 2- starts top right, goes left, down, right...
+ 3- starts bottom right, goes left, up, right...
+
+
+ block_size_mode, block_x_size, resolution:
+ block_size_mode = 0:
+ - user sets block_x_size to a float between 0 and 1,
+ corresponding to the block size as a fraction of the
+ total x extents (block_y_size will be determined by
+ block_x_size and the window's aspect ratio).
+ resolution is ignored in this mode.
+
+ block_size_mode = 1:
+ - same as mode 0, except that block_x_size is in view
+ coordinates rather than a fraction of total x extents
+ to be panned.
+
+ block_size_mode = 2:
+ - block size is set so that the size of pixels in the
+ view will be constant at resolution.
+
+ num_views: number of secondary views associated with
+ the tool.
+ """
+ return _gv.gv_autopan_tool_get_state(self._o)
+
+ def clear_trail(self):
+ """ Clear the stored trail and refresh secondary views. """
+ return _gv.gv_autopan_tool_clear_trail(self._o)
+
+ def set_trail_color(self, view, red, green, blue, alpha):
+ """ Set the trail color for a secondary view.
+
+ Inputs:
+ view- view to reset the trail color of.
+ red, green, blue, alpha- floating point values in
+ the range 0-1.
+ """
+ return _gv.gv_autopan_tool_set_trail_color(self._o, view._o, red,
+ green, blue, alpha)
+
+ def set_trail_mode(self, view, trail_mode):
+ """ Set whether or not to display a trail in a secondary
+ view.
+
+ Inputs:
+ view- view to reset the trail mode on.
+ trail_mode- integer 0 or 1.
+ """
+ return _gv.gv_autopan_tool_set_trail_mode(self._o, view._o, trail_mode)
+
+ def set_trail_parameters(self, overview_extents, overview_width_pixels):
+ """ Set the rough predicted extents that the trail will cover, and
+ the width that this should correspond to in screen pixels. """
+ return _gv.gv_autopan_tool_set_trail_parameters(self._o,
+ overview_extents,
+ overview_width_pixels)
+
+ def get_trail_parameters(self):
+ """ Get the trail parameters and number of trail tiles.
+
+ Returns a tuple (extents,width,num tiles):
+ extents, width- parameters used to decide trail tile
+ coverage and resolution (see
+ set_trail_parameters)
+ num tiles- number of trail tiles created so far.
+ """
+ tup = _gv.gv_autopan_tool_get_trail_parameters(self._o)
+ return ((tup[0],tup[1],tup[2],tup[3]),tup[4],tup[5])
+
+
+ def save_trail_tiles(self, basename):
+ """ Saves trail tiles to files named basename+'0',
+ basename+'1', etc. Returns the number of tiles saved
+ (-1 if an error occured). Tiles are always saved
+ to Geotiff format (requires metadata capability).
+ """
+ return _gv.gv_autopan_tool_save_trail_tiles(self._o,
+ basename)
+
+ def load_trail_tiles(self, basename, num_trail_tiles):
+ """ Loads trail tiles from files named basename+'0',
+ basename+'1', etc., up to basename+str(num_trail_tiles-1)
+ Returns the number of tiles loaded
+ (-1 if an error occured).
+ """
+ return _gv.gv_autopan_tool_load_trail_tiles(self._o,
+ basename,
+ num_trail_tiles)
+
+ def register_view(self, view, can_resize=0, can_reposition=0,
+ trail_mode=0):
+ """ Register a secondary view. Current panning extents will
+ be drawn as a blue-green rectangle in this view.
+ Inputs:
+ view- view to register
+ can_resize- integer 0 or 1: 1 if user can resize the
+ current panning block size by banding
+ the rectangle in the secondary view, 0
+ if they can't. NOT IMPLEMENTED YET: set
+ to 0.
+ can_reposition- integer 0 or 1: 1 if user can reposition the
+ current panning block size by dragging
+ the rectangle in the secondary view, 0
+ if they can't.
+ trail_mode- integer 0 or 1: 0 if view should not show
+ trail already traveled; 1 if it should.
+ """
+ return _gv.gv_autopan_tool_register_view(self._o, view._o,
+ can_resize, can_reposition,
+ trail_mode)
+
+ def remove_view(self, view):
+ """ De-register a secondary view. """
+ return _gv.gv_autopan_tool_remove_view(self._o, view)
+
+
+###############################################################################
+class GvViewLink(_gtk.GtkObject):
+ get_type = _gv.gv_view_link_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_view_link_new()
+ def register_view(self, view):
+ _gv.gv_view_link_register_view(self._o, view._o)
+ def remove_view(self, view):
+ _gv.gv_view_link_remove_view(self._o, view._o)
+ def enable(self):
+ _gv.gv_view_link_enable(self._o)
+ def disable(self):
+ _gv.gv_view_link_disable(self._o)
+ def set_cursor_mode(self,mode=0):
+ try:
+ _gv.gv_view_link_set_cursor_mode(self._o,mode)
+ except:
+ pass
+
+###############################################################################
+class GvSymbolManager(_gtk.GtkObject):
+ get_type = _gv.gv_symbol_manager_get_type
+
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_get_symbol_manager()
+
+ def get_symbol( self, name ):
+ result = _gv.gv_symbol_manager_get_symbol( self._o, name )
+ if result is not None and result[0] == 1:
+ result = (result[0], GvShape( _obj = result[1] ) )
+
+ return result
+
+ def has_symbol( self, name ):
+ return _gv.gv_symbol_manager_has_symbol( self._o, name )
+
+ def get_names( self ):
+ return _gv.gv_symbol_manager_get_names( self._o )
+
+ def inject_raster_symbol( self, name, width, height, rgba_buffer ):
+ _gv.gv_symbol_manager_inject_raster_symbol( self._o, name,
+ width, height, rgba_buffer)
+
+ def inject_vector_symbol( self, name, shape ):
+ _gv.gv_symbol_manager_inject_vector_symbol( self._o, name, shape._o )
+
+ def eject_symbol( self, name ):
+ return _gv.gv_symbol_manager_eject_symbol( self._o, name )
+
+ def save_vector_symbol( self, name, newname ):
+ _gv.gv_symbol_manager_save_vector_symbol( self._o, name, newname )
+
+ def serialize( self ):
+ tree = [gdal.CXT_Element, 'GvSymbolManager']
+
+ names = self.get_names()
+
+ for name in names:
+ sym = self.get_symbol( name )
+ if sym[0] == 0:
+ print 'rasters symbol serialization not yet supported.'
+
+ elif sym[0] == 1:
+ vs = [CXT_Element, 'GvVectorSymbol',
+ [CXT_Attribute, 'name',
+ [CXT_Text, name]]]
+ vs.append( sym[1].serialize() )
+ tree.append( vs )
+ else:
+ print 'unsupported symbol type, not serialized'
+
+ return tree
+
+ def initialize_from_xml( self, tree, filename=None ):
+ for item in tree[2:]:
+ if item[0] == CXT_Element and item[1] == 'GvVectorSymbol':
+ name = gvutils.XMLFindValue(item, 'name', None )
+ shape = GvShapeFromXML( gvutils.XMLFind( item, 'GvShape' ), None )
+ self.inject_vector_symbol( name, shape )
+
+###############################################################################
+class GvManager(_gtk.GtkObject):
+ get_type = _gv.gv_manager_get_type
+ def __init__(self, _obj=None):
+ if _obj: self._o = _obj; return
+ self._o = _gv.gv_get_manager()
+
+ def add_dataset(self, dataset):
+ """Adds gdal.Dataset instance to the list of managed datasets.
+
+ This method adds given gdal.Dataset instance to the list of available
+ datasets. Does nothing if this dataset already listed.
+
+ Returns a gdal.Dataset object (the same as given in parameters)."""
+
+ swig_ds = _gv.gv_manager_add_dataset(self._o, dataset._o)
+ if swig_ds is None:
+ return None
+
+ return gdal.Dataset( _obj=swig_ds )
+
+ def get_dataset(self, filename):
+ """Fetch gdal.Dataset for a filename.
+
+ This method fetches a gdal.Dataset for a given filename, while
+ ensuring that the dataset is only opened once, even if requested
+ more than once.
+
+ Returns an opened gdal.Dataset object."""
+
+ swig_ds = _gv.gv_manager_get_dataset(self._o, filename)
+ if swig_ds is None:
+ return None
+
+ return gdal.Dataset( _obj=swig_ds )
+
+ def get_dataset_raster(self,dataset,band):
+ """Fetch GvRaster for a dataset band.
+
+ This method fetches a GvRaster for a given dataset band, while
+ ensuring that only one GvRaster is instantiated for the band
+ across the whole application. """
+
+ raster_o = _gv.gv_manager_get_dataset_raster(self._o, dataset._o,band)
+ if raster_o is None:
+ return None
+
+ return GvRaster(_obj=raster_o)
+
+ def set_busy( self, busy_flag ):
+ _gv.gv_manager_set_busy( self._o, busy_flag )
+
+ def get_busy( self ):
+ return _gv.gv_manager_get_busy( self._o )
+
+ def queue_task( self, task_name, priority, cb, cb_data = None ):
+ """Queue an idle task.
+
+ The GvManager has a concept of a unified, prioritized set of idle
+ tasks. These are only executed when there is no further pending
+ user input, or windows events to process, and are typically used to
+ perform low priority work like loading additional tiles in GvRasters
+ for display purposes.
+
+ This mechanism can also be used by the application level, for
+ instance, to update the gui, or perform chunks of processing.
+
+ Note that there is no mechanism available to remove a task from
+ the queue untill it is actually executed. Items in the list can be
+ dumped to stderr with the GvManager.dump() call for debugging purposes.
+
+ The OpenEV core currently has three idle tasks which may be queued:
+
+ - zoompan-handler (priority 2): used to implement continuous zooming.
+ - 3d-motion-handler (priority 2): similar to zoompan-handler for 3d.
+ - raster-layer-update (priority 10): used to load, and process
+ additional raster tiles.
+
+ Note that the return value of the user callback is examined to
+ determine if the task should be requeued automatically. A value
+ of zero indicates that the task should not be requeued, while any
+ other numeric value results in automatic requeuing.
+
+ task_name -- name for task, useful in debugging.
+ priority -- numeric priority. Higher values have lower priority.
+ cb -- python callback to invoke
+ cb_data -- single argument to pass to callback (optional).
+ """
+
+ _gv.gv_manager_queue_task( self._o, task_name, priority, cb, cb_data )
+
+ def dump( self ):
+ """Dump GvManager info to stderr.
+
+ The list of preferences, openev datasets, and idle tasks is written
+ to stderr in human readable format. Useful as a debugging aid.
+ """
+ _gv.gv_manager_dump( self._o )
+
+
+###############################################################################
+def undo_register(data):
+ """Register GvData for undo.
+
+ data -- GvData to be registered.
+
+ This call registers the passed GvData with the undo system. As long
+ as it exists, and the undo system is enabled any changes to it will
+ be recorded for undo. There is no way to unregister an individual GvData
+ once registered."""
+ _gv.gv_undo_register_data(data._o)
+
+
+###############################################################################
+def can_undo():
+ """Returns TRUE if undo system is enabled."""
+ return _gv.gv_undo_can_undo()
+
+
+###############################################################################
+def undo_pop():
+ """Undo the most recent undo group."""
+ _gv.gv_undo_pop();
+
+###############################################################################
+def undo_clear():
+ """Destroy all saved undo steps."""
+ _gv.gv_undo_clear();
+
+###############################################################################
+def undo_close():
+ """Temporarily disable capture of undo steps."""
+ _gv.gv_undo_close();
+
+###############################################################################
+def undo_open():
+ """Enable capture of undo steps."""
+ _gv.gv_undo_open();
+
+###############################################################################
+def undo_start_group():
+ """Establish a multi operation undo group.
+
+ All undo operations saved to the undo stack after this call, and
+ before the next undo_end_group() call will be considered to be a single
+ group. A single call to undo_pop() will cause the entire group of
+ undo steps to be applied.
+
+ This is normally used to group multiple underlying operations that
+ should appear to be a single operation to the user.
+
+ Returns the undo group integer identifier. This should be kept and
+ passed to the undo_end_group() method to terminate the grouping."""
+ return _gv.gv_undo_start_group()
+
+###############################################################################
+def undo_end_group( group ):
+ """Close off a multi operation undo group.
+
+ group -- the group id to be terminated. This should be the value
+ returned by the corresponding undo_start_group()."""
+ return _gv.gv_undo_end_group( group )
+
+
+
+###############################################################################
+# Manage Application Properties:
+
+app_preferences = None
+app_preffile = None
+
+def set_default_preferences( defaults ):
+ """
+ add a set of default preferences to the gview preference manager if they are not already
+ loaded.
+
+ defaults - a dictionary of pref_name = default_value pairs.
+
+ this checks to make sure that the preferences are already loaded.
+ """
+ global app_preferences
+
+ if app_preferences is None:
+ load_preferences()
+ for key in defaults.keys():
+ if get_preference(str(key)) is None:
+ set_preference( str(key), str(defaults[key]))
+
+
+def get_preference(name, default = None):
+ """Fetch preference value
+
+ This method will return a String value, or None if the preference is
+ unknown.
+
+ name -- the name of the preference to fetch.
+ """
+ global app_preferences
+
+ if app_preferences is None:
+ load_preferences()
+
+ res = _gv.gv_manager_get_preference(manager._o,name)
+ if res is None:
+ return default
+ else:
+ return res
+
+def set_preference(name,value):
+ """Set preference value
+
+ This method will set the preference value in a global application list,
+ which will be saved on application shutdown in the $HOME/.openev file,
+ and restore on subsequent startups.
+
+ name -- preference name (String)
+ value -- preference value (String)
+ """
+ global app_preferences
+
+ if app_preferences is None:
+ load_preferences()
+
+ return _gv.gv_manager_set_preference(manager._o,name,value)
+
+def load_preferences():
+ global app_preferences
+
+ app_preferences = {}
+
+ if not os.path.exists(get_preffile()):
+ return
+
+ file = open(get_preffile(),'r')
+ contents = file.readlines()
+ file.close()
+
+ for line in contents:
+ tokens = string.split(line, '=', 1)
+ if len(tokens) == 2:
+ name,value = tokens
+ set_preference( string.strip(name), string.strip(value) )
+
+def save_preferences():
+ global app_preferences
+
+ if app_preferences is None:
+ return
+
+ prefs = _gv.gv_manager_get_preferences(manager._o)
+
+ if not os.path.exists(os.path.dirname(get_preffile())):
+ return
+
+ file = open(get_preffile(), 'w')
+ for item in prefs.items():
+ name, value = item
+ file.write(name + '=' + value + '\n')
+ file.close()
+
+def get_preffile():
+ global app_preffile
+
+ if app_preffile is None:
+ app_preffile = os.path.expanduser('~/.openev')
+ if app_preffile == '\\/.openev' or app_preffile == '~/.openev':
+ app_preffile = 'C:\\.openev'
+
+ return app_preffile
+
+
+###############################################################################
+def find_gview():
+ try:
+ gv_path = os.environ['OPENEV_HOME']
+ if os.path.isdir(os.path.join(gv_path,'pics')):
+ return gv_path
+ except:
+ pass
+
+ try:
+ gv_path = os.environ['OPENEVHOME']
+ if os.path.isdir(os.path.join(gv_path,'pics')):
+ return gv_path
+ except:
+ pass
+
+ for dir in sys.path:
+ gv_path = os.path.normpath(os.path.join(dir,'..'))
+ if os.path.isdir(os.path.join(gv_path,'pics')):
+ return gv_path
+
+ gv_path = os.path.expanduser('~/devel/gview')
+ if os.path.isdir(os.path.join(gv_path,'pics')):
+ return gv_path
+
+ gv_path = os.path.dirname(os.path.abspath(sys.argv[0]))
+ if os.path.isdir(os.path.join(gv_path,'pics')):
+ return gv_path
+
+ print 'Unable to find OpenEV tree ... some problems may be encountered.'
+ return ''
+
+###############################################################################
+def raster_cache_get_max():
+ return _gv.gv_raster_cache_get_max()
+
+def raster_cache_set_max(new_max):
+ _gv.gv_raster_cache_set_max(new_max)
+
+def raster_cache_get_used():
+ return _gv.gv_raster_cache_get_used()
+
+def texture_cache_get_max():
+ return _gv.gv_texture_cache_get_max()
+
+def texture_cache_set_max(new_max):
+ _gv.gv_texture_cache_set_max(new_max)
+
+def texture_cache_get_used():
+ return _gv.gv_texture_cache_get_used()
+
+def texture_cache_dump():
+ return _gv.gv_texture_cache_dump()
+
+###############################################################################
+
+def rgba_to_rgb(rgba):
+ #Convert RGBA data to RGB.
+ #
+ #This function is used to accelerate conversion of RGBA LUTs into RGB
+ #so that they can be displayed in a GtkPreview. Currently only used by
+ #gvrasterpropdlg.py.
+ return _gv.gv_rgba_to_rgb(rgba)
+
+###############################################################################
+
+def gtk_object_deref_and_destroy(object):
+ _gtkmissing.gtk_object_deref_and_destroy(object._o)
+
+def gtk_object_get_ref_count(object):
+ return _gtkmissing.gtk_object_get_ref_count(object._o)
+
+def gtk_object_sink(object):
+ return _gtkmissing.gtk_object_sink(object._o)
+
+def gtk_object_ref(object):
+ return _gtkmissing.gtk_object_ref(object._o)
+
+def gtk_object_unref(object):
+ return _gtkmissing.gtk_object_ref(object._o)
+
+def py_object_get_ref_count(object):
+ return _gtkmissing.py_object_get_ref_count(object)
+
+pgu.gtk_register('IpGcpLayer', IpGcpLayer)
+pgu.gtk_register('AppCurLayer', AppCurLayer)
+for m in map(lambda x: eval(x), filter(lambda x: x[:2] == 'Gv', dir())):
+ if m != 'GvShape':
+ pgu.gtk_register(m.__name__,m)
+
+del m
+
+manager = GvManager(_obj = _gv.gv_get_manager())
+get_preference('test')
+
+"""Home directory of OpenEV tree for purposes of finding icons, online help,
+etc"""
+home_dir = find_gview()
+
+if get_preference('gdal_cache') != None:
+ import gdal
+ gdal.SetCacheMax( int(get_preference('gdal_cache')) )
+else:
+ gdal.SetCacheMax( 12582912 )
+
+if get_preference('gvraster_cache') != None:
+ raster_cache_set_max( int(get_preference('gvraster_cache')) )
+else:
+ raster_cache_set_max( 39845888 )
+
+if get_preference('texture_cache') != None:
+ texture_cache_set_max( int(get_preference('texture_cache')) )
+else:
+ texture_cache_set_max( 33554432 )
Added: packages/openev/branches/upstream/current/pymod/gviewapp.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gviewapp.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gviewapp.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2162 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gviewapp.py,v 1.29 2005/10/17 18:21:13 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: GViewApp and related definitions.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gviewapp.py,v $
+# Revision 1.29 2005/10/17 18:21:13 gmwalter
+# Force proper locale.
+#
+# Revision 1.28 2004/09/26 01:31:42 warmerda
+# added project to rfl list after open.
+#
+# Revision 1.27 2004/07/02 16:40:51 dem
+# - Implement project files portability
+# - last_strech restored in projects reloading
+# - add a "File/Save Project as..." menu
+#
+# Revision 1.26 2004/04/21 14:35:25 andrey_kiselev
+# New option: save last visited directory.
+#
+# Revision 1.25 2004/02/18 18:00:10 warmerda
+# Fixed return in save_project() as per Julien's note.
+#
+# Revision 1.24 2004/02/12 16:56:41 andrey_kiselev
+# Comment out gvenhdlg.
+#
+# Revision 1.23 2004/02/10 15:51:27 andrey_kiselev
+# Added open_gdal_dataset method.
+#
+# Revision 1.22 2004/01/22 19:52:10 andrey_kiselev
+# New switch to control displaying "[NODATA]" marks in the tracker tool. Tweaks
+# in 'Preferences' dialog.
+#
+# Revision 1.21 2003/09/12 18:31:28 pgs
+# updated preference dialog with legend preferences
+#
+# Revision 1.20 2003/07/28 19:42:33 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.19 2003/06/25 17:52:08 warmerda
+# added rotate tool
+#
+# Revision 1.18 2003/03/12 19:50:01 gmwalter
+# Add cursor type preference.
+#
+# Revision 1.17 2003/02/20 19:27:20 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.16 2003/01/24 15:44:29 warmerda
+# browse command may be None if browser not found
+#
+# Revision 1.15 2002/12/12 07:42:14 warmerda
+# added gvcorecmds to pyshell
+#
+# Revision 1.14 2002/11/04 21:08:56 warmerda
+# added float() locale check when starting up app
+#
+# Revision 1.13 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.12 2002/07/11 01:05:26 warmerda
+# fix bug in save_project
+#
+# Revision 1.11 2002/07/08 19:46:03 warmerda
+# added project save/load capability
+#
+# Revision 1.10 2002/07/07 21:06:14 warmerda
+# preliminary addition of project saving
+#
+# Revision 1.9 2002/05/16 15:04:38 warmerda
+# ensure there is a graceful recovery if there is no tools directory
+#
+# Revision 1.8 2002/05/08 17:57:38 gmwalter
+# Fixed close_all_views to unsubscribe from the main app's 'rfl-change'
+# signal before destroying themselves.
+#
+# Revision 1.7 2002/04/25 15:19:58 gmwalter
+# Updated the menu extension mechanism to get rid of the extend_menu function and to allow the help menu to remain on the right side of the menubar. Got rid of some extra print statements and the gnuplot 0 y-range warning in the histogram tool initialization.
+#
+# Revision 1.6 2002/04/18 20:35:15 warmerda
+# Added ability to auto-load tools
+#
+# Revision 1.5 2002/04/12 14:20:29 gmwalter
+# Added functions to clamp and scale gvmesh z values.
+#
+# Revision 1.4 2002/03/23 20:03:05 gmwalter
+# Added changes to allow plotting on windows (i.e. specify the temporary
+# file as a preference rather than relying on os.tempnam(), check that
+# unix-style filenames are passed to gnuplot).
+#
+# Revision 1.3 2002/02/28 18:52:22 gmwalter
+# Added a point-of-interest tool similar to the region-of-interest
+# tool (allows a user to select a temporary point without having to add a
+# new layer). Added a mechanism to allow some customization of openev
+# via a textfile defining external modules.
+#
+# Revision 1.2 2001/11/14 22:35:28 warmerda
+# added import of plot from gvplot for pyshell
+#
+# Revision 1.1 2001/11/12 18:43:31 warmerda
+# New
+#
+
+from gvsignaler import Signaler
+import gtk
+from gtk import FALSE, TRUE
+from GDK import *
+import gtkmissing
+import sys
+import GtkExtra
+import gview
+import gvconst
+import layerdlg
+#import gvenhdlg
+import gdal
+import gvutils
+import os
+import os.path
+import pgufilesel
+import pguprogress
+import math
+import gvviewwindow
+import gvhtml
+import gvselbrowser
+import sys
+import traceback
+
+# Force standard c settings for floating point (. rather than ,)
+import locale
+locale.setlocale(locale.LC_NUMERIC,'C')
+
+import pgufont
+default_font = pgufont.XLFDFontSpec()
+default_font.set_font_part('Family', 'Arial')
+default_font.set_font_part('Point Size', '120')
+
+default_preferences = {
+ 'legend-background-color': (1.0, 1.0, 1.0, 1.0),
+ 'legend-label-font': default_font,
+ 'legend-label-font-color': (0.0, 0.0, 0.0, 1.0),
+ 'legend-title-font': default_font,
+ 'legend-title-font-color': (0.0, 0.0, 0.0, 1.0),
+ 'default-font': default_font,
+}
+
+gview.set_default_preferences( default_preferences )
+
+class GViewApp(Signaler):
+ def __init__(self,toolfile=None,menufile=None,iconfile=None,pyshellfile=None,notools=0):
+ self.view_manager = ViewManager()
+ self.sel_manager = gvselbrowser.GvSelectionManager( self.view_manager )
+ self.pref_dialog = None
+ self.filename = None
+
+ # Toolbar
+ self.toolbar = Toolbar()
+ self.view_manager.set_toolbar( self.toolbar )
+
+ # Other dialogs, etc.
+ self.layerdlg = layerdlg.Launch()
+ self.view_manager.set_layerdlg(self.layerdlg)
+
+ self.publish('quit')
+ self.publish('rfl-change')
+
+ # Verify that float() works properly.
+ try:
+ x = float('0.9')
+ except:
+ gvutils.warning( 'It appears that float() doesn\'t work properly on your system.\nThis is likely due to use of a numeric locale with an alternate decimal\nrepresentation. Please try setting the LC_NUMERIC environment variable\nto C and restarting OpenEV.' )
+
+ # Default configuration files for view and python shell
+ self.menufile=menufile
+ self.iconfile=iconfile
+ self.pyshellfile=pyshellfile
+
+ # External tools to import and add to view menu
+ self.Tool_List = []
+ if toolfile is not None:
+ self.load_tools_file( toolfile )
+
+ if not notools:
+ self.scan_tools_directories()
+
+ # Tool index: a dictionary with the tool name as a
+ # key and the tool's position in the list as the value
+ self.tool_index = {}
+ for idx in range(len(self.Tool_List)):
+ self.tool_index[self.Tool_List[idx][0]]=idx
+
+ self.shell = None
+
+ def serialize(self,base=None, filename=None):
+ if base is None:
+ base = [gdal.CXT_Element, 'GViewApp']
+
+ for vw in self.view_manager.view_list:
+ base.append( vw.serialize( filename=filename ) )
+
+ return base
+
+ def clear_project( self ):
+ self.view_manager.close_all_views()
+ pass
+
+ def load_project(self, filename):
+ try:
+ raw_xml = open(filename).read()
+ except:
+ gvutils.error( 'Unable to load '+filename )
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ gvutils.error( 'Problem occured parsing project file '+filename )
+ return
+
+ if tree[1] != 'GViewApp':
+ gvutils.error( 'Root of %s is not GViewApp node.' % filename )
+ return
+
+ self.clear_project()
+ self.filename = filename
+ self.add_to_rfl( filename )
+
+ for subnode in tree[2:]:
+ if subnode[0] == gdal.CXT_Element:
+ gvutils.XMLInstantiate( subnode, self, filename=filename )
+
+ def save_project_with_name_cb( self, filename, *args ):
+ if os.path.splitext(filename)[1] == '':
+ filename = filename + '.opf'
+
+ self.save_project( filename )
+ self.add_to_rfl( filename )
+
+ def save_project_as( self ):
+ if self.filename is None:
+ default_filename = 'default.opf'
+ else:
+ default_filename = self.filename
+ pgufilesel.SimpleFileSelect( self.save_project_with_name_cb,
+ title = 'Project Filename',
+ default_filename = default_filename )
+
+ def save_project(self, filename = None):
+ if filename is None and self.filename is not None:
+ filename = self.filename
+
+ if filename is None:
+ self.save_project_as()
+ return
+
+ tree = self.serialize( filename=filename )
+ open( filename, 'w' ).write( gdal.SerializeXMLTree(tree) )
+
+ self.filename = filename
+
+ def load_tools_file(self, toolfile):
+ tool_count = 0
+ # read in toolfile, initialize tools
+ tool_file = open(toolfile,"r")
+ cur_module = None
+ cur_tool = None
+ for new_line in tool_file.readlines():
+ [key,val] = gvutils.read_keyval( new_line )
+ if (key == "MODULE_NAME"):
+ cur_module = val
+ elif (key == "TOOL_NAME"):
+ cur_tool = val
+ if ((cur_module is not None) and (cur_tool is not None)):
+ self.load_tool( cur_module, cur_tool )
+ else:
+ raise AttributeError,"Invalid tool file format"
+
+ def scan_tools_directories(self):
+ self.scan_tool_directory( os.path.join(gview.home_dir,'tools') )
+
+ def scan_tool_directory(self, dir_name):
+ try:
+ files = os.listdir(dir_name)
+ except:
+ return
+
+ old_path = sys.path
+ sys.path.append(dir_name)
+ for file in files:
+ # print file
+ if file[-3:] == '.py':
+ print 'Loading tools from '+os.path.join(dir_name,file)
+ module = file[:-3]
+
+ try:
+ exec "import " + module
+ exec "tool_list = " + module + ".TOOL_LIST"
+ for item in tool_list:
+ exec "tool_inst=" + module + "." + item + "(app=self)"
+ self.Tool_List.append((item,tool_inst))
+ except:
+ print '... failed to load ... skipping.'
+ gdal.Debug( "GDA", '-'*60 )
+ sys_type, sys_value, sys_traceback = sys.exc_info()
+ exp = traceback.format_exception( sys_type, sys_value, sys_traceback )
+ exception = ""
+ for line in exp:
+ exception = exception + line
+ gdal.Debug( "GDA", exception )
+ gdal.Debug( "GDA", '-'*60 )
+
+ # We only add the tool directory to the python path long enough
+ # to load the tool files.
+ sys.path = old_path
+
+ def load_tool(self, module_name, tool_name ):
+ exec "import " + module_name
+ exec "cur_tool_class = " + module_name + "." + tool_name + "(app=self)"
+ self.Tool_List.append([tool_name,cur_tool_class])
+
+ def request_quit(self, *args):
+ response = \
+ GtkExtra.message_box( 'Confirmation',
+ 'Are you sure you want to exit OpenEV?',
+ ('Yes', 'No') )
+
+ if response == 'Yes':
+ self.quit()
+ return 1
+ else:
+ return 0
+
+ def quit(self, *args):
+ # Save preferences
+ gview.save_preferences()
+
+ # Notify listeners of quit event
+ self.notify('quit')
+
+ def add_to_rfl(self, filename):
+ # Don't add NUMPY arrays to file list.
+ if filename[:7] == 'NUMPY::':
+ return
+
+ next_value = filename
+ for i in range(1,6):
+ rbl_name = 'recent_file_'+str(i)
+ rbl_value = gview.get_preference(rbl_name)
+ gview.set_preference(rbl_name, next_value)
+
+ if rbl_value is None or rbl_value == filename:
+ break;
+
+ next_value = rbl_value
+
+ self.notify('rfl-change')
+
+ def get_rfl(self):
+ list = []
+ for i in range(1,6):
+ rbl_name = 'recent_file_'+str(i)
+ rbl_value = gview.get_preference(rbl_name)
+ if rbl_value is not None:
+ list.append(rbl_value)
+ return list
+
+ def show_layerdlg(self, *args):
+ self.layerdlg.show()
+ self.layerdlg.get_window()._raise()
+
+ def show_toolbardlg(self, *args):
+ self.toolbar.show()
+ self.toolbar.get_window()._raise()
+
+ def show_enhdlg(self, *args):
+ self.enhdlg = gvenhdlg.EnchancementDialog()
+
+ def load_menus_file_from_xml(self,menufile,view_name):
+ # Scan the XML menu file to find which tools to
+ # load, and where to position them.
+
+ import string
+
+ menufile = os.path.join(gview.home_dir,'xmlconfig',menufile)
+
+ # menu_list contains a mix of regular and tool menu entries,
+ # in order.
+ menu_list = []
+ try:
+ raw_xml = open(menufile).read()
+ except:
+ raise AttributeError,"Unable to load " + menufile
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ raise AttributeError,"Problem occured parsing menu file " + menufile
+ return
+
+ if tree[1] != 'GViewAppMenu':
+ raise AttributeError,"Root of %s is not GViewAppMenu node " % menufile
+ return
+
+ # loop over entries getting path,accelerator,callback and arguments
+ menu_trees = gvutils.XMLFind( tree, 'Menu')
+ if menu_trees is None:
+ raise AttributeError,"Invalid menu file format"
+
+ # Tools can be specified in a number of ways. The
+ # <tools> entry can be 'All', 'None', or 'Some'.
+ # In the "All" case, all tools will be loaded up.
+ # If toolentries are specified, the defaults
+ # will be overidden for those tools. This is the
+ # default. If "Some" is specified, only the
+ # tools entered in the xml file will be included.
+ # If None is specified, no tools will be loaded
+ # and if toolentries are specified an error will
+ # be raised.
+ tools_to_include = 'All'
+
+ # If tools to include is All, use this list to check for
+ # tools that haven't been added yet, and add them at the
+ # end using their defaults.
+ tools_accounted_for=[]
+
+
+ menu_list = []
+
+ for node in menu_trees[2:]:
+ if node[1] == 'entry':
+ node_path = gvutils.XMLFind( node, 'path')
+ if node_path is None:
+ raise AttributeError,"Invalid menu file format - missing path"
+
+ entry_type = gvutils.XMLFindValue( node_path, 'type', '')
+ entry_path = gvutils.XMLFindValue( node, 'path','')
+
+ if (string.find(entry_path,"/") == -1):
+ raise AttributeError,"Invalid menu file format - bad path:%s" % entry_path
+
+ if (entry_type != ''):
+ entry_type = "<" + entry_type + ">"
+ path_split=string.split(entry_path,"/")
+ path_split[-1] = entry_type + path_split[-1]
+ entry_path=string.join(path_split,"/")
+
+ entry_accelerator = gvutils.XMLFindValue( node, 'accelerator', 'None')
+ if (entry_accelerator != 'None'):
+ (key,mod) = string.split(entry_accelerator,'+')
+ entry_accelerator = "'<" + key + ">" + mod + "'"
+
+ entry_callback = gvutils.XMLFindValue( node, 'callback', 'None')
+ entry= "(" \
+ + string.join((entry_path,entry_accelerator, \
+ entry_callback),",")
+
+ arguments = gvutils.XMLFind( node, 'arguments')
+ if arguments is not None:
+ args_list = []
+ args = gvutils.XMLFind( arguments, 'arg','')
+ if args is not None:
+ for arg in args:
+ args_list.append(gvutils.XMLFindValue( arg, '',''))
+ entry = entry + "," + string.join(args_list,",")
+
+ entry = entry + ")"
+
+ menu_list.append(entry)
+
+ elif node[1] == 'tools':
+ tools_to_include=node[2][1]
+
+ elif node[1] == 'simpletoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid menu file format - missing tool name"
+
+ if self.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid menu file format- tool "+toolname+" not loaded."
+
+ ctool=self.Tool_List[self.tool_index[toolname]][1]
+ for cpath in ctool.menu_entries.entries.keys():
+ caccel=ctool.menu_entries.entries[cpath][2]
+ if caccel is None:
+ caccel=str(None)
+ else:
+ caccel="'"+caccel+"'"
+ # main application is stored as self.app in GvViewWindow
+ # ccb (current callback string) specifies the path to the
+ # callback from within the gvviewwindow.
+ ccb="self.app.Tool_List[self.app.tool_index['"+toolname+"']]"+\
+ "[1].menu_entries.entries['"+cpath+"'][1]"
+
+ # The name of the view that launched the tool is passed to
+ # the callback in case the tool needs to locate the view that
+ # launched it (a view doesn't always become the currently
+ # active view until its view area is clicked on, so simply
+ # getting the active view is not sufficient). If the tool
+ # wishes to act on the view that launched it rathern than
+ # the currently active layer, it must locate the view with
+ # this name and activate it before proceeding.
+ viewstr="('"+view_name+"')"
+
+ entry="("+string.join(("'"+cpath+"'",caccel,ccb,viewstr),",")+")"
+ menu_list.append(entry)
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+
+ elif node[1] == 'complextoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid menu file format - missing tool name"
+
+ oldpath = gvutils.XMLFindValue( node, 'oldpath')
+
+ if oldpath is None:
+ txt="Invalid menu file format - complex tool entry\nrequires oldpath item."
+ raise AttributeError,txt
+ oldpath = oldpath[1:-1] # Entries in XML file are surrounded by quotes- get rid of them
+
+ newpath = gvutils.XMLFindValue( node, 'newpath')
+ if newpath is None:
+ txt="Invalid menu file format - complex tool entry\nrequires newpath item."
+ raise AttributeError,txt
+ newpath = newpath[1:-1] # Entries in XML file are surrounded by quotes- get rid of them
+
+ if self.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid menu file format- tool "+toolname+" not loaded."
+
+ ctool=self.Tool_List[self.tool_index[toolname]][1]
+ if ctool.menu_entries.entries.has_key(oldpath) == 0:
+ raise AttributeError,'Invalid menu file entry- tool '+toolname+' has no\nmenu entry '+oldpath
+
+ caccel=gvutils.XMLFindValue(node,'accelerator')
+ if caccel is None:
+ caccel=ctool.menu_entries.entries[oldpath][2]
+ if caccel is None:
+ caccel=str(None)
+ else:
+ caccel="'"+caccel+"'"
+ else:
+ # XML file specifies key sequence string without
+ # the "<" and ">"'s to avoid confusion with tags
+ # (eg. control+D rather than <control>D). Add them
+ # back in here, since parser expects them.
+ (key,mod)=string.split(caccel,'+')
+ caccel="'<"+key+">"+mod+"'"
+
+ ccb="self.app.Tool_List[self.app.tool_index['"+toolname+"']]"+\
+ "[1].menu_entries.entries['"+oldpath+"'][1]"
+
+ viewstr="('"+view_name+"')"
+
+ entry="("+string.join(("'"+newpath+"'",caccel,ccb,viewstr),",")+")"
+ menu_list.append(entry)
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+ if tools_to_include not in ['All','None','Some']:
+ raise AttributeError,"Invalid menu file format- <tool> entry should be All, None, or Some."
+
+ if ((tools_to_include == 'None') and (len(tools_accounted_for) > 0)):
+ txt = "Invalid menu file format- if <tool> entry is None,\nno "
+ txt = txt+"simpletoolentry or complextoolentry items may be specified."
+ raise AttributeError,txt
+
+ if tools_to_include == 'All':
+ for citem in self.Tool_List:
+ if citem[0] not in tools_accounted_for:
+ ctool=citem[1]
+ for cpath in ctool.menu_entries.entries.keys():
+ # default position: find where to insert
+ # tool.
+ cpos=ctool.menu_entries.entries[cpath][0]
+ cpos=max(cpos,0)
+
+ splitpath=string.split(cpath,'/')
+ rootp=string.join(splitpath[:-1],'/')+'/'
+ nchars=len(rootp)
+ matches=0
+ idx=0
+ for nextentry in menu_list:
+ if (len(nextentry) > nchars):
+ if (nextentry[2:nchars+2] == rootp):
+ matches=matches+1
+ if matches > cpos:
+ break
+ idx=idx+1
+
+ caccel=ctool.menu_entries.entries[cpath][2]
+ if caccel is None:
+ caccel=str(None)
+ else:
+ caccel="'"+caccel+"'"
+ ccb="self.app.Tool_List[self.app.tool_index['"+citem[0]+"']]"+\
+ "[1].menu_entries.entries['"+cpath+"'][1]"
+
+ viewstr="('"+view_name+"')"
+
+ entry="("+string.join(("'"+cpath+"'",caccel,ccb,viewstr),",")+")"
+ menu_list.insert(idx,entry)
+
+ # Move help entries to end so that Help menu is on the far right
+ help_list=[]
+ idx=0
+ for count in range(len(menu_list)):
+ if len(menu_list[idx]) > 7:
+ if menu_list[idx][:7] == "('Help/":
+ help_list.append(menu_list.pop(idx))
+ else:
+ idx=idx+1
+ else:
+ idx=idx+1
+
+ menu_list.extend(help_list)
+
+ menu_cmd = "self.menuf.add_entries([" + string.join(menu_list,',') + "])"
+ return menu_cmd
+
+
+ def load_icons_file_from_xml(self,iconfile):
+ # Scan the XML icon file to find which tools to
+ # load, and where to position them.
+
+ import string
+
+ iconfile = os.path.join(gview.home_dir,'xmlconfig',iconfile)
+
+ # icon_count: current position
+ icon_count=0
+ try:
+ raw_xml = open(iconfile).read()
+ except:
+ raise AttributeError,"Unable to load " + iconfile
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ raise AttributeError,"Problem occured parsing icon file " + iconfile
+ return
+
+ if tree[1] != 'GViewAppIconBar':
+ raise AttributeError,"Root of %s is not GViewAppIconBar node " % iconfile
+ return
+
+ # loop over entries getting path,accelerator,callback and arguments
+ icon_trees = gvutils.XMLFind( tree, 'Iconbar')
+ if icon_trees is None:
+ raise AttributeError,"Invalid menu file format"
+
+ # Tools can be specified in a number of ways. The
+ # <tools> entry can be 'All', 'None', or 'Some'.
+ # In the "All" case, all tools will be loaded up.
+ # If toolentries are specified, the defaults
+ # will be overidden for those tools. This is the
+ # default. If "Some" is specified, only the
+ # tools entered in the xml file will be included.
+ # If None is specified, no tools will be loaded
+ # and if toolentries are specified an error will
+ # be raised.
+ tools_to_include = 'All'
+
+ # If tools to include is All, use this list to check for
+ # tools that haven't been added yet, and add them at the
+ # end using their defaults.
+ tools_accounted_for=[]
+
+ icon_list = []
+
+ for node in icon_trees[2:]:
+ if node[1] == 'icon':
+ type = None
+ icon_label = gvutils.XMLFindValue( node, 'label','None')
+ icon_hint = gvutils.XMLFindValue( node, 'hint','None')
+ icon_callback = gvutils.XMLFindValue( node, 'callback','None')
+ icon_help = gvutils.XMLFindValue( node, 'help','None')
+ icon_file = gvutils.XMLFindValue( node, 'xpm','None')
+ # xpm files - need to add path and possible help
+ if (icon_file != 'None'):
+ type = 'xpm'
+ icon = "self.add_icon_to_bar(" \
+ + string.join((icon_file,icon_label,icon_hint, \
+ icon_callback,icon_help),",") \
+ + ")"
+
+ # pixmap files - not adding path or help
+ icon_file = gvutils.XMLFindValue( node, 'pixmap','None')
+ if (icon_file!= 'None'):
+ type = 'pixmap'
+ icon = "self.iconbar.append_item(" \
+ + string.join((icon_label,icon_hint,icon_hint, \
+ icon_file,icon_callback),",") \
+ + ")"
+
+ # widget
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ if (icon_file!= 'None'):
+ type = 'widget'
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ icon = "self.iconbar.append_widget(" \
+ + string.join((icon_file,icon_hint,icon_hint),",") \
+ + ")"
+ # none of the above
+ if type is None:
+ raise AttributeError,"Invalid icon file format - unknown type"
+
+ icon_list.append(icon)
+ elif node[1] == 'tools':
+ tools_to_include=node[2][1]
+ elif node[1] == 'simpletoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid icon file format - missing tool name"
+
+ if self.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid icon file format- tool "+toolname+" not loaded."
+
+ ctool=self.Tool_List[self.tool_index[toolname]][1]
+
+ idx=0
+ for centry in ctool.icon_entries.entries:
+ icon_file=centry[0]
+
+ icon_label=centry[1]
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ icon_hint=centry[2]
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ # Ignore position- it is overridden by this entry's location in the
+ # xml file
+ icon_callback=centry[4]
+ icon_help=centry[5]
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ icon_type=centry[6]
+ if icon_type == 'xpm':
+ icon = "self.add_icon_to_bar(" \
+ + string.join(("'"+icon_file+"'",icon_label,icon_hint, \
+ "self.app.Tool_List[self.app.tool_index['"+\
+ toolname+"']][1].icon_entries.entries["+\
+ str(idx)+"][4]",icon_help),",")+")"
+
+ icon_list.append(icon)
+ else:
+ raise AttributeError,"Invalid icon type "+icon_type+" in tool "+toolname+"."
+ idx=idx+1
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+ elif node[1] == 'complextoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid icon file format - missing tool name."
+
+ oindex = gvutils.XMLFindValue( node, 'index')
+
+ if oindex is None:
+ txt="Invalid icon file format - complex tool entry\nrequires the index of the icon entry\n"
+ txt=txt+"to replace (0...number of entries-1).\n"
+ raise AttributeError,txt
+ try:
+ oindex=int(oindex)
+ except:
+ raise AttributeError,"Invalid icon file- icon index to replace must be an integer."
+
+ if self.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid icon file entry- tool "+toolname+" not loaded."
+
+ ctool=self.Tool_List[self.tool_index[toolname]][1]
+
+ if len(ctool.icon_entries.entries) < (oindex+1):
+ txt='Invalid file file entry- for tool '+toolname+'.\n maximum entry index is '
+ txt=txt+str(len(ctool.icon_entries.entries)-1)+'.'
+
+ icon_file=gvutils.XMLFindValue( node, 'xpm')
+ icon_hint=gvutils.XMLFindValue( node, 'hint')
+ icon_label=gvutils.XMLFindValue( node, 'label')
+ icon_help=gvutils.XMLFindValue( node, 'help')
+
+ if icon_file is None:
+ icon_file="'"+ctool.icon_entries.entries[oindex][0]+"'"
+ elif os.path.isfile(icon_file):
+ if os.name == 'nt':
+ icon_file="'"+string.replace(icon_file,"\\","\\\\")+"'"
+ else:
+ icon_file="'"+icon_file+"'"
+ elif os.path.isfile(os.path.join(gview.home_dir,'tools',icon_file)):
+ icon_file="'"+os.path.join(gview.home_dir,'tools',icon_file)+"'"
+ if os.name == 'nt':
+ icon_file=string.replace(icon_file,"\\","\\\\")
+ elif os.path.isfile(os.path.join(gview.home_dir,'pics',icon_file)):
+ icon_file="'"+os.path.join(gview.home_dir,'pics',icon_file)+"'"
+ if os.name == 'nt':
+ icon_file=string.replace(icon_file,"\\","\\\\")
+ else:
+ txt = "Cannot find file "+tempf+'. Either the full\n'
+ txt = txt+"path must be specified, or "+tempf+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
+
+
+ if icon_label is None:
+ icon_label=ctool.icon_entries.entries[oindex][1]
+
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ if icon_hint is None:
+ icon_hint=ctool.icon_entries.entries[oindex][2]
+
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ if icon_help is None:
+ icon_help=ctool.icon_entries.entries[oindex][5]
+
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ icon_callback=ctool.icon_entries.entries[oindex][4]
+ icon_type=ctool.icon_entries.entries[oindex][6]
+ if icon_type == 'xpm':
+ icon = "self.add_icon_to_bar(" \
+ + string.join((icon_file,icon_label,icon_hint, \
+ "self.app.Tool_List[self.app.tool_index['"+toolname+\
+ "']][1].icon_entries.entries["+str(oindex)+"][4]",\
+ icon_help),",") + ")"
+ icon_list.append(icon)
+ else:
+ raise AttributeError,"Invalid icon type "+icon_type+" in tool "+toolname+"."
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+
+ if tools_to_include not in ['All','None','Some']:
+ raise AttributeError,"Invalid icon file format- <tool> entry should be All, None, or Some."
+
+ if ((tools_to_include == 'None') and (len(tools_accounted_for) > 0)):
+ txt = "Invalid icon file format- if <tool> entry is None,\nno "
+ txt = txt+"simpletoolentry or complextoolentry items may be specified."
+ raise AttributeError,txt
+
+ if tools_to_include == 'All':
+ for citem in self.Tool_List:
+ if citem[0] not in tools_accounted_for:
+ ctool=citem[1]
+ idx=0
+ for centry in ctool.icon_entries.entries:
+ if centry[6] != 'xpm':
+ raise AttributeError,"Error loading tool entry for tool "+\
+ citem[0]+"- icon type "+centry[6]+" invalid."
+
+ icon_file="'"+centry[0]+"'"
+ icon_label=centry[1]
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ icon_hint=centry[2]
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ icon_help=centry[5]
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ # Default position in icon bar used
+ pos=centry[3]
+ icon = "self.add_icon_to_bar(" +\
+ string.join((icon_file,icon_label,icon_hint, \
+ "self.app.Tool_List[self.app.tool_index['"+\
+ citem[0]+"']][1].icon_entries.entries["+\
+ str(idx)+"][4]",icon_help),",") + ")"
+
+ pos=max(pos,0)
+ if pos > len(icon_list):
+ icon_list.append(icon)
+ else:
+ icon_list.insert(pos,icon)
+ idx=idx+1
+
+ return icon_list
+
+ def new_view(self, title=None, menufile=None,iconfile=None, *args):
+ # If menu/icon files aren't specified, use application-wide
+ # defaults
+ if ((menufile is None) and (self.menufile is not None)):
+ menufile=self.menufile
+ if ((iconfile is None) and (self.iconfile is not None)):
+ iconfile=self.iconfile
+
+ view_window = gvviewwindow.GvViewWindow(app=self, title=title, menufile=menufile, iconfile=iconfile)
+ view_name=view_window.title
+ view_menu = view_window.menuf
+
+ if ((len(self.Tool_List) > 0) and (menufile is None)):
+ # If no menu configuration file is specified, put
+ # tools in the default positions specified by
+ # the tool menu entry's position parameter.
+ for cur_tool_list in self.Tool_List:
+ cur_tool = cur_tool_list[1]
+ if hasattr(cur_tool.menu_entries.entries,'keys'):
+ for item in cur_tool.menu_entries.entries.keys():
+ view_menu.insert_entry(
+ cur_tool.menu_entries.entries[item][0],
+ item,
+ cur_tool.menu_entries.entries[item][2],
+ cur_tool.menu_entries.entries[item][1],
+ (view_name))
+
+ # Icons- Note: currently it is assumed that the tool icons are
+ # xpms. Support for pixmaps and widgets will be added
+ # later if necessary (icon type would have to be detected
+ # from last entry of the relevant tool icon entry, and
+ # a function would have to be created to deal with them.
+ # They are slightly more complicated than the xpm case
+ # and wouldn't use insert_tool_icon. Would also need
+ # code in the complextoolentry case to avoid an icon
+ # of one type (eg. xpm) being replaced by another type
+ # (eg. widget, pixmap).
+ #
+ # ALSO: GtkToolbar does not allow callback information
+ # to be specified, so the viewname cannot be
+ # passed as an argument to tool icon callbacks
+ # the way it is for menu callbacks. However,
+ # if the view is needed, it can be obtained
+ # using:
+ # view=args[0].get_toplevel()
+ # The view title is under:
+ # view['title']. Note that this is not quite
+ # the same as the view's self.title, but is based
+ # on it (usually 'OpenEV: '+self.title)
+
+ if ((len(self.Tool_List) > 0) and (iconfile is None)):
+ for cur_tool_list in self.Tool_List:
+ cur_tool=cur_tool_list[1]
+ for item in cur_tool.icon_entries.entries:
+ view_window.insert_tool_icon(
+ item[0], # filename
+ item[1], # label
+ item[2], # hint text
+ item[4], # callback
+ item[5], # help topic
+ item[3], # position
+ )
+ view_window.show()
+ return view_window
+
+ def open_gdal_dataset(self, dataset, lut=None, sds_check=1, *args):
+ view = self.view_manager.get_active_view_window()
+ if view is None:
+ self.new_view()
+ view = self.view_manager.get_active_view_window()
+
+ if view is None:
+ return
+
+ view.open_gdal_dataset( dataset, lut = lut, sds_check = sds_check )
+
+ def file_open_by_name(self, filename, lut=None, sds_check=1, *args):
+ view = self.view_manager.get_active_view_window()
+ if view is None:
+ self.new_view()
+ view = self.view_manager.get_active_view_window()
+
+ if view is None:
+ return
+
+ view.file_open_by_name( filename, lut = lut, sds_check = sds_check )
+
+ def launch_preferences(self, *args):
+ if self.pref_dialog is None:
+ self.pref_dialog = PrefDialog()
+ self.pref_dialog.connect('destroy', self.destroy_preferences)
+ self.pref_dialog.show()
+ self.pref_dialog.get_window()._raise()
+
+ def destroy_preferences(self,*args):
+ self.pref_dialog = None
+
+ def pyshell(self, *args):
+ import pyshell
+ pyshell.launch(pyshellfile=self.pyshellfile)
+
+ def do_auto_imports(self):
+ i = 1
+ al = gview.get_preference('auto_load_'+str(i))
+ while al is not None:
+ try:
+ exec 'import '+al
+ except:
+ print 'auto_load_'+str(i)+' error: import '+al
+ print sys.exc_info()[0], sys.exc_info()[1]
+
+ i = i + 1
+ al = gview.get_preference('auto_load_'+str(i))
+
+ def active_layer(self):
+ return self.view_manager.active_view.viewarea.active_layer()
+
+class Toolbar(gtk.GtkWindow):
+ def __init__(self):
+ gtk.GtkWindow.__init__(self)
+
+ gvhtml.set_help_topic( self, "edittools.html" );
+
+ toolbox = gview.GvToolbox()
+ toolbox.add_tool("select", gview.GvSelectionTool())
+ toolbox.add_tool("zoompan", gview.GvZoompanTool())
+ toolbox.add_tool("line", gview.GvLineTool())
+ toolbox.add_tool("rect", gview.GvRectTool())
+ toolbox.add_tool("rotate", gview.GvRotateTool())
+ toolbox.add_tool("area", gview.GvAreaTool())
+ toolbox.add_tool("node", gview.GvNodeTool())
+ toolbox.add_tool("point", gview.GvPointTool())
+ toolbox.add_tool("pquery", gview.GvPointTool())
+ self.roi_tool = gview.GvRoiTool()
+ toolbox.add_tool("roi", self.roi_tool)
+ self.poi_tool = gview.GvPoiTool()
+ toolbox.add_tool("poi", self.poi_tool)
+
+ toolbar = gtk.GtkToolbar(gtk.ORIENTATION_VERTICAL, gtk.TOOLBAR_TEXT)
+ self.add(toolbar)
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, None,
+ 'Select', 'Selection tool',
+ None, None, self.toggle, "select")
+ self.select_button=but
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Zoom', 'Zoom/Pan mode',
+ None, None, self.toggle, "zoompan")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Point Edit', 'Point editing tool',
+ None, None, self.toggle, "point")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Point Query', 'Point query tool',
+ None, None, self.toggle, "pquery")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Line', 'Line drawing tool',
+ None, None, self.toggle, "line")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Rotate/Resize','Rotate/resize symbol tool',
+ None, None, self.toggle, "rotate")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Rectangle','Rectangle drawing tool',
+ None, None, self.toggle, "rect")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Area', 'Area drawing tool',
+ None, None, self.toggle, "area")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Edit Node', 'Node edit tool',
+ None, None, self.toggle, "node")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Labels', 'Label drawing tool',
+ None, None, self.toggle, "label")
+
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw ROI', 'ROI drawing tool',
+ None, None, self.toggle, "roi")
+ self.roi_button = but
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Choose POI', 'POI selection tool',
+ None, None, self.toggle, "poi")
+ self.poi_button = but
+
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_TOGGLEBUTTON, None,
+ 'Link Views', 'Link views together',
+ None, None, self.link)
+
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_TOGGLEBUTTON, None,
+ 'Cursor', 'Create cursor in all views',
+ None, None, self.cursor)
+ self.cursor_button=but
+
+ toolbox.activate_tool("select")
+ toolbar.show()
+ self.toolbox = toolbox
+ self.toolbar = toolbar
+ self.link = gview.GvViewLink()
+ self.connect('delete-event', self.close)
+
+ def close(self, *args):
+ self.hide()
+ return gtk.TRUE
+
+ def toggle(self, but, data):
+ button = gtk.GtkRadioButton(_obj=but)
+ if not button.active:
+ return
+
+ # For Point Query Tool:
+ # Make the special point query layer the current layer and if there
+ # isn't one, create it.
+ if data == "pquery":
+ view = self.toolbox.get_view()
+ if view is not None:
+ layer_list = view.list_layers()
+ result_layer = None
+ for layer in layer_list:
+ if layer.get_property('pquery') is not None:
+ result_layer = layer
+
+ if result_layer is None:
+ result_layer = gview.GvPqueryLayer()
+ gview.undo_register( result_layer.get_parent() )
+ result_layer.set_property('pquery','true')
+ view.add_layer(result_layer)
+
+ view.set_active_layer( result_layer )
+
+ if data == 'label':
+ import gvlabeledit
+ gvlabeledit.launch()
+ data = 'select'
+
+ self.toolbox.activate_tool(data)
+
+ def link(self, but):
+ but = gtk.GtkToggleButton(_obj=but)
+ if (but.active):
+ self.link.enable()
+ else:
+ self.link.disable()
+
+ def cursor(self, but):
+ but = gtk.GtkToggleButton(_obj=but)
+ if (but.active):
+ if ((gview.get_preference('cursor_type') is not None) and
+ (gview.get_preference('cursor_type') == 'nonadaptive')):
+ self.link.set_cursor_mode(1)
+ else:
+ self.link.set_cursor_mode(2)
+ else:
+ self.link.set_cursor_mode(0)
+
+ def add_view(self, view):
+ self.toolbox.activate(view)
+ self.link.register_view(view)
+
+ def get_roi(self):
+ return self.roi_tool.get_rect()
+
+ def get_poi(self):
+ return self.poi_tool.get_point()
+
+class ViewManager(Signaler):
+
+ def __init__(self):
+ self.layerdlg = None
+ self.toolbar = None
+ self.active_view = None
+ self.view_list = []
+ self.publish( 'active-view-changed' )
+ self.updating = FALSE
+
+ def set_layerdlg(self,layerdlg):
+ self.layerdlg = layerdlg
+ self.layerdlg.subscribe('active-view-changed',self.layerdlg_cb)
+
+ def layerdlg_cb(self,*args):
+ self.set_active_view( self.layerdlg.get_active_view() )
+
+ def set_toolbar(self,toolbar):
+ self.toolbar = toolbar
+ self.toolbar.toolbox.connect('activate',self.toolbar_cb)
+
+ def toolbar_cb(self,*args):
+ self.set_active_view( self.toolbar.toolbox.get_view() )
+
+ def add_view(self, new_view ):
+ self.updating = TRUE
+ self.view_list.append( new_view )
+ if self.toolbar is not None:
+ self.toolbar.add_view(new_view.viewarea)
+
+ if self.layerdlg is not None:
+ self.layerdlg.add_view(new_view.title, new_view.viewarea)
+
+ new_view.connect('destroy', self.view_closing_cb)
+
+ self.updating = FALSE
+ self.set_active_view( new_view )
+
+ def view_closing_cb( self, view_window_in, *args ):
+ # lookup original ViewWindow instance with internal variables.
+ view_window = None
+ for v in self.view_list:
+ if v == view_window_in:
+ view_window = v
+
+ if view_window is None:
+ gdal.Debug( "OpenEV",
+ "unexpectedly missing view in ViewManager" )
+ return
+
+ self.view_list.remove( view_window )
+
+ if view_window_in == self.active_view:
+ if len(self.view_list) > 0:
+ self.set_active_view( self.view_list[0] )
+ else:
+ self.set_active_view( None );
+
+ if self.layerdlg is not None:
+ self.layerdlg.remove_view( view_window.title )
+
+ if self.toolbar is not None:
+ self.toolbar.toolbox.deactivate( view_window.viewarea )
+
+
+
+ def close_all_views( self, *args ):
+ old_len = len(self.view_list)+1
+ while len(self.view_list) < old_len and old_len > 1:
+ old_len = len(self.view_list)
+ # If views have menus, make sure the main app
+ # doesn't keep trying to update their rfls after
+ # they're gone...
+ if self.view_list[0].menuf is not None:
+ try:
+ self.view_list[0].app.unsubscribe('rfl-change',
+ self.view_list[0].show_rfl)
+ except:
+ pass
+
+ self.view_list[0].destroy()
+
+ if len(self.view_list) > 0:
+ print 'failed to destroy all views.'
+
+
+ def get_views(self):
+ return self.view_list
+
+ def get_active_view(self):
+ if self.active_view == None:
+ return None
+ else:
+ return self.active_view.viewarea
+
+ def get_active_view_window(self):
+ return self.active_view
+
+ def set_active_view(self, new_view):
+ if self.updating:
+ return
+
+ if new_view == self.active_view:
+ return
+
+ if self.active_view is not None \
+ and new_view == self.active_view.viewarea:
+ return
+
+ for v in self.view_list:
+ if v.viewarea == new_view:
+ new_view = v
+
+ self.active_view = new_view
+ if new_view is not None and new_view.get_window() is not None:
+ new_view.get_window()._raise()
+
+ self.notify('active-view-changed')
+
+ if self.layerdlg is not None and new_view is not None:
+ self.layerdlg.view_selected( None, new_view.title )
+
+ if self.toolbar is not None and new_view is not None:
+ self.toolbar.toolbox.activate(new_view.viewarea)
+
+
+class PrefDialog(gtk.GtkWindow):
+ def __init__(self):
+ import pgufont
+
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Preferences')
+
+ gvhtml.set_help_topic( self, "preferences.html" );
+
+ self.default_color = (0.5, 1.0, 0.5, 1.0)
+
+ self.default_font = pgufont.XLFDFontSpec()
+ self.default_font.set_font_part('Family', 'Arial')
+ self.default_font.set_font_part('Point Size', '120')
+
+ self.tips = gtk.GtkTooltips()
+
+
+ self.set_border_width(3)
+ self.notebook = gtk.GtkNotebook()
+ self.add( self.notebook )
+
+ self.create_tracking_tool_prefs()
+ self.create_raster_prefs()
+ self.create_cache_prefs()
+ self.create_paths_and_windows_prefs()
+ #self.create_temporaryfile_prefs()
+
+ self.notebook.append_page(self.page_legend(),
+ gtk.GtkLabel( 'Legend' ))
+
+ self.show_all()
+
+ def gvplot_cb(self, *args):
+ fname = self.gvplot_tempfile_entry.get_text()
+ gview.set_preference('gvplot_tempfile',fname)
+
+ def create_cache_prefs(self):
+ self.cachep = gtk.GtkVBox(spacing=10)
+ self.cachep.set_border_width(10)
+ self.notebook.append_page(self.cachep, gtk.GtkLabel('Caching'))
+ table = gtk.GtkTable(rows=2, cols=2)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+ self.cachep.pack_start(table, expand=FALSE)
+
+ # File Cache
+ gdal_cache_label = gtk.GtkLabel('File Cache (bytes):')
+ gdal_cache_label.set_alignment(0, 0.5)
+ table.attach(gdal_cache_label, 0, 1, 0, 1)
+
+ self.gdal_cache = gtk.GtkEntry(maxlen=9)
+ self.gdal_cache.connect('activate',self.gdal_cb)
+ self.gdal_cache.connect('leave-notify-event',self.gdal_cb)
+ table.attach(self.gdal_cache, 1, 2, 0, 1)
+
+ self.gdal_cache.set_text(str(gdal.GetCacheMax() \
+ +gview.raster_cache_get_max()))
+
+ # Texture Cache
+ texture_cache_label = gtk.GtkLabel('GL Texture (bytes):')
+ texture_cache_label.set_alignment(0, 0.5)
+ table.attach(texture_cache_label, 0, 1, 1, 2)
+
+ self.texture_cache = gtk.GtkEntry(maxlen=9)
+ self.texture_cache.connect('activate',self.tcache_cb)
+ self.texture_cache.connect('leave-notify-event',self.tcache_cb)
+ table.attach(self.texture_cache, 1, 2, 1, 2)
+
+ self.texture_cache.set_text(str(gview.texture_cache_get_max()))
+
+ def create_raster_prefs(self):
+
+ self.rpp = gtk.GtkVBox(spacing=10)
+ self.rpp.set_border_width(10)
+ self.notebook.append_page( self.rpp, gtk.GtkLabel('Raster'))
+ table = gtk.GtkTable(rows=6, cols=2)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+ self.rpp.pack_start(table, expand=FALSE)
+
+ # Warp with GCPs
+ gcp_warp_label = gtk.GtkLabel('Display Georeferenced:')
+ gcp_warp_label.set_alignment(0, 0.5)
+ table.attach(gcp_warp_label, 0, 1, 0, 1)
+
+ self.gcp_warp_om = \
+ gvutils.GvOptionMenu(('Yes','No'), self.set_gcp_warp_mode)
+ table.attach(self.gcp_warp_om, 1, 2, 0, 1)
+
+ if gview.get_preference('gcp_warp_mode') is not None \
+ and gview.get_preference('gcp_warp_mode') == 'no':
+ self.gcp_warp_om.set_history(1)
+
+ # Sample Method
+ sm_label = gtk.GtkLabel('Overview Sampling:')
+ sm_label.set_alignment(0, 0.5)
+ table.attach(sm_label, 0, 1, 1, 2)
+
+ self.sm_om = \
+ gvutils.GvOptionMenu(('Decimate','Average'),
+ self.set_sample_method)
+ table.attach(self.sm_om, 1, 2, 1, 2)
+
+ if gview.get_preference('default_raster_sample') is not None \
+ and gview.get_preference('default_raster_sample') == 'average':
+ self.sm_om.set_history(1)
+
+ # Pixel Interpolation
+ im_label = gtk.GtkLabel('Subpixel Interpolation:')
+ im_label.set_alignment(0, 0.5)
+ table.attach(im_label, 0, 1, 2, 3)
+
+ self.im_om = \
+ gvutils.GvOptionMenu(('Bilinear','Off (Nearest)'),
+ self.set_interp_method)
+ table.attach(self.im_om, 1, 2, 2, 3)
+
+ if gview.get_preference('interp_mode') is not None \
+ and gview.get_preference('interp_mode') == 'nearest':
+ self.im_om.set_history(1)
+
+ # Default Autoscaling Method
+ scale_label = gtk.GtkLabel('Autoscaling Method:')
+ scale_label.set_alignment(0, 0.5)
+ table.attach(scale_label, 0, 1, 3, 4)
+
+ self.scale_om = \
+ gvutils.GvOptionMenu(('Percent Tail Trim',
+ 'Standard Deviations'),
+ self.set_scaling_method)
+ table.attach(self.scale_om, 1, 2, 3, 4)
+
+ if gview.get_preference('scale_algorithm') is not None \
+ and gview.get_preference('scale_algorithm') == 'std_deviation':
+ self.scale_om.set_history(1)
+
+ # Tail Trim Percentage.
+ tt_label = gtk.GtkLabel('Tail Trim Percentage:')
+ tt_label.set_alignment(0, 0.5)
+ table.attach(tt_label, 0, 1, 4, 5)
+
+ self.tt_entry = gtk.GtkEntry(maxlen=9)
+ self.tt_entry.connect('activate',self.tail_trim_cb)
+ self.tt_entry.connect('leave-notify-event',self.tail_trim_cb)
+ table.attach(self.tt_entry, 1, 2, 4, 5)
+
+ tt_val = gview.get_preference('scale_percent_tail')
+
+ if tt_val is None:
+ tt_val = '0.02'
+
+ self.tt_entry.set_text(str(float(tt_val)*100.0))
+
+ # Scaling Standard Deviations.
+ sd_label = gtk.GtkLabel('Standard Deviations:')
+ sd_label.set_alignment(0, 0.5)
+ table.attach(sd_label, 0, 1, 5, 6)
+
+ self.sd_entry = gtk.GtkEntry(maxlen=9)
+ self.sd_entry.connect('activate',self.std_dev_cb)
+ self.sd_entry.connect('leave-notify-event',self.std_dev_cb)
+ table.attach(self.sd_entry, 1, 2, 5, 6)
+
+ sd_val = gview.get_preference('scale_std_deviations')
+
+ try:
+ if sd_val is None or float(sd_val) == 0.0:
+ sd_val = '2.5'
+ except:
+ sd_val = '2.5'
+
+ self.sd_entry.set_text(sd_val)
+
+ def create_paths_and_windows_prefs(self):
+ self.pwp = gtk.GtkVBox(spacing=10)
+ self.pwp.set_border_width(10)
+ self.notebook.append_page(self.pwp, gtk.GtkLabel('Program Paths'))
+ table = gtk.GtkTable(rows=3, cols=2)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+ self.pwp.pack_start(table, expand=FALSE)
+
+ # HTML Browser
+ html_command_label = gtk.GtkLabel('Browser Command:')
+ html_command_label.set_alignment(0, 0.5)
+ table.attach(html_command_label, 0, 1, 0, 1)
+
+ self.html_command = gtk.GtkEntry()
+ self.html_command.connect('activate',self.html_cb)
+ self.html_command.connect('leave-notify-event',self.html_cb)
+ table.attach(self.html_command, 1, 2, 0, 1)
+
+ if gvhtml.GetBrowseCommand() is not None:
+ self.html_command.set_text(gvhtml.GetBrowseCommand())
+ else:
+ self.html_command.set_text('')
+
+ # Temporary paths
+ gvplot_tempfile_label = gtk.GtkLabel('Plot file (full path):')
+ gvplot_tempfile_label.set_alignment(0, 0.5)
+ table.attach(gvplot_tempfile_label, 0, 1, 1, 2)
+
+ self.gvplot_tempfile_entry = gtk.GtkEntry(maxlen=100)
+ self.gvplot_tempfile_entry.connect('activate',self.gvplot_cb)
+ self.gvplot_tempfile_entry.connect('leave-notify-event',self.gvplot_cb)
+ table.attach(self.gvplot_tempfile_entry, 1, 2, 1, 2)
+
+ if gview.get_preference('gvplot_tempfile') is not None:
+ gvtext = str(gview.get_preference('gvplot_tempfile'))
+ self.gvplot_tempfile_entry.set_text(gvtext)
+ else:
+ self.gvplot_tempfile_entry.set_text('')
+
+ # Save last visited directory
+ save_recent_dir_label = gtk.GtkLabel('Save last visited directory:')
+ save_recent_dir_label.set_alignment(0, 0.5)
+ table.attach(save_recent_dir_label, 0, 1, 2, 3)
+
+ self.save_recent_dir_om = \
+ gvutils.GvOptionMenu(('Off','On'), self.set_save_recent_dir)
+ table.attach(self.save_recent_dir_om, 1, 2, 2, 3)
+
+ if gview.get_preference('save_recent_directory') is not None \
+ and gview.get_preference('save_recent_directory') == 'off':
+ self.save_recent_dir_om.set_history(1)
+ else:
+ self.save_recent_dir_om.set_history(0)
+
+ def html_cb(self, *args):
+ command = self.html_command.get_text()
+ if len(command) > 0 and command[len(command)-1] != ' ':
+ command = command + ' '
+ gvhtml.SetBrowseCommand( command )
+
+ def gdal_cb(self, *args):
+ value = int(self.gdal_cache.get_text())
+ if value < 2000000:
+ self.gdal_cache.set_text(str(gdal.GetCacheMax()
+ +gview.raster_cache_get_max()))
+ return
+
+ if value == gdal.GetCacheMax() + gview.raster_cache_get_max():
+ return
+
+ gdal_cache = int( 900000 + (value - 900000) * 0.25)
+ gvraster_cache = value - gdal_cache
+
+ gview.set_preference( 'gdal_cache', str(gdal_cache) )
+ gdal.SetCacheMax( gdal_cache )
+
+ gview.set_preference( 'gvraster_cache', str(gvraster_cache) )
+ gview.raster_cache_set_max(gvraster_cache)
+
+ def tcache_cb(self, *args):
+ value = int(self.texture_cache.get_text())
+ if value > 4000000:
+ gview.set_preference( 'texture_cache', str(value) )
+ gview.texture_cache_set_max(value)
+ else:
+ self.texture_cache.set_text(str(gview.texture_cache_get_max()))
+
+ def create_tracking_tool_prefs(self):
+ self.ttp = gtk.GtkVBox(spacing=10)
+ self.ttp.set_border_width(10)
+ self.notebook.append_page( self.ttp, gtk.GtkLabel('Tracking Tool'))
+ table = gtk.GtkTable(rows=4, cols=2)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+ self.ttp.pack_start(table, expand=FALSE)
+
+ # Coordinate
+ coord_label = gtk.GtkLabel('Coordinate:')
+ coord_label.set_alignment(0, 0.5)
+ table.attach(coord_label, 0, 1, 0, 1)
+
+ self.coord_om = gvutils.GvOptionMenu(
+ ('Off','Raster Pixel/Line','Georeferenced','Geodetic (lat/long)'),
+ self.set_coordinate_mode)
+ table.attach(self.coord_om, 1, 2, 0, 1)
+
+ if gview.get_preference('_coordinate_mode') is not None:
+ if gview.get_preference('_coordinate_mode') == 'raster':
+ self.coord_om.set_history(1)
+ elif gview.get_preference('_coordinate_mode') == 'georef':
+ self.coord_om.set_history(2)
+ elif gview.get_preference('_coordinate_mode') == 'latlong':
+ self.coord_om.set_history(3)
+ else:
+ self.coord_om.set_history(0)
+ else:
+ self.coord_om.set_history(2)
+
+ # Lat/Long Display format (dms or decimal)
+ degree_mode_label = gtk.GtkLabel('Lat/Long Format:')
+ degree_mode_label.set_alignment(0, 0.5)
+ table.attach(degree_mode_label, 0, 1, 1, 2)
+
+ self.degree_mode_om = gvutils.GvOptionMenu(('ddd:mm:ss.ss', \
+ 'ddd.ddddddd'), self.set_degree_mode)
+ table.attach(self.degree_mode_om, 1, 2, 1, 2)
+
+ if gview.get_preference('_degree_mode') is not None \
+ and gview.get_preference('_degree_mode') == 'decimal':
+ self.degree_mode_om.set_history(1)
+ else:
+ self.degree_mode_om.set_history(0)
+
+ # Raster Value
+ pixel_mode_label = gtk.GtkLabel('Pixel Value:')
+ pixel_mode_label.set_alignment(0, 0.5)
+ table.attach(pixel_mode_label, 0, 1, 2, 3)
+
+ self.pixel_mode_om = \
+ gvutils.GvOptionMenu(('On','Off'), self.set_pixel_mode)
+ table.attach(self.pixel_mode_om, 1, 2, 2, 3)
+
+ if gview.get_preference('_pixel_mode') is not None \
+ and gview.get_preference('_pixel_mode') == 'off':
+ self.pixel_mode_om.set_history(1)
+ else:
+ self.pixel_mode_om.set_history(0)
+
+ # NODATA mark
+ nodata_mode_label = gtk.GtkLabel('Show NODATA mark:')
+ nodata_mode_label.set_alignment(0, 0.5)
+ table.attach(nodata_mode_label, 0, 1, 3, 4)
+
+ self.nodata_mode_om = \
+ gvutils.GvOptionMenu(('On','Off'), self.set_nodata_mode)
+ table.attach(self.nodata_mode_om, 1, 2, 3, 4)
+
+ if gview.get_preference('_nodata_mode') is not None \
+ and gview.get_preference('_nodata_mode') == 'off':
+ self.nodata_mode_om.set_history(1)
+ else:
+ self.nodata_mode_om.set_history(0)
+
+ def set_coordinate_mode(self, om):
+ if self.coord_om.get_history() == 0:
+ gview.set_preference( '_coordinate_mode', 'off')
+ elif self.coord_om.get_history() == 1:
+ gview.set_preference( '_coordinate_mode', 'raster')
+ elif self.coord_om.get_history() == 2:
+ gview.set_preference( '_coordinate_mode', 'georef')
+ elif self.coord_om.get_history() == 3:
+ gview.set_preference( '_coordinate_mode', 'latlong')
+
+ def set_pixel_mode(self, om):
+ if om.get_history() == 1:
+ gview.set_preference( '_pixel_mode', 'off')
+ else:
+ gview.set_preference( '_pixel_mode', 'on')
+
+ def set_nodata_mode(self, om):
+ if om.get_history() == 1:
+ gview.set_preference( '_nodata_mode', 'off')
+ else:
+ gview.set_preference( '_nodata_mode', 'on')
+
+ def set_degree_mode(self, om):
+ if om.get_history() == 1:
+ gview.set_preference( '_degree_mode', 'decimal')
+ else:
+ gview.set_preference( '_degree_mode', 'dms')
+
+ def set_gcp_warp_mode(self, om):
+ if om.get_history() == 1:
+ gview.set_preference( 'gcp_warp_mode', 'no' )
+ else:
+ gview.set_preference( 'gcp_warp_mode', 'yes' )
+
+ def set_sample_method(self, om):
+ if om.get_history() == 0:
+ gview.set_preference( 'default_raster_sample', 'sample' )
+ else:
+ gview.set_preference( 'default_raster_sample', 'average' )
+
+ def set_interp_method(self, im):
+ if im.get_history() == 0:
+ gview.set_preference( 'interp_mode', 'linear' )
+ else:
+ gview.set_preference( 'interp_mode', 'nearest' )
+
+ def set_scaling_method(self, om):
+ if om.get_history() == 0:
+ gview.set_preference( 'scale_algorithm', 'percent_tail_trim' )
+ else:
+ gview.set_preference( 'scale_algorithm', 'std_deviation' )
+
+ def tail_trim_cb(self,*args):
+ try:
+ gview.set_preference( 'scale_percent_tail',
+ str(float(self.tt_entry.get_text())/100.0) )
+ except:
+ pass
+
+ def std_dev_cb(self,*args):
+ try:
+ if float(self.sd_entry.get_text()) > 0.0:
+ gview.set_preference( 'scale_std_deviations',
+ self.sd_entry.get_text())
+ except:
+ pass
+
+ def set_save_recent_dir(self, om):
+ if om.get_history() == 0:
+ gview.set_preference( 'save_recent_directory', 'off')
+ else:
+ gview.set_preference( 'save_recent_directory', 'on')
+
+ def page_legend(self):
+ """
+ properties for the legend dialog
+ """
+ import pgucolor
+ import pgufont
+
+ vbox = gtk.GtkVBox()
+ table = gtk.GtkTable(rows=1, cols=3)
+ table.set_border_width(6)
+ table.set_row_spacings(6)
+ table.set_col_spacings(6)
+ vbox.pack_start(table)
+
+ # Background color
+ lbl = gtk.GtkLabel('Legend Background Color:')
+ table.attach(lbl, 0, 1, 0, 1,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+
+ color = gview.get_preference('legend-background-color',
+ str(self.default_color))
+
+ cb = pgucolor.ColorButton( pgucolor.color_string_to_tuple( color ) )
+ cb.connect('color-set', self.set_color_preference,
+ 'legend-background-color')
+ table.attach(cb, 1, 2, 0, 1,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(cb,
+ 'Click to change the default color for the legend background')
+
+ # Title Font
+ lbl = gtk.GtkLabel('Title Font:')
+ table.attach(lbl, 0, 1, 1, 2,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+
+ color = gview.get_preference('legend-title-font-color',
+ self.default_color)
+ cb = pgucolor.ColorButton( pgucolor.color_string_to_tuple( color ) )
+ cb.connect('color-set', self.set_color_preference,
+ 'legend-title-font-color')
+ table.attach(cb, 1, 2, 1, 2,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(cb,
+ 'Click to change the default color for the legend font')
+
+ title_font = pgufont.pguFontControl()
+ title_font.subscribe('font-changed', self.set_any_preference,
+ 'legend-title-font', title_font.get_font_string)
+ title_font.set_font(gview.get_preference('legend-title-font',
+ self.default_font))
+ table.attach(title_font, 2, 3, 1, 2,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(title_font, 'Select a font for the legend title')
+
+
+ # Label Font
+ lbl = gtk.GtkLabel('Label Font:')
+ table.attach(lbl, 0, 1, 2, 3,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ color = gview.get_preference('legend-label-font-color',
+ self.default_color)
+ cb = pgucolor.ColorButton( pgucolor.color_string_to_tuple( color ) )
+ cb.connect('color-set', self.set_color_preference,
+ 'legend-label-font-color')
+ table.attach(cb, 1, 2, 2, 3,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(cb,
+ 'Click to change the default color for the legend font')
+
+ label_font = pgufont.pguFontControl()
+ label_font.subscribe('font-changed', self.set_any_preference,
+ 'legend-label-font', label_font.get_font_string)
+ label_font.set_font(gview.get_preference('legend-label-font',
+ self.default_font))
+ table.attach(label_font, 2, 3, 2, 3,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(label_font, 'Select a font for legend labels')
+
+ # Sample Size
+
+ lbl = gtk.GtkLabel( 'Legend Samples:')
+ table.attach(lbl, 0, 1, 3, 4,
+ xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
+
+ lbl = gtk.GtkLabel( 'X Size:')
+ table.attach(lbl, 1, 2, 3, 4,
+ xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
+
+
+ x = gview.get_preference('legend-sample-x-size', 30)
+ y = gview.get_preference('legend-sample-y-size', 20)
+
+ spin_adjust = gtk.GtkAdjustment(value=float(x), lower=0.0,
+ upper=50.0, step_incr=1.0)
+ spin = gtk.GtkSpinButton(spin_adjust)
+ spin.set_digits(0)
+ spin.set_usize(75, 0)
+ spin.connect('changed', self.set_spin_preference,
+ 'legend-sample-x-size')
+ spin.connect('focus-out-event', self.check_spin_preference,
+ 'legend-sample-x-size')
+ table.attach(spin, 2, 3, 3, 4,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(spin, 'The X Size of a sample on the legend dialog')
+
+ lbl = gtk.GtkLabel( 'Y Size:')
+ table.attach(lbl, 3, 4, 3, 4,
+ xoptions=gtk.SHRINK, yoptions=gtk.SHRINK)
+
+ spin_adjust = gtk.GtkAdjustment(value=float(y), lower=0.0,
+ upper=50.0, step_incr=1.0)
+ spin = gtk.GtkSpinButton(spin_adjust)
+ spin.set_digits(0)
+ spin.set_usize(75, 0)
+ spin.connect('changed', self.set_spin_preference,
+ 'legend-sample-y-size')
+ spin.connect('focus-out-event', self.check_spin_preference,
+ 'legend-sample-y-size')
+ table.attach(spin, 4, 5, 3, 4,
+ xoptions = gtk.SHRINK, yoptions=gtk.SHRINK)
+ self.tips.set_tip(spin, 'The Y Size of a sample on the legend dialog')
+ return vbox
+
+ def set_entry_text(self, widget, dlg, entry, pref):
+ directory = dlg.get_directory()
+ entry.set_text(directory)
+ entry.grab_focus()
+ gview.set_preference( pref, directory )
+ dlg.destroy()
+
+ def set_color_preference(self, widget, color, pref):
+ """
+ """
+ gview.set_preference(pref, str(widget.get_color()))
+
+ def set_toggle_preference( self, widget, pref ):
+ """set a preference from a toggle button
+ """
+ gview.set_preference( pref, str(widget.get_active()) )
+
+ def set_any_preference(self, widget, pref, func):
+ """
+ set a preference from the results of a function call
+ """
+ gview.set_preference(pref, str(func()))
+
+ def set_directory_preference(self, widget, event, pref, func):
+ """
+ set a preference for a directory. Check the value first.
+ """
+ self.current_widget = widget
+
+ value = func()
+ if not os.path.isdir( value ) and value != "":
+ warning( "Invalid Path:\n%s" % value )
+ widget.set_text( gview.get_preference( pref, gview.home_dir) )
+ else:
+ self.set_any_preference(widget, pref, func)
+
+ def set_menu_preference(self, widget, pref, value):
+ """
+ """
+ gview.set_preference(pref, str(value))
+
+ def set_spin_preference(self, widget, pref):
+ """
+ """
+
+ if widget.get_text() != str(widget.get_value_as_int()):
+ if widget.get_text() == str(round(widget.get_value_as_float(),2)):
+ gview.set_preference( pref,
+ str(round(widget.get_value_as_float(),2)))
+ else:
+ try:
+ i = float( widget.get_text() )
+ except:
+ i = 0
+ widget.set_value( i )
+ else:
+ gview.set_preference(pref, str(widget.get_value_as_int()))
+
+ def check_spin_preference(self, widget, event, pref):
+ """
+ added to catch unset preferences in spin buttons on focus-out events.
+ """
+ self.set_spin_preference( widget, pref )
+
+
+
+class Position_3D_Dialog(gtk.GtkWindow):
+ def __init__(self, view_manager):
+ gtk.GtkWindow.__init__(self)
+ self.set_title('3D Position')
+ self.set_border_width(3)
+ self.create_position_dialog()
+ self.create_lookAt_dialog()
+ self.show_all()
+ self.view_manager = view_manager
+
+ def create_position_dialog(self):
+ self.dialog = gtk.GtkVBox(homogeneous=FALSE, spacing=3)
+ self.add(self.dialog)
+ self.dialog.pack_start(gtk.GtkLabel('Current Position:'))
+
+ # x
+ x_box = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ self.dialog.pack_start(x_box, expand=FALSE)
+
+ x = gtk.GtkLabel('X: ')
+ x_value = gtk.GtkEntry(maxlen=10)
+ x_value.set_text('')
+ x_box.pack_start(x, expand=FALSE)
+ x_box.pack_start(x_value, expand=FALSE)
+
+ # y
+ y_box = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ self.dialog.pack_start(y_box, expand=FALSE)
+
+ y = gtk.GtkLabel('Y: ')
+ y_value = gtk.GtkEntry(maxlen=10)
+ y_value.set_text('')
+ y_box.pack_start(y, expand=FALSE)
+ y_box.pack_start(y_value, expand=FALSE)
+
+ # z
+ z_box = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ self.dialog.pack_start(z_box, expand=FALSE)
+
+ z = gtk.GtkLabel('Z: ')
+ z_value = gtk.GtkEntry(maxlen=10)
+ z_value.set_text('')
+ z_box.pack_start(z, expand=FALSE)
+ z_box.pack_start(z_value, expand=FALSE)
+
+ self.x_value = x_value
+ self.y_value = y_value
+ self.z_value = z_value
+
+ self.x_value.connect('activate', self.set_position_cb)
+ self.x_value.connect('leave-notify-event',self.set_position_cb)
+ self.y_value.connect('activate', self.set_position_cb)
+ self.y_value.connect('leave-notify-event',self.set_position_cb)
+ self.z_value.connect('activate', self.set_position_cb)
+ self.z_value.connect('leave-notify-event',self.set_position_cb)
+
+
+ def create_lookAt_dialog(self):
+ # Assume create_position_dialog called
+
+ # Row or x
+ self.dialog.pack_start(gtk.GtkHSeparator())
+ self.dialog.pack_start(gtk.GtkLabel('Looking At Position:'))
+ row_box = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ self.dialog.pack_start(row_box, expand=FALSE)
+
+ row = gtk.GtkLabel('X: ')
+ row_value = gtk.GtkEntry(maxlen=10)
+ row_value.set_text('')
+ row_box.pack_start(row, expand=FALSE)
+ row_box.pack_start(row_value, expand=FALSE)
+
+ # Column or y
+ col_box = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ self.dialog.pack_start(col_box, expand=FALSE)
+
+ col = gtk.GtkLabel('Y: ')
+ col_value = gtk.GtkEntry(maxlen=10)
+ col_value.set_text('')
+ col_box.pack_start(col, expand=FALSE)
+ col_box.pack_start(col_value, expand=FALSE)
+
+ self.row_value = row_value
+ self.col_value = col_value
+
+ self.row_value.connect('activate', self.set_look_at_cb)
+ self.row_value.connect('leave-notify-event',self.set_look_at_cb)
+ self.col_value.connect('activate', self.set_look_at_cb)
+ self.col_value.connect('leave-notify-event',self.set_look_at_cb)
+
+
+ def update_cb(self, view, *args):
+ # Reset Dialog values
+
+ eye_pos = view.get_eye_pos()
+ if eye_pos:
+ self.x_value.set_text(str(round(eye_pos[0],2)))
+ self.y_value.set_text(str(round(eye_pos[1],2)))
+ self.z_value.set_text(str(round(eye_pos[2],2)))
+ else:
+ self.x_value.set_text('')
+ self.y_value.set_text('')
+ self.z_value.set_text('')
+
+ lookat_pos = view.get_look_at_pos()
+ if lookat_pos:
+ self.row_value.set_text(str(round(lookat_pos[0],2)))
+ self.col_value.set_text(str(round(lookat_pos[1],2)))
+ else:
+ self.row_value.set_text('')
+ self.col_value.set_text('')
+
+ def update_test(self, view, *args):
+ eye_pos = view.get_eye_pos()
+ lookat_pos = view.get_look_at_pos()
+
+ view.set_3d_view_look_at((eye_pos[0]+300, eye_pos[1], eye_pos[2]) , lookat_pos)
+
+
+
+ def set_look_at_cb(self, *args):
+ view = self.view_manager.get_active_view()
+
+ # get lookat values, except if at horizon, then None
+ try:
+ lookat_pos = (float(self.row_value.get_text()), float(self.col_value.get_text()))
+ except ValueError:
+ lookat_pos = None
+
+ eye_pos = view.get_eye_pos()
+
+ if lookat_pos:
+ view.set_3d_view_look_at(eye_pos, lookat_pos )
+
+ def set_position_cb(self, *args):
+ view = self.view_manager.get_active_view()
+
+ lookat_pos = view.get_look_at_pos()
+ eye_pos = ( float(self.x_value.get_text()),
+ float(self.y_value.get_text()),
+ float(self.z_value.get_text()))
+
+ # Could be looking at horizon
+ if lookat_pos:
+ view.set_3d_view_look_at(eye_pos, lookat_pos)
+ else:
+ eye_dir = view.get_eye_dir()
+ view.set_3d_view(eye_pos, eye_dir)
+
+
+
+class Tool_GViewApp:
+ # Abstract base class to derive tools from
+ def __init__(self,app=None):
+ self.app = app
+ self.menu_entries = Tool_GViewAppMenuEntries()
+ self.icon_entries = Tool_GViewAppIconEntries()
+ self.pymenu_entries = Tool_GViewAppMenuEntries()
+ self.pyicon_entries = Tool_GViewAppIconEntries()
+ # def set_menu(self):
+ # placeholder function- make self.menu_entries.set_entry
+ # calls here...
+ # pass
+
+
+class Tool_GViewAppMenuEntries:
+ # Class to store entries to be added to openev's menu
+ def __init__(self):
+ self.entries = {}
+
+ def set_entry(self,item,position=0,callback=None,accelerator=None):
+ # item = a string describing menu location
+ # position = default location in the menu (integer): Ignored if an
+ # xml menu entry is specified for the tool. Note:
+ # when used, the position refers to position in the
+ # lowest level menu. Eg. if a menu entry is
+ # 'File/menu1/entryN', position refer's to entryN's
+ # position within menu1, not menu1's position in
+ # File. For more flexibility, use the xml form of
+ # configuration.
+ # callback = callback
+ # accelerator = shortcut key
+
+ if (type(item) == type('')):
+ if (type(position) == type(0)):
+ self.entries[item] = (position,callback, accelerator)
+ else:
+ raise AttributeError,"position should be an integer"
+ else:
+ raise AttributeError,"Menu entry item must be a string"
+
+
+class Tool_GViewAppIconEntries:
+ # Class to store entries to be added to openev's menu
+ def __init__(self):
+ self.entries = []
+
+ def set_entry(self,iconfile,hint_text,position=0,callback=None,help_topic=None,label=None,icontype='xpm'):
+ # iconfile=icon filename (xpm case), or some other string not yet defined
+ # (pixmap/widget case- not yet supported- may never be)
+ # hint_text=tooltip text to use
+ # position = default location in the icon bar (integer)
+ # callback = callback
+ # help topic = html help file (not yet used by anything)
+ # label = some gtk think- not sure what this does
+ # icontype = 'xpm' (later may allow 'pixmap' or 'widget', but not yet)
+
+ if (type(iconfile) == type('')):
+ import os
+ if os.path.isfile(iconfile):
+ fullfilename=iconfile
+ elif os.path.isfile(os.path.join(gview.home_dir,'tools',iconfile)):
+ fullfilename=os.path.join(gview.home_dir,'tools',iconfile)
+ elif os.path.isfile(os.path.join(gview.home_dir,'pics',iconfile)):
+ fullfilename=os.path.join(gview.home_dir,'pics',iconfile)
+ else:
+ txt = "Cannot find file "+iconfile+'. Either the full\n'
+ txt = txt+"path must be specified, or "+iconfile+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
+
+ # On nt, path separators need to be trapped and doubled to avoid
+ # being interpreted as an escape before special characters.
+ if os.name == 'nt':
+ import string
+ fullfilename=string.replace(fullfilename,"\\","\\\\")
+
+ if (type(position) == type(0)):
+ self.entries.append((fullfilename,label,hint_text,position,callback,help_topic,icontype))
+ else:
+ raise AttributeError,"position should be an integer"
+ else:
+ txt = "Cannot find file "+iconfile+'. Either the full\n'
+ txt = txt+"path must be specified, or "+iconfile+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
Added: packages/openev/branches/upstream/current/pymod/gvlabeledit.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvlabeledit.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvlabeledit.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,313 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gvlabeledit.py,v 1.8 2002/12/10 15:49:11 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Label Edit Tool.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvlabeledit.py,v $
+# Revision 1.8 2002/12/10 15:49:11 gmwalter
+# Avoid checking "tool_name" on None object.
+#
+# Revision 1.7 2001/08/23 16:52:15 pgs
+# added default_ogrfs to __init__ to override built in default
+#
+# Revision 1.6 2001/08/07 18:17:25 pgs
+# pick up default color if avail and added\nmissing signal in close()
+#
+# Revision 1.5 2001/05/05 18:26:40 pgs
+# added optional interactive editing
+#
+# Revision 1.4 2001/05/04 19:03:40 pgs
+# split code for new label into separate method to support starting labels from another location
+#
+# Revision 1.3 2001/05/04 02:58:31 pgs
+# some bug fixes
+#
+# Revision 1.2 2001/04/24 14:24:46 warmerda
+# added indirect text application, various cleanup
+#
+# Revision 1.1 2001/04/23 21:20:28 warmerda
+# New
+#
+#
+
+from gtk import *
+import gview
+import string
+import gvselbrowser
+import pgucolorsel
+import gvutils
+import gvogrfs
+import gvogrfsgui
+import pgufont
+
+def launch(interactive=FALSE):
+ try:
+ gview.gvlabeledit.get_window()._raise()
+ except:
+ gview.gvlabeledit = GvLabelEdit(interactive = interactive)
+
+ return gview.gvlabeledit
+
+
+class GvLabelEdit(GtkWindow):
+
+ def __init__(self, interactive=FALSE, default_ogrfs = None):
+ GtkWindow.__init__(self)
+ self.set_title('Label Edit Tool')
+ gview.app.sel_manager.subscribe( 'active-layer-changed',
+ self.gui_update )
+ gview.app.sel_manager.subscribe( 'selection-changed',
+ self.gui_update )
+ gview.app.sel_manager.subscribe( 'subselection-changed',
+ self.gui_update )
+
+ if default_ogrfs is None:
+ font = pgufont.XLFDFontSpec()
+ default_font = gview.get_preference('label-font')
+ if default_font is None:
+ font.set_font_part('Family', 'fixed')
+ else:
+ font.parse_font_spec(default_font)
+
+ color = gview.get_preference('label-color')
+
+ if color is None:
+ color = "#88FF88"
+ else:
+ try:
+ color = string.replace( color, "(", "" )
+ color = string.replace( color, ")", "" )
+ r, g, b, a = string.split( color, "," )
+ r = float(r)
+ g = float(g)
+ b = float(b)
+ a = float(a)
+ color = ( r, g, b, a )
+ color = gvogrfs.gv_to_ogr_color( color )
+ except:
+ color = "#88FF88"
+ default_ogrfs = 'LABEL(t:"",f:"%s",c:%s)' % (font, color)
+
+
+ self.default_ogrfs = default_ogrfs
+ self.selected_shape = None
+ self.layer = None
+ self.interactive = interactive
+ self.create_gui()
+ self.show()
+
+ self.edit_mode = 0
+
+ self.view = gview.app.view_manager.get_active_view()
+ self.key_sig = self.view.connect('key-press-event', self.key_press_cb)
+ self.connect('delete-event', self.close)
+
+ self.gui_update()
+
+ def close(self, window, event):
+ gview.app.sel_manager.unsubscribe( 'selection-changed',
+ self.gui_update )
+ gview.app.sel_manager.unsubscribe( 'subselection-changed',
+ self.gui_update )
+ gview.app.sel_manager.unsubscribe( 'active-layer-changed',
+ self.gui_update )
+ #remember to disconnect from the view's key press event
+ self.view.disconnect(self.key_sig)
+
+ def create_gui(self):
+ box1 = GtkVBox(spacing=10)
+ box1.set_border_width(10)
+ self.add(box1)
+ box1.show()
+
+ #######################################################################
+ # Create a control box for the text related widgets.
+ self.text_frame = GtkFrame('Text Style')
+ box1.pack_start(self.text_frame,expand=FALSE)
+
+ self.label_style = gvogrfsgui.GvLabelStyle(text_entry = TRUE,
+ label_field = FALSE,
+ interactive = self.interactive)
+ self.label_style.subscribe('ogrfs-changed', self.label_ogrfs_cb)
+ self.label_style.subscribe('apply-text-to-field',
+ self.text_apply_cb)
+ self.text_frame.add(self.label_style)
+ self.text_frame.show()
+
+ def set_default_ogrfs(self, prototype):
+ if prototype is None or len(prototype) == 0:
+ return
+
+ try:
+ ogrfs_obj = gvogrfs.OGRFeatureStylePart()
+ ogrfs_obj.parse( prototype )
+ except:
+ return
+
+ text_parm = gvogrfs.OGRFeatureStyleParam()
+ text_parm.parse('t:""')
+ ogrfs_obj.set_parm( text_parm )
+
+ self.default_ogrfs = ogrfs_obj.unparse()
+
+ def text_apply_cb(self, widget, field, value ):
+ try:
+ self.layer = gview.app.sel_manager.get_active_layer()
+ shapes = self.layer.get_parent()
+ self.selected_shape = self.layer.get_subselected()
+ shape_obj = shapes[self.selected_shape]
+ except:
+ self.selected_shape = -1
+ shape_obj = None
+
+ if shape_obj is None:
+ return
+
+ shape_obj = shape_obj.copy()
+ shape_obj.set_property( field, value )
+ shapes[self.selected_shape] = shape_obj
+
+ self.gui_update()
+
+ def label_ogrfs_cb(self, *args):
+ self.edit_mode = 0
+
+ try:
+ shape_obj = (self.layer.get_parent())[self.selected_shape]
+ except:
+ shape_obj = None
+
+ if shape_obj is None:
+ return
+
+ if self.label_style.ogrfs_obj is None:
+ ogrfs = ''
+ else:
+ ogrfs = self.label_style.ogrfs_obj.unparse()
+ self.set_default_ogrfs( ogrfs )
+
+ style = gvogrfs.OGRFeatureStyle()
+ try:
+ #the shape may or may not have a property already.
+ style.parse(shape_obj._gv_ogrfs)
+ except:
+ style.parse(self.layer.get_property('_gv_ogrfs'))
+
+ style.parse_part(ogrfs)
+
+ shape_obj = shape_obj.copy()
+ shape_obj._gv_ogrfs = style.unparse()
+ (self.layer.get_parent())[self.selected_shape] = shape_obj
+
+ def gui_update(self,*args):
+ self.edit_mode = 0
+
+ try:
+ self.layer = gview.app.sel_manager.get_active_layer()
+ shapes = self.layer.get_parent()
+ self.selected_shape = self.layer.get_subselected()
+ shape_obj = shapes[self.selected_shape]
+ except:
+ self.selected_shape = -1
+ shape_obj = None
+
+ if shape_obj is None:
+ # add stuff to grey out interface.
+ self.label_style.set_sensitive(FALSE)
+ return
+ else:
+ self.label_style.set_sensitive(TRUE)
+
+ try:
+ ogrfs = shape_obj._gv_ogrfs
+ except:
+ ogrfs = None
+
+ change_enabled = 1
+ if ogrfs is None:
+ ogrfs = self.layer.get_property('_gv_ogrfs')
+ if ogrfs is not None:
+ change_enabled = 0
+
+ # Parse the ogrfs.
+ try:
+ ogrfs_obj = gvogrfs.OGRFeatureStyle()
+ ogrfs_obj.parse( ogrfs )
+ label_obj = ogrfs_obj.get_part('LABEL')
+ if label_obj is not None:
+ self.set_default_ogrfs( label_obj.unparse() )
+ except:
+ ogrfs_obj = None
+
+ # Display type specific information.
+ if ((ogrfs_obj is None) or
+ ((label_obj is not None) and label_obj.tool_name == 'LABEL')):
+ self.label_style.set_ogrfs( label_obj, layer = self.layer,
+ shape_obj = shape_obj )
+ self.label_style.show()
+
+ def key_press_cb(self, view, event, *args):
+ if self.edit_mode:
+ self.label_style.text_input(event.keyval)
+ if event.keyval == GDK.Return:
+ self.edit_mode = 0
+ return TRUE
+
+ #######################################################################
+ # We only want to respond to <ENTER> keystrokes.
+ if event.keyval != GDK.Return:
+ return
+
+ if self.layer is None:
+ print 'gvlabeledit: no layer'
+ return
+
+ self.view = gview.app.view_manager.get_active_view()
+ self.new_label()
+
+
+ def new_label(self):
+ #######################################################################
+ # Create a new point shape at the current pointer location.
+
+ pointer_loc = self.view.get_pointer()
+ new_label = gview.GvShape(type=gview.GVSHAPE_POINT)
+ new_label.set_node(pointer_loc[0], pointer_loc[1])
+ new_label._gv_ogrfs = self.default_ogrfs
+
+ #######################################################################
+ # Attach it to the current layer, and make it selected.
+
+ shapes = self.layer.get_parent()
+ id = shapes.append(new_label)
+ self.layer.clear_selection()
+ self.layer.select_shape(id)
+
+ self.edit_mode = 1
+
+ self.get_window()._raise()
+ self.label_style.text_entry.grab_focus()
+
+
Added: packages/openev/branches/upstream/current/pymod/gvlegenddlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvlegenddlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvlegenddlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,424 @@
+###############################################################################
+# $Id: gvlegenddlg.py,v 1.21 2004/01/20 19:45:51 gmwalter Exp $
+#
+# Project: CIETMap / OpenEV
+# Purpose: Implement Legend Display Dialog
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Frank Warmerdam <warmerda at home.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvlegenddlg.py,v $
+# Revision 1.21 2004/01/20 19:45:51 gmwalter
+# Get a default font if preferred one can't
+# be loaded, fix window title.
+#
+# Revision 1.20 2002/09/10 15:43:54 pgs
+# updated for new gvclassification (removed deprecated calls)
+#
+# Revision 1.19 2002/08/28 18:04:26 pgs
+# removed sys.stdout.flush() to prevent problems on windows when running
+# with no console.
+#
+# Revision 1.18 2002/08/13 17:43:31 pgs
+# fixed raster classification and fixed legend for point layers
+#
+# Revision 1.17 2002/08/01 20:11:45 warmerda
+# minor changes for vector capable classifications
+#
+# Revision 1.16 2001/07/06 17:02:53 warmerda
+# Use Pixel Size instead of Point Size for defaults
+#
+# Revision 1.15 2001/07/01 03:05:34 pgs
+# modified resize logic
+#
+# Revision 1.14 2001/05/25 16:22:09 pgs
+# resize legend to accomodate all classes
+#
+# Revision 1.13 2001/05/14 15:40:05 pgs
+# handle multi-line titles
+#
+# Revision 1.12 2001/05/12 16:15:22 pgs
+# made sample size configurable
+#
+# Revision 1.11 2001/05/08 17:03:33 pgs
+# fixed bugs in font handling
+#
+# Revision 1.10 2001/04/14 14:53:38 pgs
+# added ability to control legend title and label font, color and size
+#
+# Revision 1.9 2001/03/21 05:35:45 warmerda
+# don't print messages in view_state_cb
+#
+# Revision 1.8 2001/02/20 20:40:21 pgs
+# fixed error from changing gvclassification
+#
+# Revision 1.7 2000/10/19 16:44:42 warmerda
+# made changes to organize the legend into columns to fit better
+#
+# Revision 1.6 2000/10/17 19:00:51 pgs
+# fixed legend refresh problem
+#
+# Revision 1.5 2000/10/09 18:52:30 pgs
+# modified show_legend to return the legend just opened and added find_legend to find
+# a legend attached to a raster (for printing).
+#
+# Revision 1.4 2000/10/06 16:48:56 warmerda
+# added GvViewArea background color
+#
+# Revision 1.3 2000/10/06 15:58:19 warmerda
+# ensure only one legend per layer, and destroy when layer is destroyed
+#
+# Revision 1.2 2000/09/27 14:35:27 warmerda
+# added auto update of legend, and classification serial numbers
+#
+# Revision 1.1 2000/09/21 03:02:01 warmerda
+# New
+#
+#
+
+from gtk import *
+import gview
+import gvclassification
+from gvogrfs import gv_to_ogr_color
+from pgucolor import color_string_to_tuple
+import pgufont
+import string
+import sys
+import gdal
+
+legend_dialogs = []
+
+def show_legend( layer ):
+
+ for ld in legend_dialogs:
+ if ld.layer._o == layer._o:
+ ld.show()
+ ld.get_window()._raise()
+ return ld
+
+ ld = GvLegendDialog()
+ ld.set_raster( layer )
+ legend_dialogs.append( ld )
+ return ld
+
+def find_legend( layer ):
+
+ for ld in legend_dialogs:
+ if ld.layer._o == layer._o:
+ return ld
+ return None
+
+#
+# It was my goal to have the GvLegendDialog use the GvLegendView to
+# implement the legend, and that the GvLegendView would manage a legend
+# at some assign region of an existing GvViewArea so that legend could
+# eventually be embedded in other views. I haven't gotten around to that
+# yet, but it is still my eventual goal.
+#
+class GvLegendView:
+ def __init__(self):
+ pass
+
+class GvLegendDialog(GtkWindow):
+
+ def __init__(self):
+ GtkWindow.__init__(self)
+
+ self.layer = None
+ self.teardown_id = None
+ self.changed_id = None
+ self.resizing = FALSE
+ self.resize_count = 0
+
+ self.set_title('Legend: Empty')
+ self.set_policy(TRUE,TRUE,FALSE)
+ self.set_usize(300, 300)
+ self.viewarea = gview.GvViewArea()
+ back_color = gview.get_preference('legend-background-color')
+ if back_color is None:
+ back_color = (1.0, 1.0, 1.0, 1.0 )
+ else:
+ back_color = color_string_to_tuple(back_color)
+
+ self.viewarea.set_background_color( back_color )
+ self.shapes = gview.GvShapes()
+ self.vlayer = gview.GvShapesLayer(self.shapes)
+ self.viewarea.add_layer( self.vlayer )
+ self.add( self.viewarea )
+
+ self.connect( 'delete-event', self.close )
+ self.show_all()
+
+ self.viewarea.fit_extents(0,
+ self.viewarea.get_height(),
+ self.viewarea.get_width(),
+ -self.viewarea.get_height() )
+
+ self.changing_view_state = 0
+ self.viewarea.connect('view-state-changed', self.view_state_cb )
+
+ def set_raster(self, layer ):
+ self.layer = layer
+
+ self.changed_id = self.layer.connect('changed',
+ self.check_for_legend_change_cb )
+ self.teardown_id = self.layer.connect('teardown', self.close )
+
+ self.classification = gvclassification.GvClassification()
+ self.classification.add_layer( layer )
+
+ self.prepare_legend()
+
+ def prepare_legend(self):
+
+ if self.resizing:
+ return
+
+ if self.layer.get_property('Class_sn') is not None:
+ self.Class_sn = int(self.layer.get_property('Class_sn'))
+
+ #remove any existing shapes
+ self.shapes.delete_shapes(range(len(self.shapes)))
+
+ samp_x_size = gview.get_preference('legend-sample-x-size')
+ if samp_x_size is None:
+ samp_x_size = 20
+ else:
+ samp_x_size = int(samp_x_size)
+
+ samp_y_size = gview.get_preference('legend-sample-y-size')
+ if samp_y_size is None:
+ samp_y_size = 20
+ else:
+ samp_y_size = int(samp_y_size)
+
+
+ title_font = pgufont.XLFDFontSpec()
+ font_spec = gview.get_preference('legend-title-font')
+ if font_spec is None:
+ title_font.set_font_part('Family', 'times')
+ title_font.set_font_part('Pixel Size', '20')
+ else:
+ title_font.parse_font_spec(font_spec)
+
+
+ title_font_color = gview.get_preference('legend-title-font-color')
+ if title_font_color is None:
+ title_font_color = (0.0, 0.0, 0.0, 1.0)
+ else:
+ title_font_color = color_string_to_tuple(title_font_color)
+ title_ogr_color = gv_to_ogr_color(title_font_color)
+
+ label_font = pgufont.XLFDFontSpec()
+ font_spec = gview.get_preference('legend-label-font')
+ if font_spec is None:
+ label_font.set_font_part('Family', 'times')
+ label_font.set_font_part('Pixel Size', '14')
+ else:
+ label_font.parse_font_spec(font_spec)
+
+ label_font_color = gview.get_preference('legend-label-font-color')
+ if label_font_color is None:
+ label_font_color = (0.0, 0.0, 0.0, 1.0)
+ else:
+ label_font_color = color_string_to_tuple(label_font_color)
+ label_ogr_color = gv_to_ogr_color(label_font_color)
+
+ #handle large fonts in the sample text
+ try:
+ gdk_font = load_font(str(label_font))
+ except:
+ # get a default font if preferred one
+ # can't be loaded.
+ gdk_font = load_font('*')
+
+ h = gdk_font.height("Wj")
+ samp_offset = max(samp_y_size, h) + 10
+
+ #handle multi-line text for the title.
+ try:
+ gdk_title_font = load_font(str(title_font))
+ except:
+ gdk_title_font = load_font('*')
+
+ lines = string.split(self.classification.title, '\\n')
+
+ x_offset = 10 #start title 10 pixels in from left edge
+ col_offset = 30 #space columns apart
+ y_offset = 35 #start title 35 pixels down from top edge
+ title_width = 0
+ max_height = 0
+
+ #resize the window appropriately
+
+ title_height = y_offset
+ title_width = 0
+ for idx in range(len(lines)):
+ line = lines[idx]
+ title_height = title_height + gdk_title_font.height(line)
+ title_width = max(title_width, gdk_title_font.width(line))
+
+ title_height = title_height + 10
+ title_width = x_offset + title_width + 10
+
+ cols = int (self.classification.count / 8)
+ samps = min( 8, self.classification.count )
+
+ samp_height = samps * (samp_offset) + 10
+ samp_width = x_offset
+
+ for i in range( cols + 1):
+ idx = 8 * i
+ col_width = 0
+ while idx < self.classification.count and idx < 8 * (i + 1):
+ name = self.classification.name[idx]
+ width = samp_x_size + 20 + gdk_font.width(name)
+ col_width = max(col_width, width)
+ idx = idx + 1
+ samp_width = samp_width + col_width + col_offset
+ samp_width = samp_width + 10
+
+ total_width = max(title_width, samp_width)
+ total_height = title_height + samp_height
+
+ self.resizing = TRUE
+
+ if (self.get_window().width < total_width) or \
+ (self.get_window().height < total_height):
+ self.resize_count = self.resize_count + 1
+ if self.resize_count < 2:
+ self.set_usize(total_width, total_height)
+
+ self.resizing = FALSE
+
+ for idx in range(len(lines)):
+ line = lines[idx]
+ w = gdk_title_font.width(line)
+ h = gdk_title_font.height(line)
+ title_width = max(title_width, w)
+
+ samp_text = gview.GvShape()
+ samp_text.add_node( x_offset, y_offset )
+ samp_text.set_property( '_gv_ogrfs',
+ 'LABEL(c:' + title_ogr_color + \
+ ',f:"' + str(title_font) + '",' \
+ + 't:"' + line + '")' )
+
+ self.shapes.append(samp_text)
+ y_offset = y_offset + h
+
+ if ((len(lines[0]) > 6) and (lines[0][:6] != 'Legend') and
+ (lines[0][:6] != 'legend')):
+ self.set_title('Legend: ' + lines[0] + '...')
+ else:
+ self.set_title(lines[0] + '...')
+
+ y_offset = y_offset + 10
+ title_offset = y_offset
+
+ max_width = 0
+ max_height = 0
+
+ for class_id in range(self.classification.count):
+ color = self.classification.get_color( class_id )
+ symbol = self.classification.get_symbol( class_id )
+ scale = self.classification.get_scale( class_id )
+ if symbol is not None:
+ samp = gview.GvShape( type = gview.GVSHAPE_POINT )
+ samp.add_node( x_offset + (samp_x_size/2),
+ y_offset + (samp_y_size/2) )
+ ogrfs_color = '#%02x%02x%02x%02x' % (int(color[0] * 255.999),
+ int(color[1] * 255.999),
+ int(color[2] * 255.999),
+ int(color[3] * 255.999))
+ ogrfs = "SYMBOL(id:%s,c:%s,s:%s)" % (symbol, ogrfs_color,
+ scale)
+ samp.set_property( "_gv_ogrfs", ogrfs )
+ else:
+ samp = gview.GvShape( type = gview.GVSHAPE_AREA )
+ samp.add_node( x_offset, y_offset )
+ samp.add_node( x_offset+samp_x_size, y_offset )
+ samp.add_node( x_offset+samp_x_size, y_offset+samp_y_size )
+ samp.add_node( x_offset, y_offset+samp_y_size )
+ samp.add_node( x_offset, y_offset )
+
+ color = '%f %f %f %f' % color
+
+ samp.set_property( '_gv_color', color )
+ samp.set_property( '_gv_fill_color', color )
+
+ self.shapes.append( samp )
+
+ name = self.classification.name[class_id]
+ samp_text = gview.GvShape()
+ samp_text.add_node( x_offset+samp_x_size+10, y_offset + 17 )
+ font = str(label_font)
+ samp_text.set_property( '_gv_ogrfs',
+ 'LABEL(c:' + label_ogr_color + \
+ ',f:"'+font+'",t:"'+name+'")' )
+ self.shapes.append( samp_text )
+
+ this_width = samp_x_size + 20 + gdk_font.width(name)
+ if max_width < this_width:
+ max_width = this_width
+
+ y_offset = y_offset + samp_offset
+
+ if y_offset+samp_offset > self.viewarea.get_height():
+ max_height = max(max_height, y_offset + samp_offset)
+ y_offset = title_offset
+ x_offset = x_offset + col_offset + max_width
+ max_width = 0
+
+ self.vlayer.changed()
+
+ def check_for_legend_change_cb(self,*args):
+ if self.layer.get_property('Class_sn') is not None:
+ if int(self.layer.get_property('Class_sn')) == self.Class_sn:
+ return
+ self.classification.remove_layer( self.layer )
+ self.classification.add_layer( self.layer )
+ self.prepare_legend()
+
+ def view_state_cb( self, *args ):
+ if self.changing_view_state != 0:
+ return
+
+ self.changing_view_state = 1
+ self.viewarea.fit_extents(0,
+ self.viewarea.get_height(),
+ self.viewarea.get_width(),
+ -self.viewarea.get_height() )
+ self.prepare_legend()
+ self.changing_view_state = 0
+
+ def close( self, *args ):
+ if self.teardown_id is not None:
+ self.layer.disconnect(self.teardown_id )
+ self.layer.disconnect(self.changed_id )
+
+ try:
+ legend_dialogs.remove(self)
+ except:
+ print 'GvLegendDialog.remove failed.'
+
+ self.layer = None
+ self.destroy()
+
Added: packages/openev/branches/upstream/current/pymod/gvmaptools.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvmaptools.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvmaptools.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,754 @@
+#! /usr/bin/env python
+##############################################################################
+# $Id: gvmaptools.py,v 1.1 2004/01/07 20:41:48 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Grid layers, north arrows, etc.
+# Author: Gillian Walter <gillian.walter at atlantis-scientific.com>
+#
+# Developed by Atlantis Scientific Inc. (www.atlantis-scientific.com) for
+# DRDC Ottawa
+#
+###############################################################################
+# Copyright (c) Her majesty the Queen in right of Canada as represented
+# by the Minister of National Defence, 2003.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvmaptools.py,v $
+# Revision 1.1 2004/01/07 20:41:48 gmwalter
+# Initial check-in of plotting and
+# annotation layer modules developed
+# for DRDC Ottawa.
+#
+#
+
+import gview
+import Numeric
+import gtk
+import os
+import gvogrfs
+import string
+
+#########################################################################
+# Grid/graticule layers #
+#########################################################################
+
+def SimpleReferenceGrid(min_x,min_y,max_x,max_y,x_divisions,y_divisions,
+ color=(0.5,1.0,0.5,1.0),xoff=-0.15,yoff=-0.04,
+ label_type=None,shapes_name="Grid"):
+ """ Create a reference grid for an unprojected raster.
+ min_x, min_y- minimum lat/longs, in decimal degrees
+ max_x, max_y- minimum lat/longs, in decimal degrees
+ x_divisions- number of divisions in horizontal direction
+ y_divisions- number of divisions in vertical direction
+ xoff- horizontal offset of vertical labels, as a fraction
+ of max_x-min_x. Offset is relative to min_x.
+ yoff- vertical offset of horizontal labels, as a fraction
+ of max_y-min_y. Offset is relative to min_y.
+ color- start color for the grid
+ label_type- not used yet; might be later for formatting.
+
+ """
+
+ shps=gview.GvShapes(name=shapes_name)
+ gview.undo_register( shps )
+ shps.add_field('position','string',20)
+
+ if os.name == 'nt':
+ font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ else:
+ #font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ #font="-urw-helvetica-medium-r-normal-*-9-*-*-*-p-*-iso8859-2"
+ font="-adobe-helvetica-medium-r-normal-*-8-*-*-*-p-*-iso10646-1"
+ #font="-misc-fixed-medium-r-*-*-9-*-*-*-*-*-*-*"
+
+
+ lxoff=(max_x-min_x)*xoff # horizontal label placement
+ lyoff=(max_y-min_y)*yoff # vertical label placement
+
+ hspc=(max_x-min_x)/x_divisions
+ vspc=(max_y-min_y)/y_divisions
+
+ for hval in Numeric.arange(min_x,max_x+hspc/100.0,hspc):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(hval,max_y,0,0)
+ nshp.set_node(hval,min_y,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(hval,min_y+lyoff)
+ pshp.set_property('position',"%.1f" % hval)
+ shps.append(pshp)
+
+ for vval in Numeric.arange(min_y,max_y+vspc/100.0,vspc):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(min_x,vval,0,0)
+ nshp.set_node(max_x,vval,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(min_x+lxoff,vval)
+ pshp.set_property('position',"%.1f" % vval)
+ shps.append(pshp)
+
+ cstr=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr) < 9:
+ cstr=cstr+"FF"
+ clstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+' '+str(color[3])
+
+ layer=gview.GvShapesLayer(shps)
+ layer.set_property('_line_color',clstr)
+ layer.set_property('_point_color',clstr)
+ # Set antialias property so that lines look nice
+ # when rotated.
+ layer.set_property('_gl_antialias','1')
+ layer.set_property('_gv_ogrfs_point',
+ 'LABEL(t:{position},f:"'+font+'",c:'+cstr+')')
+ layer.set_read_only(gtk.TRUE)
+
+ return layer
+
+
+def SimpleMeasuredGrid(min_x,min_y,max_x,max_y,x_spacing,y_spacing,
+ color=(0.5,1.0,0.5,1.0),xoff=-0.14,yoff=1.04,
+ label_type=None,shapes_name="Grid"):
+ """ Create a reference grid for a utm-projected raster.
+ min_x, min_y, max_x, max_y- extents that grid should cover
+ x_spacing- line spacing in horizontal direction
+ y_spacing- line spacing in vertical direction
+ xoff- horizontal offset of vertical labels, as a fraction
+ of max_x-min_x. Offset is relative to min_x.
+ yoff- vertical offset of horizontal labels, as a fraction
+ of max_y-min_y. Offset is relative to min_y.
+ color- start color for the grid
+ label_type- not used yet; might be later for formatting.
+ shapes_name- name to give the shapes forming the layer.
+
+ """
+
+ shps=gview.GvShapes(name=shapes_name)
+ gview.undo_register( shps )
+ shps.add_field('position','string',20)
+
+ if os.name == 'nt':
+ font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ else:
+ #font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ #font="-urw-helvetica-medium-r-normal-*-9-*-*-*-p-*-iso8859-2"
+ font="-adobe-helvetica-medium-r-normal-*-8-*-*-*-p-*-iso10646-1"
+ #font="-misc-fixed-medium-r-*-*-9-*-*-*-*-*-*-*"
+
+
+ # Round to nearest integer space
+ max_x=min_x+Numeric.floor((max_x-min_x)/x_spacing)*x_spacing
+ max_y=min_y+Numeric.floor((max_y-min_y)/y_spacing)*y_spacing
+
+ lxoff=(max_x-min_x)*xoff # horizontal label placement
+ lyoff=(max_y-min_y)*yoff # vertical label placement
+
+ for hval in Numeric.arange(min_x,
+ max_x+x_spacing/100.0,
+ x_spacing):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(hval,max_y,0,0)
+ nshp.set_node(hval,min_y,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(hval,min_y+lyoff)
+ pshp.set_property('position',"%d" % int(hval+0.5))
+ shps.append(pshp)
+
+ for vval in Numeric.arange(min_y,
+ max_y+y_spacing/100.0,
+ y_spacing):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(min_x,vval,0,0)
+ nshp.set_node(max_x,vval,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(min_x+lxoff,vval)
+ pshp.set_property('position',"%d" % int(vval+0.5))
+ shps.append(pshp)
+
+ cstr=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr) < 9:
+ cstr=cstr+"FF"
+ clstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+' '+str(color[3])
+
+ layer=gview.GvShapesLayer(shps)
+ layer.set_property('_line_color',clstr)
+ layer.set_property('_point_color',clstr)
+ # Set antialias property so that lines look nice
+ # when rotated.
+ layer.set_property('_gl_antialias','1')
+ layer.set_property('_gv_ogrfs_point',
+ 'LABEL(t:{position},f:"'+font+'",c:'+cstr+')')
+ layer.set_read_only(gtk.TRUE)
+
+ return layer
+
+
+def SimpleLatLongGrid(min_x,min_y,max_x,max_y,hdeg,hmin,hsec,vdeg,vmin,vsec,
+ color=(0.5,1.0,0.5,1.0),xoff=-0.18,yoff=1.04,
+ label_type=None,shapes_name="Grid"):
+ """ Create a reference graticule.
+ min_x, min_y- minimum lat/longs, in decimal degrees
+ max_x, max_y- minimum lat/longs, in decimal degrees
+ hdeg/hmin/hsec- horizontal spacing (degrees/min/sec)
+ vdeg/vmin/vsec- vertical spacing (degrees/min/sec)
+
+ decimal degrees=degrees+(minutes/60.0)+(seconds/3600.0)
+
+ xoff- horizontal offset of vertical labels, as a fraction
+ of max_x-min_x. Offset is relative to min_x.
+ yoff- vertical offset of horizontal labels, as a fraction
+ of max_y-min_y. Offset is relative to min_y.
+
+ color- start color for the grid
+ label_type- not used yet; might be later for formatting.
+
+ extents may be shifted slightly to generate 'nice' labels.
+
+ Note that the min_x, min_y, max_x, max_y extents include
+ a border 5% in from each side, and room for labels.
+ """
+
+ shps=gview.GvShapes(name=shapes_name)
+ gview.undo_register( shps )
+ shps.add_field('position','string',20)
+
+ if os.name == 'nt':
+ font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ else:
+ #font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ #font="-urw-helvetica-medium-r-normal-*-9-*-*-*-p-*-iso8859-2"
+ font="-adobe-helvetica-medium-r-normal-*-8-*-*-*-p-*-iso10646-1"
+ #font="-misc-fixed-medium-r-*-*-9-*-*-*-*-*-*-*"
+
+ x_spacing=float(hdeg)+(float(hmin)+(float(hsec)/60.0))/60.0
+ y_spacing=float(vdeg)+(float(vmin)+(float(vsec)/60.0))/60.0
+
+
+ # Round to nearest integer space
+ max_x=min_x+Numeric.floor((max_x-min_x)/x_spacing)*x_spacing
+ max_y=min_y+Numeric.floor((max_y-min_y)/y_spacing)*y_spacing
+
+ lxoff=(max_x-min_x)*xoff # horizontal label placement
+ lyoff=(max_y-min_y)*yoff # vertical label placement
+
+ for hval in Numeric.arange(min_x,
+ max_x+x_spacing/100.0,
+ x_spacing):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(hval,max_y,0,0)
+ nshp.set_node(hval,min_y,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(hval,min_y+lyoff)
+ hstr=GetLatLongString(hval,'longitude')
+ pshp.set_property('position',hstr)
+ shps.append(pshp)
+
+ for vval in Numeric.arange(min_y,
+ max_y+y_spacing/100.0,
+ y_spacing):
+ nshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ nshp.set_node(min_x,vval,0,0)
+ nshp.set_node(max_x,vval,0,1)
+ shps.append(nshp)
+ pshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ pshp.set_node(min_x+lxoff,vval)
+ vstr=GetLatLongString(vval,'latitude')
+ pshp.set_property('position',vstr)
+ shps.append(pshp)
+
+ cstr=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr) < 9:
+ cstr=cstr+"FF"
+ clstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+' '+str(color[3])
+
+ layer=gview.GvShapesLayer(shps)
+ layer.set_property('_line_color',clstr)
+ layer.set_property('_point_color',clstr)
+ # Set antialias property so that lines look nice
+ # when rotated.
+ layer.set_property('_gl_antialias','1')
+ layer.set_property('_gv_ogrfs_point',
+ 'LABEL(t:{position},f:"'+font+'",c:'+cstr+')')
+ layer.set_read_only(gtk.TRUE)
+
+ return layer
+
+#########################################################################
+# North Arrow layers #
+#########################################################################
+
+if os.name == "nt":
+ GVNORTHSYM1 = "\\North1"
+else:
+ GVNORTHSYM1 = "/North1"
+
+def CreateNorthSymbol(ntype=GVNORTHSYM1,color1=(0.0,0.0,0.0,1.0),
+ color2=(1.0,1.0,1.0,1.0),scale=1.0,symbol_manager=None):
+ """ Create the North Symbol and put it in a symbol manager.
+ Input:
+ ntype- type of north arrow to create
+ color1- first color
+ color2- second color (if needed)
+ scale- amount to scale size by.
+ symbol_manager- symbol manager to inject symbol into (a
+ new one will be created if this is set
+ to None).
+ """
+
+ if symbol_manager is None:
+ sm=gview.GvSymbolManager()
+ else:
+ sm=symbol_manager
+
+ cstr1=gvogrfs.gv_to_ogr_color(color1)
+ if len(cstr1) < 9:
+ cstr1=cstr1+"FF"
+
+ cstr2=gvogrfs.gv_to_ogr_color(color2)
+ if len(cstr2) < 9:
+ cstr2=cstr2+"FF"
+
+ sstr=string.replace(str(scale),'.','_')
+
+ refname=ntype+cstr1[1:]+cstr2[1:]+sstr
+ if ntype==GVNORTHSYM1:
+ shape=gview.GvShape(type=gview.GVSHAPE_AREA)
+ shape.set_node(1.0*scale,-2.6*scale,node=0)
+ shape.set_node(0.0,-0.8*scale,node=1)
+ shape.set_node(-1.0*scale,-2.6*scale,node=2)
+ shape.set_node(0.0,2.6*scale,node=3)
+ shape.set_node(1.0*scale,-2.6*scale,node=4)
+ shape.set_property('_gv_ogrfs','PEN(c:'+cstr1+');BRUSH(c:'+\
+ cstr2+')')
+ sm.inject_vector_symbol(refname,shape)
+
+ return (refname,sm)
+
+def CreateNorthSymbols(color1=(0.0,0.0,0.0,1.0),color2=(1.0,1.0,1.0,1.0),
+ scale=1.0,symbol_manager=None):
+ """ Create North symbols of all types using two specified colors,
+ and inject them into a symbol manager.
+ Input:
+ color1- first color
+ color2- second color (if needed)
+ scale- amount to scale size by.
+ symbol_manager- symbol manager to inject symbols into (a
+ new one will be created if this is set
+ to None).
+ """
+
+ if symbol_manager is None:
+ sm=gview.GvSymbolManager()
+ else:
+ sm=symbol_manager
+
+ refnames=[]
+ for item in [GVNORTHSYM1]:
+ rname,junk=CreateNorthSymbol(color1,color2,scale,sm)
+ refnames.append(rname)
+
+ return (refnames,sm)
+
+
+def SimpleNorthLayer(xoffset,yoffset,ntype=GVNORTHSYM1,
+ color1=(0.0,0.0,0.0,1.0),
+ color2=(1.0,1.0,1.0,1.0),
+ scale=1.0,
+ shapes_name="North Arrow"):
+ """ Create a layer with a North arrow symbol,
+ with the North arrow located at (xoffset,yoffset).
+ The 'ntype' parameter will eventually be used for
+ different types of north arrows. The layer
+ will contain two shapes: an area or line, and
+ label.
+ Input:
+ xoffset,yoffset- where to center North Arrow (in
+ display coordinates).
+
+ ntype- index of north arrow type (currently only one type).
+ color1- First color and outline color for north arrow. A tuple
+ of 4 values between 0 and 1.
+ color2- Second color (not used yet).
+ scale- amount to scale size of symbol by.
+ shapes_name- name to give the shapes that form
+ the north arrow.
+ """
+
+ shps=gview.GvShapes(name=shapes_name)
+ gview.undo_register( shps )
+
+ nshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ nshp.set_node(xoffset,yoffset)
+
+ cstr1=gvogrfs.gv_to_ogr_color(color1)
+ if len(cstr1) < 9:
+ cstr1=cstr1+"FF"
+
+ refname,sm=CreateNorthSymbol(ntype,color1,color2,scale)
+ dxstr=str(-1.5*scale)
+ dystr=str(-15.0*scale)
+ nshp.set_property('_gv_ogrfs',
+ 'SYMBOL(c:'+cstr1+',s:4,id:"'+refname+'");'+\
+ 'LABEL(c:'+cstr1+',t:"N",dx:'+dxstr+\
+ ',dy:'+dystr+')' )
+ shps.append(nshp)
+
+ layer=gview.GvShapesLayer(shps)
+ # Set antialias property so that lines look nice
+ # when rotated.
+ layer.set_property('_gl_antialias','1')
+
+ return layer
+
+#############################################################
+# Scale bar layers #
+#############################################################
+
+# Types of scale bars
+GVSCALE1=0
+
+def SimpleScalebarLayer(xoffset,yoffset,dwidth,swidth,
+ angle,units_label=None,stype=GVSCALE1,
+ color1=(0.0,0.0,0.0,1.0),
+ color2=(1.0,1.0,1.0,1.0),
+ offset=-0.2,
+ shapes_name="Scale Bar"):
+ """ Create a layer with a Scale bar located at
+ stretching from dmin to dmax on the display
+ Input:
+ xoffset,yoffset- where to center scale bar (in
+ display coordinates)
+
+ dwidth- width of scale bar in display coordinates
+ swidth- width of scale bar in scale coordinates
+ (same if scale units and geocoding units
+ are the same; different if for example
+ display is UTM- meters- and scale bar is
+ in km)
+ angle- angle of scale bar relative to display
+ (in RADIANS)
+ units_label- label for units (left out if None)
+ stype- index of scale bar type (currently must be 0)
+ color1- First color and outline color for scale bar. A tuple
+ of 4 values between 0 and 1.
+ color2- Second color (only used in alternating scale bars)
+ offset- Vertical offset of labels for scale bar as a
+ fraction of scale bar width.
+ shapes_name- name to give the shapes that form
+ the scalebar.
+ """
+
+ shps=gview.GvShapes(name=shapes_name)
+ gview.undo_register( shps )
+ shps.add_field('label','string',20)
+
+ if os.name == 'nt':
+ font="-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*"
+ else:
+ #font="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+ #font="-urw-helvetica-medium-r-normal-*-9-*-*-*-p-*-iso8859-2"
+ font="-adobe-helvetica-medium-r-normal-*-8-*-*-*-p-*-iso10646-1"
+ #font="-misc-fixed-medium-r-*-*-9-*-*-*-*-*-*-*"
+
+ sc=dwidth/swidth
+ svals,labels=GetScaleBlocks(swidth)
+
+ cstr1=str(color1[0])+' '+str(color1[1])+' '+str(color1[2])+\
+ ' '+str(color1[3])
+ cstr2=str(color2[0])+' '+str(color2[1])+' '+str(color2[2])+\
+ ' '+str(color2[3])
+
+ if stype == GVSCALE1:
+ # Rectangle with alternating filled/unfilled
+ # sections.
+ smax=svals[len(svals)-1]
+
+ # rectangle nodes before rotation
+ hbr=(svals-(smax/2.0))*sc # horizontal- shift to -smax/2:+smax/2
+ # so that rectangle is centered about 0.
+ # rectangle extends from -smax/20 (bbr) to +smax/20 (tbr) vertically,
+ # labels are placed at + or - smax/5
+ tbr=smax/20.0*Numeric.ones(Numeric.shape(hbr))
+ bbr=-1*smax/20.0*Numeric.ones(Numeric.shape(hbr))
+ lbr=offset*smax*Numeric.ones(Numeric.shape(hbr))
+
+ # units label location before rotation
+ uxbr=(hbr[len(hbr)-1]-hbr[0])*0.05+hbr[len(hbr)-1]
+
+ # rotate
+ ctheta=Numeric.cos(angle)
+ stheta=Numeric.sin(angle)
+ tx=hbr*ctheta-tbr*stheta + xoffset
+ ty=hbr*stheta+tbr*ctheta + yoffset
+ bx=hbr*ctheta-bbr*stheta + xoffset
+ by=hbr*stheta+bbr*ctheta + yoffset
+ lx=hbr*ctheta-lbr*stheta + xoffset
+ ly=hbr*stheta+lbr*ctheta + yoffset
+ ux=uxbr*ctheta + xoffset
+ uy=uxbr*stheta + yoffset
+
+ # LATER: once shape collections are working, use them instead
+ # so that entire scale bar can be selected and shifted as
+ # a whole rather than separate shapes...
+
+ #shp=gview.GvShape(type=gview.GVSHAPE_COLLECTION)
+ #shp.set_property('_gv_ogrfs_point',
+ # 'LABEL(t:{label},f:"%s",c:#000000FF)' % font)
+ #shps.append(shp)
+ for idx in range(len(tx)-1):
+ nshp=gview.GvShape(type=gview.GVSHAPE_AREA)
+ nshp.add_node(tx[idx],ty[idx],0)
+ nshp.add_node(tx[idx+1],ty[idx+1],0)
+ nshp.add_node(bx[idx+1],by[idx+1],0)
+ nshp.add_node(bx[idx],by[idx],0)
+ nshp.add_node(tx[idx],ty[idx],0)
+ if idx % 2:
+ nshp.set_property('_gv_color',cstr1)
+ nshp.set_property('_gv_fill_color',cstr2)
+ else:
+ nshp.set_property('_gv_color',cstr1)
+ nshp.set_property('_gv_fill_color',cstr1)
+
+ shps.append(nshp)
+
+ for idx in range(len(lx)):
+ if labels[idx] is not None:
+ lshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ lshp.set_node(lx[idx],ly[idx])
+ lshp.set_property('label',labels[idx])
+ shps.append(lshp)
+
+ if units_label is not None:
+ lshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ lshp.set_node(ux,uy)
+ lshp.set_property('label',units_label)
+ shps.append(lshp)
+
+ layer=gview.GvShapesLayer(shps)
+ # Set antialias property so that lines look nice
+ # when rotated.
+ layer.set_property('_gl_antialias','1')
+ cstr3=gvogrfs.gv_to_ogr_color(color1)
+ if len(cstr3) < 9:
+ cstr3=cstr3+"FF"
+
+ layer.set_property('_gv_ogrfs_point',
+ 'LABEL(t:{label},f:"%s",c:%s)' % (font,cstr3))
+ return layer
+
+def GetScaleBlocks(width):
+ """ Get 'nice' scale bar block sizes and start/end
+ values.
+ Input:
+ width- geocoded width
+
+ Output:
+ values- geocoded values at divisions (array)
+ labels- labels for divisions
+ """
+
+ rord=Numeric.log10(abs(width)/2.0)
+ nrord=rord % 1
+
+ if nrord < Numeric.log10(2):
+ spc=0.2*pow(10,Numeric.floor(rord))
+ smallspc=spc
+ bigspc=5*spc
+ newspc=[0,smallspc,smallspc*2,smallspc*3,smallspc*4,smallspc*5]
+ elif nrord < Numeric.log10(5):
+ spc=0.5*pow(10,Numeric.floor(rord))
+ smallspc=spc
+ bigspc=5*spc
+ newspc=[0,smallspc,smallspc*2,smallspc*3,smallspc*4]
+ else:
+ spc=pow(10,Numeric.floor(rord))
+ smallspc=spc
+ bigspc=spc*5
+ newspc=[0,smallspc,smallspc*2,smallspc*3,smallspc*4,smallspc*5]
+
+ if len(newspc) == 5:
+ #labels=['0',None,"%g" % smallspc*2,None,"%g" % (smallspc*4)]
+ labels=['0',None,None,None,"%g" % (smallspc*4)]
+ else:
+ labels=['0',None,None,None,None,"%g" % (smallspc*5)]
+
+ temp_max=newspc[len(newspc)-1]
+ start=temp_max
+ for temp in Numeric.arange(start,width-bigspc/2,bigspc):
+ temp_max=temp_max+bigspc
+ newspc.append(temp_max)
+ labels.append("%g" % temp_max)
+
+ #start=temp_max
+ #for temp in Numeric.arange(start,width-smallspc/2,smallspc):
+ # labels.append(None)
+ # temp_max=temp_max+smallspc
+ # newspc.append(temp_max)
+
+ return (Numeric.array(newspc,Numeric.Float32),labels)
+
+
+#############################################################
+# Utility functions #
+#############################################################
+
+# "Nice" function logic:
+#
+# spacings: restrict to three significant digits; if
+# a third one is present, it must be 5.
+#
+# min/max values: there should be an integer number of
+# "spacings" between min and max values. min and max
+# values may each be rounded by up to tolerance*spacing
+# or tolerance*(max-min)/divisions in either direction
+# in order to be "nicer". Tolerance defaults to 0.5.
+#
+# "Nice" numbers have fewer significant digits
+# (eg. 3000 is "nicer" than 3013), and having 5 as
+# the last significant digit is "nicer" than having
+# 1,2,3,4,6,7,8,9.
+#
+# TO DO: Create "nice" functions, and use them in the grids.
+
+def GetNiceExtentsByDivisions(minval,maxval,divisions,tolerance):
+ """ Try to find nice default extents based on
+ approximate min/max values and a number of divisions.
+
+ Input:
+ minval- minimum value
+ maxval- maximum value
+ divisions- number of divisions
+ tolerance- minval and maxval may each be altered by
+ up to tolerance*(maxval-minval)/divisions
+
+ Output:
+ newmin- new minimum value
+ newmax- new maximum value
+ spacing- spacing
+ """
+ pass
+
+def GetNiceExtentsBySpacing(minval,maxval,spacing,tolerance):
+ """ Try to find nice default extents based on
+ approximate min/max values and a spacing.
+ If the spacing is itself not a nice value,
+ it will also be somewhat adjusted.
+
+ Input:
+ minval- minimum value
+ maxval- maximum value
+ spacing- space between values
+ tolerance- minval and maxval may each be altered by
+ up to tolerance*spacing
+
+
+ Output:
+ newmin- new minimum value
+ newmax- new maximum value
+ newspacing- new spacing
+ """
+ pass
+
+
+def GetLatLongString(ddvalue,lltype='latitude'):
+ """ Convert a decimal degree value to a
+ string appropriate for Lat/Long
+ display.
+
+ ddvalue- position in decimal degrees
+ lltype- latitude or longitude
+
+ returns: lat/long string
+ """
+ import Numeric
+
+ deg=int(abs(ddvalue))
+ min=int((abs(ddvalue)-deg)*60)
+ sec=int((abs(ddvalue)-deg-(float(min)/60.0))*3600.0)
+ if lltype == 'latitude':
+ if Numeric.sign(ddvalue) == -1:
+ ch='S'
+ else:
+ ch='N'
+ else:
+ if Numeric.sign(ddvalue) == -1:
+ ch='W'
+ else:
+ ch='E'
+
+ nstr="%dd%d'%.1f''%s" % (deg,min,sec,ch)
+ return nstr
+
+
+def GetLatLongSpacings(min_ddvalue,max_ddvalue,approx_divs):
+ """ Get spacing values for latitude or longitude
+ min/max values.
+
+ Input:
+ min_ddvalue- minimum extent (decimal degrees)
+ max_ddvalue- maximum extent (decimal degrees)
+ approx_divs- An approximate number of divisions.
+
+ Output:
+ (degspc,minspc,secspc)
+ degspc- degree spacing (integer)
+ minspc- minute spacing (integer)
+ secspc- second spacing (float)
+ """
+
+ diff=max_ddvalue-min_ddvalue
+ degspc=int(diff/approx_divs)
+ minspc=int((diff-float(degspc*approx_divs))*60.0/approx_divs)
+ sdiff=diff-float(degspc*approx_divs)-(float(minspc*approx_divs)/60.0)
+
+ # second spacing is rounded down to the nearest 0.1
+ secspc=float("%.1f" % (sdiff*3600.0/approx_divs))
+ if secspc > (sdiff*3600.0/approx_divs):
+ secspc=secspc-0.1
+
+ return (degspc,minspc,secspc)
+
+def GetAlphabeticGridString(index):
+ """ Get string for reference grid horizontal
+ index (1='A',2='B',...,27='AA',...)
+ """
+ # This function doesn't work yet.
+ alphabet=['A','B','C','D','E','F','G','H','I','J','K',
+ 'L','M','N','O','P','Q','R','S','T','U','V',
+ 'W','X','Y','Z']
+ alen=len(alphabet)
+ sc=Numeric.log(alen)
+ nletters=int(Numeric.log(index)/sc)
+ str=''
+ rem=index
+ for idx in range(nletters,-1,-1):
+ rint=int(rem/pow(alen,idx-1))
+ rem=rem-rint*pow(alen,idx-1)
+ print 'rint ',rint,' rem: ',rem
+ if (rint == 0) and (len(str) == 0):
+ continue
+ if rem == 0:
+ str=str+alphabet[0]
+ else:
+ str=str+alphabet[rint-1]
+
+ return str
Added: packages/openev/branches/upstream/current/pymod/gvmodule.c
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvmodule.c (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvmodule.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4825 @@
+/******************************************************************************
+ * $Id: gvmodule.c,v 1.120 2005/10/17 19:19:15 gmwalter Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Hand generated python bindings for OpenEV C functions.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: gvmodule.c,v $
+ * Revision 1.120 2005/10/17 19:19:15 gmwalter
+ * Wrap gvshape delete_ring function.
+ *
+ * Revision 1.119 2005/09/12 15:33:10 gmwalter
+ * Update autopan tool for line paths.
+ *
+ * Revision 1.118 2005/08/30 13:00:05 andrey_kiselev
+ * Signedness fixes in LUT related code.
+ *
+ * Revision 1.117 2005/04/25 05:37:01 warmerda
+ * progress callback should now be CPL_STDCALL if defined
+ *
+ * Revision 1.116 2005/02/22 13:22:39 gmwalter
+ * Add autopan tool.
+ *
+ * Revision 1.115 2005/01/14 16:52:02 gmwalter
+ * Checked in Aude's gv_shapes_add_shape_last function
+ * (allows shapes to be added without repeating
+ * indices if others have been deleted).
+ *
+ * Revision 1.114 2005/01/04 18:50:33 gmwalter
+ * Checked in Aude's new gvshape function changes.
+ *
+ * Revision 1.113 2004/09/28 19:45:22 warmerda
+ * slight change in PyProxy code to avoid uninit data reference
+ *
+ * Revision 1.112 2004/08/18 20:55:21 pgs
+ * added ability to return columns of data in a python dictionary
+ *
+ * Revision 1.111 2004/06/23 14:35:17 gmwalter
+ * Added support for multi-band complex imagery.
+ *
+ * Revision 1.110 2004/05/12 10:00:27 dem
+ *
+ * Fix a bug in _wrap_gv_raster_layer_get_mesh_lod : this wrapper created
+ * a python double from a C int and then the mesh_lod was wrong (example 223.454).
+ * The wrapper now returns an int.
+ * This bug crashed OpenEV when for example we save a project, then reload it :
+ * if the wrong mesh is big on a lot of images of the project, this uses a lot of
+ * memory and done an allocation error...
+ * Note that all projects saved until this fix have wrong mesh_lods.
+ *
+ * Revision 1.109 2004/02/12 22:36:08 gmwalter
+ * Add functions for easily creating a line from three
+ * lists of nodes (x,y,z), avoiding python-level for
+ * loop.
+ *
+ * Revision 1.108 2004/02/10 15:48:56 andrey_kiselev
+ * Added wrapper for gv_manager_add_dataset() function.
+ *
+ * Revision 1.107 2004/01/22 20:47:43 andrey_kiselev
+ * Added wrappers for gv_raster_layer_nodata_set(), gv_raster_layer_nodata_get()
+ * and gv_raster_layer_type_get().
+ *
+ * Revision 1.106 2003/09/02 17:29:10 warmerda
+ * added get_names() method
+ *
+ * Revision 1.105 2003/08/29 20:52:43 warmerda
+ * added to/from xml translation for GvShape
+ *
+ * Revision 1.104 2003/08/23 04:02:39 warmerda
+ * added gv_records_recode
+ *
+ * Revision 1.103 2003/08/20 20:04:18 warmerda
+ * Added collection methods on GvShape
+ *
+ * Revision 1.102 2003/08/08 18:10:49 warmerda
+ * added gv_ciet.c
+ *
+ * Revision 1.101 2003/08/06 22:23:14 warmerda
+ * added progress monitor to gv_records load/save funcs
+ *
+ * Revision 1.100 2003/08/06 17:17:53 warmerda
+ * gv_records_to_dbf() now supports passing in a list of selected items to write.
+ * gv_records_get_typed_properties() and gv_records_get_properties() will no
+ * longer put NULL properties in the dictionary.
+ *
+ * Revision 1.99 2003/08/05 15:25:22 warmerda
+ * fixed formatting for integer fields when fetching from GvRecords
+ *
+ * Revision 1.98 2003/07/27 05:00:47 warmerda
+ * fleshed out gvrecords support
+ *
+ * Revision 1.97 2003/05/23 16:18:18 warmerda
+ * added GvRecords for CIETMap
+ *
+ * Revision 1.96 2003/04/08 18:11:40 andrey_kiselev
+ * FAdded missed return value in _wrap_gv_symbol_manager_save_vector_symbol()
+ *
+ * Revision 1.95 2003/04/08 11:58:33 andrey_kiselev
+ * Added wrapper for gv_symbol_manager_save_vector_symbol() function.
+ *
+ * Revision 1.94 2003/04/02 15:46:59 pgs
+ * added wrapper for gv_format_point_query
+ *
+ * Revision 1.93 2003/03/07 22:24:47 warmerda
+ * added example MyGDALOperator for Diana
+ *
+ * Revision 1.92 2003/03/02 17:06:24 warmerda
+ * new symbolmanager support
+ *
+ * Revision 1.91 2003/02/20 19:27:20 gmwalter
+ * Updated link tool to include Diana's ghost cursor code, and added functions
+ * to allow the cursor and link mechanism to use different gcps
+ * than the display for georeferencing. Updated raster properties
+ * dialog for multi-band case. Added some signals to layerdlg.py and
+ * oeattedit.py to make it easier for tools to interact with them.
+ * A few random bug fixes.
+ *
+ * Revision 1.90 2003/01/06 21:39:50 warmerda
+ * added gv_shapes_from_ogr_layer
+ *
+ * Revision 1.89 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.88 2002/09/11 20:40:50 warmerda
+ * fixed so that 3d views can be saved
+ *
+ * Revision 1.87 2002/07/29 21:01:31 warmerda
+ * return missing properties as None
+ *
+ * Revision 1.86 2002/07/24 20:33:22 warmerda
+ * added gv_shape_get_property
+ *
+ * Revision 1.85 2002/07/18 19:43:53 warmerda
+ * added gv_shapes_get_typed_properties
+ *
+ * Revision 1.84 2002/07/18 19:34:40 pgs
+ * added wrapper for gv_shapes_to_dbf
+ *
+ * Revision 1.83 2002/07/16 14:17:06 warmerda
+ * added support for getting background color
+ *
+ * Revision 1.82 2002/03/07 18:31:56 warmerda
+ * added preliminary gv_shape_clip_to_rect() implementation
+ *
+ * Revision 1.81 2002/02/28 18:52:22 gmwalter
+ * Added a point-of-interest tool similar to the region-of-interest
+ * tool (allows a user to select a temporary point without having to add a
+ * new layer). Added a mechanism to allow some customization of openev
+ * via a textfile defining external modules.
+ *
+ * Revision 1.80 2002/01/18 05:48:13 warmerda
+ * added GvShapes.get_extents() method in python
+ *
+ * Revision 1.79 2001/12/08 04:49:39 warmerda
+ * added point in polygon test
+ *
+ * Revision 1.78 2001/11/28 19:18:30 warmerda
+ * Added set_gcps(), and get_gcps() methods on GvRaster, and the
+ * geotransform-changed signal generated when the gcps change.
+ *
+ * Revision 1.77 2001/11/07 15:20:38 warmerda
+ * fixed other similar memory leaks
+ *
+ * Revision 1.76 2001/11/07 14:55:44 warmerda
+ * fixed serious memory leak in gv_shape_get_properties() implementation
+ *
+ * Revision 1.75 2001/10/16 18:52:14 warmerda
+ * added autoscale and histogram methods
+ *
+ * Revision 1.74 2001/09/17 15:31:23 pgs
+ * removed extraneous initialization in _wrap_gtk_color_well_get_d
+ *
+ * Revision 1.73 2001/09/17 03:44:14 pgs
+ * removed extra declaration from _wrap_gtk_color_well_get_d
+ *
+ * Revision 1.72 2001/09/16 04:40:55 warmerda
+ * removed extra Py_INCREF call
+ *
+ * Revision 1.71 2001/09/16 03:29:10 pgs
+ * added gtk_color_well_get_d binding.
+ *
+ * Revision 1.70 2001/09/14 14:22:01 warmerda
+ * added GtkColorWell bindings
+ *
+ * Revision 1.69 2001/08/14 17:03:24 warmerda
+ * added standard deviation autoscaling support
+ *
+ * Revision 1.68 2001/08/08 17:46:52 warmerda
+ * added GvShape reference counting support
+ *
+ * Revision 1.67 2001/07/24 02:59:25 warmerda
+ * added force_load method on GvRaster
+ *
+ * Revision 1.66 2001/07/13 22:13:35 warmerda
+ * added function to get height from mesh
+ *
+ * Revision 1.65 2001/07/09 20:40:48 warmerda
+ * added skirt prototype
+ *
+ * Revision 1.64 2001/04/23 18:51:51 warmerda
+ * added set_properties() and __delattr__ to GvShape
+ *
+ * Revision 1.63 2001/04/22 17:35:25 pgs
+ * added get_short_path_name and changed wid_interpolate to a variable exponent for d
+ *
+ * Revision 1.62 2001/04/02 18:10:46 warmerda
+ * expose gv_raster_autoscale() to python
+ *
+ * Revision 1.61 2001/03/29 14:59:56 warmerda
+ * added fill_short flag to control handling of slivers
+ *
+ * Revision 1.60 2001/03/29 04:49:36 warmerda
+ * added gv_view_area_get_volume access
+ *
+ * Revision 1.59 2001/03/21 04:32:04 warmerda
+ * fixed out-of-range __getitem__ on GvShape
+ *
+ * Revision 1.58 2001/01/30 15:18:01 warmerda
+ * added queue_task() access from python
+ *
+ * Revision 1.57 2000/10/06 16:48:56 warmerda
+ * added GvViewArea background color
+ *
+ * Revision 1.56 2000/09/29 16:09:20 srawlin
+ * added Goto function requring fuction to map lat/long to view coordinates
+ *
+ * Revision 1.55 2000/09/29 04:27:58 warmerda
+ * fix type of nodata arguments
+ *
+ * Revision 1.54 2000/09/29 00:59:46 warmerda
+ * take care to return None from GvShapes.__getitem__ on deleted shapes
+ *
+ * Revision 1.53 2000/09/21 03:01:09 warmerda
+ * added gv_data_set_properties
+ *
+ * Revision 1.52 2000/09/15 15:12:45 warmerda
+ * added gv_shape_destroy
+ *
+ * Revision 1.51 2000/09/15 01:30:02 warmerda
+ * added gv_raster_rasterize_shapes cover
+ *
+ * Revision 1.50 2000/09/12 19:19:33 warmerda
+ * added WIDInterpolate
+ *
+ * Revision 1.49 2000/08/25 20:14:31 warmerda
+ * added appcurlayer, and raster layer nodata support
+ *
+ * Revision 1.48 2000/07/31 21:15:50 srawlin
+ * added functions in GvRaster and GvShapes to convert a C change_info struct into a Python tuple
+ *
+ * Revision 1.47 2000/07/27 20:06:23 warmerda
+ * added boundary constraints
+ *
+ * Revision 1.46 2000/07/25 17:04:49 warmerda
+ * Fixed bug with reference leak in gv_view_area_list_layers().
+ *
+ * Revision 1.45 2000/07/24 14:39:19 warmerda
+ * added GvRasterLayer pixel_to_view, view_to_pixel methods
+ *
+ * Revision 1.44 2000/07/20 19:21:24 warmerda
+ * fixed delete_shapes bug for Ahmed
+ *
+ * Revision 1.43 2000/07/13 19:17:12 warmerda
+ * added gv_shape_copy, gv_shapes_replace_shapes
+ *
+ * Revision 1.41 2000/07/11 20:54:59 srawlin
+ * added GvViewArea methods to get and set viewing direction relative to z-plane in 3D
+ *
+ * Revision 1.40 2000/07/11 18:24:38 warmerda
+ * added shape deletion
+ *
+ * Revision 1.39 2000/07/03 20:59:05 warmerda
+ * added some 3d view methods
+ *
+ * Revision 1.38 2000/06/30 18:05:19 srawlin
+ * added ability to set ROI constraints
+ *
+ * Revision 1.37 2000/06/29 16:13:28 srawlin
+ * added ROI Tool creation function
+ *
+ * Revision 1.36 2000/06/26 15:14:22 warmerda
+ * added GvManager dataset support
+ *
+ * Revision 1.35 2000/06/23 12:57:32 warmerda
+ * added GvRasterSource support
+ *
+ * Revision 1.34 2000/06/20 13:39:06 warmerda
+ * added standard headers
+ *
+ */
+
+#include "gview.h"
+#include "gvutils.h"
+#include "invdistance.h"
+#include "gvrasterize.h"
+#include "gtkcolorwell.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gvtypes.h" // define GV_USE_DOUBLE_PRECISION_COORD
+
+#ifndef CPL_STDCALL
+#define CPL_STDCALL
+#endif
+
+// SD select float or double
+#ifdef GV_USE_DOUBLE_PRECISION_COORD
+#
+# define Ccast "d"
+# define CC "dd"
+# define CCC "ddd"
+# define CCCC "dddd"
+# define CCCCCC "dddddd"
+#
+#else
+#
+# define Ccast "f"
+# define CC "ff"
+# define CCC "fff"
+# define CCCC "ffff"
+# define CCCCCC "ffffff"
+#
+#endif
+
+
+
+GvLayer *gv_build_skirt( GvRasterLayer *, double base_z );
+
+#ifdef WIN32
+# include <pygtk.h>
+#else
+# include <pygtk/pygtk.h>
+#endif
+
+
+/*
+ * This is a function for extracting a raw pointer from a SWIG pointer
+ * string.
+ */
+static
+void *SWIG_SimpleGetPtr(char *_c, char *_t)
+{
+ unsigned long _p;
+ if( _c == NULL || _c[0] != '_' )
+ return NULL;
+
+ if( _t != NULL && strstr(_c,_t) == NULL )
+ return NULL;
+
+ _c++;
+ /* Extract hex value from pointer */
+ _p = 0;
+ while (*_c) {
+ if ((*_c >= '0') && (*_c <= '9'))
+ _p = (_p << 4) + (*_c - '0');
+ else if ((*_c >= 'a') && (*_c <= 'f'))
+ _p = (_p << 4) + ((*_c - 'a') + 10);
+ else
+ break;
+ _c++;
+ }
+
+ return (void *) _p;
+}
+
+static
+void SWIG_SimpleMakePtr(char *_c, const void *_ptr, char *type) {
+ static char _hex[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'};
+ unsigned long _p, _s;
+ char _result[20], *_r; /* Note : a 64-bit hex number = 16 digits */
+ _r = _result;
+ _p = (unsigned long) _ptr;
+ if (_p > 0) {
+ while (_p > 0) {
+ _s = _p & 0xf;
+ *(_r++) = _hex[_s];
+ _p = _p >> 4;
+ }
+ *_r = '_';
+ while (_r >= _result)
+ *(_c++) = *(_r--);
+ } else {
+ strcpy (_c, "NULL");
+ }
+ if (_ptr)
+ strcpy (_c, type);
+}
+
+/*
+** Stuff to support progress reporting callbacks.
+*/
+
+typedef struct {
+ PyObject *psPyCallback;
+ PyObject *psPyCallbackData;
+ int nLastReported;
+} PyProgressData;
+
+/************************************************************************/
+/* PyProgressProxy() */
+/* */
+/* Copied from gdal.i */
+/************************************************************************/
+
+static int CPL_STDCALL
+PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
+
+{
+ PyProgressData *psInfo = (PyProgressData *) pData;
+ PyObject *psArgs, *psResult;
+ int bContinue = TRUE;
+
+ if( psInfo->psPyCallback == NULL || psInfo->psPyCallback == Py_None )
+ return TRUE;
+
+ if( psInfo->nLastReported == (int) (100.0 * dfComplete) )
+ return TRUE;
+
+ psInfo->nLastReported = (int) 100.0 * dfComplete;
+
+ if( pszMessage == NULL )
+ pszMessage = "";
+
+ if( psInfo->psPyCallbackData == NULL )
+ psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
+ else
+ psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage,
+ psInfo->psPyCallbackData );
+
+ psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
+ Py_XDECREF(psArgs);
+
+ if( psResult == NULL )
+ {
+ return TRUE;
+ }
+
+ if( psResult == Py_None )
+ {
+ Py_XDECREF(Py_None);
+ return TRUE;
+ }
+
+ if( !PyArg_Parse( psResult, "i", &bContinue ) )
+ {
+ PyErr_SetString(PyExc_ValueError, "bad progress return value");
+ return FALSE;
+ }
+
+ Py_XDECREF(psResult);
+
+ return bContinue;
+}
+
+/************************************************************************/
+/* PyListToXMLTree() */
+/************************************************************************/
+
+static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
+
+{
+ int nChildCount = 0, iChild, nType;
+ CPLXMLNode *psThisNode;
+ CPLXMLNode *psChild;
+ char *pszText = NULL;
+
+ nChildCount = PyList_Size(pyList) - 2;
+ if( nChildCount < 0 )
+ {
+ PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
+ return NULL;
+ }
+
+ PyArg_Parse( PyList_GET_ITEM(pyList,0), "i", &nType );
+ PyArg_Parse( PyList_GET_ITEM(pyList,1), "s", &pszText );
+ psThisNode = CPLCreateXMLNode( NULL, (CPLXMLNodeType) nType, pszText );
+
+ for( iChild = 0; iChild < nChildCount; iChild++ )
+ {
+ psChild = PyListToXMLTree( PyList_GET_ITEM(pyList,iChild+2) );
+ CPLAddXMLChild( psThisNode, psChild );
+ }
+
+ return psThisNode;
+}
+
+/************************************************************************/
+/* XMLTreeToPyList() */
+/************************************************************************/
+
+static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
+
+{
+ PyObject *pyList;
+ int nChildCount = 0, iChild;
+ CPLXMLNode *psChild;
+
+ for( psChild = psTree->psChild;
+ psChild != NULL;
+ psChild = psChild->psNext )
+ nChildCount++;
+
+ pyList = PyList_New(nChildCount+2);
+
+ PyList_SetItem( pyList, 0, Py_BuildValue( "i", (int) psTree->eType ) );
+ PyList_SetItem( pyList, 1, Py_BuildValue( "s", psTree->pszValue ) );
+
+ for( psChild = psTree->psChild, iChild = 2;
+ psChild != NULL;
+ psChild = psChild->psNext, iChild++ )
+ {
+ PyList_SetItem( pyList, iChild, XMLTreeToPyList( psChild ) );
+ }
+
+ return pyList;
+}
+
+/*
+ * Functions not handled by the wrapper generator
+ */
+
+static PyObject *
+_wrap_gv_shape_new(PyObject *self, PyObject *args)
+{
+ int type;
+ char swig_ptr[32];
+ GvShape *shape;
+
+ if (!PyArg_ParseTuple(args, "i:gv_shape_new",
+ &type) )
+ return NULL;
+
+ shape = gv_shape_new(type);
+ SWIG_SimpleMakePtr( swig_ptr, shape, "_GvShape" );
+
+ return Py_BuildValue("s",swig_ptr);
+}
+
+static PyObject *
+_wrap_gv_shape_from_xml(PyObject *self, PyObject *args)
+{
+ GvShape *shape;
+ CPLXMLNode *cpl_tree;
+ PyObject *py_tree = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shape_from_xml",
+ &PyList_Type, &py_tree ) )
+ return NULL;
+
+ cpl_tree = PyListToXMLTree( py_tree );
+
+ shape = gv_shape_from_xml_tree( cpl_tree );
+ if( shape == NULL )
+ {
+ PyErr_SetString( PyExc_ValueError,
+ "XML translation to GvShape filed." );
+ return NULL;
+ }
+ else
+ {
+ char swig_ptr[32];
+ SWIG_SimpleMakePtr( swig_ptr, shape, "_GvShape" );
+ return Py_BuildValue("s",swig_ptr);
+ }
+}
+
+static PyObject *
+_wrap_gv_shape_to_xml(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ CPLXMLNode *psTree;
+ PyObject *py_xml = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_to_xml",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape == NULL )
+ return NULL;
+
+ psTree = gv_shape_to_xml_tree( shape );
+ py_xml = XMLTreeToPyList( psTree );
+ CPLDestroyXMLNode( psTree );
+
+ return py_xml;
+}
+
+static PyObject *
+_wrap_gv_shape_destroy(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_destroy",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ gv_shape_delete( shape );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_ref(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_ref",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ gv_shape_ref( shape );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_unref(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_unref",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ gv_shape_unref( shape );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_get_ref(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_get_ref",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ {
+ return Py_BuildValue( "i", gv_shape_get_ref( shape ) );
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *
+_wrap_gv_shape_copy(PyObject *self, PyObject *args)
+{
+ char swig_ptr[32];
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL, *copy = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_copy",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ copy = gv_shape_copy( shape );
+
+ SWIG_SimpleMakePtr( swig_ptr, copy, "_GvShape" );
+
+ return Py_BuildValue("s",swig_ptr);
+}
+
+static PyObject *
+_wrap_gv_shape_delete_ring(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int ring = 0;
+
+ if (!PyArg_ParseTuple(args, "si:gv_shape_ref",
+ &swig_shape_ptr, &ring))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ gv_shape_delete_ring( shape, ring );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_line_from_nodelists(PyObject *self, PyObject *args)
+{
+ PyObject *pyxlist=NULL;
+ PyObject *pyylist=NULL;
+ PyObject *pyzlist=NULL;
+
+ int node_count, i;
+ char swig_ptr[32];
+ GvShape *shape;
+ gvgeocoord xnode, ynode, znode;
+ int ring=0;
+
+ if (!PyArg_ParseTuple(args, "O!O!O!:gv_shape_line_from_nodelist",
+ &PyList_Type,&pyxlist,
+ &PyList_Type,&pyylist,
+ &PyList_Type,&pyzlist) )
+ return NULL;
+
+ node_count=PyList_Size(pyxlist);
+ if (node_count < 1)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "require at least one node in list for gv_shape_line_from_nodelist");
+ return NULL;
+ }
+ if ((node_count != PyList_Size(pyylist)) ||
+ (node_count != PyList_Size(pyzlist)))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "x, y, and z node lists must have identical lengths for gv_shape_line_from_nodelist");
+ return NULL;
+ }
+
+ shape = gv_shape_new(GVSHAPE_LINE);
+
+ for( i = 0; i < node_count; i++ )
+ {
+ if ( ( !PyArg_Parse( PyList_GET_ITEM(pyxlist,i),
+ Ccast ":gv_shape_line_from_nodelist" , &xnode ) ) ||
+ ( !PyArg_Parse( PyList_GET_ITEM(pyylist,i),
+ Ccast ":gv_shape_line_from_nodelist" , &ynode ) ) ||
+ ( !PyArg_Parse( PyList_GET_ITEM(pyzlist,i),
+ Ccast ":gv_shape_line_from_nodelist" , &znode ) ))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting floats in gv_shape_line_from_nodelist arguments");
+ gv_shape_delete(shape);
+ return NULL;
+ }
+ gv_shape_add_node(shape,ring,xnode,ynode,znode);
+
+ }
+
+ SWIG_SimpleMakePtr( swig_ptr, shape, "_GvShape" );
+
+ return Py_BuildValue("s",swig_ptr);
+}
+
+
+static PyObject *
+_wrap_gv_shapes_lines_for_vecplot(PyObject *self, PyObject *args)
+{
+ PyObject *pyxlist=NULL;
+ PyObject *pyylist=NULL;
+ PyObject *pyzlist=NULL;
+ PyObject *pyoklist=NULL;
+
+ int node_count, i, j, last_ok, shape_count,last_shape_nodes, oknode;
+ GvShape *shape;
+ GvShapes *shapes;
+ gvgeocoord xnode, ynode, znode;
+ int ring=0;
+ int *shape_ids=NULL;
+
+ if (!PyArg_ParseTuple(args, "O!O!O!O!:gv_shape_lines_for_vecplot",
+ &PyList_Type,&pyxlist,
+ &PyList_Type,&pyylist,
+ &PyList_Type,&pyzlist,
+ &PyList_Type,&pyoklist) )
+ return NULL;
+
+ node_count=PyList_Size(pyxlist);
+ if (node_count < 1)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "require at least one node in list for gv_shapes_lines_for_vecplot");
+ return NULL;
+ }
+ if ((node_count != PyList_Size(pyylist)) ||
+ (node_count != PyList_Size(pyzlist)) ||
+ (node_count != PyList_Size(pyoklist)))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "x, y, z, ok lists must have identical lengths for gv_shapes_lines_for_vecplot");
+ return NULL;
+ }
+ shapes = (GvShapes *) gv_shapes_new();
+ shape = gv_shape_new(GVSHAPE_LINE);
+ gv_shapes_add_shape(shapes,shape);
+ last_ok=1;
+ shape_count=1;
+ last_shape_nodes=0;
+ for( i = 0; i < node_count; i++ )
+ {
+ if(( !PyArg_Parse( PyList_GET_ITEM(pyxlist,i),
+ Ccast ":gv_shapes_lines_for_vecplot" , &xnode ) ) ||
+ ( !PyArg_Parse( PyList_GET_ITEM(pyylist,i),
+ Ccast ":gv_shapes_lines_for_vecplot" , &ynode ) ) ||
+ ( !PyArg_Parse( PyList_GET_ITEM(pyzlist,i),
+ Ccast ":gv_shapes_lines_for_vecplot" , &znode ) ) ||
+ ( !PyArg_Parse( PyList_GET_ITEM(pyoklist,i),
+ "i:gv_shapes_lines_for_vecplot" , &oknode ) ))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting floats for nodes, ints for ok in gv_shapes_lines_for_vecplot arguments");
+ shape_ids=g_new(int,shape_count);
+ for ( j= 0 ; j < shape_count; j++ )
+ {
+ *(shape_ids+sizeof(int)) = j;
+ }
+ gv_shapes_delete_shapes(shapes,shape_count,shape_ids);
+ g_free(shape_ids);
+ return NULL;
+ }
+ if (oknode == 1)
+ {
+ gv_shape_add_node(shape,ring,xnode,ynode,znode);
+ last_ok = 1;
+ last_shape_nodes=last_shape_nodes+1;
+ }
+ else if (last_ok == 1)
+ {
+ shape=gv_shape_new(GVSHAPE_LINE);
+ gv_shapes_add_shape(shapes,shape);
+ shape_count=shape_count+1;
+ last_shape_nodes=0;
+ last_ok = 0;
+ }
+ }
+ if (last_shape_nodes == 0)
+ {
+ shape_ids=g_new(int,1);
+ *shape_ids=shape_count-1;
+ gv_shapes_delete_shapes(shapes,1,shape_ids);
+ g_free(shape_ids);
+ }
+
+ return PyGtk_New((GtkObject *) shapes);
+}
+
+
+
+static PyObject *
+_wrap_gv_shape_get_property(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ char *key;
+ GvShape *shape = NULL;
+ const char *value = NULL;
+
+ if (!PyArg_ParseTuple(args, "ss:gv_shape_get_property",
+ &swig_shape_ptr, &key))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ value = gv_properties_get( gv_shape_get_properties( shape ), key );
+
+ if( value != NULL )
+ return Py_BuildValue( "s", value );
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *
+_wrap_gv_shape_get_properties(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_get_properties",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ properties = gv_shape_get_properties( shape );
+
+ psDict = PyDict_New();
+ if( properties != NULL )
+ {
+ int i, count;
+
+ count = gv_properties_count( properties );
+ for( i = 0; i < count; i++ )
+ {
+ const char *value, *name;
+ PyObject *py_name, *py_value;
+
+ value = gv_properties_get_value_by_index(properties,i);
+ name = gv_properties_get_name_by_index(properties,i);
+
+ py_name = Py_BuildValue("s",name);
+ py_value = Py_BuildValue("s",value);
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+ }
+
+ return psDict;
+}
+
+
+/************************************************************************/
+/* gv_shape_get_typed_properties() */
+/* */
+/* This function fetches a dictionary of property values for a */
+/* given GvShape. It operates similarly to the normal */
+/* get_properties() call on the GvShape with the following */
+/* changes: */
+/* o The list of fields to extract are passed in. */
+/* o The passed in field list includes an indicator of whether */
+/* the field should be auto-converted to a numeric type. */
+/* */
+/* The input argument (beside the shape) is a list of tuples */
+/* for the field. The tuples consist of the name, and an */
+/* integer flag indicating (non-zero) if the field should be */
+/* converted to a numeric value. */
+/************************************************************************/
+
+static PyObject *
+_wrap_gv_shape_get_typed_properties(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+ PyObject *pyFieldList = NULL;
+ int nCount, i;
+
+ if (!PyArg_ParseTuple(args, "sO!:get_typed_properties",
+ &swig_shape_ptr, &PyList_Type, &pyFieldList))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape != NULL )
+ properties = gv_shape_get_properties( shape );
+
+ psDict = PyDict_New();
+ if( properties == NULL )
+ return psDict;
+
+ nCount = PyList_Size(pyFieldList);
+ for( i = 0; i < nCount; i++ )
+ {
+ char *pszFieldName = NULL;
+ int nNumericFlag = 0;
+ const char *value;
+ PyObject *py_name, *py_value;
+
+ if( !PyArg_Parse( PyList_GET_ITEM(pyFieldList,i), "(si)",
+ &pszFieldName, &nNumericFlag ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting (name,flag) tuples in list.");
+ return NULL;
+ }
+
+ value = gv_properties_get(properties,pszFieldName);
+ if( value == NULL )
+ {
+ py_value = Py_None;
+ Py_INCREF( Py_None );
+ }
+ else if( nNumericFlag )
+ py_value = Py_BuildValue("f",atof(value));
+ else
+ py_value = Py_BuildValue("s",value);
+
+ py_name = Py_BuildValue("s",pszFieldName);
+
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+
+ return psDict;
+}
+
+static PyObject *
+_wrap_gv_shape_set_property(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL, *name=NULL, *value=NULL;
+ GvShape *shape = NULL;
+ GvProperties *properties = NULL;
+
+ if (!PyArg_ParseTuple(args, "sss:gv_shape_set_property",
+ &swig_shape_ptr, &name, &value))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ {
+ properties = gv_shape_get_properties( shape );
+ gv_properties_set( properties, name, value );
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_set_properties(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+ PyObject *pyKey = NULL, *pyValue = NULL;
+
+ if (!PyArg_ParseTuple(args, "sO!:gv_shape_set_properties",
+ &swig_shape_ptr, &PyDict_Type, &psDict))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ {
+ int i;
+
+ properties = gv_shape_get_properties( shape );
+
+ gv_properties_clear( properties );
+
+ i = 0;
+ while( PyDict_Next( psDict, &i, &pyKey, &pyValue ) )
+ {
+ char *key = NULL, *value = NULL;
+
+ if( !PyArg_Parse( pyKey, "s", &key )
+ || !PyArg_Parse( pyValue, "s", &value ))
+ continue;
+
+ gv_properties_set( properties, key, value );
+
+ pyKey = pyValue = NULL;
+ }
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_get_type(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_get_rings",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ return Py_BuildValue("i",gv_shape_type(shape));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_get_rings(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_get_rings",
+ &swig_shape_ptr))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ return Py_BuildValue("i",gv_shape_get_rings(shape));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_get_nodes(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int ring = 0;
+
+ if (!PyArg_ParseTuple(args, "si:gv_shape_get_nodes",
+ &swig_shape_ptr, &ring))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ return Py_BuildValue("i",gv_shape_get_nodes(shape,ring));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_add_node(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int ring = 0;
+ gvgeocoord x=0.0, y=0.0, z=0.0;
+
+ if (!PyArg_ParseTuple(args, "s" CCC "i:gv_shape_add_node", &swig_shape_ptr,
+ &x, &y, &z, &ring ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ return Py_BuildValue("i",gv_shape_add_node(shape,ring, x,y,z));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_set_node(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int ring = 0, node = 0;
+ gvgeocoord x=0.0, y=0.0, z=0.0;
+
+ if (!PyArg_ParseTuple(args, "s" CCC "ii:gv_shape_set_node", &swig_shape_ptr,
+ &x, &y, &z, &node, &ring ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL )
+ return Py_BuildValue("i",
+ gv_shape_set_xyz(shape, ring, node, x,y,z));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_get_node(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int ring = 0, node = 0;
+
+ if (!PyArg_ParseTuple(args, "sii:gv_shape_get_node",
+ &swig_shape_ptr, &node, &ring ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( shape != NULL ){
+ return Py_BuildValue("(" CCC ")",
+ gv_shape_get_x(shape,ring,node),
+ gv_shape_get_y(shape,ring,node),
+ gv_shape_get_z(shape,ring,node) );
+ }else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_point_in_polygon(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "sdd:gv_shape_point_in_polygon",
+ &swig_shape_ptr, &x, &y ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape != NULL )
+ return Py_BuildValue("i", gv_shape_point_in_polygon(shape, x, y ));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_distance_from_polygon(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "sdd:gv_shape_distance_from_polygon",
+ &swig_shape_ptr, &x, &y ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape != NULL )
+ return Py_BuildValue("d", gv_shape_distance_from_polygon(shape, x, y ));
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_clip_to_rect(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ double x, y, width, height;
+
+ if (!PyArg_ParseTuple(args, "sdddd:gv_shape_clip_to_rect",
+ &swig_shape_ptr, &x, &y, &width, &height ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape != NULL )
+ {
+ GvRect rect;
+ GvShape *new_shape;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ new_shape = gv_shape_clip_to_rect( shape, &rect );
+
+ if( new_shape == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ {
+ char swig_ptr[128];
+
+ SWIG_SimpleMakePtr( swig_ptr, new_shape, "_GvShape" );
+
+ return Py_BuildValue("s",swig_ptr);
+ }
+ }
+ else
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_shape_add_shape(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ char *swig_sub_shape_ptr = NULL;
+ GvShape *shape = NULL, *sub_shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "ss:gv_shape_add_shape",
+ &swig_shape_ptr, &swig_sub_shape_ptr ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( swig_sub_shape_ptr )
+ sub_shape = SWIG_SimpleGetPtr( swig_sub_shape_ptr, "_GvShape" );
+
+ if( shape != NULL && sub_shape != NULL )
+ gv_shape_collection_add_shape( shape, sub_shape );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_get_shape(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+ int shape_index;
+
+ if (!PyArg_ParseTuple(args, "si:gv_shape_get_shape",
+ &swig_shape_ptr, &shape_index ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape == NULL )
+ {
+ PyErr_SetString(PyExc_ValueError, "no shape passed into get_shape().");
+ return NULL;
+ }
+
+ shape = gv_shape_collection_get_shape( shape, shape_index );
+ if( shape == NULL )
+ {
+ PyErr_SetString(PyExc_IndexError, "shape index out of range for collection");
+ return NULL;
+ }
+ else
+ {
+ char swig_ptr[128];
+
+ SWIG_SimpleMakePtr( swig_ptr, shape, "_GvShape" );
+
+ return Py_BuildValue("s",swig_ptr);
+ }
+}
+
+static PyObject *
+_wrap_gv_shape_collection_get_count(PyObject *self, PyObject *args)
+{
+ char *swig_shape_ptr = NULL;
+ GvShape *shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shape_get_shape",
+ &swig_shape_ptr ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape == NULL )
+ {
+ PyErr_SetString(PyExc_ValueError, "no shape passed into get_shape().");
+ return NULL;
+ }
+
+ return Py_BuildValue( "i", gv_shape_collection_get_count( shape ) );
+}
+
+static PyObject *
+_wrap_gv_symbol_manager_get_names(PyObject *self, PyObject *args)
+{
+ PyObject *manager, *py_name_list;
+ char **name_list;
+ int i, count;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_symbol_manager_get_names",
+ &PyGtk_Type, &manager ))
+ return NULL;
+
+ name_list =
+ gv_symbol_manager_get_names( GV_SYMBOL_MANAGER(PyGtk_Get(manager)) );
+
+ count = CSLCount( name_list );
+ py_name_list = PyList_New( count );
+ for( i = 0; i < count; i++ )
+ PyList_SetItem( py_name_list, i, Py_BuildValue( "s", name_list[i] ) );
+
+ g_free( name_list );
+
+ return py_name_list;
+}
+
+static PyObject *
+_wrap_gv_symbol_manager_inject_vector_symbol(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ GvShape *shape = NULL;
+ char *swig_shape_ptr = NULL;
+ char *symbol_name = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!ss:gv_symbol_manager_inject_vector_symbol",
+ &PyGtk_Type, &manager, &symbol_name,
+ &swig_shape_ptr ))
+ return NULL;
+
+ if( swig_shape_ptr )
+ shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+
+ if( shape )
+ gv_symbol_manager_inject_vector_symbol(
+ GV_SYMBOL_MANAGER(PyGtk_Get(manager)),
+ symbol_name, shape );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_symbol_manager_inject_raster_symbol(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *rgba_string = NULL;
+ char *symbol_name = NULL;
+ int width, height, rgba_len;
+
+ if (!PyArg_ParseTuple(args,
+ "O!siiz#:gv_symbol_manager_inject_raster_symbol",
+ &PyGtk_Type, &manager, &symbol_name,
+ &width, &height, &rgba_string, &rgba_len ))
+ return NULL;
+
+ if( width*height*4 > rgba_len )
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "rgba raster symbol buffer seems to be too small (width*height*4)\nin gv_symbol_manager_inject_raster_symbol()." );
+ return NULL;
+ }
+
+ gv_symbol_manager_inject_raster_symbol(
+ GV_SYMBOL_MANAGER(PyGtk_Get(manager)),
+ symbol_name, width, height, rgba_string );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_symbol_manager_get_symbol(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *symbol_name = NULL;
+ GvSymbolObj *symbol;
+
+ if (!PyArg_ParseTuple(args,"O!s:gv_symbol_manager_get_symbol",
+ &PyGtk_Type, &manager, &symbol_name ) )
+ return NULL;
+
+ symbol = gv_symbol_manager_get_symbol(
+ GV_SYMBOL_MANAGER(PyGtk_Get(manager)),
+ symbol_name );
+
+ if( symbol == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if( symbol->type == GV_SYMBOL_VECTOR )
+ {
+ char swig_shape_ptr[32];
+
+ SWIG_SimpleMakePtr( swig_shape_ptr, symbol->buffer, "_GvShape" );
+
+ return Py_BuildValue("(is)", symbol->type, swig_shape_ptr );
+ }
+ else
+ {
+ PyObject *py_rgba_buffer;
+ PyObject *py_result;
+
+ py_rgba_buffer =
+ PyString_FromStringAndSize( symbol->buffer,
+ symbol->width * symbol->height * 4 );
+
+ py_result = Py_BuildValue("(iiiO)",
+ symbol->type, symbol->width, symbol->height,
+ py_rgba_buffer );
+ Py_DECREF( py_rgba_buffer );
+
+ return py_result;
+ }
+}
+
+static PyObject *
+_wrap_gv_symbol_manager_save_vector_symbol(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *symbol_name = NULL, *new_name = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!ss:gv_symbol_manager_save_vector_symbol",
+ &PyGtk_Type, &manager, &symbol_name, &new_name ))
+ return NULL;
+
+ if( symbol_name && new_name )
+ {
+ if ( gv_symbol_manager_save_vector_symbol(
+ GV_SYMBOL_MANAGER(PyGtk_Get(manager)),
+ symbol_name, new_name ) )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "error while saving new symbol in gv_symbol_manager_save_vector_symbol()." );
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static PyObject *
+_wrap_gv_data_get_properties(PyObject *self, PyObject *args)
+{
+ PyObject *data;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_get_properties",
+ &PyGtk_Type, &data))
+ return NULL;
+
+ if( data != NULL )
+ properties = gv_data_get_properties( GV_DATA(PyGtk_Get(data)) );
+
+ psDict = PyDict_New();
+ if( properties != NULL )
+ {
+ int i, count;
+
+ count = gv_properties_count( properties );
+ for( i = 0; i < count; i++ )
+ {
+ const char *value, *name;
+ PyObject *py_name, *py_value;
+
+ value = gv_properties_get_value_by_index(properties,i);
+ name = gv_properties_get_name_by_index(properties,i);
+
+ py_name = Py_BuildValue("s",name);
+ py_value = Py_BuildValue("s",value);
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+ }
+
+ return psDict;
+}
+
+static PyObject *
+_wrap_gv_data_set_properties(PyObject *self, PyObject *args)
+{
+ PyObject *data;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+ int i;
+ PyObject *pyKey = NULL, *pyValue = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_data_set_properties",
+ &PyGtk_Type, &data,
+ &PyDict_Type, &psDict))
+ return NULL;
+
+ if( data != NULL )
+ properties = gv_data_get_properties( GV_DATA(PyGtk_Get(data)) );
+
+ gv_properties_clear( properties );
+
+ i = 0;
+ while( PyDict_Next( psDict, &i, &pyKey, &pyValue ) )
+ {
+ char *key = NULL, *value = NULL;
+
+ if( !PyArg_Parse( pyKey, "s", &key )
+ || !PyArg_Parse( pyValue, "s", &value ))
+ continue;
+
+ gv_properties_set( properties, key, value );
+
+ pyKey = pyValue = NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_data_changed(PyObject *self, PyObject *args)
+{
+ PyObject *data;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_changed", &PyGtk_Type, &data))
+ return NULL;
+ gv_data_changed(GV_DATA(PyGtk_Get(data)), NULL);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_layer_extents(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_layer_extents", &PyGtk_Type, &layer))
+ return NULL;
+ gv_layer_extents(GV_LAYER(PyGtk_Get(layer)), &rect);
+ return Py_BuildValue( "(" CCCC ")", rect.x, rect.y, rect.width, rect.height);
+}
+
+static PyObject *
+_wrap_gv_layer_display_change(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_layer_display_change",
+ &PyGtk_Type, &layer))
+ return NULL;
+
+ gv_layer_display_change( GV_LAYER(PyGtk_Get(layer)), NULL );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_view_area_list_layers(PyObject *self, PyObject *args)
+{
+ PyObject *view, *py_list;
+ GList *list;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_list_layers", &PyGtk_Type,
+ &view))
+ return NULL;
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+ list = gv_view_area_list_layers(GV_VIEW_AREA(PyGtk_Get(view)));
+ py_list = PyList_New(0);
+ for ( ; list != NULL; list = list->next)
+ {
+ PyObject *layer = PyGtk_New(GTK_OBJECT(list->data));
+ PyList_Append(py_list, layer);
+ Py_DECREF(layer);
+ }
+ g_list_free(list);
+ return py_list;
+}
+
+static PyObject *
+_wrap_gv_view_area_get_fontnames(PyObject *self, PyObject *args)
+{
+ PyObject *view;
+ GPtrArray *g_list;
+ PyObject *py_list;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_fontnames",
+ &PyGtk_Type, &view) )
+ return NULL;
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ g_list = gv_view_area_get_fontnames( GV_VIEW_AREA(PyGtk_Get(view)) );
+
+ py_list = PyList_New(0);
+ for( i = 0; i < g_list->len; i++ )
+ {
+ const char *item = (const char *) g_ptr_array_index(g_list,i);
+ PyObject *py_item;
+
+ py_item = Py_BuildValue( "s", item );
+ PyList_Append( py_list, py_item );
+ Py_DECREF( py_item );
+ }
+
+ g_ptr_array_free( g_list, FALSE );
+
+ return py_list;
+}
+
+static PyObject *
+_wrap_gv_view_area_set_background_color(PyObject *self, PyObject *args)
+{
+ PyObject *view;
+ GvColor color;
+
+ if (!PyArg_ParseTuple(args, "O!(ffff):gv_view_area_set_background_color",
+ &PyGtk_Type, &view,
+ &color[0], &color[1], &color[2], &color[3]))
+ return NULL;
+
+ gv_view_area_set_background_color(GV_VIEW_AREA(PyGtk_Get(view)), color);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_view_area_get_background_color(PyObject *self, PyObject *args)
+{
+ PyObject *view;
+ GvColor color;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_background_color",
+ &PyGtk_Type, &view))
+ return NULL;
+
+ gv_view_area_get_background_color(GV_VIEW_AREA(PyGtk_Get(view)), color);
+
+ return Py_BuildValue("(ffff)", color[0], color[1], color[2], color[3] );
+}
+
+static PyObject *
+_wrap_gv_view_area_create_thumbnail(PyObject *self, PyObject *args)
+{
+#ifdef WIN32
+ PyErr_SetString(PyExc_RuntimeError, "not supported on this platform");
+ return NULL;
+#else
+
+ PyObject *view, *layer, *ret;
+ GdkPixmap *pixmap;
+ int width, height;
+
+ if (!PyArg_ParseTuple(args, "O!O!ii:gv_view_area_create_thumbnail",
+ &PyGtk_Type, &view, &PyGtk_Type, &layer,
+ &width, &height))
+ return NULL;
+ pixmap = gv_view_area_create_thumbnail(GV_VIEW_AREA(PyGtk_Get(view)),
+ PyGtk_Get(layer), width, height);
+ if (!pixmap)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "could not create pixmap");
+ return NULL;
+ }
+ ret = PyGdkWindow_New(pixmap);
+ gdk_pixmap_unref(pixmap);
+ return ret;
+#endif
+}
+
+static PyObject *
+_wrap_gv_view_area_set_3d_view(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ vec3_t eye_pos, eye_dir;
+
+ if (!PyArg_ParseTuple(args, "O!(" CCC ")(" CCC "):gv_view_area_set_3d_view",
+ &PyGtk_Type, &py_view,
+ eye_pos+0, eye_pos+1, eye_pos+2,
+ eye_dir+0, eye_dir+1, eye_dir+2))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_set_3d_view( view, eye_pos, eye_dir );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_view_area_set_3d_view_look_at(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ vec3_t eye_pos;
+ gvgeocoord eye_look_at[2];
+
+ if (!PyArg_ParseTuple(args, "O!(" CCC ")(" CC "):gv_view_area_set_3d_view_look_at",
+ &PyGtk_Type, &py_view,
+ eye_pos+0, eye_pos+1, eye_pos+2,
+ eye_look_at+0, eye_look_at+1))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_set_3d_view_look_at( view, eye_pos, eye_look_at );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_view_area_get_eye_pos(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_eye_pos",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ return Py_BuildValue( "(" CCC ")",
+ view->state.eye_pos[0],
+ view->state.eye_pos[1],
+ view->state.eye_pos[2] );
+}
+
+static PyObject *
+_wrap_gv_view_area_get_eye_dir(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_eye_dir",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ return Py_BuildValue( "(" CCC ")",
+ view->state.eye_dir[0],
+ view->state.eye_dir[1],
+ view->state.eye_dir[2] );
+}
+
+
+static PyObject *
+_wrap_gv_view_area_get_look_at_pos(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord x, y;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_look_at_pos",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+
+ if (!gv_view_area_get_look_at_pos( view, &x, &y))
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return Py_BuildValue("(" CC ")", x, y);
+
+}
+
+static PyObject *
+_wrap_gv_view_area_map_location(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord x, y;
+
+ if (!PyArg_ParseTuple(args, "O!(" CC "):gv_view_area_map_location",
+ &PyGtk_Type, &py_view, &x, &y))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_map_location( view, x, y, &x, &y );
+
+ return Py_BuildValue("(" CC ")", x, y );
+}
+
+static PyObject *
+_wrap_gv_view_area_get_pointer(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord x, y;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_pointer",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_map_pointer( view,
+ view->state.mpos_x, view->state.mpos_y,
+ &x, &y );
+
+ return Py_BuildValue("(" CC ")", x, y );
+}
+
+static PyObject *
+_wrap_gv_view_area_map_pointer(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord x, y;
+
+ if (!PyArg_ParseTuple(args, "O!(" CC "):gv_view_area_map_pointer",
+ &PyGtk_Type, &py_view, &x, &y))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_map_pointer( view, x, y, &x, &y );
+
+ return Py_BuildValue("(" CC ")", x, y );
+}
+
+static PyObject *
+_wrap_gv_view_area_inverse_map_pointer(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord x, y;
+
+ if (!PyArg_ParseTuple(args, "O!(" CC "):gv_view_area_inverse_map_pointer",
+ &PyGtk_Type, &py_view, &x, &y))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ gv_view_area_inverse_map_pointer( view, x, y, &x, &y );
+
+ return Py_BuildValue("(" CC ")", x, y );
+}
+
+static PyObject *
+_wrap_gv_view_area_get_translation(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_translation",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+ return Py_BuildValue( "(" CC ")", view->state.tx, view->state.ty );
+}
+
+static PyObject *
+_wrap_gv_view_area_get_extents(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ gvgeocoord xmin, ymin, xmax, ymax;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_extents",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+
+ gv_view_area_get_extents( view, &xmin, &ymin, &xmax, &ymax );
+
+ return Py_BuildValue("(" CCCC ")", xmin, ymin, xmax, ymax );
+}
+
+
+static PyObject *
+_wrap_gv_view_area_get_volume(PyObject *self, PyObject *args)
+{
+ PyObject *py_view;
+ GvViewArea *view;
+ double volume[6];
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_volume",
+ &PyGtk_Type, &py_view))
+ {
+ return NULL;
+ }
+
+ if (!GV_IS_VIEW_AREA(PyGtk_Get(py_view)))
+ {
+ PyErr_SetString(PyExc_TypeError, "argument must be a GvViewArea");
+ return NULL;
+ }
+
+ view = GV_VIEW_AREA( PyGtk_Get(py_view) );
+
+ gv_view_area_get_volume( view, volume );
+
+ return Py_BuildValue("(" CCCCCC ")",
+ volume[0], volume[1],
+ volume[2], volume[3],
+ volume[4], volume[5] );
+}
+
+
+static PyObject *
+_wrap_gv_tool_set_boundary(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!(" CCCC "):gv_tool_new_rect",
+ &PyGtk_Type, &tool, &rect.x, &rect.y,
+ &rect.width, &rect.height))
+ return NULL;
+
+ if (!gv_tool_set_boundary(GV_TOOL(PyGtk_Get(tool)), &rect))
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "invalid ROI constraining region specified, width or height <= 0.0");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_roi_tool_get_rect(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_roi_tool_get_rect", &PyGtk_Type, &tool))
+ return NULL;
+ if (!gv_roi_tool_get_rect(GV_ROI_TOOL(PyGtk_Get(tool)), &rect))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "no ROI marked");
+ return NULL;
+ }
+ return Py_BuildValue("(" CCCC ")", rect.x, rect.y, rect.width, rect.height);
+}
+
+static PyObject *
+_wrap_gv_roi_tool_new_rect(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!(" CCCC "):gv_roi_tool_new_rect", &PyGtk_Type, &tool, &rect.x, &rect.y,
+ &rect.width, &rect.height))
+ return NULL;
+
+ if (!gv_roi_tool_new_rect(GV_ROI_TOOL(PyGtk_Get(tool)), &rect))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "invalid ROI specified");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_poi_tool_get_point(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvVertex point;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_poi_tool_get_point", &PyGtk_Type, &tool))
+ return NULL;
+ if (!gv_poi_tool_get_point(GV_POI_TOOL(PyGtk_Get(tool)), &point))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "no POI marked");
+ return NULL;
+ }
+ return Py_BuildValue("(" CC ")", point.x, point.y);
+}
+
+static PyObject *
+_wrap_gv_poi_tool_new_point(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvVertex point;
+
+ if (!PyArg_ParseTuple(args, "O!(" CC "):gv_poi_tool_new_point", &PyGtk_Type, &tool, &point.x, &point.y))
+ return NULL;
+
+ if (!gv_poi_tool_new_point(GV_POI_TOOL(PyGtk_Get(tool)), &point))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "invalid POI specified");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_records_get_typed_properties(PyObject *self, PyObject *args)
+{
+ PyObject *py_records;
+ int shp_index = -1, iField, ii;
+ GvRecords *records;
+ const char *pachRecData;
+ PyObject *psDict = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_records_get_typed_properties",
+ &PyGtk_Type, &py_records, &shp_index) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ if( shp_index < 0 || shp_index >= records->nRecordCount )
+ return NULL;
+
+ psDict = PyDict_New();
+ pachRecData = gv_records_get_raw_record_data( records, shp_index );
+ for( ii = 0; ii < records->nUsedFieldCount; ii++ )
+ {
+ PyObject *py_name, *py_value;
+ const char *value;
+
+ iField = records->panUsedFieldList[ii];
+
+ value = pachRecData + records->panFieldOffset[iField];
+
+ if( *value == GV_NULL_MARKER )
+ {
+ py_value = Py_None;
+ Py_INCREF( Py_None );
+ }
+ else if( records->panFieldType[iField] == GV_RFT_INTEGER )
+ py_value = Py_BuildValue("i",atoi(value));
+ else if( records->panFieldType[iField] == GV_RFT_FLOAT )
+ py_value = Py_BuildValue("f",atof(value));
+ else
+ py_value = Py_BuildValue("s",value);
+
+ py_name = Py_BuildValue("s",records->papszFieldName[iField]);
+
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+
+ return psDict;
+}
+
+static PyObject *
+_wrap_gv_records_get_properties(PyObject *self, PyObject *args)
+{
+ PyObject *py_records;
+ int shp_index = -1, iField;
+ GvRecords *records;
+ const char *pachRecData;
+ PyObject *psDict = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_records_get_properties",
+ &PyGtk_Type, &py_records, &shp_index) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ if( shp_index < 0 || shp_index >= records->nRecordCount )
+ return NULL;
+
+ psDict = PyDict_New();
+ pachRecData = gv_records_get_raw_record_data( records, shp_index );
+ for( iField = 0; iField < records->nFieldCount; iField++ )
+ {
+ PyObject *py_name, *py_value;
+ const char *value;
+
+ value = pachRecData + records->panFieldOffset[iField];
+ if( *value == GV_NULL_MARKER )
+ continue;
+
+ py_value = Py_BuildValue("s",value);
+ py_name = Py_BuildValue("s",records->papszFieldName[iField]);
+
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+
+ return psDict;
+}
+
+static PyObject *
+_wrap_gv_records_set_used_properties(PyObject *self, PyObject *args)
+{
+ PyObject *py_records;
+ PyObject *py_list;
+ GvRecords *records;
+ int nFieldCount, *panFieldList = NULL, i;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_records_set_used_properties",
+ &PyGtk_Type, &py_records, &PyList_Type, &py_list) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ nFieldCount = PyList_Size(py_list);
+ panFieldList = g_new( int, nFieldCount );
+
+ for( i = 0; i < nFieldCount; i++ )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(py_list,i), "i", panFieldList + i ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting ints in gv_records_set_used_fields argument");
+ return NULL;
+ }
+ }
+
+ gv_records_set_used_properties( records, nFieldCount, panFieldList );
+
+ g_free( panFieldList );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_records_to_dbf(PyObject *self, PyObject *args)
+{
+ PyObject *py_records;
+ PyObject *py_list;
+ char *filename = NULL;
+ GvRecords *records;
+ int nSelectionCount, *panSelectionList = NULL, i, result;
+ PyProgressData sProgressInfo;
+
+ sProgressInfo.psPyCallback = NULL;
+ sProgressInfo.psPyCallbackData = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!sO!OO:gv_records_to_dbf",
+ &PyGtk_Type, &py_records, &filename,
+ &PyList_Type, &py_list,
+ &(sProgressInfo.psPyCallback),
+ &(sProgressInfo.psPyCallbackData) ) )
+ return NULL;
+
+ if( !GV_IS_RECORDS(PyGtk_Get(py_records)) )
+ return NULL;
+
+ records = GV_RECORDS(PyGtk_Get(py_records));
+
+ nSelectionCount = PyList_Size(py_list);
+ if( nSelectionCount != 0 )
+ panSelectionList = g_new( int, nSelectionCount );
+
+ for( i = 0; i < nSelectionCount; i++ )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(py_list,i), "i", panSelectionList + i ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting ints in gv_records_to_dbf argument");
+ return NULL;
+ }
+ }
+
+ result = gv_records_to_dbf( records, filename,
+ nSelectionCount, panSelectionList,
+ PyProgressProxy, &sProgressInfo );
+
+ g_free( panSelectionList );
+
+ return Py_BuildValue("i", result );
+}
+
+#include "gv_ciet.c"
+
+static PyObject *
+_wrap_gv_shapes_get_shape(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapes;
+ int shp_index = -1;
+ char swig_shape_ptr[32];
+ GvShape *gv_shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_shapes_get_shape",
+ &PyGtk_Type, &py_shapes, &shp_index) )
+ return NULL;
+
+ if( GV_IS_SHAPES(PyGtk_Get(py_shapes))
+ && shp_index >= 0
+ && shp_index < gv_shapes_num_shapes(GV_SHAPES(PyGtk_Get(py_shapes))) )
+ {
+ gv_shape = gv_shapes_get_shape( GV_SHAPES(PyGtk_Get(py_shapes)),
+ shp_index );
+ }
+
+ if( gv_shape == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ SWIG_SimpleMakePtr( swig_shape_ptr, gv_shape, "_GvShape" );
+
+ return Py_BuildValue("s", swig_shape_ptr );
+}
+
+static PyObject *
+_wrap_gv_shapes_from_ogr_layer(PyObject *self, PyObject *args)
+{
+ GvData *data = NULL;
+ char *ogrlayer_in = NULL;
+ void *hLayer;
+ PyObject *py_ret = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shapes_from_ogr_layer",
+ &ogrlayer_in) )
+ return NULL;
+
+ hLayer = SWIG_SimpleGetPtr(ogrlayer_in, "OGRLayerH" );
+ if( hLayer == NULL )
+ {
+ PyErr_SetString(PyExc_IOError,
+ "Unable to extract OGRLayerH handle in gv_shapes_from_ogr_layer()");
+ return NULL;
+ }
+
+ data = gv_shapes_from_ogr_layer( hLayer );
+ if( data == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ py_ret = PyGtk_New( GTK_OBJECT(data) );
+ gtk_object_sink( GTK_OBJECT(data) );
+
+ return py_ret;
+}
+
+static PyObject *
+_wrap_gv_shapes_add_shape(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapes;
+ char *swig_shape_ptr;
+ int shp_index = -1;
+ GvShape *gv_shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_shapes_add_shape",
+ &PyGtk_Type, &py_shapes, &swig_shape_ptr) )
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ gv_shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( GV_IS_SHAPES(PyGtk_Get(py_shapes)) && gv_shape )
+ shp_index = gv_shapes_add_shape( GV_SHAPES(PyGtk_Get(py_shapes)),
+ gv_shape );
+
+ return Py_BuildValue("i", shp_index );
+}
+
+static PyObject *
+_wrap_gv_shapes_add_shape_last(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapes;
+ char *swig_shape_ptr;
+ int shp_index = -1;
+ GvShape *gv_shape = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_shapes_add_shape_last",
+ &PyGtk_Type, &py_shapes, &swig_shape_ptr) )
+ return NULL;
+
+ if( swig_shape_ptr )
+ {
+ gv_shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ }
+
+ if( GV_IS_SHAPES(PyGtk_Get(py_shapes)) && gv_shape )
+ shp_index = gv_shapes_add_shape_last( GV_SHAPES(PyGtk_Get(py_shapes)),
+ gv_shape );
+
+ return Py_BuildValue("i", shp_index );
+}
+
+static PyObject *
+_wrap_gv_shapes_delete_shapes(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapes;
+ int shape_count, i;
+ PyObject *pylist = NULL;
+ GvShapes *shapes = NULL;
+ int *shape_ids = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_shapes_delete_shapes",
+ &PyGtk_Type, &py_shapes,
+ &PyList_Type, &pylist) )
+ return NULL;
+
+ if( GV_IS_SHAPES(PyGtk_Get(py_shapes)) )
+ shapes = GV_SHAPES(PyGtk_Get(py_shapes));
+
+ shape_count = PyList_Size(pylist);
+ shape_ids = g_new(int,shape_count);
+
+ for( i = 0; i < shape_count; i++ )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(pylist,i), "i", shape_ids + i ) )
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting ints in gv_shapes_delete_shapes argument");
+ return NULL;
+ }
+ }
+
+ gv_shapes_delete_shapes( shapes, shape_count, shape_ids );
+
+ g_free( shape_ids );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shapes_replace_shapes(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapes;
+ int shape_count, i;
+ PyObject *pyindex_list = NULL, *pyshape_list = NULL;
+ GvShapes *shapes = NULL;
+ GvShape **shape_list = NULL;
+ int *shape_ids = NULL;
+ int copy_flag = FALSE;
+
+ if (!PyArg_ParseTuple(args, "O!O!O!|d:gv_shapes_replace_shapes",
+ &PyGtk_Type, &py_shapes,
+ &PyList_Type, &pyindex_list,
+ &PyList_Type, &pyshape_list,
+ ©_flag ) )
+ return NULL;
+
+ if( GV_IS_SHAPES(PyGtk_Get(py_shapes)) )
+ shapes = GV_SHAPES(PyGtk_Get(py_shapes));
+
+ if( PyList_Size(pyindex_list) != PyList_Size(pyshape_list) )
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Size of index & shape lists differ in gv_shapes_replace_shapes().");
+ return NULL;
+ }
+
+ shape_count = PyList_Size(pyindex_list);
+ shape_ids = g_new(int,shape_count);
+ shape_list = g_new(GvShape*,shape_count);
+
+ for( i = 0; i < shape_count; i++ )
+ {
+ char *shape_swigid = NULL;
+
+ if( !PyArg_Parse( PyList_GET_ITEM(pyindex_list,i), "i", shape_ids+i ))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting ints in gv_shapes_replace_shapes argument");
+ return NULL;
+ }
+
+ if( !PyArg_Parse( PyList_GET_ITEM(pyshape_list,i), "s",&shape_swigid ))
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "expecting GvShape in gv_shapes_replace_shapes argument");
+ return NULL;
+ }
+
+ shape_list[i] = SWIG_SimpleGetPtr( shape_swigid, "_GvShape" );
+ }
+
+
+ gv_shapes_replace_shapes( shapes, shape_count, shape_ids, shape_list,
+ copy_flag );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shapes_get_extents(PyObject *self, PyObject *args)
+{
+ PyObject *shapes;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shapes_extents", &PyGtk_Type, &shapes))
+ return NULL;
+
+ gv_shapes_get_extents(GV_SHAPES(PyGtk_Get(shapes)), &rect);
+ return Py_BuildValue("(" CCCC ")", rect.x, rect.y, rect.width, rect.height);
+}
+
+static PyObject *
+_wrap_gv_shapes_get_change_info(PyObject *self, PyObject *args)
+{
+ GvShapeChangeInfo *change_info;
+ PyObject *c_change_info;
+ PyObject *id_list;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O:gv_shapes_get_change_info", &c_change_info))
+ return NULL;
+
+ if (!PyCObject_Check (c_change_info))
+ return NULL;
+
+ change_info = (GvShapeChangeInfo *) PyCObject_AsVoidPtr(c_change_info);
+
+ id_list = PyTuple_New(change_info->num_shapes);
+
+ for(i=0; i<change_info->num_shapes; i++)
+ {
+ PyTuple_SetItem(id_list, i, PyInt_FromLong((long)change_info->shape_id[i]));
+ }
+
+ return Py_BuildValue( "(iiO)",
+ change_info->change_type,
+ change_info->num_shapes,
+ id_list );
+}
+
+static PyObject *
+_wrap_gv_points_get_point(PyObject *self, PyObject *args)
+{
+ PyObject *pypoints;
+ GvPoints *points;
+ GvPoint *point;
+ int index;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_points_get_point", &PyGtk_Type,
+ &pypoints, &index))
+ return NULL;
+
+ points = GV_POINTS(PyGtk_Get(pypoints));
+ if (index < 0 || index >= gv_points_num_points(points))
+ {
+ PyErr_SetString(PyExc_IndexError, "point index out of range");
+ return NULL;
+ }
+ point = gv_points_get_point(points, index);
+ return Py_BuildValue("(" CC ")", point->v.x, point->v.y);
+}
+
+static PyObject *
+_wrap_gv_points_new_point(PyObject *self, PyObject *args)
+{
+ PyObject *pypoints;
+ GvVertex vertex;
+
+ if (!PyArg_ParseTuple(args, "O!(" CC "):gv_points_new_point", &PyGtk_Type,
+ &pypoints, &vertex.x, &vertex.y))
+ return NULL;
+ return PyInt_FromLong(gv_points_new_point(GV_POINTS(PyGtk_Get(pypoints)),
+ &vertex));
+}
+
+static PyObject *
+build_py_line(GArray *line)
+{
+ PyObject *pylist;
+ GvVertex *v;
+ int i;
+
+ pylist = PyList_New(line->len);
+ for (i=0; i < line->len; i++)
+ {
+ PyObject *py_value;
+
+ v = &g_array_index(line, GvVertex, i);
+ py_value = Py_BuildValue("(" CC ")", v->x, v->y);
+ PyList_SetItem(pylist, i, py_value);
+ }
+ return pylist;
+}
+
+static GArray *
+build_gv_line(PyObject *pylist, int min_len)
+{
+ GArray *line;
+ GvVertex *v;
+ int i;
+
+ if (PyList_Size(pylist) < min_len)
+ {
+ PyErr_SetString(PyExc_ValueError, "line too short");
+ return NULL;
+ }
+
+ line = g_array_new(FALSE, FALSE, sizeof(GvVertex));
+ g_array_set_size(line, PyList_Size(pylist));
+ for (i=0; i < line->len; i++)
+ {
+ v = &g_array_index(line, GvVertex, i);
+ if (!PyArg_ParseTuple(PyList_GET_ITEM(pylist, i), CC, &v->x, &v->y))
+ {
+ PyErr_SetString(PyExc_ValueError, "bad line format");
+ g_array_free(line, TRUE);
+ return NULL;
+ }
+ }
+ return line;
+}
+
+static PyObject *
+_wrap_gv_polylines_get_line(PyObject *self, PyObject *args)
+{
+ PyObject *pypline;
+ GvPolylines *pline;
+ int index;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_polylines_get_line", &PyGtk_Type,
+ &pypline, &index))
+ return NULL;
+ pline = GV_POLYLINES(PyGtk_Get(pypline));
+ if (index < 0 || index >= gv_polylines_num_lines(pline))
+ {
+ PyErr_SetString(PyExc_IndexError, "line index out of range");
+ return NULL;
+ }
+ return build_py_line(gv_polylines_get_line(pline, index));
+}
+
+static PyObject *
+_wrap_gv_polylines_new_line(PyObject *self, PyObject *args)
+{
+ PyObject *pypline, *pylist;
+ GArray *line;
+ int index;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_polylines_new_line", &PyGtk_Type,
+ &pypline, &PyList_Type, &pylist))
+ return NULL;
+ line = build_gv_line(pylist, 2);
+ if (!line) return NULL;
+ index = gv_polylines_new_line_with_data(GV_POLYLINES(PyGtk_Get(pypline)),
+ line->len, (GvVertex*)line->data);
+ g_array_free(line, TRUE);
+ return PyInt_FromLong(index);
+}
+
+static PyObject *
+_wrap_gv_areas_get_area(PyObject *self, PyObject *args)
+{
+ PyObject *pyareas, *pyarea;
+ GvAreas *areas;
+ GvArea *area;
+ int index, ring;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_areas_get_area", &PyGtk_Type,
+ &pyareas, &index))
+ return NULL;
+ areas = GV_AREAS(PyGtk_Get(pyareas));
+ if (index < 0 || index >= gv_areas_num_areas(areas))
+ {
+ PyErr_SetString(PyExc_IndexError, "area index out of range");
+ return NULL;
+ }
+ area = gv_areas_get_area(areas, index);
+
+ pyarea = PyList_New(gv_areas_num_rings(area));
+ for (ring = 0; ring < gv_areas_num_rings(area); ring++)
+ {
+ PyObject *pyline = build_py_line(gv_areas_get_ring(area, ring));
+ PyList_SetItem(pyarea, ring, pyline);
+ }
+ return pyarea;
+}
+
+static PyObject *
+_wrap_gv_areas_new_area(PyObject *self, PyObject *args)
+{
+ PyObject *pyareas, *pyarea;
+ GvAreas *areas;
+ GvArea *area;
+ int index, ring, num_rings;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_areas_new_area", &PyGtk_Type,
+ &pyareas, &PyList_Type, &pyarea))
+ return NULL;
+ areas = GV_AREAS(PyGtk_Get(pyareas));
+ num_rings = PyList_Size(pyarea);
+ if (num_rings < 1)
+ {
+ PyErr_SetString(PyExc_ValueError, "empty ring list");
+ return NULL;
+ }
+
+ area = gv_area_new(FALSE);
+ for (ring = 0; ring < num_rings; ring++)
+ {
+ GArray *line = build_gv_line(PyList_GET_ITEM(pyarea, ring), 3);
+ if (!line) break;
+ g_ptr_array_add(area->rings, line);
+ }
+ if (PyErr_Occurred())
+ {
+ gv_area_delete(area);
+ return NULL;
+ }
+
+ index = gv_areas_new_area_with_data(areas, area);
+ gv_area_delete(area);
+ return PyInt_FromLong(index);
+}
+
+static PyObject *
+_wrap_gv_shape_layer_set_color(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ GvColor color;
+
+ if (!PyArg_ParseTuple(args, "O!(ffff):gv_shape_layer_set_color",
+ &PyGtk_Type, &layer,
+ &color[0], &color[1], &color[2], &color[3]))
+ return NULL;
+ gv_shape_layer_set_color(GV_SHAPE_LAYER(PyGtk_Get(layer)), color);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_shape_layer_get_selected(PyObject *self, PyObject *args)
+{
+ PyObject *layer, *list;
+ GArray *array;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shape_layer_set_color",
+ &PyGtk_Type, &layer ) )
+ return NULL;
+
+ array = g_array_new(FALSE,TRUE,sizeof(gint));
+ gv_shape_layer_selected(GV_SHAPE_LAYER(PyGtk_Get(layer)),
+ GV_ALL, (void *) array );
+
+ list = PyList_New(array->len);
+ for( i = 0; i < array->len; i++ )
+ {
+ PyList_SetItem( list, i,
+ Py_BuildValue("i", g_array_index(array,gint,i)) );
+ }
+
+ g_array_free( array, TRUE );
+
+ return list;
+}
+
+static PyObject *
+_wrap_gv_shape_layer_pick_shape( PyObject *self, PyObject *args )
+{
+ PyObject *layer;
+ PyObject *view;
+ gint shape_id;
+ float x, y;
+
+ if (!PyArg_ParseTuple(args, "O!O!ff:gv_shape_layer_pick_shape",
+ &PyGtk_Type, &layer, &PyGtk_Type, &view, &x, &y ))
+ {
+ return NULL;
+ }
+
+ if (gv_shape_layer_pick_shape( GV_SHAPE_LAYER(PyGtk_Get(layer)),
+ GV_VIEW_AREA(PyGtk_Get(view)),
+ x, y, &shape_id ))
+ {
+ return PyInt_FromLong( (long)shape_id );
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+/******************
+ * gv_raster_new
+ *
+ * This function makes assumptions about the dataio lib and should
+ * be modified once the dataio situation is sorted out.
+ *
+ * Args: filename, format (optional)
+ ******************/
+
+static PyObject *
+_wrap_gv_raster_new(PyObject *self, PyObject *args, PyObject *keywds)
+{
+ PyObject * py_ret;
+ char *filename = NULL, *dataset_string = NULL;
+ GDALDatasetH dataset;
+ static int gdal_initialized = 0;
+ GvSampleMethod sm = GvSMAverage;
+ int rband = 1;
+ static char *kwlist[] = {"filename", "sample", "real",
+ "dataset", NULL};
+ GvRaster *raster;
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "|ziiz", kwlist,
+ &filename, &sm, &rband,
+ &dataset_string))
+ return NULL;
+
+ if( !gdal_initialized )
+ {
+ GDALAllRegister();
+ gdal_initialized = 1;
+ }
+
+ if( dataset_string != NULL )
+ {
+ dataset = (GDALDatasetH)
+ SWIG_SimpleGetPtr(dataset_string, "GDALDatasetH" );
+ if (dataset == NULL)
+ {
+ PyErr_SetString(PyExc_IOError,
+ "Unable to extract GDALDatasetH handle in gv_raster_new()");
+ return NULL;
+ }
+ }
+ else if( filename != NULL )
+ {
+ dataset = GDALOpen( filename, GA_ReadOnly );
+
+ if (dataset == NULL)
+ {
+ PyErr_SetString(PyExc_IOError, "failed to open data file");
+ return NULL;
+ }
+
+ GDALDereferenceDataset( dataset );
+ }
+ else
+ {
+ PyErr_SetString(PyExc_IOError,
+ "gv_raster_new: either a filename, or dataset handle"
+ " is required. Neither provided." );
+ return NULL;
+ }
+
+ raster = GV_RASTER(gv_raster_new(dataset,rband,sm));
+ if( filename != NULL )
+ gv_data_set_name(GV_DATA(raster), filename);
+
+ py_ret = PyGtk_New( GTK_OBJECT(raster) );
+
+ gtk_object_sink( GTK_OBJECT(raster) );
+
+ return py_ret;
+}
+
+static PyObject *
+_wrap_gv_raster_autoscale(PyObject *self, PyObject *args)
+
+{
+ int alg = GvASAAutomatic, assign = 0, success;
+ double alg_param = -1.0;
+ PyObject *py_raster;
+ GvRaster *raster = NULL;
+ double out_min, out_max;
+
+ if (!PyArg_ParseTuple(args, "O!idi:gv_raster_autoscale", &PyGtk_Type,
+ &py_raster, &alg, &alg_param, &assign))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( assign == 0 )
+ {
+ success = gv_raster_autoscale(raster, alg, alg_param, 0, NULL,
+ NULL, NULL);
+ if( !success )
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "autoscale() failed, failed to get samples?" );
+ return NULL;
+ }
+
+ return Py_BuildValue("(dd)", raster->min, raster->max);
+ }
+ else
+ {
+ success = gv_raster_autoscale(raster, alg, alg_param,
+ 0, NULL,
+ &out_min, &out_max);
+
+ if( !success )
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "autoscale() failed, failed to get samples?" );
+ return NULL;
+ }
+
+ return Py_BuildValue("(dd)", out_min, out_max );
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_get_gdal_band(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ char swig_ptr[32];
+ GDALRasterBandH band;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_get_gdal_band",
+ &PyGtk_Type, &py_raster ) )
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+ if( raster == NULL )
+ return NULL;
+
+ band = raster->gdal_band;
+
+ if( band == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ SWIG_SimpleMakePtr( swig_ptr, band, "_GDALRasterBandH" );
+ return Py_BuildValue("s",swig_ptr);
+}
+
+static PyObject *
+_wrap_gv_raster_get_gdal_dataset(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ char swig_ptr[32];
+ GDALDatasetH dataset;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_get_gdal_dataset",
+ &PyGtk_Type, &py_raster ) )
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+ if( raster == NULL )
+ return NULL;
+
+ dataset = raster->dataset;
+
+ if( dataset == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ SWIG_SimpleMakePtr( swig_ptr, dataset, "_GDALDatasetH" );
+ return Py_BuildValue("s",swig_ptr);
+}
+
+static PyObject *
+_wrap_gv_raster_force_load(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_force_load",
+ &PyGtk_Type, &py_raster ) )
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+ if( raster == NULL )
+ return NULL;
+
+ for( i = 0; i < raster->max_tiles; i++ )
+ gv_raster_tile_get( raster, i, 0 );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_raster_data_changing(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ int x_off=0, y_off=0, width=0, height=0;
+ GvRasterChangeInfo change_info;
+
+ if (!PyArg_ParseTuple(args, "O!iiii:gv_raster_data_changing",
+ &PyGtk_Type, &py_raster,
+ &x_off, &y_off, &width, &height ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( height > 0 )
+ {
+ change_info.change_type = GV_CHANGE_REPLACE;
+ change_info.x_off = x_off;
+ change_info.y_off = y_off;
+ change_info.width = width;
+ change_info.height = height;
+
+ gv_data_changing( GV_DATA(raster), &change_info );
+ }
+ else
+ {
+ gv_data_changing( GV_DATA(raster), NULL );
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_raster_data_changed(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ int x_off=0, y_off=0, width=0, height=0;
+ GvRasterChangeInfo change_info;
+
+ if (!PyArg_ParseTuple(args, "O!iiii:gv_raster_data_changed",
+ &PyGtk_Type, &py_raster,
+ &x_off, &y_off, &width, &height ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( height > 0 )
+ {
+ change_info.change_type = GV_CHANGE_REPLACE;
+ change_info.x_off = x_off;
+ change_info.y_off = y_off;
+ change_info.width = width;
+ change_info.height = height;
+
+ gv_data_changed( GV_DATA(raster), &change_info );
+ }
+ else
+ {
+ gv_data_changed( GV_DATA(raster), NULL );
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_raster_get_sample(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ double x, y, real, imaginary;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_get_sample",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( !gv_raster_get_sample(raster, x, y, &real, &imaginary ) )
+ return NULL;
+ else if( GDALDataTypeIsComplex(raster->gdal_type) )
+ return Py_BuildValue( "(ff)", real, imaginary );
+ else
+ return Py_BuildValue( "f", real );
+}
+
+static PyObject *
+_wrap_gv_raster_georef_to_pixel(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_georef_to_pixel",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( gv_raster_georef_to_pixel(raster, &x, &y, NULL) )
+ {
+ return Py_BuildValue( "(ff)", x, y );
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "georef_to_pixel transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_pixel_to_georef(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_pixel_to_georef",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( gv_raster_pixel_to_georef(raster, &x, &y, NULL ) )
+ {
+ return Py_BuildValue("(ff)", x, y);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "georef_to_pixel transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_get_gcps(PyObject *self, PyObject *args) {
+
+ PyObject *py_raster;
+ GvRaster *raster;
+ const GDAL_GCP * pasGCPList;
+ PyObject *psList;
+ int iGCP;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"O!:gv_raster_get_gcps",
+ &PyGtk_Type, &py_raster ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+ pasGCPList = gv_raster_get_gcps( raster );
+
+ psList = PyList_New(raster->gcp_count);
+ for( iGCP = 0; pasGCPList != NULL && iGCP < raster->gcp_count; iGCP++)
+ {
+ PyObject *py_item;
+
+ py_item = Py_BuildValue("(ssddddd)",
+ pasGCPList[iGCP].pszId,
+ pasGCPList[iGCP].pszInfo,
+ pasGCPList[iGCP].dfGCPPixel,
+ pasGCPList[iGCP].dfGCPLine,
+ pasGCPList[iGCP].dfGCPX,
+ pasGCPList[iGCP].dfGCPY,
+ pasGCPList[iGCP].dfGCPZ );
+ PyList_SetItem(psList, iGCP, py_item );
+ }
+
+ return psList;
+}
+
+static PyObject *
+_wrap_gv_raster_georef_to_pixelCL(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_georef_to_pixelCL",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( gv_raster_georef_to_pixelCL(raster, &x, &y, NULL) )
+ {
+ return Py_BuildValue( "(ff)", x, y );
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "georef_to_pixelCL transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_pixel_to_georefCL(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRaster *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_pixel_to_georefCL",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( gv_raster_pixel_to_georefCL(raster, &x, &y, NULL ) )
+ {
+ return Py_BuildValue("(ff)", x, y);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "georef_to_pixelCL transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_get_gcpsCL(PyObject *self, PyObject *args) {
+
+ PyObject *py_raster;
+ GvRaster *raster;
+ const GDAL_GCP * pasGCPList;
+ PyObject *psList;
+ int iGCP;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"O!:gv_raster_get_gcps",
+ &PyGtk_Type, &py_raster ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+ pasGCPList = gv_raster_get_gcpsCL( raster );
+
+ psList = PyList_New(raster->gcp_countCL);
+ for( iGCP = 0; pasGCPList != NULL && iGCP < raster->gcp_countCL; iGCP++)
+ {
+ PyObject *py_item;
+
+ py_item = Py_BuildValue("(ssddddd)",
+ pasGCPList[iGCP].pszId,
+ pasGCPList[iGCP].pszInfo,
+ pasGCPList[iGCP].dfGCPPixel,
+ pasGCPList[iGCP].dfGCPLine,
+ pasGCPList[iGCP].dfGCPX,
+ pasGCPList[iGCP].dfGCPY,
+ pasGCPList[iGCP].dfGCPZ );
+ PyList_SetItem(psList, iGCP, py_item );
+ }
+
+ return psList;
+}
+
+static PyObject *
+_wrap_gv_raster_set_gcps(PyObject *self, PyObject *args) {
+
+ PyObject *py_raster;
+ GvRaster *raster;
+ GDAL_GCP * pasGCPList;
+ PyObject *psList;
+ int iGCP, nGCPCount, success;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"O!O!:gv_raster_set_gcps",
+ &PyGtk_Type, &py_raster,
+ &PyList_Type, &psList))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ nGCPCount = PyList_Size(psList);
+ pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+ GDALInitGCPs( nGCPCount, pasGCPList );
+
+ for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+ {
+ char *pszId = NULL, *pszInfo = NULL;
+
+ if( !PyArg_Parse( PyList_GET_ITEM(psList,iGCP), "(ssddddd)",
+ &pszId, &pszInfo,
+ &(pasGCPList[iGCP].dfGCPPixel),
+ &(pasGCPList[iGCP].dfGCPLine),
+ &(pasGCPList[iGCP].dfGCPX),
+ &(pasGCPList[iGCP].dfGCPY),
+ &(pasGCPList[iGCP].dfGCPZ) ) )
+ {
+ PyErr_SetString(PyExc_ValueError, "improper GCP tuple");
+ return NULL;
+ }
+
+ CPLFree( pasGCPList[iGCP].pszId );
+ pasGCPList[iGCP].pszId = CPLStrdup(pszId);
+ CPLFree( pasGCPList[iGCP].pszInfo );
+ pasGCPList[iGCP].pszInfo = CPLStrdup(pszInfo);
+ }
+
+ success = gv_raster_set_gcps( raster, nGCPCount, pasGCPList );
+
+ GDALDeinitGCPs( nGCPCount, pasGCPList );
+ CPLFree( pasGCPList );
+
+ return Py_BuildValue("d", success);
+}
+
+static PyObject *
+_wrap_gv_raster_set_gcpsCL(PyObject *self, PyObject *args) {
+
+ PyObject *py_raster;
+ GvRaster *raster;
+ GDAL_GCP * pasGCPList;
+ PyObject *psList;
+ int iGCP, nGCPCount, success, poly_order;
+
+ self = self;
+ if(!PyArg_ParseTuple(args,"O!O!i:gv_raster_set_gcpsCL",
+ &PyGtk_Type, &py_raster,
+ &PyList_Type, &psList,
+ &poly_order))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ nGCPCount = PyList_Size(psList);
+ pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+ GDALInitGCPs( nGCPCount, pasGCPList );
+
+ for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+ {
+ char *pszId = NULL, *pszInfo = NULL;
+
+ if( !PyArg_Parse( PyList_GET_ITEM(psList,iGCP), "(ssddddd)",
+ &pszId, &pszInfo,
+ &(pasGCPList[iGCP].dfGCPPixel),
+ &(pasGCPList[iGCP].dfGCPLine),
+ &(pasGCPList[iGCP].dfGCPX),
+ &(pasGCPList[iGCP].dfGCPY),
+ &(pasGCPList[iGCP].dfGCPZ) ) )
+ {
+ PyErr_SetString(PyExc_ValueError, "improper GCP tuple");
+ return NULL;
+ }
+
+ CPLFree( pasGCPList[iGCP].pszId );
+ pasGCPList[iGCP].pszId = CPLStrdup(pszId);
+ CPLFree( pasGCPList[iGCP].pszInfo );
+ pasGCPList[iGCP].pszInfo = CPLStrdup(pszInfo);
+ }
+
+ success = gv_raster_set_gcpsCL( raster, nGCPCount, pasGCPList,poly_order);
+
+ GDALDeinitGCPs( nGCPCount, pasGCPList );
+ CPLFree( pasGCPList );
+
+ return Py_BuildValue("d", success);
+}
+
+static PyObject *
+_wrap_gv_raster_layer_new(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ PyObject *py_properties = NULL;
+ GvRaster *raster;
+ GvRasterLayer *layer;
+ GvProperties properties = NULL;
+ int mode = GV_RLM_AUTO;
+
+ if (!PyArg_ParseTuple(args, "O!|iO!:gv_raster_layer_new",
+ &PyGtk_Type, &py_raster, &mode,
+ &PyList_Type, &py_properties ))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( py_properties != NULL )
+ {
+ int i;
+
+ for( i = 0; i < PyList_Size(py_properties); i++ )
+ {
+ char *name, *value;
+ PyObject *tuple = PyList_GET_ITEM(py_properties, i);
+
+ if (!PyArg_ParseTuple(tuple, "ss", &name, &value))
+ {
+ PyErr_SetString(PyExc_ValueError, "properties format");
+ return NULL;
+ }
+
+ gv_properties_set( &properties, name, value );
+ }
+ }
+
+ layer = GV_RASTER_LAYER(gv_raster_layer_new( mode, raster, properties ));
+
+ gv_properties_destroy( &properties );
+
+ return PyGtk_New(GTK_OBJECT(layer));
+}
+
+static PyObject *
+_wrap_gv_raster_layer_autoscale_view(PyObject *self, PyObject *args)
+
+{
+ int alg = GvASAAutomatic, isrc = 0, success;
+ double alg_param = -1.0;
+ PyObject *py_raster;
+ GvRasterLayer *rlayer = NULL;
+ double out_min, out_max;
+
+ if (!PyArg_ParseTuple(args, "O!idi:gv_raster_layer_autoscale_view",
+ &PyGtk_Type, &py_raster, &alg, &alg_param, &isrc))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER(PyGtk_Get(py_raster));
+
+ success = gv_raster_layer_autoscale_view(rlayer, isrc, alg, alg_param,
+ &out_min, &out_max );
+ if( !success )
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "autoscale() failed, failed to get samples?" );
+ return NULL;
+ }
+
+ return Py_BuildValue("(dd)", out_min, out_max );
+}
+
+static PyObject *
+_wrap_gv_raster_layer_get_mesh_lod(PyObject *self, PyObject *args)
+
+{
+ PyObject *py_raster;
+ GvRasterLayer *rlayer = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_layer_get_mesh_lod",
+ &PyGtk_Type, &py_raster))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER(PyGtk_Get(py_raster));
+
+ return Py_BuildValue("i", rlayer->mesh->detail );
+}
+
+static PyObject *
+_wrap_gv_raster_layer_histogram_view(PyObject *self, PyObject *args)
+
+{
+ PyObject *py_rlayer, *py_list;
+ GvRasterLayer *rlayer = NULL;
+ double scale_min, scale_max;
+ int hist_size = 256, isrc = 0, hist_count, i;
+ int *histogram = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!iddi:gv_raster_layer_autoscale_view",
+ &PyGtk_Type, &py_rlayer, &isrc,
+ &scale_min, &scale_max, &hist_size))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER(PyGtk_Get(py_rlayer));
+
+ histogram = g_new(int, hist_size);
+
+ hist_count =
+ gv_raster_layer_histogram_view(rlayer, isrc,
+ scale_min, scale_max, TRUE,
+ hist_size, histogram );
+ if( hist_count == 0 )
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "histogram() failed, failed to get samples?" );
+ return NULL;
+ }
+
+ py_list = PyList_New(0);
+ for( i = 0; i < hist_size; i++ )
+ {
+ PyObject *py_value = Py_BuildValue("i", histogram[i]);
+ PyList_Append(py_list, py_value);
+ Py_DECREF( py_value );
+ }
+ g_free( histogram );
+
+ return py_list;
+}
+
+static PyObject *
+_wrap_gv_raster_layer_pixel_to_view(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRasterLayer *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_layer_pixel_to_view",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER_LAYER(PyGtk_Get(py_raster));
+
+ if( gv_raster_layer_pixel_to_view(raster, &x, &y, NULL ) )
+ {
+ return Py_BuildValue("(ff)", x, y);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "pixel_to_view transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_view_to_pixel(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRasterLayer *raster;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_layer_view_to_pixel",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ raster = GV_RASTER_LAYER(PyGtk_Get(py_raster));
+
+ if( gv_raster_layer_view_to_pixel(raster, &x, &y, NULL ) )
+ {
+ return Py_BuildValue("(ff)", x, y);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "view_to_pixel transformation failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_texture_mode_set(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ int texture_mode;
+ GvColor color;
+
+ if (!PyArg_ParseTuple(args, "O!i(ffff):gv_raster_layer_texture_mode_set",
+ &PyGtk_Type, &layer, &texture_mode,
+ &color[0], &color[1], &color[2], &color[3]))
+ return NULL;
+
+ return PyInt_FromLong( gv_raster_layer_texture_mode_set(GV_RASTER_LAYER(PyGtk_Get(layer)), texture_mode, color) );
+}
+
+static PyObject *
+_wrap_gv_raster_layer_alpha_get(PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ float alpha_val;
+ int alpha_mode;
+
+ if (!PyArg_ParseTuple( args, "O!:gv_raster_layer_alpha_get",
+ &PyGtk_Type, &layer ))
+ return NULL;
+
+ if (gv_raster_layer_alpha_get( GV_RASTER_LAYER( PyGtk_Get(layer)), &alpha_mode, &alpha_val ))
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+ return Py_BuildValue("(if)", alpha_mode, alpha_val );
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_blend_mode_get( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ int blend_mode;
+ int sfactor;
+ int dfactor;
+
+ if (!PyArg_ParseTuple( args, "O!:gv_raster_layer_blend_mode_get",
+ &PyGtk_Type, &layer ))
+ return NULL;
+
+ if (gv_raster_layer_blend_mode_get( GV_RASTER_LAYER( PyGtk_Get(layer)), &blend_mode, &sfactor, &dfactor ))
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+ return Py_BuildValue("(iii)", blend_mode, sfactor, dfactor );
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_texture_mode_get( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ int texture_mode;
+ GvColor color;
+ PyObject *py_color, *py_retval;
+
+ if (!PyArg_ParseTuple( args, "O!:gv_raster_layer_texture_mode_get",
+ &PyGtk_Type, &layer ))
+ return NULL;
+
+ if (gv_raster_layer_texture_mode_get( GV_RASTER_LAYER( PyGtk_Get(layer)), &texture_mode, &color ))
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+ py_color = Py_BuildValue( "(ffff)", color[0], color[1], color[2], color[3] );
+ py_retval = Py_BuildValue( "(iO)", texture_mode, py_color );
+ Py_DECREF( py_color );
+ return py_retval;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_lut_put( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ char *lut;
+ int lut_len, height;
+
+ if (!PyArg_ParseTuple( args, "O!z#:gv_raster_layer_lut_put",
+ &PyGtk_Type, &layer, &lut, &lut_len ))
+ return NULL;
+
+ if( lut != NULL && lut_len != 1024 && lut_len != 1024 * 256 )
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "lut string must be 256x1x4 or 256x256x4 in gv_raster_layer_lut_put");
+ return NULL;
+ }
+
+ height = lut_len / 1024;
+ gv_raster_layer_lut_put( GV_RASTER_LAYER( PyGtk_Get(layer)),
+ (unsigned char*)lut, height );
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_raster_layer_lut_get( PyObject *self, PyObject *args)
+{
+ PyObject *layer, *py_lut, *py_retval;
+ char *lut;
+ int width, height;
+ int rgba_complex=0;
+
+ if (!PyArg_ParseTuple( args, "O!|i:gv_raster_layer_lut_get",
+ &PyGtk_Type, &layer, &rgba_complex ))
+ return NULL;
+
+ if ( (lut = (char *)gv_raster_layer_lut_get( GV_RASTER_LAYER( PyGtk_Get(layer)), &width, &height, rgba_complex )) == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+
+ if ( ( py_lut = PyString_FromStringAndSize( lut, width * height * 4 ) ) == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ py_retval = Py_BuildValue( "(Oii)", py_lut, width, height );
+ Py_DECREF( py_lut );
+ return py_retval;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_source_get_lut( PyObject *self, PyObject *args)
+{
+ PyObject *layer, *py_lut;
+ char *lut;
+ int isource=0;
+
+ if (!PyArg_ParseTuple( args, "O!i:gv_raster_layer_source_get_lut",
+ &PyGtk_Type, &layer, &isource ))
+ return NULL;
+
+ lut = (char *)gv_raster_layer_source_get_lut(
+ GV_RASTER_LAYER( PyGtk_Get(layer)), isource );
+ if( lut == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if ( ( py_lut = PyString_FromStringAndSize( lut, 256 ) ) == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return py_lut;
+}
+
+static PyObject *
+_wrap_gv_raster_layer_nodata_get( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ GvRasterLayer *rlayer;
+ int isource = 0;
+ gint ret;
+ double nodata_real, nodata_imaginary;
+
+ if (!PyArg_ParseTuple( args, "O!i:gv_raster_layer_nodata_get",
+ &PyGtk_Type, &layer, &isource ))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER(PyGtk_Get(layer));
+ ret = gv_raster_layer_nodata_get( rlayer, isource,
+ &nodata_real, &nodata_imaginary );
+ if( ret )
+ {
+ if( GDALDataTypeIsComplex(gv_raster_layer_type_get(rlayer, isource)) )
+ return Py_BuildValue( "(ff)", nodata_real, nodata_imaginary );
+ else
+ return Py_BuildValue( "f", nodata_real );
+ }
+ else
+ {
+ Py_INCREF( Py_None );
+ return Py_None;
+ }
+}
+
+/* XXX: gv_raster_layer_get_nodata() now DEPRECATED. */
+static PyObject *
+_wrap_gv_raster_layer_get_nodata( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ GvRasterLayer *rlayer;
+ int isource=0;
+
+ if (!PyArg_ParseTuple( args, "O!i:gv_raster_layer_get_nodata",
+ &PyGtk_Type, &layer, &isource ))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER( PyGtk_Get(layer) );
+ if( rlayer != NULL && isource >= 0 && isource < rlayer->source_count )
+ {
+ GvRasterSource *source = rlayer->source_list + isource;
+
+ if( source->nodata_active && source->data != NULL
+ && source->data->gdal_type == GDT_CFloat32 )
+ return Py_BuildValue( "(ff)", source->nodata_real,
+ source->nodata_imaginary );
+ else
+ return Py_BuildValue( "f", source->nodata_real );
+ }
+ else
+ {
+ Py_INCREF( Py_None );
+ return Py_None;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_set_source( PyObject *self, PyObject *args)
+{
+ PyObject *layer, *py_raster;
+ GvRaster *raster = NULL;
+ char *lut = NULL;
+ int isource, const_value, ret, lut_len=0, nodata_active=FALSE;
+ float min, max;
+ PyObject *nodata = NULL;
+ float nodata_real=-1e8, nodata_imaginary=0.0;
+
+ if (!PyArg_ParseTuple( args, "O!iOffi|z#O:gv_raster_layer_set_source",
+ &PyGtk_Type, &layer, &isource,
+ &py_raster, &min, &max, &const_value,
+ &lut, &lut_len, &nodata ))
+ return NULL;
+
+ if( py_raster == NULL || py_raster == Py_None )
+ raster = NULL;
+ else
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ if( nodata == NULL || nodata == Py_None )
+ {
+ nodata_real = 0.0;
+ nodata_imaginary = 0.0;
+ nodata_active = FALSE;
+ }
+ else if( PyTuple_Check(nodata) )
+ {
+ if( !PyArg_ParseTuple( nodata, "ff", &nodata_real, &nodata_imaginary) )
+ return NULL;
+
+ nodata_active = TRUE;
+ }
+ else
+ {
+ if( !PyArg_Parse( nodata, "f", &nodata_real ) )
+ return NULL;
+
+ nodata_imaginary = 0.0;
+ nodata_active = TRUE;
+ }
+
+ ret = gv_raster_layer_set_source( GV_RASTER_LAYER( PyGtk_Get(layer)),
+ isource, raster,
+ min, max, const_value,
+ (unsigned char*)lut,
+ nodata_active,
+ nodata_real, nodata_imaginary );
+
+ return Py_BuildValue("i", ret);
+}
+
+static PyObject *
+_wrap_gv_raster_layer_zoom_get( PyObject *self, PyObject *args)
+{
+ PyObject *layer;
+ int mag, min;
+
+ if (!PyArg_ParseTuple( args, "O!:gv_raster_layer_zoom_get",
+ &PyGtk_Type, &layer ))
+ return NULL;
+
+ if( gv_raster_layer_zoom_get( GV_RASTER_LAYER( PyGtk_Get(layer)), &mag, &min ) )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ } else {
+ return Py_BuildValue( "(ii)", min, mag );
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_layer_get_height(PyObject *self, PyObject *args)
+{
+ PyObject *py_raster;
+ GvRasterLayer *layer;
+ GvMesh *mesh;
+ double x, y, result;
+ int success;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_raster_layer_get_height",
+ &PyGtk_Type, &py_raster, &x, &y ))
+ return NULL;
+
+ layer = GV_RASTER_LAYER(PyGtk_Get(py_raster));
+ mesh = layer->mesh;
+
+ result = gv_mesh_get_height( mesh, x, y, &success );
+
+ if( success )
+ return Py_BuildValue("f", result );
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "gv_mesh_get_height() failed." );
+ return NULL;
+ }
+}
+
+static PyObject *
+_wrap_gv_raster_get_change_info(PyObject *self, PyObject *args)
+{
+ GvRasterChangeInfo *change_info;
+ PyObject *c_change_info;
+
+ if (!PyArg_ParseTuple(args, "O:gv_raster_get_change_info", &c_change_info))
+ return NULL;
+
+ if (!PyCObject_Check (c_change_info))
+ return NULL;
+
+ change_info = (GvRasterChangeInfo *) PyCObject_AsVoidPtr(c_change_info);
+
+ return Py_BuildValue( "(iiiii)",
+ change_info->change_type,
+ change_info->x_off,
+ change_info->y_off,
+ change_info->width,
+ change_info->height
+ );
+}
+
+
+static PyObject *
+_wrap_gv_manager_get_preferences(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ GvProperties *properties = NULL;
+ PyObject *psDict = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_manager_get_properties",
+ &PyGtk_Type, &manager))
+ return NULL;
+
+ if( manager != NULL )
+ properties =
+ gv_manager_get_preferences(GV_MANAGER(PyGtk_Get(manager)));
+
+ psDict = PyDict_New();
+ if( properties != NULL )
+ {
+ int i, count;
+
+ count = gv_properties_count( properties );
+ for( i = 0; i < count; i++ )
+ {
+ const char *value, *name;
+ PyObject *py_name, *py_value;
+
+ value = gv_properties_get_value_by_index(properties,i);
+ name = gv_properties_get_name_by_index(properties,i);
+
+ py_name = Py_BuildValue("s",name);
+ py_value = Py_BuildValue("s",value);
+ PyDict_SetItem( psDict, py_name, py_value );
+
+ Py_DECREF(py_name);
+ Py_DECREF(py_value);
+ }
+ }
+
+ return psDict;
+}
+
+static PyObject *
+_wrap_gv_manager_add_dataset(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *dataset_string=NULL;
+ char swig_ptr[32];
+ GDALDatasetH dataset = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_manager_get_dataset",
+ &PyGtk_Type, &manager, &dataset_string))
+ return NULL;
+
+ if( manager == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ dataset = (GDALDatasetH) SWIG_SimpleGetPtr(dataset_string, "GDALDatasetH");
+ if( dataset == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ dataset = gv_manager_add_dataset( GV_MANAGER(PyGtk_Get(manager)), dataset );
+ SWIG_SimpleMakePtr( swig_ptr, dataset, "_GDALDatasetH" );
+ return Py_BuildValue( "s", swig_ptr );
+}
+
+static PyObject *
+_wrap_gv_manager_get_dataset(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *filename = NULL;
+ char swig_ptr[32];
+ GDALDatasetH dataset = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_manager_get_dataset",
+ &PyGtk_Type, &manager, &filename))
+ return NULL;
+
+ if( manager != NULL )
+ dataset = gv_manager_get_dataset( GV_MANAGER(PyGtk_Get(manager)),
+ filename );
+
+ if( dataset == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ {
+ SWIG_SimpleMakePtr( swig_ptr, dataset, "_GDALDatasetH" );
+ return Py_BuildValue( "s", swig_ptr );
+ }
+}
+
+static PyObject *
+_wrap_gv_manager_get_dataset_raster(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ char *dataset_string=NULL;
+ int band = 0;
+ GDALDatasetH dataset = NULL;
+ GvRaster *raster = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!si:gv_manager_get_dataset_raster",
+ &PyGtk_Type, &manager, &dataset_string, &band))
+ return NULL;
+
+ if( manager == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ dataset = (GDALDatasetH) SWIG_SimpleGetPtr(dataset_string, "GDALDatasetH");
+ if( dataset == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ raster = gv_manager_get_dataset_raster( GV_MANAGER(PyGtk_Get(manager)),
+ dataset, band );
+
+ if( raster == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else
+ {
+ return PyGtk_New((GtkObject*)raster);
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/* Idle Task C callback structure. */
+/* -------------------------------------------------------------------- */
+typedef struct {
+ PyObject *psPyCallback;
+ PyObject *psPyCallbackData;
+ PyThreadState *psThreadState;
+} PyTaskData;
+
+int PyIdleTaskProxy( void *task_info )
+
+{
+ PyTaskData *psInfo = (PyTaskData *) task_info;
+ PyObject *psArgs, *psResult;
+ int bContinue = TRUE;
+ PyThreadState *tstate;
+
+ tstate = PyThreadState_Swap( psInfo->psThreadState );
+
+ psArgs = Py_BuildValue("(O)", psInfo->psPyCallbackData );
+
+ psResult = PyEval_CallObject( psInfo->psPyCallback, psArgs);
+
+ tstate = PyThreadState_Swap( tstate );
+ if( tstate == NULL )
+ {
+ CPLDebug( "OpenEV",
+ "PyIdleTaskProxy: Thread state unexpectedly disappeared.\n"
+ " Skipping check for error.\n" );
+ }
+ else
+ {
+ tstate = PyThreadState_Swap( tstate );
+ if( PyErr_Occurred() )
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+
+ Py_XDECREF(psArgs);
+
+ PyThreadState_Swap( tstate );
+
+ if( psResult == NULL
+ || psResult == Py_None
+ || !PyArg_Parse( psResult, "i", &bContinue )
+ || !bContinue )
+ {
+ bContinue = FALSE;
+ Py_XDECREF( psInfo->psPyCallback );
+ Py_XDECREF( psInfo->psPyCallbackData );
+ g_free( task_info );
+ }
+
+ Py_XDECREF(psResult);
+
+ return bContinue;
+}
+
+static PyObject *
+_wrap_gv_manager_queue_task(PyObject *self, PyObject *args)
+{
+ PyObject *manager;
+ int priority;
+ char *task_name;
+ PyTaskData *psProgressInfo;
+
+ psProgressInfo = g_new(PyTaskData,1);
+ psProgressInfo->psPyCallback = NULL;
+ psProgressInfo->psPyCallbackData = Py_None;
+
+ if (!PyArg_ParseTuple(args, "O!siO|O:gv_manager_queue_task",
+ &PyGtk_Type, &manager, &task_name, &priority,
+ &(psProgressInfo->psPyCallback),
+ &(psProgressInfo->psPyCallbackData) ) )
+ return NULL;
+
+ if( manager == NULL )
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ Py_XINCREF( psProgressInfo->psPyCallback );
+ Py_XINCREF( psProgressInfo->psPyCallbackData );
+
+ psProgressInfo->psThreadState = PyThreadState_Get();
+
+ gv_manager_queue_task( GV_MANAGER(PyGtk_Get(manager)),
+ task_name, priority,
+ PyIdleTaskProxy,
+ psProgressInfo );
+
+ Py_INCREF(Py_None);
+
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_launch_url(PyObject *self, PyObject *args)
+{
+ char *url = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_launch_url",
+ &url))
+ return NULL;
+
+ return Py_BuildValue("i",gv_launch_url(url));
+}
+
+static PyObject *
+_wrap_gv_rgba_to_rgb(PyObject *self, PyObject *args)
+{
+ PyObject *rgba_obj = NULL;
+ PyObject *rgb_obj = NULL;
+ const char *rgba;
+ char *rgb;
+ int length, i;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_rgba_to_rgb",
+ &PyString_Type, &rgba_obj))
+ return NULL;
+
+ length = PyString_Size( rgba_obj ) / 4;
+ rgba = PyString_AS_STRING( rgba_obj );
+
+ rgb = (char *) malloc(length*3);
+
+ for( i = 0; i < length; i++ )
+ {
+ rgb[i*3 ] = rgba[i*4 ];
+ rgb[i*3+1] = rgba[i*4+1];
+ rgb[i*3+2] = rgba[i*4+2];
+ }
+
+ rgb_obj = PyString_FromStringAndSize( rgb, length * 3 );
+
+ free( rgb );
+
+ return rgb_obj;
+}
+
+/*
+ * Algorithms not very specific to OpenEV.
+ */
+
+static PyObject *
+_wrap_WIDInterpolate(PyObject *self, PyObject *args)
+{
+ PyObject *poPyPoints;
+ PyProgressData sProgressInfo;
+ char *pszSwigBand = NULL;
+ int nPoints, i, nErr;
+ double *padfXYVW;
+ double fExponent;
+ GDALRasterBandH hBand;
+
+ sProgressInfo.psPyCallback = NULL;
+ sProgressInfo.psPyCallbackData = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!s|dOO:WIDInterpolate",
+ &PyList_Type, &poPyPoints,
+ &pszSwigBand,
+ &fExponent,
+ &(sProgressInfo.psPyCallback),
+ &(sProgressInfo.psPyCallbackData) ) )
+ return NULL;
+
+ hBand = (GDALRasterBandH)
+ SWIG_SimpleGetPtr(pszSwigBand, "_GDALRasterBandH" );
+
+ if( hBand == NULL )
+ {
+ PyErr_SetString( PyExc_ValueError,
+ "Couldn't parse GDALRasterBandH argument." );
+ return NULL;
+ }
+
+ nPoints = PyList_Size(poPyPoints);
+ padfXYVW = g_new(double,4*nPoints);
+ for( i = 0; i < nPoints; i++ )
+ {
+ if( !PyArg_Parse( PyList_GET_ITEM(poPyPoints,i), "(dddd)",
+ padfXYVW + i + 0*nPoints,
+ padfXYVW + i + 1*nPoints,
+ padfXYVW + i + 2*nPoints,
+ padfXYVW + i + 3*nPoints ) )
+ {
+ g_free( padfXYVW );
+ PyErr_SetString(PyExc_ValueError,
+ "bad point format (x,y,value,weight)" );
+ return NULL;
+ }
+ }
+
+ nErr = WIDInterpolate( nPoints, padfXYVW, padfXYVW+nPoints,
+ padfXYVW+nPoints*2, padfXYVW+nPoints*3, hBand,
+ fExponent, PyProgressProxy, &sProgressInfo );
+
+ g_free( padfXYVW );
+
+ return Py_BuildValue( "i", nErr );
+}
+
+static PyObject *
+_wrap_gv_raster_rasterize_shapes(PyObject *self, PyObject *args)
+{
+ PyObject *py_shapelist;
+ PyObject *py_raster;
+ GvRaster *raster;
+ double burn_value;
+ int shape_count, i, ret_value, fill_short = 1;
+ GvShape **shape_list;
+
+ if (!PyArg_ParseTuple(args, "O!O!di:gv_raster_rasterize_shapes",
+ &PyGtk_Type, &py_raster,
+ &PyList_Type, &py_shapelist,
+ &burn_value, &fill_short))
+ return NULL;
+
+ raster = GV_RASTER(PyGtk_Get(py_raster));
+
+ shape_count = PyList_Size(py_shapelist);
+ shape_list = g_new(GvShape*,shape_count);
+ for( i = 0; i < shape_count; i++ )
+ {
+ GvShape *gv_shape;
+ char *swig_shape_ptr;
+
+ if( !PyArg_Parse( PyList_GET_ITEM(py_shapelist,i), "s",
+ &swig_shape_ptr) )
+ {
+ g_free( shape_list );
+ PyErr_SetString( PyExc_ValueError,
+ "bad item in shapelist" );
+ return NULL;
+ }
+ gv_shape = SWIG_SimpleGetPtr( swig_shape_ptr, "_GvShape" );
+ if( gv_shape == NULL )
+ {
+ g_free( shape_list );
+ PyErr_SetString( PyExc_ValueError,
+ "bad item in shapelist(2)" );
+ return NULL;
+ }
+
+ shape_list[i] = gv_shape;
+ }
+
+ ret_value = gv_raster_rasterize_shapes( raster, shape_count, shape_list,
+ burn_value, fill_short );
+
+ return Py_BuildValue( "i", ret_value );
+}
+
+/*
+ * wrapper function for getting a DOS 8.3 compatible file name on
+ * Windows systems. On other systems, this will return the
+ * value passed in.
+ */
+static PyObject * _wrap_gv_short_path_name(PyObject *self, PyObject *args)
+{
+ char *lpszLongPath = NULL;
+ PyObject * result = NULL;
+
+ if (!PyArg_ParseTuple(args, "s:gv_short_path_name",
+ &lpszLongPath))
+ return NULL;
+
+ result = Py_BuildValue("s",gv_short_path_name(lpszLongPath));
+
+ //invalid path in lpszLongPath results in zero length string
+ if (PyString_Size(result) == 0)
+ {
+ PyErr_Format(PyExc_OSError, "path (%s) does not exist.", lpszLongPath);
+ return NULL;
+ }
+
+ return result;
+}
+
+static PyObject * _wrap_gtk_color_well_get_d( PyObject *self, PyObject *args)
+{
+ PyObject *color_well;
+ gdouble r, g, b, a;
+
+ if (!PyArg_ParseTuple(args, "O!:gtk_color_well_get_d",
+ &PyGtk_Type, &color_well))
+ return NULL;
+
+ gtk_color_well_get_d( GTK_COLOR_WELL(PyGtk_Get(color_well)),
+ &r, &g, &b, &a );
+
+ return Py_BuildValue( "(dddd)", r, g, b, a );
+}
+
+static PyObject *_wrap_gv_shapes_to_dbf(PyObject *self, PyObject *args) {
+ PyObject *data;
+ char *filename;
+
+ if (!PyArg_ParseTuple(args, "sO!:gv_shapes_to_dbf", &filename, &PyGtk_Type, &data))
+ return NULL;
+ return PyInt_FromLong(gv_shapes_to_dbf(filename, GV_DATA(PyGtk_Get(data))));
+}
+
+static PyObject *_wrap_gv_format_point_query( PyObject *self, PyObject *args )
+{
+ gdouble x, y;
+ char *text;
+ PyObject *py_view;
+ GvViewArea *view = NULL;
+ GvManager *manager;
+
+ if (!PyArg_ParseTuple( args, "O!dd:gv_format_point_query", &PyGtk_Type, &py_view, &x, &y ))
+ return NULL;
+
+ if (py_view != NULL)
+ view = GV_VIEW_AREA(PyGtk_Get( py_view ));
+
+ manager = gv_get_manager();
+
+ text = (char *) gv_format_point_query( view, &(manager->preferences), x, y );
+
+ return Py_BuildValue( "s", text );
+}
+
+
+static PyObject *_wrap_gv_test_entry( PyObject *self, PyObject *args )
+
+{
+ PyObject *py_rlayer;
+ GvRasterLayer *rlayer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_test_entry",
+ &PyGtk_Type, &py_rlayer ))
+ return NULL;
+
+ rlayer = GV_RASTER_LAYER(PyGtk_Get(py_rlayer));
+
+ return Py_BuildValue( "d", 0.0 );
+}
+
+static PyObject *
+_wrap_MyGDALOperator(PyObject *self, PyObject *args)
+{
+ char *pszSwigDS1 = NULL;
+ char *pszSwigDS2 = NULL;
+ GDALDatasetH hDS1 = NULL, hDS2 = NULL;
+ int nErr = 1;
+
+ if (!PyArg_ParseTuple(args, "ss:MyGDALOperator",
+ &pszSwigDS1, &pszSwigDS2 ) )
+ return NULL;
+
+ hDS1 = (GDALDatasetH) SWIG_SimpleGetPtr(pszSwigDS1, "_GDALDatasetH" );
+ hDS2 = (GDALDatasetH) SWIG_SimpleGetPtr(pszSwigDS2, "_GDALDatasetH" );
+
+ if( hDS1 != NULL && hDS2 != NULL )
+ {
+ /* do something with hDS1 and hDS2 */
+ printf( "%s -> %s\n",
+ GDALGetDescription( hDS1 ),
+ GDALGetDescription( hDS2 ) );
+ nErr = 0;
+ }
+
+ return Py_BuildValue( "i", nErr );
+}
+
+
+static PyObject *
+_wrap_gv_autopan_tool_new_rect(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!(" CCCC "):gv_autopan_tool_new_rect", &PyGtk_Type, &tool, &rect.x, &rect.y,
+ &rect.width, &rect.height))
+ return NULL;
+
+ if (!gv_autopan_tool_new_rect(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &rect))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Invalid extents specified");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_gv_autopan_tool_get_rect(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_rect", &PyGtk_Type, &tool))
+ return NULL;
+ if (!gv_autopan_tool_get_rect(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &rect))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "no pan region set");
+ return NULL;
+ }
+ return Py_BuildValue("(" CCCC ")", rect.x, rect.y, rect.width, rect.height);
+}
+
+static PyObject *
+_wrap_gv_autopan_tool_get_location(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ gvgeocoord x, y, z;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_location", &PyGtk_Type, &tool))
+ return NULL;
+ if (!gv_autopan_tool_get_location(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &x, &y, &z))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "no location set");
+ return NULL;
+ }
+ return Py_BuildValue("(" CCC ")", x, y, z);
+}
+
+static PyObject *
+_wrap_gv_autopan_tool_get_state(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ gvgeocoord block_x_size, x_resolution;
+ gint play_flag, path_type, block_size_mode, num_views;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_state", &PyGtk_Type, &tool))
+ return NULL;
+
+ gv_autopan_tool_get_state(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &play_flag, &path_type, &block_size_mode, &block_x_size, &x_resolution, &num_views);
+
+ return Py_BuildValue("(iii" CC "i)", play_flag, path_type, block_size_mode, block_x_size, x_resolution, num_views);
+}
+
+
+
+static PyObject *
+_wrap_gv_autopan_tool_get_trail_parameters(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect overview_extents;
+ gint overview_width_pixels, num_trail_tiles;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_trail_parameters", &PyGtk_Type, &tool))
+ return NULL;
+
+ gv_autopan_tool_get_trail_parameters(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &overview_extents, &overview_width_pixels, &num_trail_tiles);
+
+ return Py_BuildValue("(" CCCC "ii)", overview_extents.x, overview_extents.y,overview_extents.width, overview_extents.height, overview_width_pixels, num_trail_tiles);
+}
+
+
+static PyObject *
+_wrap_gv_autopan_tool_set_trail_parameters(PyObject *self, PyObject *args)
+{
+ PyObject *tool;
+ GvRect rect;
+ int overview_width_pixels;
+
+ if (!PyArg_ParseTuple(args, "O!(" CCCC ")i:gv_autopan_tool_set_trail_parameters", &PyGtk_Type, &tool, &rect.x, &rect.y,
+ &rect.width, &rect.height, &overview_width_pixels))
+ return NULL;
+
+ if (!gv_autopan_tool_set_trail_parameters(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), &rect,overview_width_pixels))
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Invalid parameters specified");
+ return NULL;
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+/*
+ * Generated wrapper functions
+ */
+
+#include "gvmodule_impl.c"
+
+/*
+ * Method defs
+ */
+
+static PyMethodDef gv_methods[] =
+{
+ {"gv_test_entry", _wrap_gv_test_entry, 1},
+ {"gv_shape_new", _wrap_gv_shape_new, 1},
+ {"gv_shape_from_xml", _wrap_gv_shape_from_xml, 1},
+ {"gv_shape_to_xml", _wrap_gv_shape_to_xml, 1},
+ {"gv_shape_destroy", _wrap_gv_shape_destroy, 1},
+ {"gv_shape_ref", _wrap_gv_shape_ref, 1},
+ {"gv_shape_unref", _wrap_gv_shape_unref, 1},
+ {"gv_shape_get_ref", _wrap_gv_shape_get_ref, 1},
+ {"gv_shape_copy", _wrap_gv_shape_copy, 1},
+ {"gv_shape_delete_ring", _wrap_gv_shape_delete_ring, 1},
+ {"gv_shape_line_from_nodelists",_wrap_gv_shape_line_from_nodelists, 1},
+ {"gv_shapes_lines_for_vecplot",_wrap_gv_shapes_lines_for_vecplot, 1},
+ {"gv_shape_get_property", _wrap_gv_shape_get_property, 1},
+ {"gv_shape_get_properties", _wrap_gv_shape_get_properties, 1},
+ {"gv_shape_get_typed_properties", _wrap_gv_shape_get_typed_properties, 1},
+ {"gv_shape_set_property", _wrap_gv_shape_set_property, 1},
+ {"gv_shape_set_properties", _wrap_gv_shape_set_properties, 1},
+ {"gv_shape_get_rings", _wrap_gv_shape_get_rings, 1},
+ {"gv_shape_get_nodes", _wrap_gv_shape_get_nodes, 1},
+ {"gv_shape_add_node", _wrap_gv_shape_add_node, 1},
+ {"gv_shape_set_node", _wrap_gv_shape_set_node, 1},
+ {"gv_shape_get_node", _wrap_gv_shape_get_node, 1},
+ {"gv_shape_get_type", _wrap_gv_shape_get_type, 1},
+ {"gv_shape_point_in_polygon", _wrap_gv_shape_point_in_polygon, 1},
+ {"gv_shape_distance_from_polygon", _wrap_gv_shape_distance_from_polygon, 1},
+ {"gv_shape_clip_to_rect", _wrap_gv_shape_clip_to_rect, 1},
+ {"gv_shape_add_shape", _wrap_gv_shape_add_shape, 1},
+ {"gv_shape_get_shape", _wrap_gv_shape_get_shape, 1},
+ {"gv_shape_collection_get_count", _wrap_gv_shape_collection_get_count, 1},
+ {"gv_symbol_manager_get_names", _wrap_gv_symbol_manager_get_names, 1 },
+ {"gv_symbol_manager_inject_vector_symbol",
+ _wrap_gv_symbol_manager_inject_vector_symbol, 1},
+ {"gv_symbol_manager_inject_raster_symbol",
+ _wrap_gv_symbol_manager_inject_raster_symbol, 1},
+ {"gv_symbol_manager_get_symbol", _wrap_gv_symbol_manager_get_symbol, 1},
+ {"gv_symbol_manager_save_vector_symbol",
+ _wrap_gv_symbol_manager_save_vector_symbol, 1},
+ {"gv_data_get_properties", _wrap_gv_data_get_properties, 1},
+ {"gv_data_set_properties", _wrap_gv_data_set_properties, 1},
+ {"gv_data_changed", _wrap_gv_data_changed, 1},
+ {"gv_layer_extents", _wrap_gv_layer_extents, 1},
+ {"gv_layer_display_change", _wrap_gv_layer_display_change, 1},
+ {"gv_view_area_list_layers", _wrap_gv_view_area_list_layers, 1},
+ {"gv_view_area_get_translation", _wrap_gv_view_area_get_translation, 1},
+ {"gv_view_area_map_location", _wrap_gv_view_area_map_location, 1},
+ {"gv_view_area_get_pointer", _wrap_gv_view_area_get_pointer, 1},
+ {"gv_view_area_map_pointer", _wrap_gv_view_area_map_pointer, 1},
+ {"gv_view_area_get_extents", _wrap_gv_view_area_get_extents, 1 },
+ {"gv_view_area_get_volume", _wrap_gv_view_area_get_volume, 1 },
+ {"gv_view_area_inverse_map_pointer",
+ _wrap_gv_view_area_inverse_map_pointer, 1},
+ {"gv_view_area_get_fontnames", _wrap_gv_view_area_get_fontnames, 1},
+ {"gv_view_area_set_background_color",
+ _wrap_gv_view_area_set_background_color, 1},
+ {"gv_view_area_get_background_color",
+ _wrap_gv_view_area_get_background_color, 1},
+ {"gv_view_area_create_thumbnail", _wrap_gv_view_area_create_thumbnail, 1},
+ {"gv_view_area_set_3d_view", _wrap_gv_view_area_set_3d_view, 1 },
+ {"gv_view_area_set_3d_view_look_at", _wrap_gv_view_area_set_3d_view_look_at, 1 },
+ {"gv_view_area_get_eye_pos", _wrap_gv_view_area_get_eye_pos, 1 },
+ {"gv_view_area_get_eye_dir", _wrap_gv_view_area_get_eye_dir, 1 },
+ {"gv_view_area_get_look_at_pos", _wrap_gv_view_area_get_look_at_pos, 1 },
+ {"gv_roi_tool_get_rect", _wrap_gv_roi_tool_get_rect, 1},
+ {"gv_roi_tool_new_rect", _wrap_gv_roi_tool_new_rect, 1},
+ {"gv_poi_tool_get_point", _wrap_gv_poi_tool_get_point, 1},
+ {"gv_poi_tool_new_point", _wrap_gv_poi_tool_new_point, 1},
+ {"gv_tool_set_boundary", _wrap_gv_tool_set_boundary, 1},
+ {"gv_records_set_used_properties",
+ _wrap_gv_records_set_used_properties, 1 },
+ {"gv_records_get_typed_properties",
+ _wrap_gv_records_get_typed_properties, 1},
+ {"gv_records_get_properties", _wrap_gv_records_get_properties, 1},
+ {"gv_records_to_dbf", _wrap_gv_records_to_dbf, 1},
+ {"gv_records_MultiStratifiedCollect",
+ _wrap_gv_records_MultiStratifiedCollect, 1},
+ {"gv_records_recode", _wrap_gv_records_recode, 1},
+ {"gv_records_asdict", _wrap_gv_records_asdict, 1},
+ {"gv_shapes_from_ogr_layer", _wrap_gv_shapes_from_ogr_layer, 1},
+ {"gv_shapes_get_shape", _wrap_gv_shapes_get_shape, 1},
+ {"gv_shapes_add_shape", _wrap_gv_shapes_add_shape, 1},
+ {"gv_shapes_add_shape_last", _wrap_gv_shapes_add_shape_last, 1},
+ {"gv_shapes_delete_shapes", _wrap_gv_shapes_delete_shapes, 1},
+ {"gv_shapes_replace_shapes", _wrap_gv_shapes_replace_shapes, 1},
+ {"gv_shapes_get_extents", _wrap_gv_shapes_get_extents, 1},
+ {"gv_shapes_get_change_info", _wrap_gv_shapes_get_change_info, 1},
+ {"gv_points_get_point", _wrap_gv_points_get_point, 1},
+ {"gv_points_new_point", _wrap_gv_points_new_point, 1},
+ {"gv_polylines_get_line", _wrap_gv_polylines_get_line, 1},
+ {"gv_polylines_new_line", _wrap_gv_polylines_new_line, 1},
+ {"gv_areas_get_area", _wrap_gv_areas_get_area, 1},
+ {"gv_areas_new_area", _wrap_gv_areas_new_area, 1},
+ {"gv_shape_layer_set_color", _wrap_gv_shape_layer_set_color, 1},
+ {"gv_shape_layer_get_selected", _wrap_gv_shape_layer_get_selected, 1},
+ {"gv_shape_layer_pick_shape", _wrap_gv_shape_layer_pick_shape, 1 },
+ {"gv_raster_new", (PyCFunction)_wrap_gv_raster_new,
+ METH_VARARGS|METH_KEYWORDS},
+ {"gv_raster_autoscale", _wrap_gv_raster_autoscale, 1},
+ {"gv_raster_get_gdal_band", _wrap_gv_raster_get_gdal_band, 1},
+ {"gv_raster_get_gdal_dataset", _wrap_gv_raster_get_gdal_dataset, 1},
+ {"gv_raster_force_load", _wrap_gv_raster_force_load, 1 },
+ {"gv_raster_get_sample", _wrap_gv_raster_get_sample, 1},
+ {"gv_raster_georef_to_pixel", _wrap_gv_raster_georef_to_pixel, 1},
+ {"gv_raster_pixel_to_georef", _wrap_gv_raster_pixel_to_georef, 1},
+ {"gv_raster_georef_to_pixelCL", _wrap_gv_raster_georef_to_pixelCL, 1},
+ {"gv_raster_pixel_to_georefCL", _wrap_gv_raster_pixel_to_georefCL, 1},
+ {"gv_raster_data_changing", _wrap_gv_raster_data_changing, 1},
+ {"gv_raster_data_changed", _wrap_gv_raster_data_changed, 1},
+ {"gv_raster_get_change_info", _wrap_gv_raster_get_change_info, 1},
+ {"gv_raster_get_gcps", _wrap_gv_raster_get_gcps, 1},
+ {"gv_raster_set_gcps", _wrap_gv_raster_set_gcps, 1},
+ {"gv_raster_get_gcpsCL", _wrap_gv_raster_get_gcpsCL, 1},
+ {"gv_raster_set_gcpsCL", _wrap_gv_raster_set_gcpsCL, 1},
+ {"gv_raster_layer_new", _wrap_gv_raster_layer_new, 1},
+ {"gv_raster_layer_autoscale_view", _wrap_gv_raster_layer_autoscale_view,1},
+ {"gv_raster_layer_get_mesh_lod", _wrap_gv_raster_layer_get_mesh_lod,1},
+ {"gv_raster_layer_histogram_view", _wrap_gv_raster_layer_histogram_view,1},
+ {"gv_raster_layer_view_to_pixel", _wrap_gv_raster_layer_view_to_pixel, 1},
+ {"gv_raster_layer_pixel_to_view", _wrap_gv_raster_layer_pixel_to_view, 1},
+ {"gv_raster_layer_set_source", _wrap_gv_raster_layer_set_source, 1},
+ {"gv_raster_layer_texture_mode_set", _wrap_gv_raster_layer_texture_mode_set, 1},
+ {"gv_raster_layer_texture_mode_get", _wrap_gv_raster_layer_texture_mode_get, 1},
+ {"gv_raster_layer_alpha_get", _wrap_gv_raster_layer_alpha_get, 1},
+ {"gv_raster_layer_blend_mode_get", _wrap_gv_raster_layer_blend_mode_get, 1},
+ {"gv_raster_layer_lut_put", _wrap_gv_raster_layer_lut_put, 1},
+ {"gv_raster_layer_lut_get", _wrap_gv_raster_layer_lut_get, 1},
+ {"gv_raster_layer_nodata_get", _wrap_gv_raster_layer_nodata_get,1},
+ {"gv_raster_layer_get_nodata", _wrap_gv_raster_layer_get_nodata,1},
+ {"gv_raster_layer_source_get_lut", _wrap_gv_raster_layer_source_get_lut,1},
+ {"gv_raster_layer_zoom_get", _wrap_gv_raster_layer_zoom_get, 1},
+ {"gv_raster_layer_get_height", _wrap_gv_raster_layer_get_height, 1},
+ {"gv_manager_get_preferences", _wrap_gv_manager_get_preferences, 1},
+ {"gv_manager_add_dataset", _wrap_gv_manager_add_dataset, 1},
+ {"gv_manager_get_dataset", _wrap_gv_manager_get_dataset, 1},
+ {"gv_manager_get_dataset_raster", _wrap_gv_manager_get_dataset_raster, 1},
+ {"gv_manager_queue_task", _wrap_gv_manager_queue_task, 1},
+ {"gv_launch_url", _wrap_gv_launch_url, 1},
+ {"gv_rgba_to_rgb", _wrap_gv_rgba_to_rgb, 1},
+ {"WIDInterpolate", _wrap_WIDInterpolate, 1},
+ {"gv_raster_rasterize_shapes", _wrap_gv_raster_rasterize_shapes, 1},
+ {"gv_short_path_name", _wrap_gv_short_path_name, 1},
+ {"gtk_color_well_get_d", _wrap_gtk_color_well_get_d, 1},
+ {"gv_shapes_to_dbf", _wrap_gv_shapes_to_dbf, 1},
+ {"gv_format_point_query", _wrap_gv_format_point_query, 1},
+ {"MyGDALOperator", _wrap_MyGDALOperator, 1},
+ {"gv_autopan_tool_new_rect", _wrap_gv_autopan_tool_new_rect, 1},
+ {"gv_autopan_tool_get_rect", _wrap_gv_autopan_tool_get_rect, 1},
+ {"gv_autopan_tool_get_location", _wrap_gv_autopan_tool_get_location, 1},
+ {"gv_autopan_tool_get_state", _wrap_gv_autopan_tool_get_state, 1},
+ {"gv_autopan_tool_get_trail_parameters", _wrap_gv_autopan_tool_get_trail_parameters, 1},
+ {"gv_autopan_tool_set_trail_parameters", _wrap_gv_autopan_tool_set_trail_parameters, 1},
+#include "gvmodule_defs.c"
+ {NULL, NULL, 0}
+};
+
+/*
+ * Module initialization function
+ */
+
+void
+init_gv(void)
+{
+ init_pygtk();
+
+ Py_InitModule("_gv", gv_methods);
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module _gv");
+}
Added: packages/openev/branches/upstream/current/pymod/gvmodule_defs.c
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvmodule_defs.c (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvmodule_defs.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,234 @@
+ { "gv_view_area_get_type", _wrap_gv_view_area_get_type, 1 },
+ { "gv_view_area_new", _wrap_gv_view_area_new, 1 },
+ { "gv_view_area_get_width", _wrap_gv_view_area_get_width, 1 },
+ { "gv_view_area_get_height", _wrap_gv_view_area_get_height, 1 },
+ { "gv_view_area_add_layer", _wrap_gv_view_area_add_layer, 1 },
+ { "gv_view_area_remove_layer", _wrap_gv_view_area_remove_layer, 1 },
+ { "gv_view_area_get_named_layer", _wrap_gv_view_area_get_named_layer, 1 },
+ { "gv_view_area_active_layer", _wrap_gv_view_area_active_layer, 1 },
+ { "gv_view_area_set_active_layer", _wrap_gv_view_area_set_active_layer, 1 },
+ { "gv_view_area_swap_layers", _wrap_gv_view_area_swap_layers, 1 },
+ { "gv_view_area_zoom", _wrap_gv_view_area_zoom, 1 },
+ { "gv_view_area_get_zoom", _wrap_gv_view_area_get_zoom, 1 },
+ { "gv_view_area_get_flip_x", _wrap_gv_view_area_get_flip_x, 1 },
+ { "gv_view_area_get_flip_y", _wrap_gv_view_area_get_flip_y, 1 },
+ { "gv_view_area_set_flip_xy", _wrap_gv_view_area_set_flip_xy, 1 },
+ { "gv_view_area_rotate", _wrap_gv_view_area_rotate, 1 },
+ { "gv_view_area_translate", _wrap_gv_view_area_translate, 1 },
+ { "gv_view_area_set_translation", _wrap_gv_view_area_set_translation, 1 },
+ { "gv_view_area_fit_extents", _wrap_gv_view_area_fit_extents, 1 },
+ { "gv_view_area_fit_all_layers", _wrap_gv_view_area_fit_all_layers, 1 },
+ { "gv_view_area_set_projection", _wrap_gv_view_area_set_projection, 1 },
+ { "gv_view_area_get_projection", _wrap_gv_view_area_get_projection, 1 },
+ { "gv_view_area_copy_state", _wrap_gv_view_area_copy_state, 1 },
+ { "gv_view_area_print_to_file", _wrap_gv_view_area_print_to_file, 1 },
+ { "gv_view_area_print_postscript_to_file", _wrap_gv_view_area_print_postscript_to_file, 1 },
+ { "gv_view_area_page_setup", _wrap_gv_view_area_page_setup, 1 },
+ { "gv_view_area_print_to_windriver", _wrap_gv_view_area_print_to_windriver, 1 },
+ { "gv_view_area_set_mode", _wrap_gv_view_area_set_mode, 1 },
+ { "gv_view_area_get_mode", _wrap_gv_view_area_get_mode, 1 },
+ { "gv_view_area_height_scale", _wrap_gv_view_area_height_scale, 1 },
+ { "gv_view_area_get_height_scale", _wrap_gv_view_area_get_height_scale, 1 },
+ { "gv_view_area_queue_draw", _wrap_gv_view_area_queue_draw, 1 },
+ { "gv_view_area_get_raw", _wrap_gv_view_area_get_raw, 1 },
+ { "gv_view_area_set_raw", _wrap_gv_view_area_set_raw, 1 },
+ { "gv_view_area_get_property", _wrap_gv_view_area_get_property, 1 },
+ { "gv_view_area_set_property", _wrap_gv_view_area_set_property, 1 },
+ { "gv_data_get_type", _wrap_gv_data_get_type, 1 },
+ { "gv_data_is_read_only", _wrap_gv_data_is_read_only, 1 },
+ { "gv_data_set_read_only", _wrap_gv_data_set_read_only, 1 },
+ { "gv_data_get_name", _wrap_gv_data_get_name, 1 },
+ { "gv_data_set_name", _wrap_gv_data_set_name, 1 },
+ { "gv_data_get_projection", _wrap_gv_data_get_projection, 1 },
+ { "gv_data_set_projection", _wrap_gv_data_set_projection, 1 },
+ { "gv_data_get_property", _wrap_gv_data_get_property, 1 },
+ { "gv_data_set_property", _wrap_gv_data_set_property, 1 },
+ { "gv_data_freeze", _wrap_gv_data_freeze, 1 },
+ { "gv_data_thaw", _wrap_gv_data_thaw, 1 },
+ { "gv_data_get_parent", _wrap_gv_data_get_parent, 1 },
+ { "gv_data_registry_dump", _wrap_gv_data_registry_dump, 1 },
+ { "gv_records_get_type", _wrap_gv_records_get_type, 1 },
+ { "gv_records_new", _wrap_gv_records_new, 1 },
+ { "gv_records_from_dbf", _wrap_gv_records_from_dbf, 1 },
+ { "gv_records_from_rec", _wrap_gv_records_from_rec, 1 },
+ { "gv_records_create_records", _wrap_gv_records_create_records, 1 },
+ { "gv_records_num_records", _wrap_gv_records_num_records, 1 },
+ { "gv_records_add_field", _wrap_gv_records_add_field, 1 },
+ { "gv_records_set_raw_field_data", _wrap_gv_records_set_raw_field_data, 1 },
+ { "gv_records_get_raw_field_data", _wrap_gv_records_get_raw_field_data, 1 },
+ { "gv_shapes_get_type", _wrap_gv_shapes_get_type, 1 },
+ { "gv_shapes_new", _wrap_gv_shapes_new, 1 },
+ { "gv_shapes_from_shapefile", _wrap_gv_shapes_from_shapefile, 1 },
+ { "gv_shapes_to_shapefile", _wrap_gv_shapes_to_shapefile, 1 },
+ { "gv_shapes_from_ogr", _wrap_gv_shapes_from_ogr, 1 },
+ { "gv_have_ogr_support", _wrap_gv_have_ogr_support, 1 },
+ { "gv_shapes_num_shapes", _wrap_gv_shapes_num_shapes, 1 },
+ { "gv_shapes_add_height", _wrap_gv_shapes_add_height, 1 },
+ { "gv_shape_get_count", _wrap_gv_shape_get_count, 1 },
+ { "gv_points_get_type", _wrap_gv_points_get_type, 1 },
+ { "gv_points_new", _wrap_gv_points_new, 1 },
+ { "gv_points_num_points", _wrap_gv_points_num_points, 1 },
+ { "gv_polylines_get_type", _wrap_gv_polylines_get_type, 1 },
+ { "gv_polylines_new", _wrap_gv_polylines_new, 1 },
+ { "gv_polylines_num_lines", _wrap_gv_polylines_num_lines, 1 },
+ { "gv_areas_get_type", _wrap_gv_areas_get_type, 1 },
+ { "gv_areas_new", _wrap_gv_areas_new, 1 },
+ { "gv_areas_num_areas", _wrap_gv_areas_num_areas, 1 },
+ { "gv_layer_get_type", _wrap_gv_layer_get_type, 1 },
+ { "gv_layer_is_visible", _wrap_gv_layer_is_visible, 1 },
+ { "gv_layer_set_visible", _wrap_gv_layer_set_visible, 1 },
+ { "gv_layer_reproject", _wrap_gv_layer_reproject, 1 },
+ { "gv_layer_get_view", _wrap_gv_layer_get_view, 1 },
+ { "gv_shape_layer_get_type", _wrap_gv_shape_layer_get_type, 1 },
+ { "gv_shape_layer_clear_selection", _wrap_gv_shape_layer_clear_selection, 1 },
+ { "gv_shape_layer_select_all", _wrap_gv_shape_layer_select_all, 1 },
+ { "gv_shape_layer_select_shape", _wrap_gv_shape_layer_select_shape, 1 },
+ { "gv_shape_layer_deselect_shape", _wrap_gv_shape_layer_deselect_shape, 1 },
+ { "gv_shape_layer_subselect_shape", _wrap_gv_shape_layer_subselect_shape, 1 },
+ { "gv_shape_layer_get_subselection", _wrap_gv_shape_layer_get_subselection, 1 },
+ { "gv_shapes_layer_get_type", _wrap_gv_shapes_layer_get_type, 1 },
+ { "gv_shapes_layer_new", _wrap_gv_shapes_layer_new, 1 },
+ { "gv_shapes_layer_get_symbol_manager", _wrap_gv_shapes_layer_get_symbol_manager, 1 },
+ { "gv_point_layer_get_type", _wrap_gv_point_layer_get_type, 1 },
+ { "gv_point_layer_new", _wrap_gv_point_layer_new, 1 },
+ { "gv_line_layer_get_type", _wrap_gv_line_layer_get_type, 1 },
+ { "gv_line_layer_new", _wrap_gv_line_layer_new, 1 },
+ { "gv_area_layer_get_type", _wrap_gv_area_layer_get_type, 1 },
+ { "gv_area_layer_new", _wrap_gv_area_layer_new, 1 },
+ { "gv_pquery_layer_get_type", _wrap_gv_pquery_layer_get_type, 1 },
+ { "gv_pquery_layer_new", _wrap_gv_pquery_layer_new, 1 },
+ { "ip_gcp_layer_get_type", _wrap_ip_gcp_layer_get_type, 1 },
+ { "ip_gcp_layer_new", _wrap_ip_gcp_layer_new, 1 },
+ { "app_cur_layer_get_type", _wrap_app_cur_layer_get_type, 1 },
+ { "app_cur_layer_new", _wrap_app_cur_layer_new, 1 },
+ { "gv_symbol_manager_get_type", _wrap_gv_symbol_manager_get_type, 1 },
+ { "gv_get_symbol_manager", _wrap_gv_get_symbol_manager, 1 },
+ { "gv_symbol_manager_eject_symbol", _wrap_gv_symbol_manager_eject_symbol, 1 },
+ { "gv_symbol_manager_has_symbol", _wrap_gv_symbol_manager_has_symbol, 1 },
+ { "gv_manager_get_type", _wrap_gv_manager_get_type, 1 },
+ { "gv_get_manager", _wrap_gv_get_manager, 1 },
+ { "gv_manager_get_preference", _wrap_gv_manager_get_preference, 1 },
+ { "gv_manager_set_preference", _wrap_gv_manager_set_preference, 1 },
+ { "gv_manager_get_busy", _wrap_gv_manager_get_busy, 1 },
+ { "gv_manager_set_busy", _wrap_gv_manager_set_busy, 1 },
+ { "gv_manager_dump", _wrap_gv_manager_dump, 1 },
+ { "gv_tool_get_type", _wrap_gv_tool_get_type, 1 },
+ { "gv_tool_activate", _wrap_gv_tool_activate, 1 },
+ { "gv_tool_deactivate", _wrap_gv_tool_deactivate, 1 },
+ { "gv_tool_get_view", _wrap_gv_tool_get_view, 1 },
+ { "gv_tool_set_cursor", _wrap_gv_tool_set_cursor, 1 },
+ { "gv_selection_tool_get_type", _wrap_gv_selection_tool_get_type, 1 },
+ { "gv_selection_tool_new", _wrap_gv_selection_tool_new, 1 },
+ { "gv_selection_tool_set_layer", _wrap_gv_selection_tool_set_layer, 1 },
+ { "gv_zoompan_tool_get_type", _wrap_gv_zoompan_tool_get_type, 1 },
+ { "gv_zoompan_tool_new", _wrap_gv_zoompan_tool_new, 1 },
+ { "gv_point_tool_get_type", _wrap_gv_point_tool_get_type, 1 },
+ { "gv_point_tool_new", _wrap_gv_point_tool_new, 1 },
+ { "gv_point_tool_set_layer", _wrap_gv_point_tool_set_layer, 1 },
+ { "gv_point_tool_set_named_layer", _wrap_gv_point_tool_set_named_layer, 1 },
+ { "gv_line_tool_get_type", _wrap_gv_line_tool_get_type, 1 },
+ { "gv_line_tool_new", _wrap_gv_line_tool_new, 1 },
+ { "gv_line_tool_set_layer", _wrap_gv_line_tool_set_layer, 1 },
+ { "gv_line_tool_set_named_layer", _wrap_gv_line_tool_set_named_layer, 1 },
+ { "gv_rect_tool_get_type", _wrap_gv_rect_tool_get_type, 1 },
+ { "gv_rect_tool_new", _wrap_gv_rect_tool_new, 1 },
+ { "gv_rect_tool_set_layer", _wrap_gv_rect_tool_set_layer, 1 },
+ { "gv_rect_tool_set_named_layer", _wrap_gv_rect_tool_set_named_layer, 1 },
+ { "gv_rotate_tool_get_type", _wrap_gv_rotate_tool_get_type, 1 },
+ { "gv_rotate_tool_new", _wrap_gv_rotate_tool_new, 1 },
+ { "gv_rotate_tool_set_layer", _wrap_gv_rotate_tool_set_layer, 1 },
+ { "gv_rotate_tool_set_named_layer", _wrap_gv_rotate_tool_set_named_layer, 1 },
+ { "gv_area_tool_get_type", _wrap_gv_area_tool_get_type, 1 },
+ { "gv_area_tool_new", _wrap_gv_area_tool_new, 1 },
+ { "gv_area_tool_set_layer", _wrap_gv_area_tool_set_layer, 1 },
+ { "gv_area_tool_set_named_layer", _wrap_gv_area_tool_set_named_layer, 1 },
+ { "gv_node_tool_get_type", _wrap_gv_node_tool_get_type, 1 },
+ { "gv_node_tool_new", _wrap_gv_node_tool_new, 1 },
+ { "gv_node_tool_set_layer", _wrap_gv_node_tool_set_layer, 1 },
+ { "gv_roi_tool_get_type", _wrap_gv_roi_tool_get_type, 1 },
+ { "gv_roi_tool_new", _wrap_gv_roi_tool_new, 1 },
+ { "gv_poi_tool_get_type", _wrap_gv_poi_tool_get_type, 1 },
+ { "gv_poi_tool_new", _wrap_gv_poi_tool_new, 1 },
+ { "gv_track_tool_get_type", _wrap_gv_track_tool_get_type, 1 },
+ { "gv_track_tool_new", _wrap_gv_track_tool_new, 1 },
+ { "gv_toolbox_get_type", _wrap_gv_toolbox_get_type, 1 },
+ { "gv_toolbox_new", _wrap_gv_toolbox_new, 1 },
+ { "gv_toolbox_add_tool", _wrap_gv_toolbox_add_tool, 1 },
+ { "gv_toolbox_activate_tool", _wrap_gv_toolbox_activate_tool, 1 },
+ { "gv_undo_register_data", _wrap_gv_undo_register_data, 1 },
+ { "gv_undo_pop", _wrap_gv_undo_pop, 1 },
+ { "gv_undo_clear", _wrap_gv_undo_clear, 1 },
+ { "gv_undo_can_undo", _wrap_gv_undo_can_undo, 1 },
+ { "gv_undo_close", _wrap_gv_undo_close, 1 },
+ { "gv_undo_open", _wrap_gv_undo_open, 1 },
+ { "gv_undo_start_group", _wrap_gv_undo_start_group, 1 },
+ { "gv_undo_end_group", _wrap_gv_undo_end_group, 1 },
+ { "gv_view_link_get_type", _wrap_gv_view_link_get_type, 1 },
+ { "gv_view_link_new", _wrap_gv_view_link_new, 1 },
+ { "gv_view_link_register_view", _wrap_gv_view_link_register_view, 1 },
+ { "gv_view_link_remove_view", _wrap_gv_view_link_remove_view, 1 },
+ { "gv_view_link_enable", _wrap_gv_view_link_enable, 1 },
+ { "gv_view_link_disable", _wrap_gv_view_link_disable, 1 },
+ { "gv_view_link_set_cursor_mode", _wrap_gv_view_link_set_cursor_mode, 1 },
+ { "gv_raster_get_type", _wrap_gv_raster_get_type, 1 },
+ { "gv_raster_flush_cache", _wrap_gv_raster_flush_cache, 1 },
+ { "gv_raster_get_min", _wrap_gv_raster_get_min, 1 },
+ { "gv_raster_get_max", _wrap_gv_raster_get_max, 1 },
+ { "gv_raster_cache_get_max", _wrap_gv_raster_cache_get_max, 1 },
+ { "gv_raster_cache_get_used", _wrap_gv_raster_cache_get_used, 1 },
+ { "gv_raster_cache_set_max", _wrap_gv_raster_cache_set_max, 1 },
+ { "gv_raster_set_poly_order_preference", _wrap_gv_raster_set_poly_order_preference, 1 },
+ { "gv_raster_layer_get_type", _wrap_gv_raster_layer_get_type, 1 },
+ { "gv_raster_layer_lut_color_wheel_new", _wrap_gv_raster_layer_lut_color_wheel_new, 1 },
+ { "gv_raster_layer_lut_color_wheel_new_ev", _wrap_gv_raster_layer_lut_color_wheel_new_ev, 1 },
+ { "gv_raster_layer_lut_color_wheel_1d_new", _wrap_gv_raster_layer_lut_color_wheel_1d_new, 1 },
+ { "gv_raster_layer_alpha_set", _wrap_gv_raster_layer_alpha_set, 1 },
+ { "gv_raster_layer_min_set", _wrap_gv_raster_layer_min_set, 1 },
+ { "gv_raster_layer_min_get", _wrap_gv_raster_layer_min_get, 1 },
+ { "gv_raster_layer_max_set", _wrap_gv_raster_layer_max_set, 1 },
+ { "gv_raster_layer_max_get", _wrap_gv_raster_layer_max_get, 1 },
+ { "gv_raster_layer_nodata_set", _wrap_gv_raster_layer_nodata_set, 1 },
+ { "gv_raster_layer_type_get", _wrap_gv_raster_layer_type_get, 1 },
+ { "gv_raster_layer_get_const_value", _wrap_gv_raster_layer_get_const_value, 1 },
+ { "gv_raster_layer_get_data", _wrap_gv_raster_layer_get_data, 1 },
+ { "gv_raster_layer_get_mode", _wrap_gv_raster_layer_get_mode, 1 },
+ { "gv_raster_layer_texture_clamp_set", _wrap_gv_raster_layer_texture_clamp_set, 1 },
+ { "gv_raster_layer_zoom_set", _wrap_gv_raster_layer_zoom_set, 1 },
+ { "gv_raster_layer_blend_mode_set", _wrap_gv_raster_layer_blend_mode_set, 1 },
+ { "gv_raster_layer_lut_type_get", _wrap_gv_raster_layer_lut_type_get, 1 },
+ { "gv_raster_layer_add_height", _wrap_gv_raster_layer_add_height, 1 },
+ { "gv_raster_layer_clamp_height", _wrap_gv_raster_layer_clamp_height, 1 },
+ { "gv_texture_cache_dump", _wrap_gv_texture_cache_dump, 1 },
+ { "gv_texture_cache_get_max", _wrap_gv_texture_cache_get_max, 1 },
+ { "gv_texture_cache_get_used", _wrap_gv_texture_cache_get_used, 1 },
+ { "gv_texture_cache_set_max", _wrap_gv_texture_cache_set_max, 1 },
+ { "gv_build_skirt", _wrap_gv_build_skirt, 1 },
+ { "gtk_color_well_get_type", _wrap_gtk_color_well_get_type, 1 },
+ { "gtk_color_well_new", _wrap_gtk_color_well_new, 1 },
+ { "gtk_color_well_set_d", _wrap_gtk_color_well_set_d, 1 },
+ { "gtk_color_well_set_i8", _wrap_gtk_color_well_set_i8, 1 },
+ { "gtk_color_well_set_i16", _wrap_gtk_color_well_set_i16, 1 },
+ { "gtk_color_well_set_use_alpha", _wrap_gtk_color_well_set_use_alpha, 1 },
+ { "gtk_color_well_set_continuous", _wrap_gtk_color_well_set_continuous, 1 },
+ { "gtk_color_well_set_title", _wrap_gtk_color_well_set_title, 1 },
+ { "gv_autopan_tool_get_type", _wrap_gv_autopan_tool_get_type, 1 },
+ { "gv_autopan_tool_new", _wrap_gv_autopan_tool_new, 1 },
+ { "gv_autopan_tool_play", _wrap_gv_autopan_tool_play, 1 },
+ { "gv_autopan_tool_pause", _wrap_gv_autopan_tool_pause, 1 },
+ { "gv_autopan_tool_stop", _wrap_gv_autopan_tool_stop, 1 },
+ { "gv_autopan_tool_set_speed", _wrap_gv_autopan_tool_set_speed, 1 },
+ { "gv_autopan_tool_get_speed", _wrap_gv_autopan_tool_get_speed, 1 },
+ { "gv_autopan_tool_set_location", _wrap_gv_autopan_tool_set_location, 1 },
+ { "gv_autopan_tool_set_overlap", _wrap_gv_autopan_tool_set_overlap, 1 },
+ { "gv_autopan_tool_get_overlap", _wrap_gv_autopan_tool_get_overlap, 1 },
+ { "gv_autopan_tool_set_block_x_size", _wrap_gv_autopan_tool_set_block_x_size, 1 },
+ { "gv_autopan_tool_set_x_resolution", _wrap_gv_autopan_tool_set_x_resolution, 1 },
+ { "gv_autopan_tool_set_standard_path", _wrap_gv_autopan_tool_set_standard_path, 1 },
+ { "gv_autopan_tool_set_lines_path", _wrap_gv_autopan_tool_set_lines_path, 1 },
+ { "gv_autopan_tool_clear_trail", _wrap_gv_autopan_tool_clear_trail, 1 },
+ { "gv_autopan_tool_set_trail_color", _wrap_gv_autopan_tool_set_trail_color, 1 },
+ { "gv_autopan_tool_set_trail_mode", _wrap_gv_autopan_tool_set_trail_mode, 1 },
+ { "gv_autopan_tool_save_trail_tiles", _wrap_gv_autopan_tool_save_trail_tiles, 1 },
+ { "gv_autopan_tool_load_trail_tiles", _wrap_gv_autopan_tool_load_trail_tiles, 1 },
+ { "gv_autopan_tool_register_view", _wrap_gv_autopan_tool_register_view, 1 },
+ { "gv_autopan_tool_remove_view", _wrap_gv_autopan_tool_remove_view, 1 },
Added: packages/openev/branches/upstream/current/pymod/gvmodule_impl.c
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvmodule_impl.c (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvmodule_impl.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2129 @@
+static PyObject *_wrap_gv_view_area_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_view_area_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_type());
+}
+
+static PyObject *_wrap_gv_view_area_new(PyObject *self, PyObject *args) {
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, ":gv_view_area_new"))
+ return NULL;
+ retval = (GtkObject *)gv_view_area_new();
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_width(PyObject *self, PyObject *args) {
+ PyObject *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_width", &PyGtk_Type, &view))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_width(GV_VIEW_AREA(PyGtk_Get(view))));
+}
+
+static PyObject *_wrap_gv_view_area_get_height(PyObject *self, PyObject *args) {
+ PyObject *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_height", &PyGtk_Type, &view))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_height(GV_VIEW_AREA(PyGtk_Get(view))));
+}
+
+static PyObject *_wrap_gv_view_area_add_layer(PyObject *self, PyObject *args) {
+ PyObject *view, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_area_add_layer", &PyGtk_Type, &view, &PyGtk_Type, &layer))
+ return NULL;
+ gv_view_area_add_layer(GV_VIEW_AREA(PyGtk_Get(view)), GTK_OBJECT(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_remove_layer(PyObject *self, PyObject *args) {
+ PyObject *view, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_area_remove_layer", &PyGtk_Type, &view, &PyGtk_Type, &layer))
+ return NULL;
+ gv_view_area_remove_layer(GV_VIEW_AREA(PyGtk_Get(view)), GTK_OBJECT(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_named_layer(PyObject *self, PyObject *args) {
+ PyObject *view;
+ const char *layer_name;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_view_area_get_named_layer", &PyGtk_Type, &view, &layer_name))
+ return NULL;
+ retval = (GtkObject *)gv_view_area_get_named_layer(GV_VIEW_AREA(PyGtk_Get(view)), layer_name);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_active_layer(PyObject *self, PyObject *args) {
+ PyObject *view;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_active_layer", &PyGtk_Type, &view))
+ return NULL;
+ retval = (GtkObject *)gv_view_area_active_layer(GV_VIEW_AREA(PyGtk_Get(view)));
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_set_active_layer(PyObject *self, PyObject *args) {
+ PyObject *area, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_area_set_active_layer", &PyGtk_Type, &area, &PyGtk_Type, &layer))
+ return NULL;
+ gv_view_area_set_active_layer(GV_VIEW_AREA(PyGtk_Get(area)), GTK_OBJECT(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_swap_layers(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int layer_a, layer_b;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_view_area_swap_layers", &PyGtk_Type, &area, &layer_a, &layer_b))
+ return NULL;
+ gv_view_area_swap_layers(GV_VIEW_AREA(PyGtk_Get(area)), layer_a, layer_b);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_zoom(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double zoom;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_view_area_zoom", &PyGtk_Type, &area, &zoom))
+ return NULL;
+ gv_view_area_zoom(GV_VIEW_AREA(PyGtk_Get(area)), zoom);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_zoom(PyObject *self, PyObject *args) {
+ PyObject *view;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_zoom", &PyGtk_Type, &view))
+ return NULL;
+ return PyFloat_FromDouble(gv_view_area_get_zoom(GV_VIEW_AREA(PyGtk_Get(view))));
+}
+
+static PyObject *_wrap_gv_view_area_get_flip_x(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_flip_x", &PyGtk_Type, &area))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_flip_x(GV_VIEW_AREA(PyGtk_Get(area))));
+}
+
+static PyObject *_wrap_gv_view_area_get_flip_y(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_flip_y", &PyGtk_Type, &area))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_flip_y(GV_VIEW_AREA(PyGtk_Get(area))));
+}
+
+static PyObject *_wrap_gv_view_area_set_flip_xy(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int flip_x, flip_y;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_view_area_set_flip_xy", &PyGtk_Type, &area, &flip_x, &flip_y))
+ return NULL;
+ gv_view_area_set_flip_xy(GV_VIEW_AREA(PyGtk_Get(area)), flip_x, flip_y);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_rotate(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double angle;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_view_area_rotate", &PyGtk_Type, &area, &angle))
+ return NULL;
+ gv_view_area_rotate(GV_VIEW_AREA(PyGtk_Get(area)), angle);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_translate(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double dx, dy;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_view_area_translate", &PyGtk_Type, &area, &dx, &dy))
+ return NULL;
+ gv_view_area_translate(GV_VIEW_AREA(PyGtk_Get(area)), dx, dy);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_set_translation(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double x, y;
+
+ if (!PyArg_ParseTuple(args, "O!dd:gv_view_area_set_translation", &PyGtk_Type, &area, &x, &y))
+ return NULL;
+ gv_view_area_set_translation(GV_VIEW_AREA(PyGtk_Get(area)), x, y);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_fit_extents(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double llx, llyy, width, height;
+
+ if (!PyArg_ParseTuple(args, "O!dddd:gv_view_area_fit_extents", &PyGtk_Type, &area, &llx, &llyy, &width, &height))
+ return NULL;
+ gv_view_area_fit_extents(GV_VIEW_AREA(PyGtk_Get(area)), llx, llyy, width, height);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_fit_all_layers(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_fit_all_layers", &PyGtk_Type, &area))
+ return NULL;
+ gv_view_area_fit_all_layers(GV_VIEW_AREA(PyGtk_Get(area)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_set_projection(PyObject *self, PyObject *args) {
+ PyObject *area;
+ const char *proj_name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_view_area_set_projection", &PyGtk_Type, &area, &proj_name))
+ return NULL;
+ gv_view_area_set_projection(GV_VIEW_AREA(PyGtk_Get(area)), proj_name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_projection(PyObject *self, PyObject *args) {
+ PyObject *area;
+ const char *ret;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_projection", &PyGtk_Type, &area))
+ return NULL;
+ ret = gv_view_area_get_projection(GV_VIEW_AREA(PyGtk_Get(area)));
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_view_area_copy_state(PyObject *self, PyObject *args) {
+ PyObject *area, *source;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_area_copy_state", &PyGtk_Type, &area, &PyGtk_Type, &source))
+ return NULL;
+ gv_view_area_copy_state(GV_VIEW_AREA(PyGtk_Get(area)), GV_VIEW_AREA(PyGtk_Get(source)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_print_to_file(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int width, height, is_rgb;
+ char *filename, *format;
+
+ if (!PyArg_ParseTuple(args, "O!iissi:gv_view_area_print_to_file", &PyGtk_Type, &area, &width, &height, &filename, &format, &is_rgb))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_print_to_file(GV_VIEW_AREA(PyGtk_Get(area)), width, height, filename, format, is_rgb));
+}
+
+static PyObject *_wrap_gv_view_area_print_postscript_to_file(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int width, height, is_rgb;
+ char *filename;
+ double ulx, uly, lrx, lry;
+
+ if (!PyArg_ParseTuple(args, "O!iiddddis:gv_view_area_print_postscript_to_file", &PyGtk_Type, &area, &width, &height, &ulx, &uly, &lrx, &lry, &is_rgb, &filename))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_print_postscript_to_file(GV_VIEW_AREA(PyGtk_Get(area)), width, height, ulx, uly, lrx, lry, is_rgb, filename));
+}
+
+static PyObject *_wrap_gv_view_area_page_setup(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_view_area_page_setup"))
+ return NULL;
+ gv_view_area_page_setup();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_print_to_windriver(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int width, height, is_rgb;
+ double ulx, uly, lrx, lry;
+
+ if (!PyArg_ParseTuple(args, "O!iiddddi:gv_view_area_print_to_windriver", &PyGtk_Type, &area, &width, &height, &ulx, &uly, &lrx, &lry, &is_rgb))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_print_to_windriver(GV_VIEW_AREA(PyGtk_Get(area)), width, height, ulx, uly, lrx, lry, is_rgb));
+}
+
+static PyObject *_wrap_gv_view_area_set_mode(PyObject *self, PyObject *args) {
+ PyObject *area;
+ int flag_3d;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_view_area_set_mode", &PyGtk_Type, &area, &flag_3d))
+ return NULL;
+ gv_view_area_set_mode(GV_VIEW_AREA(PyGtk_Get(area)), flag_3d);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_mode(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_mode", &PyGtk_Type, &area))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_mode(GV_VIEW_AREA(PyGtk_Get(area))));
+}
+
+static PyObject *_wrap_gv_view_area_height_scale(PyObject *self, PyObject *args) {
+ PyObject *area;
+ double scale;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_view_area_height_scale", &PyGtk_Type, &area, &scale))
+ return NULL;
+ gv_view_area_height_scale(GV_VIEW_AREA(PyGtk_Get(area)), scale);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_height_scale(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_get_height_scale", &PyGtk_Type, &area))
+ return NULL;
+ return PyFloat_FromDouble(gv_view_area_get_height_scale(GV_VIEW_AREA(PyGtk_Get(area))));
+}
+
+static PyObject *_wrap_gv_view_area_queue_draw(PyObject *self, PyObject *args) {
+ PyObject *area;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_area_queue_draw", &PyGtk_Type, &area))
+ return NULL;
+ gv_view_area_queue_draw(GV_VIEW_AREA(PyGtk_Get(area)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_area_get_raw(PyObject *self, PyObject *args) {
+ PyObject *area, *ref_layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_area_get_raw", &PyGtk_Type, &area, &PyGtk_Type, &ref_layer))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_get_raw(GV_VIEW_AREA(PyGtk_Get(area)), GTK_OBJECT(PyGtk_Get(ref_layer))));
+}
+
+static PyObject *_wrap_gv_view_area_set_raw(PyObject *self, PyObject *args) {
+ PyObject *area, *ref_layer;
+ int raw_enable;
+
+ if (!PyArg_ParseTuple(args, "O!O!i:gv_view_area_set_raw", &PyGtk_Type, &area, &PyGtk_Type, &ref_layer, &raw_enable))
+ return NULL;
+ return PyInt_FromLong(gv_view_area_set_raw(GV_VIEW_AREA(PyGtk_Get(area)), GTK_OBJECT(PyGtk_Get(ref_layer)), raw_enable));
+}
+
+static PyObject *_wrap_gv_view_area_get_property(PyObject *self, PyObject *args) {
+ PyObject *area;
+ const char *ret;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_view_area_get_property", &PyGtk_Type, &area, &name))
+ return NULL;
+ ret = gv_view_area_get_property(GV_VIEW_AREA(PyGtk_Get(area)), name);
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_view_area_set_property(PyObject *self, PyObject *args) {
+ PyObject *area;
+ const char *name, *value;
+
+ if (!PyArg_ParseTuple(args, "O!ss:gv_view_area_set_property", &PyGtk_Type, &area, &name, &value))
+ return NULL;
+ gv_view_area_set_property(GV_VIEW_AREA(PyGtk_Get(area)), name, value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_data_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_data_get_type());
+}
+
+static PyObject *_wrap_gv_data_is_read_only(PyObject *self, PyObject *args) {
+ PyObject *data;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_is_read_only", &PyGtk_Type, &data))
+ return NULL;
+ return PyInt_FromLong(gv_data_is_read_only(GV_DATA(PyGtk_Get(data))));
+}
+
+static PyObject *_wrap_gv_data_set_read_only(PyObject *self, PyObject *args) {
+ PyObject *data;
+ int read_only;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_data_set_read_only", &PyGtk_Type, &data, &read_only))
+ return NULL;
+ gv_data_set_read_only(GV_DATA(PyGtk_Get(data)), read_only);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_get_name(PyObject *self, PyObject *args) {
+ PyObject *data;
+ const char *ret;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_get_name", &PyGtk_Type, &data))
+ return NULL;
+ ret = gv_data_get_name(GV_DATA(PyGtk_Get(data)));
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_data_set_name(PyObject *self, PyObject *args) {
+ PyObject *data;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_data_set_name", &PyGtk_Type, &data, &name))
+ return NULL;
+ gv_data_set_name(GV_DATA(PyGtk_Get(data)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_get_projection(PyObject *self, PyObject *args) {
+ PyObject *data;
+ const char *ret;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_get_projection", &PyGtk_Type, &data))
+ return NULL;
+ ret = gv_data_get_projection(GV_DATA(PyGtk_Get(data)));
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_data_set_projection(PyObject *self, PyObject *args) {
+ PyObject *data;
+ char *projection;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_data_set_projection", &PyGtk_Type, &data, &projection))
+ return NULL;
+ gv_data_set_projection(GV_DATA(PyGtk_Get(data)), projection);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_get_property(PyObject *self, PyObject *args) {
+ PyObject *data;
+ const char *ret;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_data_get_property", &PyGtk_Type, &data, &name))
+ return NULL;
+ ret = gv_data_get_property(GV_DATA(PyGtk_Get(data)), name);
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_data_set_property(PyObject *self, PyObject *args) {
+ PyObject *data;
+ const char *name, *value;
+
+ if (!PyArg_ParseTuple(args, "O!ss:gv_data_set_property", &PyGtk_Type, &data, &name, &value))
+ return NULL;
+ gv_data_set_property(GV_DATA(PyGtk_Get(data)), name, value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_freeze(PyObject *self, PyObject *args) {
+ PyObject *data;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_freeze", &PyGtk_Type, &data))
+ return NULL;
+ gv_data_freeze(GV_DATA(PyGtk_Get(data)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_thaw(PyObject *self, PyObject *args) {
+ PyObject *data;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_thaw", &PyGtk_Type, &data))
+ return NULL;
+ gv_data_thaw(GV_DATA(PyGtk_Get(data)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_get_parent(PyObject *self, PyObject *args) {
+ PyObject *data;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_data_get_parent", &PyGtk_Type, &data))
+ return NULL;
+ retval = (GtkObject *)gv_data_get_parent(GV_DATA(PyGtk_Get(data)));
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_data_registry_dump(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_data_registry_dump"))
+ return NULL;
+ gv_data_registry_dump();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_records_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_records_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_records_get_type());
+}
+
+static PyObject *_wrap_gv_records_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_records_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_records_new());
+}
+
+static PyObject *_wrap_gv_records_from_dbf(PyObject *self, PyObject *args) {
+ char *filename;
+ PyProgressData sProgressInfo = {NULL,NULL,-1};
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "sOO:gv_records_from_dbf", &filename, &(sProgressInfo.psPyCallback), &(sProgressInfo.psPyCallbackData)))
+ return NULL;
+ retval = (GtkObject *)gv_records_from_dbf(filename, PyProgressProxy, &sProgressInfo);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_records_from_rec(PyObject *self, PyObject *args) {
+ char *filename;
+ PyProgressData sProgressInfo = {NULL,NULL,-1};
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "sOO:gv_records_from_rec", &filename, &(sProgressInfo.psPyCallback), &(sProgressInfo.psPyCallbackData)))
+ return NULL;
+ retval = (GtkObject *)gv_records_from_rec(filename, PyProgressProxy, &sProgressInfo);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_records_create_records(PyObject *self, PyObject *args) {
+ PyObject *records;
+ int new_records;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_records_create_records", &PyGtk_Type, &records, &new_records))
+ return NULL;
+ return PyInt_FromLong(gv_records_create_records(GV_RECORDS(PyGtk_Get(records)), new_records));
+}
+
+static PyObject *_wrap_gv_records_num_records(PyObject *self, PyObject *args) {
+ PyObject *records;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_records_num_records", &PyGtk_Type, &records))
+ return NULL;
+ return PyInt_FromLong(gv_records_num_records(GV_RECORDS(PyGtk_Get(records))));
+}
+
+static PyObject *_wrap_gv_records_add_field(PyObject *self, PyObject *args) {
+ PyObject *records;
+ const char *name;
+ int rft, width, precision;
+
+ if (!PyArg_ParseTuple(args, "O!siii:gv_records_add_field", &PyGtk_Type, &records, &name, &rft, &width, &precision))
+ return NULL;
+ return PyInt_FromLong(gv_records_add_field(GV_RECORDS(PyGtk_Get(records)), name, rft, width, precision));
+}
+
+static PyObject *_wrap_gv_records_set_raw_field_data(PyObject *self, PyObject *args) {
+ PyObject *records;
+ int record_index, field_index;
+ const char *value = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!ii|z:gv_records_set_raw_field_data", &PyGtk_Type, &records, &record_index, &field_index, &value))
+ return NULL;
+ gv_records_set_raw_field_data(GV_RECORDS(PyGtk_Get(records)), record_index, field_index, value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_records_get_raw_field_data(PyObject *self, PyObject *args) {
+ PyObject *records;
+ const char *ret;
+ int record_index, field_index;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_records_get_raw_field_data", &PyGtk_Type, &records, &record_index, &field_index))
+ return NULL;
+ ret = gv_records_get_raw_field_data(GV_RECORDS(PyGtk_Get(records)), record_index, field_index);
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_shapes_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_shapes_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_shapes_get_type());
+}
+
+static PyObject *_wrap_gv_shapes_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_shapes_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_shapes_new());
+}
+
+static PyObject *_wrap_gv_shapes_from_shapefile(PyObject *self, PyObject *args) {
+ char *filename;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "s:gv_shapes_from_shapefile", &filename))
+ return NULL;
+ retval = (GtkObject *)gv_shapes_from_shapefile(filename);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shapes_to_shapefile(PyObject *self, PyObject *args) {
+ char *filename;
+ PyObject *data;
+ int shp_type;
+
+ if (!PyArg_ParseTuple(args, "sO!i:gv_shapes_to_shapefile", &filename, &PyGtk_Type, &data, &shp_type))
+ return NULL;
+ return PyInt_FromLong(gv_shapes_to_shapefile(filename, GV_DATA(PyGtk_Get(data)), shp_type));
+}
+
+static PyObject *_wrap_gv_shapes_from_ogr(PyObject *self, PyObject *args) {
+ char *filename;
+ int layer;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "si:gv_shapes_from_ogr", &filename, &layer))
+ return NULL;
+ retval = (GtkObject *)gv_shapes_from_ogr(filename, layer);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_have_ogr_support(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_have_ogr_support"))
+ return NULL;
+ return PyInt_FromLong(gv_have_ogr_support());
+}
+
+static PyObject *_wrap_gv_shapes_num_shapes(PyObject *self, PyObject *args) {
+ PyObject *shapes;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shapes_num_shapes", &PyGtk_Type, &shapes))
+ return NULL;
+ return PyInt_FromLong(gv_shapes_num_shapes(GV_SHAPES(PyGtk_Get(shapes))));
+}
+
+static PyObject *_wrap_gv_shapes_add_height(PyObject *self, PyObject *args) {
+ PyObject *shapes, *raster;
+ double offset, default_height;
+
+ if (!PyArg_ParseTuple(args, "O!O!dd:gv_shapes_add_height", &PyGtk_Type, &shapes, &PyGtk_Type, &raster, &offset, &default_height))
+ return NULL;
+ gv_shapes_add_height(GV_SHAPES(PyGtk_Get(shapes)), GV_DATA(PyGtk_Get(raster)), offset, default_height);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_get_count(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_shape_get_count"))
+ return NULL;
+ return PyInt_FromLong(gv_shape_get_count());
+}
+
+static PyObject *_wrap_gv_points_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_points_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_points_get_type());
+}
+
+static PyObject *_wrap_gv_points_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_points_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_points_new());
+}
+
+static PyObject *_wrap_gv_points_num_points(PyObject *self, PyObject *args) {
+ PyObject *points;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_points_num_points", &PyGtk_Type, &points))
+ return NULL;
+ return PyInt_FromLong(gv_points_num_points(GV_POINTS(PyGtk_Get(points))));
+}
+
+static PyObject *_wrap_gv_polylines_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_polylines_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_polylines_get_type());
+}
+
+static PyObject *_wrap_gv_polylines_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_polylines_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_polylines_new());
+}
+
+static PyObject *_wrap_gv_polylines_num_lines(PyObject *self, PyObject *args) {
+ PyObject *lines;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_polylines_num_lines", &PyGtk_Type, &lines))
+ return NULL;
+ return PyInt_FromLong(gv_polylines_num_lines(GV_POLYLINES(PyGtk_Get(lines))));
+}
+
+static PyObject *_wrap_gv_areas_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_areas_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_areas_get_type());
+}
+
+static PyObject *_wrap_gv_areas_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_areas_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_areas_new());
+}
+
+static PyObject *_wrap_gv_areas_num_areas(PyObject *self, PyObject *args) {
+ PyObject *areas;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_areas_num_areas", &PyGtk_Type, &areas))
+ return NULL;
+ return PyInt_FromLong(gv_areas_num_areas(GV_AREAS(PyGtk_Get(areas))));
+}
+
+static PyObject *_wrap_gv_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_layer_get_type());
+}
+
+static PyObject *_wrap_gv_layer_is_visible(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_layer_is_visible", &PyGtk_Type, &layer))
+ return NULL;
+ return PyInt_FromLong(gv_layer_is_visible(GV_LAYER(PyGtk_Get(layer))));
+}
+
+static PyObject *_wrap_gv_layer_set_visible(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int visible;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_layer_set_visible", &PyGtk_Type, &layer, &visible))
+ return NULL;
+ gv_layer_set_visible(GV_LAYER(PyGtk_Get(layer)), visible);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_layer_reproject(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ char *projection;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_layer_reproject", &PyGtk_Type, &layer, &projection))
+ return NULL;
+ return PyInt_FromLong(gv_layer_reproject(GV_LAYER(PyGtk_Get(layer)), projection));
+}
+
+static PyObject *_wrap_gv_layer_get_view(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_layer_get_view", &PyGtk_Type, &layer))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_layer_get_view(GV_LAYER(PyGtk_Get(layer))));
+}
+
+static PyObject *_wrap_gv_shape_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_shape_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_shape_layer_get_type());
+}
+
+static PyObject *_wrap_gv_shape_layer_clear_selection(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shape_layer_clear_selection", &PyGtk_Type, &layer))
+ return NULL;
+ gv_shape_layer_clear_selection(GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_layer_select_all(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shape_layer_select_all", &PyGtk_Type, &layer))
+ return NULL;
+ gv_shape_layer_select_all(GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_layer_select_shape(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int shape_id;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_shape_layer_select_shape", &PyGtk_Type, &layer, &shape_id))
+ return NULL;
+ gv_shape_layer_select_shape(GV_SHAPE_LAYER(PyGtk_Get(layer)), shape_id);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_layer_deselect_shape(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int shape_id;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_shape_layer_deselect_shape", &PyGtk_Type, &layer, &shape_id))
+ return NULL;
+ gv_shape_layer_deselect_shape(GV_SHAPE_LAYER(PyGtk_Get(layer)), shape_id);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_layer_subselect_shape(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int shape_id;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_shape_layer_subselect_shape", &PyGtk_Type, &layer, &shape_id))
+ return NULL;
+ gv_shape_layer_subselect_shape(GV_SHAPE_LAYER(PyGtk_Get(layer)), shape_id);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_shape_layer_get_subselection(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_shape_layer_get_subselection", &PyGtk_Type, &layer))
+ return NULL;
+ return PyInt_FromLong(gv_shape_layer_get_subselection(GV_SHAPE_LAYER(PyGtk_Get(layer))));
+}
+
+static PyObject *_wrap_gv_shapes_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_shapes_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_shapes_layer_get_type());
+}
+
+static PyObject *_wrap_gv_shapes_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_shapes = Py_None;
+ GvShapes *shapes = NULL;
+
+ if (!PyArg_ParseTuple(args, "|O:gv_shapes_layer_new", &py_shapes))
+ return NULL;
+ if (PyGtk_Check(py_shapes))
+ shapes = GV_SHAPES(PyGtk_Get(py_shapes));
+ else if (py_shapes != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "shapes argument must be a GvShapes or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)gv_shapes_layer_new(shapes));
+}
+
+static PyObject *_wrap_gv_shapes_layer_get_symbol_manager(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int ok_to_create;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_shapes_layer_get_symbol_manager", &PyGtk_Type, &layer, &ok_to_create))
+ return NULL;
+ retval = (GtkObject *)gv_shapes_layer_get_symbol_manager(GV_SHAPES_LAYER(PyGtk_Get(layer)), ok_to_create);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_point_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_point_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_point_layer_get_type());
+}
+
+static PyObject *_wrap_gv_point_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_points = Py_None;
+ GvPoints *points = NULL;
+
+ if (!PyArg_ParseTuple(args, "|O:gv_point_layer_new", &py_points))
+ return NULL;
+ if (PyGtk_Check(py_points))
+ points = GV_POINTS(PyGtk_Get(py_points));
+ else if (py_points != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "points argument must be a GvPoints or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)gv_point_layer_new(points));
+}
+
+static PyObject *_wrap_gv_line_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_line_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_line_layer_get_type());
+}
+
+static PyObject *_wrap_gv_line_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_lines = Py_None;
+ GvPolylines *lines = NULL;
+
+ if (!PyArg_ParseTuple(args, "|O:gv_line_layer_new", &py_lines))
+ return NULL;
+ if (PyGtk_Check(py_lines))
+ lines = GV_POLYLINES(PyGtk_Get(py_lines));
+ else if (py_lines != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "lines argument must be a GvPolylines or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)gv_line_layer_new(lines));
+}
+
+static PyObject *_wrap_gv_area_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_area_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_area_layer_get_type());
+}
+
+static PyObject *_wrap_gv_area_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_areas = Py_None;
+ GvAreas *areas = NULL;
+
+ if (!PyArg_ParseTuple(args, "|O:gv_area_layer_new", &py_areas))
+ return NULL;
+ if (PyGtk_Check(py_areas))
+ areas = GV_AREAS(PyGtk_Get(py_areas));
+ else if (py_areas != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "areas argument must be a GvAreas or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)gv_area_layer_new(areas));
+}
+
+static PyObject *_wrap_gv_pquery_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_pquery_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_pquery_layer_get_type());
+}
+
+static PyObject *_wrap_gv_pquery_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_shapes = Py_None;
+ GvShapes *shapes = NULL;
+
+ if (!PyArg_ParseTuple(args, "|O:gv_pquery_layer_new", &py_shapes))
+ return NULL;
+ if (PyGtk_Check(py_shapes))
+ shapes = GV_SHAPES(PyGtk_Get(py_shapes));
+ else if (py_shapes != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "shapes argument must be a GvShapes or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)gv_pquery_layer_new(shapes));
+}
+
+static PyObject *_wrap_ip_gcp_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":ip_gcp_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(ip_gcp_layer_get_type());
+}
+
+static PyObject *_wrap_ip_gcp_layer_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":ip_gcp_layer_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)ip_gcp_layer_new());
+}
+
+static PyObject *_wrap_app_cur_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":app_cur_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(app_cur_layer_get_type());
+}
+
+static PyObject *_wrap_app_cur_layer_new(PyObject *self, PyObject *args) {
+ PyObject *py_shapes = Py_None;
+ GvShapes *shapes = NULL;
+
+ if (!PyArg_ParseTuple(args, "O:app_cur_layer_new", &py_shapes))
+ return NULL;
+ if (PyGtk_Check(py_shapes))
+ shapes = GV_SHAPES(PyGtk_Get(py_shapes));
+ else if (py_shapes != Py_None) {
+ PyErr_SetString(PyExc_TypeError, "shapes argument must be a GvShapes or None");
+ return NULL;
+ }
+ return PyGtk_New((GtkObject *)app_cur_layer_new(shapes));
+}
+
+static PyObject *_wrap_gv_symbol_manager_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_symbol_manager_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_symbol_manager_get_type());
+}
+
+static PyObject *_wrap_gv_get_symbol_manager(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_get_symbol_manager"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_get_symbol_manager());
+}
+
+static PyObject *_wrap_gv_symbol_manager_eject_symbol(PyObject *self, PyObject *args) {
+ PyObject *manager;
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_symbol_manager_eject_symbol", &PyGtk_Type, &manager, &name))
+ return NULL;
+ gv_symbol_manager_eject_symbol(GV_SYMBOL_MANAGER(PyGtk_Get(manager)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_symbol_manager_has_symbol(PyObject *self, PyObject *args) {
+ PyObject *manager;
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_symbol_manager_has_symbol", &PyGtk_Type, &manager, &name))
+ return NULL;
+ return PyInt_FromLong(gv_symbol_manager_has_symbol(GV_SYMBOL_MANAGER(PyGtk_Get(manager)), name));
+}
+
+static PyObject *_wrap_gv_manager_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_manager_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_manager_get_type());
+}
+
+static PyObject *_wrap_gv_get_manager(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_get_manager"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_get_manager());
+}
+
+static PyObject *_wrap_gv_manager_get_preference(PyObject *self, PyObject *args) {
+ PyObject *manager;
+ const char *ret, *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_manager_get_preference", &PyGtk_Type, &manager, &name))
+ return NULL;
+ ret = gv_manager_get_preference(GV_MANAGER(PyGtk_Get(manager)), name);
+ if( ret != NULL)
+ return PyString_FromString(ret);
+ else
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+
+static PyObject *_wrap_gv_manager_set_preference(PyObject *self, PyObject *args) {
+ PyObject *manager;
+ const char *name, *value;
+
+ if (!PyArg_ParseTuple(args, "O!ss:gv_manager_set_preference", &PyGtk_Type, &manager, &name, &value))
+ return NULL;
+ gv_manager_set_preference(GV_MANAGER(PyGtk_Get(manager)), name, value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_manager_get_busy(PyObject *self, PyObject *args) {
+ PyObject *manager;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_manager_get_busy", &PyGtk_Type, &manager))
+ return NULL;
+ return PyInt_FromLong(gv_manager_get_busy(GV_MANAGER(PyGtk_Get(manager))));
+}
+
+static PyObject *_wrap_gv_manager_set_busy(PyObject *self, PyObject *args) {
+ PyObject *manager;
+ int busy;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_manager_set_busy", &PyGtk_Type, &manager, &busy))
+ return NULL;
+ gv_manager_set_busy(GV_MANAGER(PyGtk_Get(manager)), busy);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_manager_dump(PyObject *self, PyObject *args) {
+ PyObject *manager;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_manager_dump", &PyGtk_Type, &manager))
+ return NULL;
+ gv_manager_dump(GV_MANAGER(PyGtk_Get(manager)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_tool_get_type());
+}
+
+static PyObject *_wrap_gv_tool_activate(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_tool_activate", &PyGtk_Type, &tool, &PyGtk_Type, &view))
+ return NULL;
+ gv_tool_activate(GV_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_tool_deactivate(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_tool_deactivate", &PyGtk_Type, &tool, &PyGtk_Type, &view))
+ return NULL;
+ gv_tool_deactivate(GV_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_tool_get_view(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_tool_get_view", &PyGtk_Type, &tool))
+ return NULL;
+ retval = (GtkObject *)gv_tool_get_view(GV_TOOL(PyGtk_Get(tool)));
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_tool_set_cursor(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ int cursor_type;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_tool_set_cursor", &PyGtk_Type, &tool, &cursor_type))
+ return NULL;
+ gv_tool_set_cursor(GV_TOOL(PyGtk_Get(tool)), cursor_type);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_selection_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_selection_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_selection_tool_get_type());
+}
+
+static PyObject *_wrap_gv_selection_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_selection_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_selection_tool_new());
+}
+
+static PyObject *_wrap_gv_selection_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_selection_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_selection_tool_set_layer(GV_SELECTION_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_zoompan_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_zoompan_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_zoompan_tool_get_type());
+}
+
+static PyObject *_wrap_gv_zoompan_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_zoompan_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_zoompan_tool_new());
+}
+
+static PyObject *_wrap_gv_point_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_point_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_point_tool_get_type());
+}
+
+static PyObject *_wrap_gv_point_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_point_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_point_tool_new());
+}
+
+static PyObject *_wrap_gv_point_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_point_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_point_tool_set_layer(GV_POINT_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_point_tool_set_named_layer(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_point_tool_set_named_layer", &PyGtk_Type, &tool, &name))
+ return NULL;
+ gv_point_tool_set_named_layer(GV_POINT_TOOL(PyGtk_Get(tool)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_line_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_line_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_line_tool_get_type());
+}
+
+static PyObject *_wrap_gv_line_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_line_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_line_tool_new());
+}
+
+static PyObject *_wrap_gv_line_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_line_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_line_tool_set_layer(GV_LINE_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_line_tool_set_named_layer(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_line_tool_set_named_layer", &PyGtk_Type, &tool, &name))
+ return NULL;
+ gv_line_tool_set_named_layer(GV_LINE_TOOL(PyGtk_Get(tool)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_rect_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_rect_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_rect_tool_get_type());
+}
+
+static PyObject *_wrap_gv_rect_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_rect_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_rect_tool_new());
+}
+
+static PyObject *_wrap_gv_rect_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_rect_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_rect_tool_set_layer(GV_RECT_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_rect_tool_set_named_layer(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_rect_tool_set_named_layer", &PyGtk_Type, &tool, &name))
+ return NULL;
+ gv_rect_tool_set_named_layer(GV_RECT_TOOL(PyGtk_Get(tool)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_rotate_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_rotate_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_rotate_tool_get_type());
+}
+
+static PyObject *_wrap_gv_rotate_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_rotate_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_rotate_tool_new());
+}
+
+static PyObject *_wrap_gv_rotate_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_rotate_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_rotate_tool_set_layer(GV_ROTATE_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_rotate_tool_set_named_layer(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_rotate_tool_set_named_layer", &PyGtk_Type, &tool, &name))
+ return NULL;
+ gv_rotate_tool_set_named_layer(GV_ROTATE_TOOL(PyGtk_Get(tool)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_area_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_area_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_area_tool_get_type());
+}
+
+static PyObject *_wrap_gv_area_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_area_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_area_tool_new());
+}
+
+static PyObject *_wrap_gv_area_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_area_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_area_tool_set_layer(GV_AREA_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_area_tool_set_named_layer(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_area_tool_set_named_layer", &PyGtk_Type, &tool, &name))
+ return NULL;
+ gv_area_tool_set_named_layer(GV_AREA_TOOL(PyGtk_Get(tool)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_node_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_node_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_node_tool_get_type());
+}
+
+static PyObject *_wrap_gv_node_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_node_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_node_tool_new());
+}
+
+static PyObject *_wrap_gv_node_tool_set_layer(PyObject *self, PyObject *args) {
+ PyObject *tool, *layer;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_node_tool_set_layer", &PyGtk_Type, &tool, &PyGtk_Type, &layer))
+ return NULL;
+ gv_node_tool_set_layer(GV_NODE_TOOL(PyGtk_Get(tool)), GV_SHAPE_LAYER(PyGtk_Get(layer)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_roi_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_roi_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_roi_tool_get_type());
+}
+
+static PyObject *_wrap_gv_roi_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_roi_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_roi_tool_new());
+}
+
+static PyObject *_wrap_gv_poi_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_poi_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_poi_tool_get_type());
+}
+
+static PyObject *_wrap_gv_poi_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_poi_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_poi_tool_new());
+}
+
+static PyObject *_wrap_gv_track_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_track_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_track_tool_get_type());
+}
+
+static PyObject *_wrap_gv_track_tool_new(PyObject *self, PyObject *args) {
+ PyObject *label;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_track_tool_new", &PyGtk_Type, &label))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_track_tool_new(GTK_OBJECT(PyGtk_Get(label))));
+}
+
+static PyObject *_wrap_gv_toolbox_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_toolbox_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_toolbox_get_type());
+}
+
+static PyObject *_wrap_gv_toolbox_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_toolbox_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_toolbox_new());
+}
+
+static PyObject *_wrap_gv_toolbox_add_tool(PyObject *self, PyObject *args) {
+ PyObject *toolbox, *tool;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!sO!:gv_toolbox_add_tool", &PyGtk_Type, &toolbox, &name, &PyGtk_Type, &tool))
+ return NULL;
+ gv_toolbox_add_tool(GV_TOOLBOX(PyGtk_Get(toolbox)), name, GV_TOOL(PyGtk_Get(tool)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_toolbox_activate_tool(PyObject *self, PyObject *args) {
+ PyObject *toolbox;
+ char *name;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_toolbox_activate_tool", &PyGtk_Type, &toolbox, &name))
+ return NULL;
+ gv_toolbox_activate_tool(GV_TOOLBOX(PyGtk_Get(toolbox)), name);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_register_data(PyObject *self, PyObject *args) {
+ PyObject *data;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_undo_register_data", &PyGtk_Type, &data))
+ return NULL;
+ gv_undo_register_data(GV_DATA(PyGtk_Get(data)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_pop(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_pop"))
+ return NULL;
+ gv_undo_pop();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_clear(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_clear"))
+ return NULL;
+ gv_undo_clear();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_can_undo(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_can_undo"))
+ return NULL;
+ return PyInt_FromLong(gv_undo_can_undo());
+}
+
+static PyObject *_wrap_gv_undo_close(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_close"))
+ return NULL;
+ gv_undo_close();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_open(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_open"))
+ return NULL;
+ gv_undo_open();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_undo_start_group(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_undo_start_group"))
+ return NULL;
+ return PyInt_FromLong(gv_undo_start_group());
+}
+
+static PyObject *_wrap_gv_undo_end_group(PyObject *self, PyObject *args) {
+ int group;
+
+ if (!PyArg_ParseTuple(args, "i:gv_undo_end_group", &group))
+ return NULL;
+ gv_undo_end_group(group);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_link_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_view_link_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_view_link_get_type());
+}
+
+static PyObject *_wrap_gv_view_link_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_view_link_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_view_link_new());
+}
+
+static PyObject *_wrap_gv_view_link_register_view(PyObject *self, PyObject *args) {
+ PyObject *link, *view;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_link_register_view", &PyGtk_Type, &link, &PyGtk_Type, &view))
+ return NULL;
+ gv_view_link_register_view(GV_VIEW_LINK(PyGtk_Get(link)), GV_VIEW_AREA(PyGtk_Get(view)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_link_remove_view(PyObject *self, PyObject *args) {
+ PyObject *link, *view;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_view_link_remove_view", &PyGtk_Type, &link, &PyGtk_Type, &view))
+ return NULL;
+ gv_view_link_remove_view(GV_VIEW_LINK(PyGtk_Get(link)), GV_VIEW_AREA(PyGtk_Get(view)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_link_enable(PyObject *self, PyObject *args) {
+ PyObject *link;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_link_enable", &PyGtk_Type, &link))
+ return NULL;
+ gv_view_link_enable(GV_VIEW_LINK(PyGtk_Get(link)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_link_disable(PyObject *self, PyObject *args) {
+ PyObject *link;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_view_link_disable", &PyGtk_Type, &link))
+ return NULL;
+ gv_view_link_disable(GV_VIEW_LINK(PyGtk_Get(link)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_view_link_set_cursor_mode(PyObject *self, PyObject *args) {
+ PyObject *link;
+ int cursor_mode;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_view_link_set_cursor_mode", &PyGtk_Type, &link, &cursor_mode))
+ return NULL;
+ gv_view_link_set_cursor_mode(GV_VIEW_LINK(PyGtk_Get(link)), cursor_mode);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_raster_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_raster_get_type());
+}
+
+static PyObject *_wrap_gv_raster_flush_cache(PyObject *self, PyObject *args) {
+ PyObject *raster;
+ int x_off, y_off, width, height;
+
+ if (!PyArg_ParseTuple(args, "O!iiii:gv_raster_flush_cache", &PyGtk_Type, &raster, &x_off, &y_off, &width, &height))
+ return NULL;
+ gv_raster_flush_cache(GV_RASTER(PyGtk_Get(raster)), x_off, y_off, width, height);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_get_min(PyObject *self, PyObject *args) {
+ PyObject *raster;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_get_min", &PyGtk_Type, &raster))
+ return NULL;
+ return PyFloat_FromDouble(gv_raster_get_min(GV_RASTER(PyGtk_Get(raster))));
+}
+
+static PyObject *_wrap_gv_raster_get_max(PyObject *self, PyObject *args) {
+ PyObject *raster;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_get_max", &PyGtk_Type, &raster))
+ return NULL;
+ return PyFloat_FromDouble(gv_raster_get_max(GV_RASTER(PyGtk_Get(raster))));
+}
+
+static PyObject *_wrap_gv_raster_cache_get_max(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_raster_cache_get_max"))
+ return NULL;
+ return PyInt_FromLong(gv_raster_cache_get_max());
+}
+
+static PyObject *_wrap_gv_raster_cache_get_used(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_raster_cache_get_used"))
+ return NULL;
+ return PyInt_FromLong(gv_raster_cache_get_used());
+}
+
+static PyObject *_wrap_gv_raster_cache_set_max(PyObject *self, PyObject *args) {
+ int new_max;
+
+ if (!PyArg_ParseTuple(args, "i:gv_raster_cache_set_max", &new_max))
+ return NULL;
+ gv_raster_cache_set_max(new_max);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_set_poly_order_preference(PyObject *self, PyObject *args) {
+ PyObject *raster;
+ int poly_order;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_set_poly_order_preference", &PyGtk_Type, &raster, &poly_order))
+ return NULL;
+ gv_raster_set_poly_order_preference(GV_RASTER(PyGtk_Get(raster)), poly_order);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_layer_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_raster_layer_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_get_type());
+}
+
+static PyObject *_wrap_gv_raster_layer_lut_color_wheel_new(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int h_type, s_type, v_type;
+ double h_param, s_param, v_param;
+
+ if (!PyArg_ParseTuple(args, "O!ididid:gv_raster_layer_lut_color_wheel_new", &PyGtk_Type, &layer, &h_type, &h_param, &s_type, &s_param, &v_type, &v_param))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_lut_color_wheel_new(GV_RASTER_LAYER(PyGtk_Get(layer)), h_type, h_param, s_type, s_param, v_type, v_param));
+}
+
+static PyObject *_wrap_gv_raster_layer_lut_color_wheel_new_ev(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int set_phase, set_magnitude;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_raster_layer_lut_color_wheel_new_ev", &PyGtk_Type, &layer, &set_phase, &set_magnitude))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_lut_color_wheel_new_ev(GV_RASTER_LAYER(PyGtk_Get(layer)), set_phase, set_magnitude));
+}
+
+static PyObject *_wrap_gv_raster_layer_lut_color_wheel_1d_new(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ double s, v, offset;
+
+ if (!PyArg_ParseTuple(args, "O!ddd:gv_raster_layer_lut_color_wheel_1d_new", &PyGtk_Type, &layer, &s, &v, &offset))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_lut_color_wheel_1d_new(GV_RASTER_LAYER(PyGtk_Get(layer)), s, v, offset));
+}
+
+static PyObject *_wrap_gv_raster_layer_alpha_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int alpha_mode;
+ double alpha_check_val;
+
+ if (!PyArg_ParseTuple(args, "O!id:gv_raster_layer_alpha_set", &PyGtk_Type, &layer, &alpha_mode, &alpha_check_val))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_alpha_set(GV_RASTER_LAYER(PyGtk_Get(layer)), alpha_mode, alpha_check_val));
+}
+
+static PyObject *_wrap_gv_raster_layer_min_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+ double min;
+
+ if (!PyArg_ParseTuple(args, "O!id:gv_raster_layer_min_set", &PyGtk_Type, &layer, &isource, &min))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_min_set(GV_RASTER_LAYER(PyGtk_Get(layer)), isource, min));
+}
+
+static PyObject *_wrap_gv_raster_layer_min_get(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_layer_min_get", &PyGtk_Type, &layer, &isource))
+ return NULL;
+ return PyFloat_FromDouble(gv_raster_layer_min_get(GV_RASTER_LAYER(PyGtk_Get(layer)), isource));
+}
+
+static PyObject *_wrap_gv_raster_layer_max_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+ double max;
+
+ if (!PyArg_ParseTuple(args, "O!id:gv_raster_layer_max_set", &PyGtk_Type, &layer, &isource, &max))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_max_set(GV_RASTER_LAYER(PyGtk_Get(layer)), isource, max));
+}
+
+static PyObject *_wrap_gv_raster_layer_max_get(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_layer_max_get", &PyGtk_Type, &layer, &isource))
+ return NULL;
+ return PyFloat_FromDouble(gv_raster_layer_max_get(GV_RASTER_LAYER(PyGtk_Get(layer)), isource));
+}
+
+static PyObject *_wrap_gv_raster_layer_nodata_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+ double nodata_real, nodata_imaginary;
+
+ if (!PyArg_ParseTuple(args, "O!idd:gv_raster_layer_nodata_set", &PyGtk_Type, &layer, &isource, &nodata_real, &nodata_imaginary))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_nodata_set(GV_RASTER_LAYER(PyGtk_Get(layer)), isource, nodata_real, nodata_imaginary));
+}
+
+static PyObject *_wrap_gv_raster_layer_type_get(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_layer_type_get", &PyGtk_Type, &layer, &isource))
+ return NULL;
+ return PyFloat_FromDouble(gv_raster_layer_type_get(GV_RASTER_LAYER(PyGtk_Get(layer)), isource));
+}
+
+static PyObject *_wrap_gv_raster_layer_get_const_value(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_layer_get_const_value", &PyGtk_Type, &layer, &isource))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_get_const_value(GV_RASTER_LAYER(PyGtk_Get(layer)), isource));
+}
+
+static PyObject *_wrap_gv_raster_layer_get_data(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int isource;
+ GtkObject *retval;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_raster_layer_get_data", &PyGtk_Type, &layer, &isource))
+ return NULL;
+ retval = (GtkObject *)gv_raster_layer_get_data(GV_RASTER_LAYER(PyGtk_Get(layer)), isource);
+ if (retval) return PyGtk_New(retval);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_layer_get_mode(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_layer_get_mode", &PyGtk_Type, &layer))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_get_mode(GV_RASTER_LAYER(PyGtk_Get(layer))));
+}
+
+static PyObject *_wrap_gv_raster_layer_texture_clamp_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int s_clamp, t_clamp;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_raster_layer_texture_clamp_set", &PyGtk_Type, &layer, &s_clamp, &t_clamp))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_texture_clamp_set(GV_RASTER_LAYER(PyGtk_Get(layer)), s_clamp, t_clamp));
+}
+
+static PyObject *_wrap_gv_raster_layer_zoom_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int max_mode, min_mode;
+
+ if (!PyArg_ParseTuple(args, "O!ii:gv_raster_layer_zoom_set", &PyGtk_Type, &layer, &max_mode, &min_mode))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_zoom_set(GV_RASTER_LAYER(PyGtk_Get(layer)), max_mode, min_mode));
+}
+
+static PyObject *_wrap_gv_raster_layer_blend_mode_set(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int mode, sfactor, dfactor;
+
+ if (!PyArg_ParseTuple(args, "O!iii:gv_raster_layer_blend_mode_set", &PyGtk_Type, &layer, &mode, &sfactor, &dfactor))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_blend_mode_set(GV_RASTER_LAYER(PyGtk_Get(layer)), mode, sfactor, dfactor));
+}
+
+static PyObject *_wrap_gv_raster_layer_lut_type_get(PyObject *self, PyObject *args) {
+ PyObject *layer;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_raster_layer_lut_type_get", &PyGtk_Type, &layer))
+ return NULL;
+ return PyInt_FromLong(gv_raster_layer_lut_type_get(GV_RASTER_LAYER(PyGtk_Get(layer))));
+}
+
+static PyObject *_wrap_gv_raster_layer_add_height(PyObject *self, PyObject *args) {
+ PyObject *layer, *height_raster;
+ double default_height;
+
+ if (!PyArg_ParseTuple(args, "O!O!d:gv_raster_layer_add_height", &PyGtk_Type, &layer, &PyGtk_Type, &height_raster, &default_height))
+ return NULL;
+ gv_raster_layer_add_height(GV_RASTER_LAYER(PyGtk_Get(layer)), GV_RASTER(PyGtk_Get(height_raster)), default_height);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_raster_layer_clamp_height(PyObject *self, PyObject *args) {
+ PyObject *layer;
+ int bclamp_min, bclamp_max;
+ double min_height, max_height;
+
+ if (!PyArg_ParseTuple(args, "O!iidd:gv_raster_layer_clamp_height", &PyGtk_Type, &layer, &bclamp_min, &bclamp_max, &min_height, &max_height))
+ return NULL;
+ gv_raster_layer_clamp_height(GV_RASTER_LAYER(PyGtk_Get(layer)), bclamp_min, bclamp_max, min_height, max_height);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_texture_cache_dump(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_texture_cache_dump"))
+ return NULL;
+ gv_texture_cache_dump();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_texture_cache_get_max(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_texture_cache_get_max"))
+ return NULL;
+ return PyInt_FromLong(gv_texture_cache_get_max());
+}
+
+static PyObject *_wrap_gv_texture_cache_get_used(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_texture_cache_get_used"))
+ return NULL;
+ return PyInt_FromLong(gv_texture_cache_get_used());
+}
+
+static PyObject *_wrap_gv_texture_cache_set_max(PyObject *self, PyObject *args) {
+ int new_max;
+
+ if (!PyArg_ParseTuple(args, "i:gv_texture_cache_set_max", &new_max))
+ return NULL;
+ gv_texture_cache_set_max(new_max);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_build_skirt(PyObject *self, PyObject *args) {
+ PyObject *raster;
+ double base_z;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_build_skirt", &PyGtk_Type, &raster, &base_z))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_build_skirt(GV_RASTER_LAYER(PyGtk_Get(raster)), base_z));
+}
+
+static PyObject *_wrap_gtk_color_well_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gtk_color_well_get_type"))
+ return NULL;
+ return PyInt_FromLong(gtk_color_well_get_type());
+}
+
+static PyObject *_wrap_gtk_color_well_new(PyObject *self, PyObject *args) {
+ char *title;
+
+ if (!PyArg_ParseTuple(args, "s:gtk_color_well_new", &title))
+ return NULL;
+ return PyGtk_New((GtkObject *)gtk_color_well_new(title));
+}
+
+static PyObject *_wrap_gtk_color_well_set_d(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ double r, g, b, a;
+
+ if (!PyArg_ParseTuple(args, "O!dddd:gtk_color_well_set_d", &PyGtk_Type, &cwell, &r, &g, &b, &a))
+ return NULL;
+ gtk_color_well_set_d(GTK_COLOR_WELL(PyGtk_Get(cwell)), r, g, b, a);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gtk_color_well_set_i8(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ int r, g, b, a;
+
+ if (!PyArg_ParseTuple(args, "O!iiii:gtk_color_well_set_i8", &PyGtk_Type, &cwell, &r, &g, &b, &a))
+ return NULL;
+ gtk_color_well_set_i8(GTK_COLOR_WELL(PyGtk_Get(cwell)), r, g, b, a);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gtk_color_well_set_i16(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ int r, g, b, a;
+
+ if (!PyArg_ParseTuple(args, "O!iiii:gtk_color_well_set_i16", &PyGtk_Type, &cwell, &r, &g, &b, &a))
+ return NULL;
+ gtk_color_well_set_i16(GTK_COLOR_WELL(PyGtk_Get(cwell)), r, g, b, a);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gtk_color_well_set_use_alpha(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ int use_alpha;
+
+ if (!PyArg_ParseTuple(args, "O!i:gtk_color_well_set_use_alpha", &PyGtk_Type, &cwell, &use_alpha))
+ return NULL;
+ gtk_color_well_set_use_alpha(GTK_COLOR_WELL(PyGtk_Get(cwell)), use_alpha);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gtk_color_well_set_continuous(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ int update_continuous;
+
+ if (!PyArg_ParseTuple(args, "O!i:gtk_color_well_set_continuous", &PyGtk_Type, &cwell, &update_continuous))
+ return NULL;
+ gtk_color_well_set_continuous(GTK_COLOR_WELL(PyGtk_Get(cwell)), update_continuous);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gtk_color_well_set_title(PyObject *self, PyObject *args) {
+ PyObject *cwell;
+ char *title;
+
+ if (!PyArg_ParseTuple(args, "O!s:gtk_color_well_set_title", &PyGtk_Type, &cwell, &title))
+ return NULL;
+ gtk_color_well_set_title(GTK_COLOR_WELL(PyGtk_Get(cwell)), title);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_autopan_tool_get_type(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_autopan_tool_get_type"))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_get_type());
+}
+
+static PyObject *_wrap_gv_autopan_tool_new(PyObject *self, PyObject *args) {
+ if (!PyArg_ParseTuple(args, ":gv_autopan_tool_new"))
+ return NULL;
+ return PyGtk_New((GtkObject *)gv_autopan_tool_new());
+}
+
+static PyObject *_wrap_gv_autopan_tool_play(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_play", &PyGtk_Type, &tool))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_play(GV_AUTOPAN_TOOL(PyGtk_Get(tool))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_pause(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_pause", &PyGtk_Type, &tool))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_pause(GV_AUTOPAN_TOOL(PyGtk_Get(tool))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_stop(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_stop", &PyGtk_Type, &tool))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_stop(GV_AUTOPAN_TOOL(PyGtk_Get(tool))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_speed(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ double speed;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_autopan_tool_set_speed", &PyGtk_Type, &tool, &speed))
+ return NULL;
+ return PyFloat_FromDouble(gv_autopan_tool_set_speed(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), speed));
+}
+
+static PyObject *_wrap_gv_autopan_tool_get_speed(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_speed", &PyGtk_Type, &tool))
+ return NULL;
+ return PyFloat_FromDouble(gv_autopan_tool_get_speed(GV_AUTOPAN_TOOL(PyGtk_Get(tool))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_location(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ double x, y, z;
+
+ if (!PyArg_ParseTuple(args, "O!ddd:gv_autopan_tool_set_location", &PyGtk_Type, &tool, &x, &y, &z))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_location(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), x, y, z));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_overlap(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ double overlap;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_autopan_tool_set_overlap", &PyGtk_Type, &tool, &overlap))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_overlap(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), overlap));
+}
+
+static PyObject *_wrap_gv_autopan_tool_get_overlap(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_get_overlap", &PyGtk_Type, &tool))
+ return NULL;
+ return PyFloat_FromDouble(gv_autopan_tool_get_overlap(GV_AUTOPAN_TOOL(PyGtk_Get(tool))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_block_x_size(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ double block_x_size;
+ int mode;
+
+ if (!PyArg_ParseTuple(args, "O!di:gv_autopan_tool_set_block_x_size", &PyGtk_Type, &tool, &block_x_size, &mode))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_block_x_size(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), block_x_size, mode));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_x_resolution(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ double resolution;
+
+ if (!PyArg_ParseTuple(args, "O!d:gv_autopan_tool_set_x_resolution", &PyGtk_Type, &tool, &resolution))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_x_resolution(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), resolution));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_standard_path(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ int path_type;
+
+ if (!PyArg_ParseTuple(args, "O!i:gv_autopan_tool_set_standard_path", &PyGtk_Type, &tool, &path_type))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_standard_path(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), path_type));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_lines_path(PyObject *self, PyObject *args) {
+ PyObject *tool, *lines;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_autopan_tool_set_lines_path", &PyGtk_Type, &tool, &PyGtk_Type, &lines))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_lines_path(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), GV_SHAPES(PyGtk_Get(lines))));
+}
+
+static PyObject *_wrap_gv_autopan_tool_clear_trail(PyObject *self, PyObject *args) {
+ PyObject *tool;
+
+ if (!PyArg_ParseTuple(args, "O!:gv_autopan_tool_clear_trail", &PyGtk_Type, &tool))
+ return NULL;
+ gv_autopan_tool_clear_trail(GV_AUTOPAN_TOOL(PyGtk_Get(tool)));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_trail_color(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+ double red, green, blue, alpha;
+
+ if (!PyArg_ParseTuple(args, "O!O!dddd:gv_autopan_tool_set_trail_color", &PyGtk_Type, &tool, &PyGtk_Type, &view, &red, &green, &blue, &alpha))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_trail_color(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view)), red, green, blue, alpha));
+}
+
+static PyObject *_wrap_gv_autopan_tool_set_trail_mode(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+ int trail_mode;
+
+ if (!PyArg_ParseTuple(args, "O!O!i:gv_autopan_tool_set_trail_mode", &PyGtk_Type, &tool, &PyGtk_Type, &view, &trail_mode))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_set_trail_mode(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view)), trail_mode));
+}
+
+static PyObject *_wrap_gv_autopan_tool_save_trail_tiles(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ const char *basename;
+
+ if (!PyArg_ParseTuple(args, "O!s:gv_autopan_tool_save_trail_tiles", &PyGtk_Type, &tool, &basename))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_save_trail_tiles(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), basename));
+}
+
+static PyObject *_wrap_gv_autopan_tool_load_trail_tiles(PyObject *self, PyObject *args) {
+ PyObject *tool;
+ const char *basename;
+ int num_trail_tiles;
+
+ if (!PyArg_ParseTuple(args, "O!si:gv_autopan_tool_load_trail_tiles", &PyGtk_Type, &tool, &basename, &num_trail_tiles))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_load_trail_tiles(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), basename, num_trail_tiles));
+}
+
+static PyObject *_wrap_gv_autopan_tool_register_view(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+ int can_resize, can_reposition, trail_mode;
+
+ if (!PyArg_ParseTuple(args, "O!O!iii:gv_autopan_tool_register_view", &PyGtk_Type, &tool, &PyGtk_Type, &view, &can_resize, &can_reposition, &trail_mode))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_register_view(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view)), can_resize, can_reposition, trail_mode));
+}
+
+static PyObject *_wrap_gv_autopan_tool_remove_view(PyObject *self, PyObject *args) {
+ PyObject *tool, *view;
+
+ if (!PyArg_ParseTuple(args, "O!O!:gv_autopan_tool_remove_view", &PyGtk_Type, &tool, &PyGtk_Type, &view))
+ return NULL;
+ return PyInt_FromLong(gv_autopan_tool_remove_view(GV_AUTOPAN_TOOL(PyGtk_Get(tool)), GV_VIEW_AREA(PyGtk_Get(view))));
+}
+
Added: packages/openev/branches/upstream/current/pymod/gvogrdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvogrdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvogrdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,228 @@
+##############################################################################
+# $Id: gvogrdlg.py,v 1.5 2003/09/09 15:18:46 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: OGR Layer Selection and Loading Dialog.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvogrdlg.py,v $
+# Revision 1.5 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.4 2003/01/07 14:56:02 warmerda
+# Removed print statement.
+#
+# Revision 1.3 2003/01/07 03:37:53 warmerda
+# lots of upgrades
+#
+# Revision 1.2 2003/01/06 22:36:47 warmerda
+# Added prototype ExecuteSQL() support
+#
+# Revision 1.1 2003/01/06 21:40:19 warmerda
+# New
+#
+#
+
+from gtk import *
+import gview
+import os.path
+import gvhtml
+import ogr
+
+
+class GvOGRDlg(GtkWindow):
+ def __init__(self, ds, viewwindow):
+ GtkWindow.__init__(self)
+ self.set_title('Vector Layer Selection')
+ self.set_usize(500, 500)
+ self.set_border_width(3)
+ self.set_policy(TRUE,TRUE,FALSE)
+ self.connect('delete-event',self.close)
+ shell = GtkVBox(homogeneous=FALSE,spacing=3)
+ self.add(shell)
+ gvhtml.set_help_topic(self, "veclayerselect.html" );
+
+ # Layer list
+ layerbox = GtkScrolledWindow()
+ shell.pack_start(layerbox)
+ layerlist = GtkCList(cols=2)
+
+ layerbox.add_with_viewport(layerlist)
+ layerlist.set_shadow_type(SHADOW_NONE)
+ layerlist.set_selection_mode(SELECTION_SINGLE)
+ layerlist.set_row_height(30)
+ layerlist.set_column_width(0, 24)
+ #layerlist.connect('select-row', self.layer_selected)
+ layerlist.connect('button-press-event', self.list_clicked)
+
+ # Clip to view?
+
+ hbox = GtkHBox(homogeneous=FALSE)
+ shell.pack_start( hbox, expand=FALSE )
+
+ self.clip_to_view_btn = GtkCheckButton()
+ hbox.pack_start( self.clip_to_view_btn, expand=FALSE )
+
+ hbox.pack_start( GtkLabel('Clip To View' ), expand=FALSE )
+
+ # SQL Box.
+
+ hbox = GtkHBox(homogeneous=FALSE, spacing=3)
+ shell.pack_start( hbox,expand=FALSE )
+
+ sql_button = GtkButton('Execute SQL:')
+ sql_button.connect('clicked', self.execute_sql)
+ hbox.pack_start(sql_button, expand=FALSE)
+
+ self.sql_cmd = GtkEntry()
+ hbox.pack_start(self.sql_cmd,expand=TRUE)
+
+ # buttons
+ button_box = GtkHButtonBox()
+ button_box.set_layout_default(BUTTONBOX_START)
+ ok_button = GtkButton('Accept')
+ ok_button.connect('clicked', self.accept)
+ loadall_button = GtkButton('Load All')
+ loadall_button.connect('clicked', self.load_all)
+ cancel_button = GtkButton('Cancel')
+ cancel_button.connect('clicked', self.close)
+ help_button = GtkButton('Help')
+ help_button.connect('clicked', self.help_cb)
+ button_box.pack_start(ok_button, expand=FALSE)
+ button_box.pack_start(loadall_button, expand=FALSE)
+ button_box.pack_start(cancel_button, expand=FALSE)
+ button_box.pack_start(help_button, expand=FALSE)
+ shell.pack_start(button_box,expand=FALSE)
+
+ self.connect('realize', self.realize)
+
+ self.sel_pixmap = \
+ GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'ck_on_l.xpm'))
+ self.not_sel_pixmap = \
+ GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'ck_off_l.xpm'))
+
+ shell.show_all()
+
+ self.ds = ds
+ self.viewwindow = viewwindow
+ self.layerlist = layerlist
+
+ layer_count = ds.GetLayerCount()
+ self.layer_names = []
+ self.layer_sel = []
+ for i in range(layer_count):
+ layer = ds.GetLayer( i )
+ self.layer_names.append( layer.GetName() )
+ self.layer_sel.append( 0 )
+
+ self.show_all()
+
+ def help_cb(self,*args):
+ gvhtml.LaunchHTML( "veclayerselect.html" );
+
+ def close(self,*args):
+ self.ds.Destroy()
+ self.hide()
+ return TRUE
+
+ def load_all(self,*args):
+ for i in range(len(self.layer_sel)):
+ self.layer_sel[i] = 1
+ self.accept()
+
+ def accept(self,*args):
+
+ if self.clip_to_view_btn.get_active():
+ xmin, ymin, xmax, ymax = self.viewwindow.viewarea.get_extents()
+
+ wkt = 'POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))' % \
+ (xmin,ymax,xmax,ymax,xmax,ymin,xmin,ymin,xmin,ymax)
+ rect = ogr.CreateGeometryFromWkt( wkt )
+ else:
+ rect = None
+
+ for i in range(len(self.layer_sel)):
+ if self.layer_sel[i]:
+ layer = self.ds.GetLayer( i )
+
+ if rect is not None:
+ layer.SetSpatialFilter( rect )
+
+ self.viewwindow.file_open_ogr_by_layer( layer )
+
+ if rect is not None:
+ layer.SetSpatialFilter( None )
+
+ if rect is not None:
+ rect.Destroy()
+
+ self.close()
+
+ def realize(self, widget):
+ lst = self.layerlist
+
+ lst.freeze()
+ lst.clear()
+
+ i = 0
+ for entry in self.layer_names:
+ lst.append(('', entry))
+
+ lst.set_pixmap(i, 0, self.not_sel_pixmap)
+
+ i = i + 1
+
+ lst.thaw()
+
+ def list_clicked(self, lst, event):
+ row, col = lst.get_selection_info(int(event.x), int(event.y))
+ lst.emit_stop_by_name('button-press-event')
+
+ if event.type is GDK._2BUTTON_PRESS:
+ for i in range(len(self.layer_sel)):
+ self.layer_sel[i] = 0
+
+ self.layer_sel[row] = 1
+ self.accept()
+ else:
+ self.layer_sel[row] = not self.layer_sel[row]
+
+ if self.layer_sel[row]:
+ lst.set_pixmap(row, 0, self.sel_pixmap)
+ else:
+ lst.set_pixmap(row, 0, self.not_sel_pixmap)
+
+ def execute_sql(self, *args):
+
+ statement = self.sql_cmd.get_text()
+
+ layer = self.ds.ExecuteSQL( statement )
+
+ if layer is not None:
+ self.viewwindow.file_open_ogr_by_layer( layer )
+
+ self.ds.ReleaseResultsSet( layer )
Added: packages/openev/branches/upstream/current/pymod/gvogrfs.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvogrfs.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvogrfs.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,349 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gvogrfs.py,v 1.7 2003/05/08 16:19:39 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: Classes for building, and parsing OGR Feature Style Specifications
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvogrfs.py,v $
+# Revision 1.7 2003/05/08 16:19:39 pgs
+# made params safe if value missing
+#
+# Revision 1.6 2001/04/29 16:27:33 pgs
+# added has_part() to OGRFeatureStyle class
+#
+# Revision 1.5 2001/04/23 21:21:28 warmerda
+# added OGRFeatureStyleParam.set() and OGRFeatureStyleParm.set_parm
+#
+# Revision 1.4 2001/04/19 22:07:53 warmerda
+# avoid use of +=
+#
+# Revision 1.3 2001/04/16 13:50:35 warmerda
+# Paul added OGRFeatureStyle class
+#
+# Revision 1.2 2001/04/09 18:37:46 warmerda
+# improved color handling
+#
+# Revision 1.1 2001/03/21 22:40:33 warmerda
+# New
+#
+#
+
+import gview
+import string
+
+def gv_to_ogr_color( rgba ):
+ if len(rgba) == 3:
+ rgba = (rgba[0], rgba[1], rgba[2], 1.0)
+
+ red = min(255,max(0,int(rgba[0] * 255 + 0.5)))
+ green = min(255,max(0,int(rgba[1] * 255 + 0.5)))
+ blue = min(255,max(0,int(rgba[2] * 255 + 0.5)))
+ alpha = min(255,max(0,int(rgba[3] * 255 + 0.5)))
+
+ color = '#%02X%02X%02X' % (red, green, blue)
+ if alpha != 255:
+ color = color + '%02X' % alpha
+
+ return color
+
+def ogr_to_gv_color( ogr_color ):
+ if len(ogr_color) == 9:
+ return (int(ogr_color[1:3],16) / 255.0,
+ int(ogr_color[3:5],16) / 255.0,
+ int(ogr_color[5:7],16) / 255.0,
+ int(ogr_color[7:9],16) / 255.0)
+ elif len(ogr_color) == 7:
+ return (int(ogr_color[1:3],16) / 255.0,
+ int(ogr_color[3:5],16) / 255.0,
+ int(ogr_color[5:7],16) / 255.0,
+ 1.0)
+ else:
+ return (0,0,0,1.0)
+
+class OGRFeatureStyleParam:
+
+ def __init__(self, parm=None):
+ if parm is not None:
+ self.parse(parm)
+
+ def set(self, name, value, role='string_value', units=''):
+ self.param_name = name
+ self.units = units
+ self.value = value
+ self.role = role
+
+ def parse(self, parm):
+ (key,value) = string.split(parm,':',1)
+ self.param_name = key
+
+ #trap params that have no value
+ if len(value) == 0:
+ self.role='numeric_value'
+ self.value = ''
+ self.units = ''
+ return
+
+ # Handle units
+ self.units = ''
+ if value[-2:] in ['px','pt','mm','cm','in']:
+ self.units = value[-2:]
+ value = value[:-2]
+ elif value[-1:] == 'g':
+ self.units = value[-1:]
+ value = value[:-1]
+
+ if value[0] == '"':
+ if value[-1:] != '"':
+ raise ValueError, 'unterminated literal - ' + parm
+
+ self.role = 'string_value'
+ self.value = value[1:-1]
+
+ elif value[0] == '{':
+ if value[-1:] != '}':
+ raise ValueError, 'unterminated fieldname - ' + parm
+
+ self.role = 'field_name'
+ self.value = value[1:-1]
+
+ else:
+ self.role = 'numeric_value'
+ self.value = value
+
+ def unparse(self):
+ result = self.param_name + ':'
+ if self.role == 'numeric_value':
+ result = result + self.value
+ elif self.role == 'field_name':
+ result = result + '{'+self.value+'}'
+ else:
+ result = result + '"'+self.value+'"'
+
+ result = result + self.units
+
+ return result
+
+ def __str__(self):
+ result = ' parm=%s role=%12s value=%-20s' \
+ % (self.param_name, self.role, self.value)
+ if len(self.units) > 0:
+ result = result + ' units:'+self.units
+
+ return result
+
+class OGRFeatureStylePart:
+ def __init__(self):
+ pass
+
+ def parse(self, style_part):
+
+ style_part = string.strip(style_part)
+ i = string.find(style_part, '(')
+ if i == -1:
+ raise ValueError, 'no args to tool name - ' + style_part
+
+ self.tool_name = string.upper(style_part[:i])
+ if self.tool_name not in [ 'PEN', 'BRUSH', 'SYMBOL', 'LABEL' ]:
+ raise ValueError, 'unrecognised tool name - ' + style_part
+
+ if style_part[-1:] != ')':
+ raise ValueError, 'missing end bracket - ' + style_part
+
+ tool_parms = style_part[i+1:-1]
+
+ parms_list = []
+ i = 0
+ last_i = 0
+ in_literal = 0
+ while i < len(tool_parms):
+
+ if tool_parms[i] == '"':
+ if not in_literal or i == 0 or tool_parms[i-1] != '\\':
+ in_literal = not in_literal
+
+ if not in_literal and tool_parms[i] == ',':
+ parms_list.append( string.strip(tool_parms[last_i:i]) )
+ i = i + 1
+ last_i = i
+
+ i = i + 1
+
+ if in_literal:
+ raise ValueError, 'unterminated string literal - ' + style_part
+
+ parms_list.append(string.strip(tool_parms[last_i:]))
+ self.parms = {}
+ for parm_literal in parms_list:
+ parm = OGRFeatureStyleParam(parm_literal)
+ self.parms[parm.param_name] = parm
+
+ def unparse(self):
+ result = self.tool_name + '('
+ first = 1
+ for key in self.parms.keys():
+ if first:
+ first = 0
+ else:
+ result = result + ','
+
+ result = result + self.parms[key].unparse()
+ result = result + ')'
+
+ return result
+
+ def set_parm(self, parm_obj ):
+ self.parms[parm_obj.param_name] = parm_obj
+
+ def get_parm(self, parm_name, default_value=None):
+ if self.parms.has_key(parm_name):
+ return self.parms[parm_name].value
+ else:
+ return default_value
+
+ def get_color(self, default_value=None):
+ color = self.get_parm('c', None)
+ if color is None or color[0] != '#':
+ return default_value
+ else:
+ return ogr_to_gv_color( color )
+
+ def __str__(self):
+ result = 'Tool:%s\n' % self.tool_name
+ for key in self.parms.keys():
+ parm = self.parms[key]
+ result = result + ' %s\n' % str(parm)
+
+ return result
+
+class OGRFeatureStyle:
+ """
+ Encapulation of an OGR Feature Style
+
+ This object keeps one tool of each type in a dictionary and allows parsing
+ and unparsing of the ogrfs property that would be stored on a vector
+ layer. The semi-colon separator is used for parts.
+ """
+ def __init__(self, style=None):
+ self.parts = {}
+
+ if style is not None:
+ self.parse(style)
+
+ def parse(self, style):
+ """
+ parse a style into style parts by breaking it apart at any
+ ';' not within '"'
+ """
+ #TODO: check to see if it is of type string
+ # or can be turned into a string as well
+ if style is None:
+ return
+
+ style = string.strip(style)
+ if style == '':
+ print 'empty style'
+ return
+ in_quote = 0
+ part_start = 0
+ for i in range(len(style)):
+ char = style[i:i+1]
+ if char == chr(34):
+ in_quote = not in_quote
+ if not in_quote and char == ";":
+ part = style[part_start:i]
+ self.parse_part(part)
+ part_start = i + 1
+ #check for the last one ...
+ if part_start != 0 or len(self.parts) == 0:
+ part = style[part_start:]
+ self.parse_part(part)
+
+ def parse_part(self, part):
+ """
+ parse a single part
+ """
+ ogr_part = OGRFeatureStylePart()
+ try:
+ ogr_part.parse(part)
+ self.add_part(ogr_part)
+ except:
+ print 'Invalid part in feature sytle definition'
+
+ def unparse(self):
+ """
+ compose the feature style into a string
+ """
+ result = ''
+ sep = ''
+ for key in self.parts.keys():
+ part = self.parts[key]
+ result = result + sep + part.unparse()
+ sep = ";"
+ return result
+
+ def add_part(self, ogr_part):
+ """
+ add an OGRFeatureStylePart
+ """
+ if issubclass(ogr_part.__class__, OGRFeatureStylePart):
+ self.parts[ogr_part.tool_name] = ogr_part
+ else:
+ raise TypeError, 'ogr_part must be an OGRFeatureStylePart'
+
+ def get_part(self, part_name, default = None):
+ if self.parts.has_key(part_name):
+ return self.parts[part_name]
+ else:
+ return default
+
+ def remove_part(self, part_name):
+ if self.parts.has_key(part_name):
+ del self.parts[part_name]
+
+ def has_part(self, part_name):
+ return self.parts.has_key(part_name)
+
+ def __str__(self):
+ result = 'Feature Style Definition:\n'
+ for key in self.parts.keys():
+ part = self.parts[key]
+ result = result + ' %s\n' % str(part)
+
+ return result
+
+
+if __name__ == '__main__':
+
+ fsp = OGRFeatureStylePart()
+
+ while 1:
+ line = raw_input('OGR FS:')
+ if len(line) == 0:
+ sys.exit(0)
+
+ fsp.parse( line )
+ print fsp
+ print fsp.unparse()
+
+
Property changes on: packages/openev/branches/upstream/current/pymod/gvogrfs.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/gvogrfsgui.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvogrfsgui.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvogrfsgui.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,554 @@
+###############################################################################
+# $Id: gvogrfsgui.py,v 1.6 2001/09/17 15:27:03 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: GUI Widgets for displaying and manipulating OGRFS rendering
+# descriptions.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvogrfsgui.py,v $
+# Revision 1.6 2001/09/17 15:27:03 pgs
+# updated to work with new ColorButton
+#
+# Revision 1.5 2001/07/01 03:06:51 pgs
+# hacked to get manual change of offsets working
+#
+# Revision 1.4 2001/05/05 18:28:14 pgs
+# added interactive updates plus reverse dy offset
+#
+# Revision 1.3 2001/05/04 02:56:56 pgs
+# a couple of bug fixes plus added label offsets
+#
+# Revision 1.2 2001/04/24 14:24:02 warmerda
+# added support for applying text indirectly
+#
+# Revision 1.1 2001/04/23 21:20:19 warmerda
+# New
+#
+#
+
+from gtk import *
+from string import *
+from gvsignaler import *
+import gvutils
+import gview
+import pgu
+import sys
+import pgucolorsel
+import pgufont
+import pgucombo
+import pgucolor
+import pgumenu
+import gvogrfs
+
+#map display names to ogr symbol names and an icon (for an image menu)
+ogrfs_symbols = {
+ 'cross' : ('"ogr-sym-0"', 'sym_cross.xpm'),
+ 'x' : ('"ogr-sym-1"', 'sym_x.xpm'),
+ 'unfilled circle' : ('"ogr-sym-2"', 'sym_circle.xpm'),
+ 'filled circle' : ('"ogr-sym-3"', 'sym_filled_circle.xpm'),
+ 'unfilled square' : ('"ogr-sym-4"', 'sym_square.xpm'),
+ 'filled square' : ('"ogr-sym-5"', 'sym_filled_square.xpm'),
+ 'unfilled triangle' : ('"ogr-sym-6"', 'sym_triangle.xpm'),
+ 'filled triangle' : ('"ogr-sym-7"', 'sym_filled_triangle.xpm'),
+ 'unfilled star' : ('"ogr-sym-8"', 'sym_star.xpm'),
+ 'filled star' : ('"ogr-sym-9"', 'sym_filled_star.xpm'),
+ 'vertical bar' : ('"ogr-sym-10"','sym_vertical.xpm')
+ }
+
+ogrfs_symbol_names = ['cross', 'x',
+ 'unfilled circle', 'filled circle',
+ 'unfilled square', 'filled square',
+ 'unfilled triangle', 'filled triangle',
+ 'unfilled star', 'filled star',
+ 'vertical bar']
+
+
+###############################################################################
+class GvLabelStyle(GtkVBox, Signaler):
+
+ ###########################################################################
+ def __init__(self, spacing=10, text_entry=FALSE, layer=None,
+ label_field = TRUE, enable_offsets=FALSE, interactive=FALSE):
+ GtkVBox.__init__(self,spacing=spacing)
+
+ self.ogrfs_obj = None
+ self.layer = layer
+ self.shape_obj = None
+ self.text_entry = text_entry
+ self.enable_offsets = enable_offsets
+ self.interactive = interactive
+ self.updating = 0
+ self.old_list = []
+
+ self.set_border_width(10)
+ self.create_gui()
+
+ self.connect('unrealize', self.close)
+
+ self.publish('ogrfs-changed')
+ self.publish('apply-text-to-field')
+
+ self.gui_update()
+ self.show_all()
+
+ if not label_field:
+ self.field_label.hide()
+ self.label_field.hide()
+
+ ###########################################################################
+ def close( self, *args ):
+ pass
+
+ ###########################################################################
+ def set_ogrfs( self, ogrfs_obj, layer = None, fontlist = None,
+ shape_obj = None ):
+
+ if layer is not None:
+ self.layer = layer
+
+ if ogrfs_obj is None:
+ ogrfs_obj = gvogrfs.OGRFeatureStylePart()
+ font = pgufont.XLFDFontSpec()
+ default_font = gview.get_preference('default-font')
+ if default_font is None:
+ font.set_font_part('Family', 'fixed')
+ else:
+ font.parse_font_spec(default_font)
+ if self.enable_offsets:
+ dx = self.x_offset.get_value_as_float()
+ dy = self.y_offset.get_value_as_float()
+ ogrfs_obj.parse('LABEL(t:"",f:"%s",c:#88FF88)' % font)
+
+ self.ogrfs_obj = ogrfs_obj
+ self.shape_obj = shape_obj
+
+ self.gui_update()
+
+ ###########################################################################
+ def create_gui(self):
+
+ table = GtkTable()
+ table.set_row_spacings(3)
+ table.set_col_spacings(3)
+ self.pack_start(table)
+
+ # collect candidate field names from the schema.
+ fnlist = [ 'disabled' ]
+
+ # Field Name
+ self.field_label = GtkLabel('Label Field:')
+ table.attach(self.field_label, 0, 1, 0, 1,
+ xoptions=SHRINK, yoptions=SHRINK)
+ self.label_field = pgucombo.pguCombo()
+ self.label_field.set_popdown_strings( fnlist )
+ self.label_field.entry.connect('changed', self.label_change_cb)
+ table.attach(self.label_field, 1, 3, 0, 1,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+ # Create Color control.
+ table.attach(GtkLabel('Color:'), 0, 1, 1, 2,
+ xoptions=SHRINK, yoptions=SHRINK)
+ self.label_color = pgucolorsel.ColorControl('Label Color',
+ self.label_change_cb)
+ table.attach(self.label_color, 1, 3, 1, 2,
+ yoptions=SHRINK)
+
+ # Font
+ table.attach(GtkLabel('Font:'), 0, 1, 2, 3,
+ xoptions=SHRINK, yoptions=SHRINK)
+ self.label_font = pgufont.pguFontControl()
+ self.label_font.subscribe('font-changed', self.label_change_cb)
+ table.attach(self.label_font, 1, 2, 2, 3,
+ xoptions=SHRINK)
+
+ #######################################################################
+ # Add Text entry/edit
+ if self.text_entry:
+ table.attach(GtkLabel('Text:'), 0, 1, 3, 4,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+ self.text_entry = GtkEntry()
+ self.text_entry.connect('activate',self.text_change_cb)
+ if self.interactive:
+ self.text_entry.connect('changed', self.text_change_cb)
+ else:
+ self.text_entry.connect('focus-out-event',self.text_change_cb)
+ table.attach(self.text_entry, 1, 3, 3, 4)
+ else:
+ self.text_entry = None
+
+ if self.enable_offsets:
+ #Label offsets
+ table.attach(GtkLabel('Label X Offset:'), 0, 1, 4, 5,
+ xoptions=SHRINK, yoptions=SHRINK)
+ spin_adjust = GtkAdjustment(value=0.0, lower=-20.0, upper=20.0, step_incr=1.0)
+ self.x_offset = GtkSpinButton(spin_adjust)
+ self.x_offset.set_editable(TRUE)
+ self.x_offset.set_digits(1)
+ self.x_offset.set_usize(75, 0)
+ self.x_offset.connect('changed', self.label_change_cb)
+ table.attach(self.x_offset, 1, 3, 4, 5,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+ #Label offsets
+ table.attach(GtkLabel('Label Y Offset:'), 0, 1, 5, 6,
+ xoptions=SHRINK, yoptions=SHRINK)
+ spin_adjust = GtkAdjustment(value=0.0, lower=-20.0, upper=20.0, step_incr=1.0)
+ self.y_offset = GtkSpinButton(spin_adjust)
+ self.y_offset.set_editable(TRUE)
+ self.y_offset.set_digits(1)
+ self.y_offset.set_usize(75, 0)
+ self.y_offset.connect('changed', self.label_change_cb)
+ table.attach(self.y_offset, 1, 3, 5, 6,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+
+ ###########################################################################
+ def gui_update(self, *args):
+
+ self.updating = TRUE
+
+ # Update the field list.
+ fnlist = [ 'disabled' ]
+ if self.layer is not None:
+ schema = self.layer.get_parent().get_schema()
+ for item in schema:
+ fnlist.append( item[0] )
+
+ if fnlist != self.old_list:
+ self.label_field.set_popdown_strings( fnlist )
+ self.old_list = fnlist
+
+ self.label_field.entry.delete_text(0,-1)
+
+ if self.ogrfs_obj is None:
+ self.label_field.entry.insert_text('disabled')
+ self.label_color.set_color( (0.5, 1.0, 0.5, 1.0) )
+ if self.enable_offsets:
+ self.x_offset.set_value(0.0)
+ self.y_offset.set_value(0.0)
+ else:
+ font = pgufont.XLFDFontSpec()
+ font_spec = self.ogrfs_obj.parms['f'].value
+ if font_spec is not None:
+ font.parse_font_spec(font_spec)
+ else:
+ default_font = gview.get_preference('default-font')
+ if default_font is None:
+ font.set_font_part('Family', 'fixed')
+ else:
+ font.parse_font_spec(default_font)
+ self.label_font.set_font(str(font))
+
+ tparm = self.ogrfs_obj.parms['t']
+ if tparm.role == 'field_name':
+ self.label_field.entry.insert_text(tparm.value)
+ if self.shape_obj is not None:
+ text_value = self.shape_obj.get_property(tparm.value,'')
+ else:
+ text_value = ''
+ else:
+ self.label_field.entry.insert_text('disabled')
+ text_value = tparm.value
+
+ color = self.ogrfs_obj.get_color((0.5, 1.0, 0.5, 1.0))
+ self.label_color.set_color( color )
+
+ if self.text_entry is not None:
+ self.text_entry.set_text(text_value)
+ #self.text_entry.set_sensitive(tparm.role != 'field_name')
+
+ if self.enable_offsets:
+ try:
+ dx = float(self.ogrfs_obj.get_parm('dx'))
+ self.x_offset.set_value(dx)
+ except:
+ dx = None
+
+ if dx is None:
+ dx = 0.0
+
+ try:
+ dy = float(self.ogrfs_obj.get_parm('dy'))
+ self.y_offset.set_value(-dy)
+ except:
+ dy = None
+
+ if dy is None:
+ dy = 0.0
+
+ #update the widgets
+
+
+ self.updating = FALSE
+
+ ###########################################################################
+ # Handle updates to the raw text. Normally we just turn this over to
+ # the generic label_change_cb(), but if we have field indirection in
+ # operation, then we instead emit a signal offering the text to the
+ # application to apply to the shape.
+
+ def text_change_cb(self, *args):
+ field_name = self.label_field.entry.get_chars(0,-1)
+ if field_name == 'disabled' or len(field_name) == 0:
+ self.label_change_cb()
+ return
+
+ #this shouldn't happen :)
+ val = ''
+ if self.text_entry is not None:
+ val = self.text_entry.get_text()
+
+ self.notify( 'apply-text-to-field',
+ field_name, val )
+ self.gui_update()
+
+ ###########################################################################
+ # Handle updates to the label font.
+
+ def label_change_cb(self, *args):
+ if self.layer is None or self.updating:
+ return
+
+ font = self.label_font.get_font()
+ field_name = self.label_field.entry.get_chars(0,-1)
+ text_value = ''
+ if self.text_entry is not None:
+ text_value = self.text_entry.get_text()
+
+ color = self.label_color.current_color
+ color = gvogrfs.gv_to_ogr_color( color )
+
+ import string
+ x_off = ''
+ y_off = ''
+
+
+
+ if self.enable_offsets:
+ #handle user editing of the values in the x and y offsets.
+ #something odd happens when listening to the 'changed' signal
+ #of the spin box, the text value is difference from the float
+ #value, even if the values should match. This hack forces the
+ #spin buttons to update the value and exits because this
+ #will be called again right away
+ x = self.x_offset.get_value_as_float()
+ y = self.y_offset.get_value_as_float()
+ sx = self.x_offset.get_text()
+ sy = self.y_offset.get_text()
+ try:
+ if float(sx) != x:
+ self.x_offset.set_value(float(sx))
+ return
+ if float(sy) != y:
+ self.y_offset.set_value(float(sy))
+ return
+ except:
+ return
+ if 0.0 != x:
+ x_off = 'dx:%s,' % x
+
+ if 0.0 != y:
+ y_off = 'dy:%s,' % -y
+
+ if field_name == 'disabled' or len(field_name) == 0:
+ if text_value is not None:
+ ogrfs = 'LABEL(%s%st:\"%s\",f:"%s",c:%s)' % \
+ (x_off, y_off, text_value,font,color)
+ else:
+ ogrfs = None
+ else:
+ ogrfs = 'LABEL(%s%st:{%s},f:"%s",c:%s)' % \
+ (x_off, y_off, field_name, font, color)
+
+ if ogrfs is None:
+ self.ogrfs_obj = None
+ else:
+ self.ogrfs_obj = gvogrfs.OGRFeatureStylePart()
+ self.ogrfs_obj.parse( ogrfs )
+
+ self.gui_update()
+
+ self.notify('ogrfs-changed')
+
+ #
+ def set_sensitive(self, sensitive):
+ self.text_entry.set_sensitive(sensitive)
+
+ ###########################################################################
+ # Handle updates to the label font.
+ def text_input(self, keyval):
+ if keyval > 31 and keyval < 256 and self.text_entry is not None:
+ new_string = self.text_entry.get_text()
+ new_string = new_string + chr(keyval)
+ self.text_entry.set_text( new_string )
+
+ elif keyval == GDK.Return:
+ self.label_change_cb()
+
+ # add support for delete, etc, later.
+
+
+
+class GvSymbolStyle(GtkVBox, Signaler):
+ """
+ A generic embeddable widget for controlling the SYMBOL ogr feature style
+ on an arbitrary object (layer or shape).
+ """
+
+ def __init__(self, spacing=10, ogrfs_obj=None, layer=None):
+ """
+ Initialize the widget optionally setting the ogr object for which this
+ represents the SYMBOL feature style.
+ """
+ GtkVBox.__init__(self, spacing=spacing)
+ self.create_gui()
+
+ self.updating = FALSE
+ self.publish('ogrfs-changed')
+ self.set_ogrfs(ogrfs_obj, layer)
+
+ def create_gui(self):
+ """
+ create the widgets for this symbol
+ """
+
+ table = GtkTable()
+ table.set_row_spacings(3)
+ table.set_col_spacings(3)
+ self.pack_start(table)
+ #symbol color
+ table.attach(GtkLabel('Color: '), 0, 1, 0, 1,
+ xoptions=SHRINK, yoptions=SHRINK)
+ self.symbol_color = pgucolor.ColorButton((0.5, 1.0, 0.5, 1.0))
+ self.symbol_color.connect('color-set', self.color_change)
+ table.attach(self.symbol_color, 1, 2, 0, 1,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+ # Point symbol
+ table.attach(GtkLabel('Symbol:'), 0, 1, 1, 2,
+ xoptions=SHRINK, yoptions=SHRINK)
+ self.symbol_type = pgumenu.pguMenuFactory(MENU_FACTORY_OPTION_MENU)
+ entries = []
+ for i in range(len(ogrfs_symbol_names)):
+ sym_name = ogrfs_symbol_names[i]
+ sym_img = ogrfs_symbols[sym_name][1]
+ a = '<image:' + sym_img + '>' + sym_name
+ entries.append((a, None, self.symbol_change, ogrfs_symbols[sym_name][0]))
+
+ self.symbol_type.add_entries(entries)
+
+ self.symbol_type.set_usize(150, 30)
+ table.attach(self.symbol_type, 1, 4, 1, 2,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+ # Point size
+ table.attach(GtkLabel('Scale: '), 0, 1, 2, 3,
+ xoptions=SHRINK, yoptions=SHRINK)
+ spin_adjust = GtkAdjustment(value=1.0, lower=0.2,
+ upper=4.0, step_incr=0.1)
+ self.symbol_size = GtkSpinButton(spin_adjust)
+ self.symbol_size.set_editable(TRUE)
+ self.symbol_size.set_digits(1)
+ self.symbol_size.set_usize(75, 0)
+ self.symbol_size.connect('changed', self.scale_change)
+ table.attach(self.symbol_size, 1, 3, 2, 3,
+ xoptions=SHRINK, yoptions=SHRINK)
+
+
+
+ def gui_update(self, *args):
+ """
+ refresh the screen
+ """
+ #get the current values
+ if self.updating:
+ return
+
+ self.updating = TRUE
+
+ sym = int(self.ogrfs_obj.parms['id'].value[8:9])
+ color = gvogrfs.ogr_to_gv_color(self.ogrfs_obj.parms['c'].value)
+ try:
+ scale = float(self.ogrfs_obj.get_parm('s'))
+ except:
+ scale = None
+
+ if scale is None:
+ scale = 1.0
+
+ #update the widgets
+ self.symbol_type.set_history(sym)
+ self.symbol_color.set_color(color)
+ self.symbol_size.set_value(scale)
+
+ self.updating = FALSE
+
+ def set_ogrfs(self, ogrfs_obj, layer = None):
+ """
+ set the ogr feature specification from the shape object passed,
+ or from the layer if the shape has none, or provide a default
+ """
+
+ if ogrfs_obj is None:
+ ogrfs_obj = gvogrfs.OGRFeatureStylePart()
+ ogrfs_obj.parse('SYMBOL(id:"ogr-sym-0",c:#88FF88)')
+
+ self.ogrfs_obj = ogrfs_obj
+ self.layer = layer
+ self.gui_update()
+
+ def color_change(self, widget, *args):
+ """
+ """
+ print 'color_change(', widget, args, ')'
+ val = 'c:%s' % gvogrfs.gv_to_ogr_color(widget.get_color())
+ parm = gvogrfs.OGRFeatureStyleParam()
+ parm.parse(val)
+ self.ogrfs_obj.set_parm(parm)
+ self.notify('ogrfs-changed')
+
+ def scale_change(self, widget):
+ """
+ change the scale ... be careful as it may not exist beforehand
+ """
+ val = 's:%s' % widget.get_value_as_float()
+ parm = gvogrfs.OGRFeatureStyleParam()
+ parm.parse(val)
+ self.ogrfs_obj.set_parm(parm)
+ self.notify('ogrfs-changed')
+
+ def symbol_change(self, widget, symbol):
+ """
+ change the symbol
+ """
+ val = 'id:%s' % symbol
+ parm = gvogrfs.OGRFeatureStyleParam()
+ parm.parse(val)
+ self.ogrfs_obj.set_parm(parm)
+ self.notify('ogrfs-changed')
+
+
+
+pgu.gtk_register('GvLabelStyle',GvLabelStyle)
+pgu.gtk_register('GvSymbolStyle', GvSymbolStyle)
Added: packages/openev/branches/upstream/current/pymod/gvplot.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvplot.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvplot.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,752 @@
+#! /usr/bin/env python
+###############################################################################
+#
+# Project: OpenEV
+# Purpose: Implement the generic Plot function for simple internal plotting.
+# Author: Frank Warmerdam <warmerdam at pobox.com>
+# Gillian Walter <gwalter at atlsci.com>
+#
+###############################################################################
+# Copyright (c) 2001, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvplot.py,v $
+# Revision 1.21 2005/08/18 19:56:15 warmerda
+# Make dependence on pygtk optional.
+#
+# Revision 1.20 2005/08/01 09:31:27 andrey_kiselev
+# Use 'png' terminal type instead of 'png color' as of recent gnuplot.
+#
+# Revision 1.19 2004/11/01 16:18:44 gmwalter
+# Add option to return a layer.
+#
+# Revision 1.18 2004/09/26 01:36:52 warmerda
+# Raise runtime error if we can't find gnuplot.
+#
+# Revision 1.17 2004/08/31 21:02:13 gmwalter
+# Added ability to return a raster layer in plot3d.
+#
+# Revision 1.16 2004/06/15 20:30:15 gmwalter
+# Check in William's plot additions.
+#
+# Revision 1.15 2003/09/30 17:56:12 gmwalter
+# Update so that window title of plots can be set.
+#
+# Revision 1.14 2003/06/17 14:58:38 gmwalter
+# gvplot: changed so that graphs don't immediately disappear
+# in the gnuplot terminal case.
+# gvrasterpropdlg: fix so that user can go back to opaque white modulation
+# colour.
+#
+# Revision 1.13 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.12 2002/04/18 18:16:16 gmwalter
+# Windows bug fixes.
+#
+# Revision 1.11 2002/04/18 16:52:05 warmerda
+# ensure file closed before unlink
+#
+# Revision 1.10 2002/04/17 18:31:46 gmwalter
+# Fixed typos.
+#
+# Revision 1.9 2002/04/17 14:43:46 warmerda
+# improved logic for finding gnuplot executable
+#
+# Revision 1.8 2002/04/17 13:41:39 warmerda
+# rewritten to avoid use of Gnuplot.py
+#
+# Revision 1.7 2002/03/25 20:57:04 gmwalter
+# Add print capability to the plot window.
+#
+# Revision 1.5 2002/03/22 15:17:09 gmwalter
+# Added contour plot option to plot3d.
+#
+# Revision 1.4 2001/12/06 14:22:52 gmwalter
+# Added loop to plot3d to check for temporary file creation before
+# trying to open it (plot3d is much slower than plot).
+#
+# Revision 1.3 2001/11/29 02:46:48 warmerda
+# Gillian provided plot3d() extention
+#
+# Revision 1.2 2001/11/23 20:07:44 warmerda
+# Use os.tempnam() to prepare a name for the temporary file.
+#
+# Revision 1.1 2001/11/14 22:34:27 warmerda
+# New
+#
+#
+
+import Numeric
+
+try:
+ import pygtk
+ pygtk.require("1.2")
+except:
+ pass
+
+import gtk
+import os
+import string
+import GtkExtra
+import gvutils
+
+###############################################################################
+# plot()
+
+def plot( data=None, xaxis=None, yaxis=None, xmin=None, xmax=None,
+ ymin=None, ymax=None, title=None, cmds=None,
+ terminal = 'openev', output = None, wintitle=None,
+ datastyle = None, multiplot = False , multilabels = (),
+ multiopts = ()):
+ """plot(data [, xaxis=text] [,yaxis=text] [,title=text]
+ [, xmin=n] [, xmax=n] [, ymin=n] [, ymax=n]
+ [, cmds=cmd_list] [,terminal={"openev","gnuplot"}]
+ [, wintitle=text] [, datastyle=text]
+ [, multiplot = {True,False}] [, multilabels = list]
+ [, multiopts = list]
+ data -- data array to plot, should be 1-D set of Y data
+ or 2-D array with pairs of (x,y) values.
+ or 3-D array with pairs of (x,y,z) values '
+ or 2-D array with tuples of (x,y1,y2,...,yN) values.'
+ """
+
+ ###########################################################################
+ # Print usage() message if no options given.
+
+ if data is None:
+ print 'Usage: plot(data [, xaxis=text] [,yaxis=text] [,title=text] '
+ print ' [, xmin=n] [, xmax=n] [, ymin=n] [, ymax=n] '
+ print ' [, cmds=cmd_list] '
+ print ' [,terminal={"openev","gnuplot"}]'
+ print ' [,wintitle=text] [, datastyle=text] '
+ print ' [, multiplot = {True,False}]'
+ print ' [, multilabels = list] [, multiopts = list] )'
+ print ''
+ print ' data -- data array to plot, should be 1-D set of Y data'
+ print ' or 2-D array with pairs of (x,y) values.'
+ print ' or 3-D array with pairs of (x,y,z) values '
+ print ' or 2-D array with tuples of (x,y1,y2,...,yN) values.'
+ print ' for the last multiplot must be true, multilables is'
+ print ' a list of text labels for the graphs, and multiopts'
+ print ' is a list of gnuplot options to be added to the'
+ print ' individual graphs'
+ print ''
+ return
+
+ ###########################################################################
+ # Work out the shape of the data. A 1-D array is assumed to be Y
+ # values. An Nx2 array is assumed to be (X,Y) values. A 3-D array is
+ # assumed to be (X,Y,Z) values. If multiplot is True we need
+ # a Nxk array, with K at least 2
+
+ try:
+ dshape = Numeric.shape( data )
+ except:
+ raise ValueError, "data argument to plot() does not appear to be a NumPy array"
+
+ dim = len(dshape)
+
+ ###########################################################################
+ # Reformat the list into a uniform Nx2 format.
+
+ if multiplot == False:
+ if dim == 1:
+ dim=2
+ list = []
+ for i in range(len(data)):
+ list.append( (i,data[i]) )
+ data = list
+ elif dim == 2 and dshape[1] == 2 and dshape[0] > 1:
+ pass
+ else:
+ raise ValueError, "data argument dimension or shape is not supported."
+ else:
+ #error checking for multiplot needs work
+ if dim > 1:
+ pass
+ else:
+ raise ValueError, "multiplot dimension too small"
+ ###########################################################################
+ # Setup Plot Options.
+
+ g = llplot()
+
+ if datastyle is not None:
+ cmd = 'set data style ' + str(datastyle)
+ g.add_cmd(cmd)
+ else:
+ g.add_cmd('set data style linespoints')
+
+ if xaxis is not None:
+ g.add_cmd( 'set xlabel "%s"' % xaxis )
+
+ if yaxis is not None:
+ g.add_cmd( 'set ylabel "%s"' % yaxis )
+
+ if title is not None:
+ g.add_cmd( 'set title "%s"' % title )
+
+ if xmin is not None and xmax is not None:
+ g.add_cmd( 'set xrange [%s:%s]' % (str(xmin),str(xmax)) )
+
+ if ymin is not None and ymax is not None:
+ g.add_cmd( 'set yrange [%s:%s]' % (str(ymin),str(ymax)) )
+
+ if cmds is not None:
+ for cmd in cmds:
+ g.add_cmd(cmd)
+
+ g.set_data( data,'',dim,1,multiplot,multilabels,multiopts)
+
+ ###########################################################################
+ # Generate output.
+
+ if terminal == 'gnuplot':
+ g.batch = 0
+ g.plot_current()
+ raw_input('Please press return to continue...\n')
+ return
+
+ elif terminal == 'postscript':
+
+ g.batch = 1
+
+ #if (os.name == 'nt'):
+ # output = string.join(string.split(output,'\\'),'/')
+
+ g.add_cmd( 'set terminal postscript color 10' )
+ g.add_cmd( "set output '%s'" % output )
+
+ g.plot_current()
+
+ return
+
+ elif terminal == 'pbm':
+
+ g.batch = 1
+
+ g.add_cmd( 'set terminal pbm color' )
+ g.add_cmd( "set output '%s'" % output )
+
+ g.plot_current()
+
+ return
+
+ elif terminal == 'xpm':
+
+ import gdal
+ import time
+
+ g.batch = 1
+
+ out_temp = gvutils.tempnam(extension='png')
+
+ g.add_cmd( 'set terminal png' )
+ g.add_cmd( "set output '%s'" % out_temp )
+
+ g.plot_current()
+
+ pngDS = gdal.Open( out_temp )
+ if pngDS is None:
+ return None
+
+ xpmDriver = gdal.GetDriverByName( 'XPM' )
+ if xpmDriver is None:
+ return None
+
+ xpmDriver.CreateCopy( output, pngDS, 0 )
+
+ pngDS = None
+ os.unlink( out_temp )
+
+ return
+
+ else:
+ import gdal
+ import gdalnumeric
+ import time
+ import gview
+
+ g.batch = 1
+
+ temp_file = gvutils.tempnam()
+
+ # make sure the file has been created
+ create_temp = open(temp_file,'w')
+ create_temp.close()
+
+ g.add_cmd( 'set terminal pbm color' )
+ g.add_cmd( "set output '%s'" % temp_file )
+
+ g.plot_current()
+
+ time.sleep( 1 )
+
+ image = gdalnumeric.LoadFile( temp_file )
+ image_ds = gdalnumeric.OpenArray( image )
+
+ try:
+ os.unlink( temp_file )
+ except:
+ pass
+ rlayer = gview.GvRasterLayer( gview.GvRaster(dataset=image_ds, real=1),
+ rl_mode = gview.RLM_RGBA )
+
+ rlayer.set_source(1, gview.GvRaster(dataset=image_ds, real=2) )
+ rlayer.set_source(2, gview.GvRaster(dataset=image_ds, real=3) )
+
+ if terminal == 'rasterlayer':
+ return rlayer
+
+ graphwin = GvGraphWindow( rlayer )
+ if wintitle is not None:
+ graphwin.set_title(wintitle)
+
+###############################################################################
+# plot3d()
+
+def plot3d( data=None, xvec=None, yvec=None, xaxis=None, yaxis=None, zaxis=None,
+ xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax = None,
+ title=None, cmds=None, terminal = 'openev', output = None,
+ plottype="parametric", wintitle=None):
+
+ """plot3d(data [,xvec=xaxis_values] [,yvec=yaxis_values]
+ [, xaxis=text] [,yaxis=text] [,zaxis=text] [,title=text]
+ [, xmin=n, xmax=n] [, ymin=n, ymax=n] [, zmin=n, zmax=n]
+ [, cmds=cmd_list] [,terminal={"openev","gnuplot","rasterlayer"}]
+ [, output=ps_filename]
+ [,plottype = {"parametric","contour"}]
+ [, wintitle=text])
+
+ data -- data array to plot, should be 2-D set of Z values.
+ Size of data should be length(x) x length(y), if x
+ and y are present.'
+ xvec -- 1-D Vector of values for axis of first dimension of data.
+ yvec -- 1-D Vector of values for axis of second dimension of data.
+ """
+
+ ###########################################################################
+ # Print usage() message if no options given.
+
+ if data is None:
+ print 'Usage: plot3d(data [,xvec=xaxis_values] [,yvec=yaxis_values] '
+ print ' [, xaxis=text] [,yaxis=text] [,zaxis=text] [,title=text] '
+ print ' [, xmin=n, xmax=n] [, ymin=n, ymax=n] [, zmin=n, zmax=n] '
+ print ' [, cmds=cmd_list] [,terminal={"openev","gnuplot,"rasterlayer"}]'
+ print ' [, output=ps_filename] [,plottype = {"parametric","contour"}]'
+ print ''
+ print ' data -- data array to plot, should be 2-D set of Z values.'
+ print ' Size of data should be length(x) x length(y), if x'
+ print ' and y are present.'
+ print ' xvec -- 1-D Vector of values for axis of first dimension of data.'
+ print ' yvec -- 1-D Vector of values for axis of second dimension of data.'
+ print ''
+ return
+
+ ###########################################################################
+ # Work out the shape of the data. A 1-D array is assumed to be Y
+ # values. An Nx2 array is assumed to be (X,Y) values. All others are
+ # currently invalid.
+
+ try:
+ dshape = Numeric.shape( data )
+ except:
+ raise ValueError, "data argument to plot() does not appear to be a NumPy array"
+
+ ##########################################################################
+ # Make sure xvec, yvec are valid indices for x/y axis and revert to
+ # default if not.
+
+ if xvec is None:
+ xvec = Numeric.arange(dshape[0])
+ else:
+ try:
+ xshape = Numeric.shape( xvec )
+ if (len(xvec) != dshape[0]):
+ print 'Incorrect length for xvec- reverting to default.'
+ xvec = Numeric.arange(dshape[0])
+ elif (len(xshape) > 1):
+ print 'xvec should be 1-D- reverting to default.'
+ xvec = Numeric.arange(dshape[0])
+ except:
+ print 'xvec appears not to be a NumPy array- reverting to default.'
+ xvec = Numeric.arange(dshape[0])
+
+ if yvec is None:
+ yvec = Numeric.arange(dshape[1])
+ else:
+ try:
+ yshape = Numeric.shape( yvec )
+ if (len(yvec) != dshape[1]):
+ print 'Incorrect length for yvec- reverting to default.'
+ yvec = Numeric.arange(dshape[1])
+ elif (len(yshape) > 1):
+ print 'yvec should be 1-D- reverting to default.'
+ yvec = Numeric.arange(dshape[1])
+ except:
+ print 'yvec appears not to be a NumPy array- reverting to default.'
+ yvec = Numeric.arange(dshape[1])
+
+
+ ###########################################################################
+ # Setup Plot Options.
+
+ g = llplot()
+
+ g.batch = 1
+
+ if plottype == "contour":
+ g.add_cmd('set nosurface')
+ g.add_cmd('set contour')
+ g.add_cmd('set view 0,0')
+ g.add_cmd('set data style lines')
+ g.add_cmd('set cntrparam levels 15')
+ else:
+# g.add_cmd('set parametric')
+ g.add_cmd('set data style lines')
+ g.add_cmd('set hidden3d')
+
+ if xaxis is not None:
+ g.add_cmd( 'set xlabel "%s"' % xaxis )
+
+ if yaxis is not None:
+ g.add_cmd( 'set ylabel "%s"' % yaxis )
+
+ if title is not None:
+ g.add_cmd( 'set title "%s"' % title )
+
+ if xmin is not None and xmax is not None:
+ g.add_cmd( 'set xrange [%s:%s]' % (str(xmin),str(xmax)) )
+
+ if ymin is not None and ymax is not None:
+ g.add_cmd( 'set yrange [%s:%s]' % (str(ymin),str(ymax)) )
+
+ if plottype != "contour":
+ if zaxis is not None:
+ g.add_cmd( 'set zlabel "%s"' % zaxis )
+
+ if plottype != "contour":
+ if zmin is not None and zmax is not None:
+ g.add_cmd( 'set zrange [%s:%s]' % (str(zmin),str(zmax)) )
+
+ if cmds is not None:
+ for cmd in cmds:
+ g.add_cmd(cmd)
+
+ ###########################################################################
+ # Attach the data.
+ #
+ # Note that we emit the x and y values with each data point. It would
+ # be nice to rewrite this to use binary format eventually.
+
+ tup_data = []
+ for x_i in range(len(xvec)):
+ for y_i in range(len(yvec)):
+ tup_data.append( (xvec[x_i], yvec[y_i], data[x_i][y_i]) )
+
+ g.set_data( tup_data, dimension = 3, xlen = len(xvec) )
+
+ ###########################################################################
+ # Generate output.
+
+ if terminal == 'gnuplot':
+ g.batch = 0
+
+ g.plot_current()
+ raw_input('Please press return to continue...\n')
+
+ elif terminal == 'postscript':
+ if (os.name == 'nt'):
+ output = string.join(string.split(output,'\\'),'/')
+
+ g.add_cmd( 'set terminal postscript color 10' )
+ g.add_cmd( "set output '%s'" % output )
+
+ g.plot_current()
+
+ else:
+ import gdal
+ import gdalnumeric
+ import time
+ import gview
+
+ temp_file = gvutils.tempnam()
+
+ g.add_cmd( 'set terminal pbm color' )
+ g.add_cmd( "set output '%s'" % temp_file )
+
+ g.plot_current()
+
+ image = gdalnumeric.LoadFile( temp_file )
+ image_ds = gdalnumeric.OpenArray( image )
+
+ try:
+ os.unlink( temp_file )
+ except:
+ pass
+
+ rlayer = gview.GvRasterLayer( gview.GvRaster(dataset=image_ds, real=1),
+ rl_mode = gview.RLM_RGBA )
+
+ rlayer.set_source(1, gview.GvRaster(dataset=image_ds, real=2) )
+ rlayer.set_source(2, gview.GvRaster(dataset=image_ds, real=3) )
+
+ if terminal == 'rasterlayer':
+ return rlayer
+
+ graphwin = GvGraphWindow( rlayer )
+ if wintitle is not None:
+ graphwin.set_title(wintitle)
+
+
+
+
+###############################################################################
+# llplot - low level plot object used to manage plot state, and pipe handling.
+#
+# Only utilized from within gvplot.py.
+
+class llplot:
+
+ def __init__(self):
+ self.cmds = []
+ self.batch = 1
+ self.data = None
+ self.data_title = ''
+ self.pipe = None
+ self.tmpnam = None
+ self.base_command = self.find_gnuplot()
+ if self.base_command is None:
+ raise RuntimeError, "Unable to find gnuplot executable."
+ self.dimension = 2
+
+ def find_gnuplot( self ):
+ import gview
+ exe = gview.get_preference('gnuplot')
+ if exe is not None:
+ if os.path.isfile(exe):
+ return exe
+ else:
+ gvutils.warning( 'Disregarding gnuplot preference "%s", executable not found.' % exe )
+
+ exe = gvutils.FindExecutable( 'gnuplot' )
+ if exe is None:
+ exe = gvutils.FindExecutable( 'pgnuplot.exe' )
+ if exe is None:
+ exe = gvutils.FindExecutable( 'wgnupl32.exe' )
+ if exe is None:
+ exe = gvutils.FindExecutable( 'wgnuplot.exe' )
+
+ return exe
+
+ def add_cmd( self, command ):
+ self.cmds.append( command )
+
+ def set_data( self, data, data_title = '', dimension = 2, xlen = 1,
+ multiplot = False, multilabels = (),multiopts =()):
+ self.data = data
+ self.data_title = data_title
+ self.dimension = dimension
+ self.xlen = xlen
+ self.multiplot = multiplot
+ self.multilabels = multilabels
+ self.multiopts = multiopts
+
+ if (multiplot == True) and (len(multilabels) == 0):
+ self.multilabels = range(self.data.shape[1]-1)
+
+ if (multiplot == True) and (len(multiopts) == 0):
+ self.multiopts=[]
+ for i in range(self.data.shape[1]-1):
+ self.multiopts.append("")
+
+
+ def plot_current( self ):
+ """Data is a list of (x,y) pairs"""
+
+ if self.batch:
+ self.open_tmpfile()
+ else:
+ self.open_pipe()
+
+ for cmd in self.cmds:
+ self.write(cmd + '\n')
+
+ if self.multiplot == False:
+ if self.dimension == 2:
+ self.write( 'plot "-" title "%s"\n' % self.data_title )
+ else:
+ self.write( 'splot "-" title "%s"\n' % self.data_title )
+
+ else:
+ cmd = '"-" title "' + str(self.multilabels[0]) + '" ' + self.multiopts[0]
+ for i in range(self.data.shape[1]-2):
+ cmd = cmd + ',"-" title "' + str(self.multilabels[i+1]) + '" ' + self.multiopts[i+1]
+ #print "cmd", cmd
+ self.write( 'plot ' + cmd +'\n')
+
+ self.write_data()
+
+ self.complete_command()
+
+ self.cleanup()
+
+ def write_data( self ):
+ if self.multiplot == False:
+ if self.dimension == 2:
+ for pnt in self.data:
+ self.write( '%s %s\n' % (pnt[0], pnt[1]) )
+ self.write('e\n')
+ else:
+ i = 0
+ for pnt in self.data:
+ self.write( '%s %s %s\n' % (pnt[0], pnt[1], pnt[2]) )
+ i = i + 1
+ if i % self.xlen == 0:
+ self.write( '\n' )
+
+ self.write('e\n')
+ else:
+ for i in range(self.data.shape[1]-1):
+ for pnt in self.data:
+ self.write( '%s %s\n' % (pnt[0], pnt[1+i]) )
+ self.write('e\n')
+
+
+ def open_pipe( self ):
+ import os
+
+ self.pipe = os.popen(self.base_command, 'w')
+
+ # forward write and flush methods:
+ self.write = self.pipe.write
+ self.flush = self.pipe.flush
+
+ def open_tmpfile( self ):
+ import os
+
+ self.tmpnam = gvutils.tempnam()
+ self.pipe = open(self.tmpnam, 'w')
+
+ # forward write and flush methods:
+ self.write = self.pipe.write
+ self.flush = self.pipe.flush
+
+ def complete_command( self ):
+ if self.pipe is not None:
+ self.pipe.flush()
+
+ if self.tmpnam is not None:
+ self.pipe.close()
+ self.pipe = None
+
+ # command = self.base_command + ' < ' + self.tmpnam
+ command = self.base_command + ' ' + self.tmpnam
+
+ os.system( command )
+
+ def cleanup( self ):
+ # Closing the pipe makes the graphs
+ # disappear immediately, so leave out
+ # pipe cleanup in gnuplot case.
+ if ((self.batch == 1) and (self.pipe is not None)):
+ self.pipe.close()
+ self.pipe = None
+
+ if self.tmpnam is not None:
+ os.unlink( self.tmpnam )
+
+###############################################################################
+# GvGraphWindow -- a very simple window for display graph images in.
+
+class GvGraphWindow(gtk.GtkWindow):
+
+ def __init__(self,rlayer):
+
+ gtk.GtkWindow.__init__(self)
+
+ import gview
+
+ self.rlayer = rlayer
+ raster = rlayer.get_data()
+ self.xsize = raster.get_dataset().RasterXSize
+ self.ysize = raster.get_dataset().RasterYSize
+
+ self.set_policy(gtk.TRUE,gtk.TRUE,gtk.FALSE)
+ # self.set_usize(self.xsize, self.ysize)
+ self.viewarea = gview.GvViewArea()
+ self.viewarea.add_layer( self.rlayer )
+ self.viewarea.size(self.xsize, self.ysize)
+ shell = gtk.GtkVBox(spacing=0)
+ self.add(shell)
+
+ # Print menu
+ menuf = GtkExtra.MenuFactory()
+ self.menuf = menuf
+ menuf.add_entries([
+ ('File/Print', None, self.print_cb)])
+
+ shell.pack_start(menuf, expand=gtk.FALSE)
+
+ shell.pack_start( self.viewarea )
+
+ self.connect( 'delete-event', self.close )
+ self.show_all()
+
+ self.viewarea.fit_extents(0, self.ysize, self.xsize, -self.ysize )
+
+ def print_cb(self, *args):
+ import gvprint
+ pd = gvprint.GvPrintDialog( self.viewarea )
+
+ def close( self, *args ):
+ self.rlayer = None
+ self.destroy()
+
+
+###############################################################################
+# main()
+
+if __name__ == '__main__':
+ data1 = [[1,2], [1.1,3], [1.2,4]]
+ plot( data1, xmin = -1, xmax = 5, terminal='gnuplot' )
+
+ data2 = [1,2,5,4,3,3]
+ plot( data2, xaxis = 'X', yaxis = 'power', title='Power Cycle',
+ ymin = 0, ymax = 6, terminal='gnuplot' )
+
+ data3 = [[1,2,3,4,5],[2,2.5,3,3.5,4],[3,3,3,3,3],[4,3.5,3,2.5,2],[5,4,3,2,1]]
+ plot3d( data3, xaxis = 'X', yaxis = 'Y', zaxis = 'F(X,Y)', title='A Plot',
+ terminal = 'gnuplot' )
+
+ xvals=[4,5,6,7,8]
+ yvals=[12,13,14,15,16]
+ plot3d( data3, xaxis = 'X', yaxis = 'Y', zaxis = 'F(X,Y)', title='A Plot',
+ terminal = 'gnuplot' , zmin=-1, zmax=5, xvec=xvals, yvec=yvals,
+ cmds = ('set view 70,40','set grid','set contour base') )
+
+ xvals=[4,5,6,7]
+ yvals=[12,11,14,13,16]
+ plot3d( data3, xaxis = 'X', yaxis = 'Y', zaxis = 'F(X,Y)', title='A Plot',
+ terminal = 'gnuplot' , zmin=-1, zmax=5, xvec=xvals, yvec=yvals,
+ cmds = ('set view 70,40','set grid','set contour base') )
+
+
+
+
Property changes on: packages/openev/branches/upstream/current/pymod/gvplot.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/gvpquerypropdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvpquerypropdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvpquerypropdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,216 @@
+###############################################################################
+# $Id: gvpquerypropdlg.py,v 1.11 2000/08/23 14:32:10 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: GvPqueryLayer Properties Dialog
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvpquerypropdlg.py,v $
+# Revision 1.11 2000/08/23 14:32:10 warmerda
+# fixed logic of pixel_mode callback
+#
+# Revision 1.10 2000/08/22 16:13:33 warmerda
+# fixed layer: prefixing of layer name
+#
+# Revision 1.9 2000/08/10 15:59:29 warmerda
+# added help topic
+#
+# Revision 1.8 2000/07/21 01:34:56 warmerda
+# added read_only flag for GvData, and utilize for vector layers
+#
+# Revision 1.7 2000/07/20 02:45:04 warmerda
+# avoid doing gui updates in response to signals if dialog destroyed
+#
+# Revision 1.6 2000/06/14 15:13:21 warmerda
+# updated pgu stuff
+#
+# Revision 1.5 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+from gtk import *
+from string import *
+
+from gvconst import *
+import gview
+import gvvectorpropdlg
+import gvutils
+import pgucolorsel
+import gvhtml
+
+pq_prop_dialog_list = []
+
+def LaunchPQueryPropDialog(layer):
+ # Check list to see if dialog exists - make it visible
+ for test_dialog in pq_prop_dialog_list:
+ if test_dialog.layer._o == layer._o:
+ test_dialog.update_gui()
+ test_dialog.show()
+ test_dialog.get_window()._raise()
+ return test_dialog
+
+ # Create new dialog if one doesn't exist already
+ new_dialog = GvPQueryPropDialog(layer)
+ pq_prop_dialog_list.append( new_dialog )
+ return new_dialog
+
+class GvPQueryPropDialog(gvvectorpropdlg.GvVectorPropDialog):
+
+ def __init__(self, layer):
+ GtkWindow.__init__(self)
+ self.set_title('GView')
+ self.layer = layer
+ self.updating = FALSE
+
+ gvhtml.set_help_topic( self, "gvpquerypropdlg.html" )
+
+ # create the general layer properties dialog
+ self.create_notebook()
+ self.create_pane1()
+
+ if self.layer is not None:
+ self.layer.connect('display-change', self.refresh_cb)
+
+ # Setup Object Drawing Properties Tab
+ self.pane2 = GtkVBox(spacing=10)
+ self.pane2.set_border_width(10)
+ self.notebook.append_page( self.pane2, GtkLabel('Draw Styles'))
+
+ vbox = GtkVBox(spacing=10)
+ self.pane2.add(vbox)
+
+ # Create Color control.
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Color:'),expand=FALSE)
+ self.point_color = \
+ pgucolorsel.ColorControl('Point Color',
+ self.color_cb,'_point_color')
+ box.pack_start(self.point_color)
+
+ # Point size
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Point Size:'),expand=FALSE)
+ self.point_size = GtkCombo()
+ self.point_size.set_popdown_strings(
+ ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '15', '20') )
+ self.point_size.entry.connect('changed', self.point_size_cb)
+ box.pack_start(self.point_size,expand=FALSE)
+
+ # Coordinate
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Coordinate:'),expand=FALSE)
+
+ self.coord_om = gvutils.GvOptionMenu(
+ ('Off','Raster Pixel/Line','Georeferenced','Geodetic (lat/long)'),
+ self.set_coordinate_mode)
+ box.pack_start(self.coord_om,expand=FALSE)
+
+ # Raster Value
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Pixel Value:'),expand=FALSE)
+
+ self.pixel_mode_om = \
+ gvutils.GvOptionMenu(('On','Off'), self.set_pixel_mode)
+ box.pack_start(self.pixel_mode_om,expand=FALSE)
+
+ self.update_gui()
+
+ self.show_all()
+
+ # Initialize GUI state from underlying object state.
+ def update_gui(self):
+ if self.flags( DESTROYED ) > 0:
+ return
+
+ if self.layer is None or self.updating == TRUE:
+ return
+
+ self.updating = TRUE
+
+ # Layer name.
+ self.layer_name.set_text( self.layer.get_name() )
+
+ # Visibility radio buttons
+ self.vis_yes.set_active( self.layer.is_visible() )
+ self.vis_no.set_active( not self.layer.is_visible() )
+
+ # Editability radio buttons
+ self.edit_yes.set_active( not self.layer.is_read_only() )
+ self.edit_no.set_active( self.layer.is_read_only() )
+
+ self.set_color_or_default('_point_color', self.point_color)
+ # point size
+ self.point_size.entry.delete_text(0,-1)
+ if self.layer.get_property('_point_size') is None:
+ self.point_size.entry.insert_text('6')
+ else:
+ self.point_size.entry.insert_text(
+ self.layer.get_property('_point_size'))
+
+ # coordinate mode
+ mode = self.layer.get_property( '_coordinate_mode' )
+ if mode is None:
+ self.coord_om.set_history(2)
+ elif mode == 'off':
+ self.coord_om.set_history(0)
+ elif mode == 'raster':
+ self.coord_om.set_history(1)
+ elif mode == 'latlong':
+ self.coord_om.set_history(3)
+ else:
+ self.coord_om.set_history(2)
+
+ # pixel mode
+ mode = self.layer.get_property( '_pixel_mode' )
+ if mode is None or mode != 'off':
+ self.pixel_mode_om.set_history(0)
+ else:
+ self.pixel_mode_om.set_history(1)
+
+ self.updating = FALSE
+
+ # Dialog closed, remove references to python object
+ def close( self, widget, args ):
+ pq_prop_dialog_list.remove(self)
+
+ def set_coordinate_mode(self, om):
+ if self.coord_om.get_history() == 0:
+ self.layer.set_property( '_coordinate_mode', 'off')
+ elif self.coord_om.get_history() == 1:
+ self.layer.set_property( '_coordinate_mode', 'raster')
+ elif self.coord_om.get_history() == 2:
+ self.layer.set_property( '_coordinate_mode', 'georef')
+ elif self.coord_om.get_history() == 3:
+ self.layer.set_property( '_coordinate_mode', 'latlong')
+ self.layer.display_change()
+
+ def set_pixel_mode(self, om):
+ if om.get_history() == 0:
+ self.layer.set_property( '_pixel_mode', 'on')
+ else:
+ self.layer.set_property( '_pixel_mode', 'off')
+ self.layer.display_change()
+
Added: packages/openev/branches/upstream/current/pymod/gvprint.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvprint.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvprint.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,442 @@
+###############################################################################
+# $Id: gvprint.py,v 1.16 2004/07/24 14:35:04 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: Print Dialog
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvprint.py,v $
+# Revision 1.16 2004/07/24 14:35:04 andrey_kiselev
+# Added possibility to explicitly specify printed image size;
+# several GUI tweaks.
+#
+# Revision 1.15 2004/01/15 19:21:20 gmwalter
+# Avoid deprecation warnings in python 2.3 related
+# to float being input instead of integer.
+#
+# Revision 1.14 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.13 2002/03/21 21:00:26 warmerda
+# add better error testing when printing
+#
+# Revision 1.12 2001/03/28 15:04:05 warmerda
+# avoid rounding oddness for stuff that should be 1:1
+#
+# Revision 1.11 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.10 2001/01/23 16:18:12 warmerda
+# Removed debug statement.
+#
+# Revision 1.9 2001/01/23 15:47:41 warmerda
+# added GIF output support
+#
+# Revision 1.8 2000/08/10 15:59:29 warmerda
+# added help topic
+#
+# Revision 1.7 2000/08/08 18:15:22 warmerda
+# fixed handling of output label
+#
+# Revision 1.6 2000/08/07 17:18:13 warmerda
+# added windows printing support
+#
+# Revision 1.5 2000/08/03 18:20:41 warmerda
+# implemented print scaling and paper sizes properly
+#
+# Revision 1.4 2000/07/26 21:04:36 warmerda
+# fixed _temp.tif name
+#
+# Revision 1.3 2000/07/20 03:22:16 warmerda
+# added greyscale support for TIFF, and got PNG working
+#
+# Revision 1.2 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+from gtk import *
+
+from gvconst import *
+import gview
+import gvutils
+import gdal
+import os
+import gvhtml
+
+paper_sizes = ( ("US Letter", 8.500, 11.000 ),
+ ("US Legal", 8.500, 14.000 ),
+ ("A4", 8.268, 11.693 ),
+ ("B5", 7.205, 10.118 ),
+ ("A3", 11.693, 16.535 ) )
+
+DR_POSTSCRIPT = 0
+DR_TIFF = 1
+DR_PNG = 2
+DR_WINPRINT = 3
+DR_GIF = 4
+
+DV_FILE = 0
+DV_PRINTER = 1
+
+class GvPrintDialog(GtkWindow):
+
+ def __init__(self, view):
+ GtkWindow.__init__(self)
+ self.set_title('Print')
+ self.connect('delete-event',self.close)
+ self.view = view
+
+ gvhtml.set_help_topic( self, "gvprint.html" );
+
+ self.command = gview.get_preference('print_command')
+ if self.command is None:
+ self.command = 'lpr'
+
+ self.filename = 'openev.ps'
+
+ cgroup = GtkVBox(spacing=6)
+ cgroup.set_border_width(10)
+ self.add( cgroup )
+
+ table = GtkTable()
+ table.n_columns = 2
+ table.n_rows = 4
+ cgroup.add(table)
+
+ # Setup Driver Option Menu
+ driver_label = GtkLabel('Driver:')
+ driver_label.set_alignment(0, 0.5)
+ table.attach(driver_label,0,1,0,1)
+ if os.name == "nt":
+ self.driver = gvutils.GvOptionMenu( ('PostScript', 'TIFF', 'PNG',
+ 'Windows Print Driver',
+ 'GIF' ),
+ self.update_cb )
+ else:
+ self.driver = gvutils.GvOptionMenu( ('PostScript', 'TIFF', 'PNG',
+ '', 'GIF' ),
+ self.update_cb )
+ table.attach(self.driver,1,2,0,1)
+
+ # Setup Device Option Menu
+ device_label = GtkLabel('Device:')
+ device_label.set_alignment(0, 0.5)
+ table.attach(device_label,0,1,1,2)
+ self.device = gvutils.GvOptionMenu( ('File', 'Spool to Printer'),
+ self.device_cb )
+ table.attach(self.device,1,2,1,2)
+
+ # Setup File/Command entry.
+ self.file_label = GtkLabel('File:')
+ self.file_label.set_alignment(0, 0.5)
+ table.attach(self.file_label,0,1,2,3)
+ self.file = GtkEntry(maxlen=40)
+ table.attach(self.file,1,2,2,3)
+
+ # Setup Output Type
+ self.output_label = GtkLabel('Output Type:')
+ self.output_label.set_alignment(0, 0.5)
+ table.attach(self.output_label,0,1,3,4)
+ self.output = gvutils.GvOptionMenu( ('Greyscale', 'Color' ), None )
+ table.attach(self.output,1,2,3,4)
+
+ # Setup Paper Type
+ self.paper_label = GtkLabel('Paper:')
+ self.paper_label.set_alignment(0, 0.5)
+ table.attach(self.paper_label,0,1,4,5)
+ sizes = []
+ for entry in paper_sizes:
+ sizes.append( entry[0] )
+ self.paper = gvutils.GvOptionMenu( sizes, self.update_cb )
+ table.attach(self.paper,1,2,4,5)
+
+ # Setup Scale slider
+ self.scale_label = GtkLabel('Scale:')
+ self.scale_label.set_alignment(0, 0.5)
+ table.attach(self.scale_label,0,1,5,6)
+ self.scale_adjustment = GtkAdjustment(1, 0, 1.25, 0.05, 0.05, 0.05)
+ self.scale_slider = GtkHScale(self.scale_adjustment)
+ table.attach(self.scale_slider,1,2,5,6)
+
+ # Setup Resolution spinner
+ resolution_label = GtkLabel('Resolution:')
+ resolution_label.set_alignment(0, 0.5)
+ table.attach(resolution_label,0,1,6,7)
+ self.resolution_adjustment = GtkAdjustment(1, 0, 10, 0.1, 0.1, 0.1)
+ self.resolution_spinner = \
+ GtkSpinButton(self.resolution_adjustment,climb_rate=0.1,digits=1)
+ self.resolution_spinner.connect("changed", self.resolution_cb)
+ table.attach(self.resolution_spinner,1,2,6,7)
+
+ # Setup Size entries
+ size_label = GtkLabel('Image size:')
+ size_label.set_alignment(0, 0.5)
+ table.attach(size_label,0,1,7,8)
+ size_box = GtkHBox(spacing=5)
+ self.xsize_entry = GtkEntry()
+ self.xsize_entry.connect('activate', self.resolution_cb)
+ self.xsize_entry.connect('leave-notify-event', self.resolution_cb)
+ size_box.pack_start(self.xsize_entry)
+ size_box.pack_start(GtkLabel('x'))
+ self.ysize_entry = GtkEntry()
+ self.ysize_entry.connect('activate', self.resolution_cb)
+ self.ysize_entry.connect('leave-notify-event', self.resolution_cb)
+ size_box.pack_start(self.ysize_entry)
+ table.attach(size_box,1,2,7,8)
+
+ # Add Print, and Close button(s)
+ btn_box = GtkHBox(spacing=10)
+
+ but = GtkButton('Print')
+ but.connect('clicked',self.print_cb)
+ btn_box.pack_start(but)
+
+ but = GtkButton('Close')
+ but.connect('clicked',self.close)
+ btn_box.pack_start(but)
+
+ table.attach(btn_box,0,2,8,9)
+
+ # Initialize values.
+ if gview.get_preference('print_driver') is not None:
+ self.driver.set_history(int(gview.get_preference('print_driver')))
+ elif os.name == 'nt':
+ self.driver.set_history(DR_WINPRINT)
+
+ if gview.get_preference('print_device') is not None:
+ self.device.set_history(int(gview.get_preference('print_device')))
+
+ if self.device.get_history() == 0:
+ self.set_default_filename()
+ else:
+ self.file.set_text( self.command )
+
+ if gview.get_preference('print_paper') is not None:
+ self.paper.set_history(int(gview.get_preference('print_paper')))
+
+ if gview.get_preference('print_output') is not None:
+ self.output.set_history(int(gview.get_preference('print_output')))
+
+ if gview.get_preference('print_resolution') is not None:
+ resolution = float(gview.get_preference('print_resolution'))
+ self.resolution_adjustment.set_value(resolution)
+ width = int(self.view.get_width() * resolution + 0.5)
+ height = int(self.view.get_height() * resolution + 0.5)
+ self.xsize_entry.set_text(str(width))
+ self.ysize_entry.set_text(str(height))
+
+ self.set_paper_size()
+ self.scale_adjustment.set_value(1.0)
+
+ # Show
+ table.set_row_spacings(6)
+ table.show_all()
+ self.update_cb()
+ cgroup.show()
+ self.show()
+
+ def resolution_cb(self,entry,*args):
+ try:
+ value = float(entry.get_text())
+ except:
+ return
+
+ if entry == self.resolution_spinner:
+ resolution = self.resolution_adjustment.value
+ width = int(self.view.get_width() * resolution + 0.5)
+ self.xsize_entry.set_text(str(width))
+ height = int(self.view.get_height() * resolution + 0.5)
+ self.ysize_entry.set_text(str(height))
+ elif entry == self.xsize_entry:
+ resolution = value / self.view.get_width()
+ height = int(self.view.get_height() * resolution + 0.5)
+ self.ysize_entry.set_text(str(height))
+ elif entry == self.ysize_entry:
+ resolution = value / self.view.get_height()
+ width = int(self.view.get_width() * resolution + 0.5)
+ self.xsize_entry.set_text(str(width))
+ self.resolution_adjustment.set_value(resolution)
+
+
+ def device_cb(self, *args):
+ if self.device.get_history() == 0:
+ self.command = self.file.get_text()
+ self.set_default_filename()
+ else:
+ self.file.set_text(self.command)
+ self.update_cb( args )
+
+ def set_default_filename(self):
+ if self.driver.get_history() == DR_TIFF:
+ self.file.set_text('openev.tif')
+ elif self.driver.get_history() == DR_PNG:
+ self.file.set_text('openev.png')
+ elif self.driver.get_history() == DR_GIF:
+ self.file.set_text('openev.gif')
+ else:
+ self.file.set_text('openev.ps')
+
+ def set_paper_size(self):
+ # Setup paper size.
+ self.paper_x = 8.5
+ self.paper_y = 11
+ try:
+ entry = paper_sizes[self.paper.get_history()]
+ self.paper_x = entry[1]
+ self.paper_y = entry[2]
+ except:
+ pass
+
+ def update_cb(self, *args):
+
+ driver = self.driver.get_history()
+
+ # Set FILE/PRINTER Device based on driver.
+ if driver == DR_TIFF or driver == DR_PNG or driver == DR_GIF:
+ self.device.set_history(DV_FILE)
+ if driver == DR_WINPRINT:
+ self.device.set_history(DV_PRINTER)
+ if driver == DR_POSTSCRIPT and os.name == 'nt':
+ self.device.set_history(DV_FILE)
+
+ self.set_paper_size()
+
+ # Hide the file/command tool for WINDRIVER
+ if driver == DR_WINPRINT:
+ self.file_label.hide()
+ self.file.hide()
+ self.output_label.hide()
+ self.output.hide()
+ else:
+ self.file_label.show()
+ self.file.show()
+ self.output_label.show()
+ self.output.show()
+
+ if self.device.get_history() == DV_PRINTER:
+ self.file_label.set_text('Command:')
+ else:
+ self.file_label.set_text('File:')
+
+ # Make Positioning controls visible only for PostScript
+ if driver == DR_POSTSCRIPT:
+ self.scale_label.show()
+ self.scale_slider.show()
+ self.paper_label.show()
+ self.paper.show()
+ else:
+ self.scale_label.hide()
+ self.scale_slider.hide()
+ self.paper_label.hide()
+ self.paper.hide()
+
+ def print_cb(self, *args):
+ if self.resolution_adjustment.value >= 0.99 \
+ and self.resolution_adjustment.value <= 1.01:
+ width = self.view.get_width()
+ height = self.view.get_height()
+ else:
+ width = self.view.get_width() * self.resolution_adjustment.value
+ height = self.view.get_height() * self.resolution_adjustment.value
+ width=int(width+0.5)
+ height=int(height+0.5)
+
+ if width / self.paper_x > height / self.paper_y:
+ pixels_per_inch = width / (self.paper_x*0.9)
+ else:
+ pixels_per_inch = height / (self.paper_y*0.9)
+
+ pixels_per_inch = pixels_per_inch * self.scale_adjustment.value
+ ulx = (self.paper_x - width/pixels_per_inch)/2.0
+ uly = (self.paper_y - height/pixels_per_inch)/2.0
+ lrx = self.paper_x - ulx
+ lry = self.paper_y - uly
+
+ try:
+ os.unlink( self.file.get_text() )
+ except:
+ pass
+
+ err = 0
+ if self.driver.get_history() == DR_POSTSCRIPT:
+ filename = self.file.get_text()
+ if self.device.get_history() == 1:
+ filename = '|' + filename
+
+ err = self.view.print_postscript_to_file(width,height,
+ ulx,uly,lrx,lry,
+ self.output.get_history(),
+ filename )
+ elif self.driver.get_history() == DR_TIFF:
+ err = self.view.print_to_file(width,height,self.file.get_text(),
+ 'GTiff',self.output.get_history())
+ elif self.driver.get_history() == DR_PNG:
+ err = self.view.print_to_file(width,height,'_temp.tif','GTiff',
+ self.output.get_history())
+ if err == 0:
+ gdal.GetDriverByName('PNG').CreateCopy(self.file.get_text(),
+ gdal.Open('_temp.tif'),TRUE)
+ os.unlink( '_temp.tif' )
+ elif self.driver.get_history() == DR_WINPRINT:
+ self.view.print_to_windriver( width, height, ulx, uly, lrx, lry,
+ self.output.get_history() )
+ elif self.driver.get_history() == DR_GIF:
+ err = self.view.print_to_file(width,height,'_temp.tif','GTiff',
+ self.output.get_history())
+ if err == 0:
+ if self.output.get_history() == 1:
+ gdal.RGBFile2PCTFile( '_temp.tif', '_temp2.tif' )
+ os.unlink('_temp.tif')
+ os.rename('_temp2.tif','_temp.tif')
+
+ gdal.GetDriverByName('GIF').CreateCopy(self.file.get_text(),
+ gdal.Open('_temp.tif'),TRUE)
+ os.unlink( '_temp.tif' )
+
+ if err != 0:
+ gvutils.error('The request to print appears to have failed.')
+
+ self.close()
+
+ def close(self, *args):
+ if self.device.get_history() == 1:
+ gview.set_preference('print_command',self.file.get_text())
+ gview.set_preference('print_driver', str(self.driver.get_history()))
+ gview.set_preference('print_device', str(self.device.get_history()))
+ gview.set_preference('print_paper', str(self.paper.get_history()))
+ gview.set_preference('print_output', str(self.output.get_history()))
+ gview.set_preference('print_resolution',
+ str(self.resolution_adjustment.value))
+ gview.set_preference('print_scale',
+ str(self.scale_adjustment.value))
+
+ self.destroy()
+
+ return TRUE
+
+
+if __name__ == '__main__':
+ dialog = GvPrintDialog(None)
+
+ dialog.connect('delete-event', mainquit)
+
+ mainloop()
Added: packages/openev/branches/upstream/current/pymod/gvrasterpropdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvrasterpropdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvrasterpropdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1240 @@
+###############################################################################
+# $Id: gvrasterpropdlg.py,v 1.57 2005/06/27 19:37:24 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: GvRasterLayer Properties Dialog
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvrasterpropdlg.py,v $
+# Revision 1.57 2005/06/27 19:37:24 gmwalter
+# Bring in Vincent's slider fix.
+#
+# Revision 1.56 2004/12/03 00:24:10 gmwalter
+# Fix scaling slider page increments so that
+# they work for small floating-point valued
+# images.
+#
+# Revision 1.55 2004/10/30 18:25:44 warmerda
+# Don't barf out of projection is None.
+#
+# Revision 1.54 2004/08/31 21:26:46 warmerda
+# trap failed efforts to fetch datum
+#
+# Revision 1.53 2004/06/23 14:35:17 gmwalter
+# Added support for multi-band complex imagery.
+#
+# Revision 1.52 2004/06/03 20:13:07 andrey_kiselev
+# Use reasonable values when projections and datums are not set.
+#
+# Revision 1.51 2004/05/12 19:26:06 andrey_kiselev
+# Preliminary support for changing projection on the fly.
+#
+# Revision 1.50 2004/04/02 17:28:45 gmwalter
+# Fix initialization bug from last changes.
+#
+# Revision 1.49 2004/04/02 17:01:02 gmwalter
+# Updated nodata support for complex and
+# rgb data.
+#
+# Revision 1.48 2004/02/20 12:34:19 andrey_kiselev
+# Generate different band names to avoid problems with equally named keys.
+#
+# Revision 1.47 2004/01/22 21:28:42 andrey_kiselev
+# New control to display and change NODATA value for viewed RasterSource.
+#
+# Revision 1.46 2003/11/05 20:27:23 gmwalter
+# Fix to allow dialog to recognize GCPProjection string if Projection
+# string isn't present.
+#
+# Revision 1.45 2003/06/17 14:58:39 gmwalter
+# gvplot: changed so that graphs don't immediately disappear
+# in the gnuplot terminal case.
+# gvrasterpropdlg: fix so that user can go back to opaque white modulation
+# colour.
+#
+# Revision 1.44 2003/04/30 15:05:24 gmwalter
+# Fixed a typo that was preventing a tuple from being formed and causing
+# bands to wrap around.
+#
+# Revision 1.43 2003/02/20 19:27:22 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.42 2002/12/17 16:11:47 gmwalter
+# Clamp lower bound of Scale_Max to 0.0 in RLM_COMPLEX case in gui_refresh
+# to avoid confusing phase flips at the 0 crossing when phase display is used.
+#
+# Revision 1.41 2002/03/04 21:52:26 warmerda
+# add support for band names
+#
+# Revision 1.40 2002/03/04 16:26:42 warmerda
+# added greyscale lock option for RGB layers
+#
+# Revision 1.39 2001/10/17 16:24:55 warmerda
+# move complex luts to gview.py
+#
+# Revision 1.38 2001/10/12 19:25:15 warmerda
+# improved logic for setting the initial scaling min/max of the scaling controls
+#
+# Revision 1.37 2001/08/22 02:16:28 warmerda
+# ensure that gvraster reference not kept from GvRasterSource
+#
+# Revision 1.36 2001/07/24 21:21:45 warmerda
+# added EV style phase colormap
+#
+# Revision 1.35 2001/07/16 15:20:40 warmerda
+# switched around so magnitude is default for complex layers
+#
+# Revision 1.34 2001/04/03 02:29:30 warmerda
+# improved some pane geometry
+#
+# Revision 1.33 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.32 2000/08/25 20:20:03 warmerda
+# added limited nodata support, upped max band count to 30
+#
+# Revision 1.31 2000/08/11 20:17:15 warmerda
+# added metadata to image info, made scrollable
+#
+# Revision 1.30 2000/08/11 19:19:31 warmerda
+# don't show scaling min for complex layers
+#
+
+from gtk import *
+from string import *
+import gvutils
+import pgucolorsel
+import sys
+import gdal
+import osr
+import gvhtml
+import Numeric
+
+from gvconst import *
+import gview
+
+prop_dialog_list = []
+
+def LaunchRasterPropDialog(layer):
+ # Check list to see if dialog exists - make it visible
+ for test_dialog in prop_dialog_list:
+ if test_dialog.layer._o == layer._o:
+ test_dialog.update_gui()
+ test_dialog.show()
+ test_dialog.get_window()._raise()
+ return test_dialog
+
+ # Create new dialog if one doesn't exist already
+ new_dialog = GvRasterPropDialog(layer)
+ prop_dialog_list.append( new_dialog )
+ return new_dialog
+
+class GvRasterSource(GtkFrame):
+ def __init__(self,name,layer,src_index,master_dialog):
+ GtkFrame.__init__(self,name)
+ self.master_dialog = master_dialog
+ self.updating = FALSE
+ self.src_index = src_index
+
+ # Eventually the following will have to be more sophisticated.
+ if layer is not None:
+ self.layer = layer
+ self.gvraster = layer.get_parent()
+ self.display_change_id = layer.connect('display-change',
+ self.gui_refresh)
+
+ vbox = GtkVBox(spacing=5)
+ vbox.set_border_width(5)
+ self.add(vbox)
+ self.updating = TRUE
+
+ # ------ Band Selection -------
+ hbox = GtkHBox(spacing=5)
+ vbox.pack_start(hbox,expand=FALSE)
+ hbox.pack_start(GtkLabel('Band:'))
+ self.band_combo = GtkCombo()
+ hbox.pack_start(self.band_combo)
+ self.band_combo.entry.connect('changed', self.set_band_cb)
+ self.band_combo.entry.connect('key_press_event', \
+ self.combo_entry_key_press_cb)
+ prototype_data = self.layer.get_parent()
+ band_list = ['constant']
+ ds = prototype_data.get_dataset()
+ band_count = ds.RasterCount
+
+ # Fill in the dictionary
+ #
+ self.__bandDic = {}
+ self.__allBands = []
+ self.__bandNums = []
+ for band in range(band_count) :
+ bandKey = self.band_desc(band+1)
+ self.__allBands.append( bandKey )
+ self.__bandNums.append( str(band+1) )
+ self.__bandDic[bandKey] = str(band+1)
+
+ for band in range(min(30,band_count)):
+ band_list.append( self.band_desc(band+1) )
+
+ if band_count > 30:
+ band_list.append( '...'+self.__allBands[-1] )
+
+ self.band_combo.set_popdown_strings( band_list )
+
+ # ------ Establish scaling range ------
+
+ smin = layer.min_get(src_index)
+ smax = layer.max_get(src_index)
+ delta = smax - smin
+ smax = smax + delta * 0.25
+ smin = smin - delta * 0.25
+
+ if self.layer.get_mode() == gview.RLM_COMPLEX:
+ smin = 0.0
+ elif self.layer.get_parent().get_band().DataType == gdal.GDT_Byte:
+ smin = 0
+ smax = 255
+ elif self.layer.get_parent().get_band().DataType == gdal.GDT_UInt16:
+ smin = 0
+ elif self.layer.get_parent().get_band().DataType == gdal.GDT_UInt32:
+ smin = 0
+
+ # Make sure slider still has reasonable step sizes
+ # for cases where image has small, floating point
+ # values.
+ if delta > 10:
+ new_inc = 1
+ else:
+ new_inc = delta/100.0
+
+ # calculate #digits for slider. If datatype is integer, #digits will
+ # be 0. if datatype is floating point, #digits will be set depending
+ # on order of magnitude of delta:
+ if self.layer.get_parent().get_band().DataType == gdal.GDT_Byte \
+ or self.layer.get_parent().get_band().DataType == gdal.GDT_UInt16 \
+ or self.layer.get_parent().get_band().DataType == gdal.GDT_Int16 \
+ or self.layer.get_parent().get_band().DataType == gdal.GDT_UInt32 \
+ or self.layer.get_parent().get_band().DataType == gdal.GDT_Int32:
+ sliderDigits = 0
+ else:
+ sliderDigits = max(0, 2 - int(Numeric.log10(delta)))
+
+
+ # ------ Scale Min -------
+ hbox = GtkHBox(spacing=5)
+ self.min_hbox = hbox
+ vbox.pack_start(hbox)
+ hbox.pack_start(GtkLabel('Scale Min:'),expand=FALSE)
+ self.min_adjustment = GtkAdjustment(layer.min_get(src_index),
+ smin, smax, new_inc, new_inc, new_inc)
+ self.min_adjustment.connect('value-changed',self.adjustment_cb)
+ self.min_slider = GtkHScale(self.min_adjustment)
+ self.min_slider.set_digits(sliderDigits)
+ hbox.pack_start(self.min_slider)
+ self.min_entry = GtkEntry(maxlen=8)
+ self.min_entry.connect('activate',self.entry_cb)
+ self.min_entry.connect('leave-notify-event',self.entry_cb)
+ hbox.pack_start(self.min_entry,expand=FALSE)
+
+ # ------ Scale Max -------
+ hbox = GtkHBox(spacing=5)
+ self.max_hbox = hbox
+ vbox.pack_start(hbox)
+ hbox.pack_start(GtkLabel('Scale Max:'),expand=FALSE)
+ self.max_adjustment = GtkAdjustment(layer.max_get(src_index),
+ smin, smax, new_inc, new_inc, new_inc)
+ self.max_adjustment.connect('value-changed',self.adjustment_cb)
+ self.max_slider = GtkHScale(self.max_adjustment)
+ self.max_slider.set_digits(sliderDigits)
+ hbox.pack_start(self.max_slider)
+ self.max_entry = GtkEntry(maxlen=8)
+ self.max_entry.connect('activate',self.entry_cb)
+ self.max_entry.connect('leave-notify-event',self.entry_cb)
+ hbox.pack_start(self.max_entry,expand=FALSE)
+
+ # ------ NODATA -------
+ hbox = GtkHBox(spacing=5)
+ self.nodata_hbox = hbox
+ vbox.pack_start(hbox)
+ hbox.pack_start(GtkLabel('NODATA value:'), expand=FALSE)
+ self.nodata_entry = GtkEntry(maxlen=19)
+ self.nodata_entry.connect('activate', self.entry_cb)
+ self.nodata_entry.connect('leave-notify-event', self.entry_cb)
+ hbox.pack_start(self.nodata_entry, expand=FALSE)
+ if (src_index < 3) and (ds.RasterCount > src_index):
+ nodata=ds.GetRasterBand(src_index+1).GetNoDataValue()
+ if nodata is not None:
+ if (type(nodata) != type(complex(1,0))):
+ nodata=complex(nodata,0)
+ self.layer.nodata_set(src_index,nodata.real,nodata.imag)
+
+ # ------- Constant Value -----
+ self.const_entry = GtkEntry(maxlen=8)
+ self.const_entry.connect('activate',self.const_cb)
+ self.const_entry.connect('leave-notify-event',self.const_cb)
+ vbox.pack_start(self.const_entry)
+
+ self.updating = FALSE
+
+ self.gui_refresh()
+
+ self.connect( 'destroy', self.cleanup)
+
+ def combo_entry_key_press_cb( self, entryBox, event, *args ) :
+ import GDK
+
+ if self.updating:
+ return
+
+ if( event.keyval == GDK.Right ) :
+ try :
+ currentIndex = self.__allBands.index( entryBox.get_text() )
+ nextIndex = min( len(self.__allBands)-1, currentIndex+1 )
+ entryBox.set_text( self.__allBands[nextIndex] )
+ except ValueError :
+ return
+
+ elif( event.keyval == GDK.Left ) :
+ try :
+ currentIndex = self.__allBands.index( entryBox.get_text() )
+ prevIndex = max( 0, currentIndex - 1 )
+ entryBox.set_text( self.__allBands[prevIndex] )
+ except ValueError :
+ return
+
+ elif( event.keyval == GDK.Return ) :
+ entryText = entryBox.get_text()
+ if( entryText in self.__bandDic.keys() ) :
+ pass
+ else :
+ try :
+ bandIndex = self.__bandNums.index(entryText)
+ entryBox.set_text( self.__allBands[bandIndex] )
+ except ValueError :
+ entryBox.set_text("")
+ except KeyError :
+ entryBox.set_text("")
+
+ def __del__(self):
+ print 'Destroying GvRasterSource'
+
+ def cleanup(self, *args):
+ self.layer = None
+ self.gvraster = None
+
+ def band_desc(self,iband):
+ band = self.layer.get_parent().get_dataset().GetRasterBand(iband)
+ if len(band.GetDescription()) > 0:
+ # XXX: band descriptions must be different, because we will use
+ # them as keys in dictionary. That's why we print band number
+ # here.
+ return '%d: %s' % (iband,band.GetDescription())
+ else:
+ return '%d' % iband
+
+ def gui_refresh(self, *args):
+
+ if self.layer is None:
+ return
+
+ if self.flags( DESTROYED ) > 0:
+ self.layer.disconnect( self.display_change_id )
+ return
+
+ if self.updating:
+ return
+
+ self.updating = TRUE
+ if self.layer.get_mode() == gview.RLM_COMPLEX:
+ new_min = max(0.0,self.layer.min_get(self.src_index))
+ else:
+ new_min = self.layer.min_get(self.src_index)
+
+ if self.layer.min_get(self.src_index) < self.min_adjustment.lower:
+ self.min_adjustment.set_all( new_min,
+ new_min,
+ self.min_adjustment.upper,
+ self.min_adjustment.step_increment,
+ self.min_adjustment.page_increment,
+ self.min_adjustment.page_size)
+ self.min_adjustment.changed()
+ self.max_adjustment.set_all( new_min,
+ new_min,
+ self.max_adjustment.upper,
+ self.max_adjustment.step_increment,
+ self.max_adjustment.page_increment,
+ self.max_adjustment.page_size)
+ self.max_adjustment.changed()
+
+ if self.layer.max_get(self.src_index) > self.max_adjustment.upper:
+ self.min_adjustment.set_all( new_min,
+ self.min_adjustment.lower,
+ self.layer.max_get(self.src_index),
+ self.min_adjustment.step_increment,
+ self.min_adjustment.page_increment,
+ self.min_adjustment.page_size)
+ self.min_adjustment.changed()
+ self.max_adjustment.set_all( new_min,
+ self.max_adjustment.lower,
+ self.layer.max_get(self.src_index),
+ self.max_adjustment.step_increment,
+ self.max_adjustment.page_increment,
+ self.max_adjustment.page_size)
+ self.max_adjustment.changed()
+
+ self.min_adjustment.set_value(new_min)
+ self.min_entry.set_text(str(new_min))
+
+ self.max_adjustment.set_value(self.layer.max_get(self.src_index))
+ self.max_entry.set_text(str(self.layer.max_get(self.src_index)))
+ nodata=self.layer.nodata_get(self.src_index)
+ if type(nodata) == type((1,)):
+ self.nodata_entry.set_text(str(nodata[0])+'+'+str(nodata[1])+
+ 'j')
+ else:
+ self.nodata_entry.set_text(str(nodata))
+
+ self.const_entry.set_text( \
+ str(self.layer.get_const_value(self.src_index)))
+
+ if self.layer.get_data(self.src_index) is None:
+ self.const_entry.show()
+ self.min_hbox.hide()
+ self.max_hbox.hide()
+ self.nodata_hbox.hide()
+ self.band_combo.entry.set_text('constant')
+ else:
+ self.const_entry.hide()
+ self.max_hbox.show()
+ if ((self.layer.get_mode() != gview.RLM_COMPLEX) and
+ (band_is_complex(self.layer,self.src_index) == 0)):
+ self.min_hbox.show()
+ else:
+ self.min_hbox.hide()
+ self.nodata_hbox.show()
+
+ # Set the band selector.
+ band = self.layer.get_data(self.src_index).get_band()
+ dataset = self.layer.get_data(self.src_index).get_dataset()
+ for iband in range(dataset.RasterCount):
+ test_band = dataset.GetRasterBand(iband+1)
+ if test_band._o == band._o:
+ self.band_combo.entry.set_text(self.band_desc(iband+1))
+ break
+
+ self.updating = FALSE
+
+ def set_band_cb(self,*args):
+ if self.updating:
+ return
+
+ if self.band_combo.entry.get_text() == 'constant':
+ self.layer.set_source(self.src_index, None,
+ self.layer.min_get(self.src_index),
+ self.layer.max_get(self.src_index),
+ self.layer.get_const_value(self.src_index),
+ self.layer.source_get_lut(self.src_index),
+ None)
+ else:
+ try:
+ tokens = self.__bandDic[self.band_combo.entry.get_text()],
+ except KeyError :
+ tokens = ""
+
+ try:
+ band_number = int(tokens[0])
+ except:
+ return
+
+ dataset = self.layer.get_parent().get_dataset()
+ raster = gview.manager.get_dataset_raster( dataset, band_number )
+ if raster is not None:
+ if( self.layer.get_property('_scale_lock') is not None and
+ self.layer.get_property('_scale_lock') == 'locked' ) :
+
+ if( self.layer.get_property("_scale_limits") ) :
+ rasterMin, rasterMax = \
+ map(atof, split(self.layer.get_property("_scale_limits")))
+ else :
+ rasterMin = raster.get_min()
+ rasterMax = raster.get_max()
+
+ self.layer.set_source(self.src_index, raster,
+ rasterMin, rasterMax,
+ self.layer.get_const_value(self.src_index),
+ self.layer.source_get_lut(self.src_index),
+ dataset.GetRasterBand(band_number).GetNoDataValue())
+
+ if self.src_index < 3 and self.master_dialog.greyscale_is_set():
+ self.master_dialog.enforce_greyscale(self.src_index)
+
+ # enable alpha support if user modifies alpha band.
+ if self.src_index == 3:
+ self.layer.blend_mode_set( RL_BLEND_FILTER )
+
+ self.gui_refresh()
+
+ def adjustment_cb(self,adjustment,*args):
+ if self.updating:
+ return
+
+ value = adjustment.value
+ if value < -1 or value > 1:
+ value = int(value*10) / 10.0
+
+ if adjustment == self.min_adjustment:
+ self.layer.min_set( self.src_index, value )
+ else:
+ self.layer.max_set( self.src_index, value )
+
+ if self.src_index < 3 and self.master_dialog.greyscale_is_set():
+ self.master_dialog.enforce_greyscale(self.src_index)
+
+
+ def entry_cb(self,entry,*args):
+ if self.updating:
+ return
+
+ try:
+ value = complex(entry.get_text())
+ except:
+ return
+
+ if entry == self.min_entry:
+ self.layer.min_set( self.src_index, value.real )
+ elif entry == self.max_entry:
+ self.layer.max_set( self.src_index, value.real )
+ else:
+ self.layer.nodata_set( self.src_index, value.real, value.imag )
+
+ if self.src_index < 3 and self.master_dialog.greyscale_is_set():
+ self.master_dialog.enforce_greyscale(self.src_index)
+
+ def const_cb(self,entry,*args):
+ if self.updating:
+ return
+
+ try:
+ self.layer.set_source(self.src_index,
+ self.layer.get_data(self.src_index),
+ self.layer.min_get(self.src_index),
+ self.layer.max_get(self.src_index),
+ int(entry.get_text()),
+ self.layer.source_get_lut(self.src_index),
+ self.layer.nodata_get(self.src_index))
+ except:
+ self.const_entry.set_text( \
+ str(self.layer.get_const_value(self.src_index)))
+
+ # enable alpha support if user modifies alpha band.
+ if self.src_index == 3:
+ self.layer.blend_mode_set( RL_BLEND_FILTER )
+
+ if self.src_index < 3 and self.master_dialog.greyscale_is_set():
+ self.master_dialog.enforce_greyscale(self.src_index)
+
+class GvRasterPropDialog(GtkWindow):
+
+ def __init__(self, layer):
+ GtkWindow.__init__(self)
+ self.set_border_width(3)
+ if layer is not None:
+ self.set_title(layer.get_name()+' Properties')
+ else:
+ self.set_title('Raster Properties')
+
+ gvhtml.set_help_topic( self, "gvrasterpropdlg.html" )
+ self.layer = layer
+ self.updating = FALSE
+
+ if self.layer is not None:
+ self.display_change_id = self.layer.connect('display-change',
+ self.refresh_cb)
+ self.teardown_id = layer.connect('teardown',self.close)
+
+
+ # create the general layer properties dialog
+ self.create_notebook()
+
+ self.create_pane1()
+
+ self.updating = TRUE
+ self.create_sourcepane()
+ self.updating = FALSE
+
+ self.create_openglprop()
+ self.create_lutprop()
+ self.create_projprop()
+ self.create_imageinfo()
+
+ self.update_gui()
+ self.show_all()
+ self.update_gui()
+
+ for source in self.sources:
+ source.gui_refresh()
+
+ def __del__(self):
+ print 'disconnect:', self.display_change_id
+ self.layer.disconnect(self.display_change_id)
+
+ def create_notebook(self):
+ self.notebook = GtkNotebook()
+ self.add( self.notebook )
+ self.connect('delete-event', self.close)
+
+ def create_lutprop(self):
+
+ self.lut_pane = GtkVBox(spacing=10)
+ self.lut_pane.set_border_width(10)
+ self.notebook.append_page( self.lut_pane, GtkLabel('LUT'))
+
+ self.lut_preview = GtkPreview()
+ self.lut_preview.size(256,32)
+ self.lut_pane.pack_start(self.lut_preview)
+
+ self.complex_lut_om = \
+ gvutils.GvOptionMenu(('Magnitude', 'Phase',
+ 'Magnitude & Phase', 'Real','Imaginary'),
+ self.complex_lut_cb)
+ self.lut_pane.pack_start(self.complex_lut_om, expand=FALSE)
+
+ def create_sourcepane(self):
+ self.sources = []
+ self.source_pane = GtkVBox(spacing=10)
+ self.source_pane.set_border_width(10)
+ self.notebook.append_page( self.source_pane, GtkLabel('Raster Source'))
+
+ if self.layer.get_mode() == gview.RLM_RGBA:
+
+ source = GvRasterSource('Red',self.layer,0,self)
+ self.source_pane.pack_start(source, expand=FALSE)
+ self.sources.append(source)
+
+ source = GvRasterSource('Green',self.layer,1,self)
+ self.source_pane.pack_start(source, expand=FALSE)
+ self.sources.append(source)
+
+ source = GvRasterSource('Blue',self.layer,2,self)
+ self.source_pane.pack_start(source, expand=FALSE)
+ self.sources.append(source)
+
+ source = GvRasterSource('Alpha',self.layer,3,self)
+ self.source_pane.pack_start(source, expand=FALSE)
+ self.sources.append(source)
+
+ self.grey_toggle = GtkCheckButton(label='Greyscale Lock')
+ self.grey_toggle.connect('toggled', self.greyscale_cb)
+ self.source_pane.pack_start(self.grey_toggle, expand=FALSE)
+ self.grey_toggle.set_active( self.greyscale_is_set() )
+
+ scaleHBox = GtkHBox(spacing=10)
+ self.scale_toggle = GtkCheckButton(label="Scale Lock")
+ self.scale_min_entry = GtkEntry()
+ self.scale_max_entry = GtkEntry()
+ self.scale_min_entry.connect( "activate", self.activateLockEntry_cb )
+ self.scale_max_entry.connect( "activate", self.activateLockEntry_cb )
+ w, h = self.scale_min_entry.size_request()
+ self.scale_min_entry.set_usize(50, h)
+ self.scale_max_entry.set_usize(50, h)
+
+
+ scaleHBox.pack_start( self.scale_toggle )
+ scaleHBox.pack_start( self.scale_min_entry )
+ scaleHBox.pack_start( self.scale_max_entry )
+
+ self.scale_toggle.connect( "toggled", self.scalelock_cb)
+ self.source_pane.pack_start( scaleHBox, expand=FALSE )
+ self.scale_toggle.set_active( self.scalelock_is_set() )
+
+ else:
+ source = GvRasterSource('Raster',self.layer,0,self)
+ self.source_pane.pack_start(source, expand=FALSE)
+ self.sources.append(source)
+
+ def create_pane1(self):
+ # Setup General Properties Tab
+ self.pane1 = GtkVBox(spacing=10)
+ self.pane1.set_border_width(10)
+ self.notebook.append_page( self.pane1, GtkLabel('General'))
+
+ # Setup layer name entry box.
+ box = GtkHBox(spacing=5)
+ self.pane1.pack_start(box, expand=FALSE)
+ label = GtkLabel('Layer:' )
+ box.pack_start(label,expand=FALSE)
+ self.layer_name = GtkEntry()
+ self.layer_name.connect('changed', self.name_cb)
+ box.pack_start(self.layer_name)
+
+ # Setup Visibility radio buttons.
+ vis_box = GtkHBox(spacing=5)
+ self.pane1.pack_start(vis_box, expand=FALSE)
+ vis_box.pack_start(GtkLabel('Visibility:'),expand=FALSE)
+ self.vis_yes = GtkRadioButton(label='yes')
+ self.vis_yes.connect('toggled', self.visibility_cb)
+ vis_box.pack_start(self.vis_yes,expand=FALSE)
+ self.vis_no = GtkRadioButton(label='no',group=self.vis_yes)
+ self.vis_no.connect('toggled', self.visibility_cb)
+ vis_box.pack_start(self.vis_no,expand=FALSE)
+
+ # Setup Editability radio buttons.
+ edit_box = GtkHBox(spacing=5)
+ self.pane1.pack_start(edit_box, expand=FALSE)
+ edit_box.pack_start(GtkLabel('Editable:'),expand=FALSE)
+ self.edit_yes = GtkRadioButton(label='yes')
+ self.edit_yes.connect('toggled', self.edit_cb)
+ edit_box.pack_start(self.edit_yes,expand=FALSE)
+ self.edit_no = GtkRadioButton(label='no',group=self.edit_yes)
+ self.edit_no.connect('toggled', self.edit_cb)
+ edit_box.pack_start(self.edit_no,expand=FALSE)
+
+ def create_openglprop(self):
+ oglpane = GtkVBox(spacing=10)
+ oglpane.set_border_width(10)
+ self.notebook.append_page(oglpane, GtkLabel('Draw Style'))
+
+ # Create Modulation Color
+ box = GtkHBox(spacing=5)
+ oglpane.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Modulation Color:'),expand=FALSE)
+ self.mod_color = pgucolorsel.ColorControl('Modulation Color',
+ self.color_cb,None)
+ box.pack_start(self.mod_color)
+
+ # Create Interpolation Control
+ box = GtkHBox(spacing=5)
+ oglpane.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Subpixel Interpolation:'),expand=FALSE)
+ self.interp_om = gvutils.GvOptionMenu(('Linear','Off (Nearest)'), \
+ self.set_interp_cb)
+ box.pack_start(self.interp_om,expand=FALSE)
+
+ def create_projparms(self):
+ """Create projection parameters controls"""
+
+ self.parm_dict = {}
+ if self.proj_table is not None:
+ self.proj_table.destroy()
+ self.proj_table = GtkTable(2, len(self.proj_parms[self.proj_index]))
+ self.proj_table.set_border_width(5)
+ self.proj_table.set_row_spacings(5)
+ self.proj_table.set_col_spacings(5)
+ self.proj_table.show()
+ row = 0
+ for i in self.proj_parms[self.proj_index]:
+ parm_label = GtkLabel(i[1])
+ parm_label.set_alignment(0, 0.5)
+ self.proj_table.attach(parm_label, 0, 1, row, row + 1)
+ parm_label.show()
+ parm_value = self.sr.GetProjParm(i[0])
+ if parm_value is None:
+ parm_value = str(i[3])
+ parm_entry = GtkEntry()
+ parm_entry.set_text(str(parm_value))
+ self.parm_dict[i[0]] = parm_value
+ parm_entry.set_editable(TRUE)
+ parm_entry.connect('changed', self.parm_entry_cb, i[0])
+ self.proj_table.attach(parm_entry, 1, 2, row, row + 1)
+ parm_entry.show()
+ row += 1
+
+ self.proj_vbox.pack_end(self.proj_table, expand=FALSE)
+
+ def create_projprop(self):
+ projpane = GtkVBox(spacing=10)
+ projpane.set_border_width(10)
+ self.notebook.append_page(projpane, GtkLabel('Coordinate System'))
+
+ self.projprop_vbox = GtkVBox(spacing=5)
+
+ # Projection frame
+ proj_frame = GtkFrame('Projection')
+ proj_frame.show()
+ projpane.pack_start(proj_frame, expand=FALSE)
+ self.proj_vbox = GtkVBox(spacing=5)
+
+ # Fetch projection record
+ self.proj_full = ''
+ proj_name = ''
+ projection = self.layer.get_projection()
+
+ self.sr = None
+ if projection is not None and len(projection) > 0:
+ self.sr = osr.SpatialReference()
+ if self.sr.ImportFromWkt( projection ) == 0:
+ self.proj_full = self.sr.ExportToPrettyWkt( simplify = 1 )
+ if self.proj_full is None:
+ self.proj_full = ''
+ proj_name = self.sr.GetAttrValue("PROJECTION")
+ if proj_name is None:
+ proj_name = ''
+
+ # Create projection switch
+ proj_hbox = GtkHBox(spacing=5)
+ proj_hbox.pack_start(GtkLabel('Projection Name:'), \
+ expand=FALSE, padding=5)
+ proj_methods = osr.GetProjectionMethods()
+ self.projs = map(lambda x: x.__getitem__(0), proj_methods)
+ self.projs.insert(0, '')
+ proj_names = map(lambda x: x.__getitem__(1), proj_methods)
+ proj_names.insert(0, 'None')
+ self.proj_parms = map(lambda x: x.__getitem__(2), proj_methods)
+ self.proj_parms.insert(0, [])
+ self.proj_index = self.projs.index(proj_name)
+
+ self.proj_table = None
+ self.proj_om = gvutils.GvOptionMenu(proj_names, self.set_proj_cb)
+ self.create_projparms()
+ self.proj_om.set_history(self.proj_index)
+ proj_hbox.pack_start(self.proj_om, padding=5)
+ self.proj_vbox.pack_start(proj_hbox, expand=FALSE)
+
+ proj_frame.add(self.proj_vbox)
+
+ # Datum frame
+ datum_frame = GtkFrame('Datum')
+ datum_frame.show()
+ projpane.pack_start(datum_frame, expand=FALSE)
+ datum_hbox = GtkHBox(spacing=5)
+ datum_hbox.pack_start(GtkLabel('Datum Name:'), expand=FALSE, padding=5)
+
+ try:
+ self.datum_name = self.sr.GetAttrValue("DATUM")
+ except:
+ self.datum_name = None
+
+ self.datum_names = {None:"None", osr.SRS_DN_NAD27:"NAD27", \
+ osr.SRS_DN_NAD83:"NAD83", osr.SRS_DN_WGS72:"WGS72", \
+ osr.SRS_DN_WGS84:"WGS84"}
+ try:
+ self.datum_index = self.datum_names.keys().index(self.datum_name)
+ except ValueError:
+ self.datum_index = self.datum_names.keys().index(None)
+ self.datum_om = gvutils.GvOptionMenu(self.datum_names.values(), \
+ self.set_datum_cb)
+ self.datum_om.set_history(self.datum_index)
+ datum_hbox.pack_start(self.datum_om, expand=FALSE, padding=5)
+
+ datum_frame.add(datum_hbox)
+
+ # Units frame
+ units_frame = GtkFrame('Units')
+ #units_frame.show()
+ #projpane.pack_start(units_frame, expand=FALSE)
+ units_hbox = GtkHBox(spacing=5)
+ units_hbox.pack_start(GtkLabel('Units:'), expand=FALSE, padding=5)
+
+ units_frame.add(units_hbox)
+
+ # WKT frame
+ proj_text_frame = GtkFrame('Well Known Text')
+ proj_text_frame.show()
+ projpane.pack_end(proj_text_frame, expand=TRUE)
+
+ self.proj_text = GtkText()
+ self.proj_text.set_line_wrap(TRUE)
+ self.proj_text.set_word_wrap(FALSE)
+ self.proj_text.set_editable(FALSE)
+ self.proj_text.show()
+ self.proj_text.insert_defaults(self.proj_full)
+
+ proj_scrollwin = GtkScrolledWindow()
+ proj_scrollwin.set_usize(0, 300)
+ proj_scrollwin.add(self.proj_text)
+ proj_text_frame.add(proj_scrollwin)
+
+ def create_imageinfo(self):
+ iipane = GtkVBox(spacing=10)
+ iipane.set_border_width(10)
+ self.notebook.append_page( iipane, GtkLabel('Image Info') )
+
+ self.ii_text = GtkText()
+ self.ii_text.set_line_wrap(FALSE)
+ self.ii_text.set_word_wrap(FALSE)
+ self.ii_text.set_editable(FALSE)
+ self.ii_text.show()
+
+ self.ii_scrollwin = GtkScrolledWindow()
+ self.ii_scrollwin.add( self.ii_text)
+ iipane.pack_start(self.ii_scrollwin,expand=TRUE)
+
+ # Now create and assign the text contents.
+ gdal_ds = self.layer.get_parent().get_dataset()
+
+ text = ''
+
+ text = text + 'Filename: ' + gdal_ds.GetDescription() + '\n'
+
+ text = text + 'Size: ' + str(gdal_ds.RasterXSize) + 'P x '
+ text = text + str(gdal_ds.RasterYSize) + 'L x '
+ text = text + str(gdal_ds.RasterCount) + 'Bands\n'
+
+ driver = gdal_ds.GetDriver()
+ text = text + 'Driver: ' + driver.LongName + '\n'
+
+ transform = gdal_ds.GetGeoTransform()
+ if transform[2] == 0.0 and transform[4] == 0.0:
+ text = text + 'Origin: ' + str(transform[0]) \
+ + ' ' + str(transform[3]) + '\n'
+ text = text + 'Pixel Size: ' + str(transform[1]) \
+ + ' x ' + str(transform[5]) + '\n'
+
+ projection = gdal_ds.GetProjection()
+ if ((projection is None) or (len(projection) == 0)):
+ projection = gdal_ds.GetGCPProjection()
+
+ if projection is None:
+ projection=""
+
+ if len(projection) > 0:
+ sr = osr.SpatialReference()
+ if sr.ImportFromWkt( projection ) == 0:
+ projection = sr.ExportToPrettyWkt( simplify = 1 )
+
+ text = text + 'Projection:\n'
+ text = text + projection + '\n'
+
+ metadata = gdal_ds.GetMetadata()
+ if len(metadata) > 0:
+ text = text + 'Metadata:\n'
+ for item in metadata.items():
+ text = text + ' '+item[0]+': '+item[1]+'\n'
+
+ for band_index in range(gdal_ds.RasterCount):
+ band = gdal_ds.GetRasterBand(band_index+1)
+
+ text = text + 'Band %2d: Type=' % (band_index+1)
+ text = text + gdal.GetDataTypeName(band.DataType)
+ if len(band.GetDescription()) > 0:
+ text = text + ' - ' + band.GetDescription()
+ text = text + '\n'
+
+ self.ii_text.insert_defaults(text)
+
+ # Initialize GUI state from underlying object state.
+ def update_gui(self):
+ if self.layer is None or self.updating == TRUE:
+ return
+
+ self.updating = TRUE
+
+ # Layer name.
+ self.layer_name.set_text( self.layer.get_name() )
+
+ # Visibility radio buttons
+ self.vis_yes.set_active( self.layer.is_visible() )
+ self.vis_no.set_active( not self.layer.is_visible() )
+
+ # Editability radio buttons
+ self.edit_yes.set_active( not self.layer.is_read_only() )
+ self.edit_no.set_active( self.layer.is_read_only() )
+
+ # modulation color
+ tflag, tcolor = self.layer.texture_mode_get()
+ if tflag == 0:
+ tcolor = (1,1,1,1)
+ self.mod_color.set_color(tcolor)
+
+ # Interpolation Mode
+ zmin, zmax = self.layer.zoom_get()
+ if zmax == RL_FILTER_BILINEAR:
+ self.interp_om.set_history(0)
+ else:
+ self.interp_om.set_history(1)
+
+ self.updating = FALSE
+
+ # LUT
+ if self.layer.get_mode() != gview.RLM_RGBA:
+ lut_tuple = self.layer.lut_get()
+ else:
+ if self.greyscale_is_set() and band_is_complex(self.layer,0):
+ # Only show complex lut frame when bands are locked,
+ # because that's the only time it makes sense
+ # to apply non-magnitude luts.
+ lut_tuple = self.layer.lut_get(rgba_complex=1)
+ # Don't let the user modulate alpha by a band, because
+ # results won't make sense unless the LUT is magnitude
+ # (when alpha is not constant, it uses the red component
+ # of the lookup table for the modulating band- this will
+ # give the expected behaviour if the LUT is magnitude,
+ # but will give non-sensible results if the LUT
+ # is phase).
+ self.sources[3].hide()
+ else:
+ lut_tuple = self.layer.lut_get()
+ self.sources[3].show()
+
+ if lut_tuple is None:
+ self.lut_pane.hide()
+ elif lut_tuple[2] == 1:
+ lut_rgba = lut_tuple[0]
+ lut_rgb = gview.rgba_to_rgb(lut_rgba)
+
+ self.lut_pane.show()
+ self.lut_preview.size(256,32)
+
+ for i in range(32):
+ self.lut_preview.draw_row( lut_rgb, 0, i, 256)
+
+ self.complex_lut_om.hide()
+ self.lut_preview.queue_draw()
+ else:
+ lut_rgba = lut_tuple[0]
+ lut_rgb = gview.rgba_to_rgb(lut_rgba)
+
+ self.lut_pane.show()
+ self.lut_preview.size(256,256)
+ for row in range(256):
+ row_data = lut_rgb[row*768:(row+1)*768]
+ self.lut_preview.draw_row( row_data, 0, row, 256)
+
+ self.complex_lut_om.show()
+ self.lut_preview.queue_draw()
+
+ def name_cb(self, *args):
+ if self.layer_name.get_text() != self.layer.get_name():
+ self.layer.set_name( self.layer_name.get_text() )
+
+ # Visibility changing
+ def visibility_cb( self, widget ):
+ self.layer.set_visible( self.vis_yes.active )
+
+ # Readonly changing
+ def edit_cb( self, widget ):
+ self.layer.set_read_only( self.edit_no.active )
+
+ def scalelock_is_set( self ) :
+ if( self.layer.get_property('_scale_lock') is not None and
+ self.layer.get_property('_scale_lock') == 'locked' ) :
+ return 1
+ else :
+ return 0
+
+ def activateLockEntry_cb( self, *args ) :
+ if( self.scale_toggle.get_active() ) :
+ self.scalelock_cb()
+
+ def scalelock_cb( self, *args ) :
+ if( self.scalelock_is_set() ) :
+ self.layer.set_property('_scale_lock', 'unlocked')
+ else :
+ self.layer.set_property('_scale_lock', 'locked' )
+
+ if( self.scalelock_is_set() ):
+ try :
+ min_scale = atof( self.scale_min_entry.get_text() )
+ max_scale = atof( self.scale_max_entry.get_text() )
+ except ValueError :
+ min_scale, max_scale = self.layer.min_get(0), self.layer.max_get(0)
+ self.scale_min_entry.set_text( str(min_scale) )
+ self.scale_max_entry.set_text( str(max_scale) )
+
+ self.layer.set_property \
+ ('_scale_limits', str(min_scale) + ' ' + str(max_scale) )
+
+ for iSource in [0,1,2] :
+ self.layer.min_set(iSource, min_scale)
+ self.layer.max_set(iSource, max_scale)
+
+ def greyscale_is_set(self):
+ if self.layer.get_property('_greyscale_lock') is not None \
+ and self.layer.get_property('_greyscale_lock') == 'locked':
+ return 1
+ else:
+ return 0
+
+ def greyscale_cb(self, *args):
+ if self.greyscale_is_set():
+ self.layer.set_property('_greyscale_lock','unlocked')
+
+ if self.layer.get_mode() == gview.RLM_RGBA:
+ self.complex_lut_om.set_history(0)
+ self.layer.complex_lut('magnitude')
+ else:
+ self.layer.set_property('_greyscale_lock','locked')
+
+ self.grey_toggle.set_active( self.greyscale_is_set() )
+
+ if self.greyscale_is_set():
+ self.enforce_greyscale(0)
+
+ # show/hide lut as necessary
+ self.update_gui()
+
+ def enforce_greyscale(self, isrc):
+ if isrc != 0:
+ self.layer.set_source(0, self.layer.get_data(isrc),
+ self.layer.min_get(isrc),
+ self.layer.max_get(isrc),
+ self.layer.get_const_value(isrc),
+ self.layer.source_get_lut(isrc),
+ self.layer.nodata_get(isrc))
+
+ if isrc != 1:
+ self.layer.set_source(1, self.layer.get_data(isrc),
+ self.layer.min_get(isrc),
+ self.layer.max_get(isrc),
+ self.layer.get_const_value(isrc),
+ self.layer.source_get_lut(isrc),
+ self.layer.nodata_get(isrc))
+
+ if isrc != 2:
+ self.layer.set_source(2, self.layer.get_data(isrc),
+ self.layer.min_get(isrc),
+ self.layer.max_get(isrc),
+ self.layer.get_const_value(isrc),
+ self.layer.source_get_lut(isrc),
+ self.layer.nodata_get(isrc))
+
+ # In multi-band complex case, reset alpha band to a constant
+ if band_is_complex(self.layer,0):
+ self.layer.set_source(3, None,
+ self.layer.min_get(3),
+ self.layer.max_get(3),
+ self.layer.get_const_value(3),
+ self.layer.source_get_lut(3),
+ None)
+
+ def complex_lut_cb(self, *args):
+ # Magnitude
+ if self.complex_lut_om.get_history() == 0:
+ method = 'magnitude'
+
+ # Phase
+ elif self.complex_lut_om.get_history() == 1:
+ method = 'phase'
+
+ # Magnitude and Phase
+ elif self.complex_lut_om.get_history() == 2:
+ method = 'magphase'
+
+ # Real
+ elif self.complex_lut_om.get_history() == 3:
+ method = 'real'
+
+ # Imaginary
+ elif self.complex_lut_om.get_history() == 4:
+ method = 'imaginary'
+
+ self.layer.complex_lut( method )
+
+ self.update_gui()
+
+ # Set modulation color
+ def color_cb( self, color, type ):
+ #if color[0] == 1.0 and color[1] == 1.0 \
+ # and color[2] == 1.0 and color[3] == 1.0:
+ # pass
+ #else:
+ if color[3] != 1.0:
+ self.layer.blend_mode_set( RL_BLEND_FILTER )
+ self.layer.texture_mode_set( 1, color )
+
+
+ def set_interp_cb(self,*args):
+ if self.interp_om.get_history() == 0:
+ self.layer.zoom_set(RL_FILTER_BILINEAR,RL_FILTER_BILINEAR)
+ else:
+ self.layer.zoom_set(RL_FILTER_NEAREST,RL_FILTER_NEAREST)
+
+ def update_proj_text(self):
+ """Update text control showing projection information"""
+ self.proj_full = self.sr.ExportToPrettyWkt( simplify = 1 )
+ if self.proj_full is None:
+ self.proj_full = ''
+ self.proj_text.delete_text(0, self.proj_text.get_length())
+ self.proj_text.insert_defaults(self.proj_full)
+
+ def parm_entry_cb(self, entry, parm):
+ """Set projection parameters"""
+ self.parm_dict[parm] = float(entry.get_text())
+ self.sr.SetNormProjParm(parm, self.parm_dict[parm])
+
+ self.update_proj_text()
+
+ def set_proj_cb(self,*args):
+ """Set projection"""
+ if self.proj_index != self.proj_om.get_history():
+ self.proj_index = self.proj_om.get_history()
+ self.sr = osr.SpatialReference()
+ self.sr.SetWellKnownGeogCS(self.datum_names[self.datum_name])
+ self.sr.SetProjection(self.projs[self.proj_index])
+ for i in self.proj_parms[self.proj_index]:
+ try:
+ self.sr.SetNormProjParm(i[0], self.parm_dict[i[0]])
+ except KeyError:
+ self.sr.SetNormProjParm(i[0], i[3])
+ self.layer.set_projection(self.sr.ExportToWkt())
+ self.create_projparms()
+
+ self.update_proj_text()
+
+ def set_datum_cb(self, *args):
+ """Set datum"""
+ if self.datum_index != self.datum_om.get_history():
+ self.datum_index = self.datum_om.get_history()
+ self.datum_name = self.datum_names.keys()[self.datum_index]
+ self.sr.SetWellKnownGeogCS(self.datum_names[self.datum_name])
+ self.update_proj_text()
+
+ # Dialog closed, remove references to python object
+ def close( self, *args ):
+ prop_dialog_list.remove(self)
+ self.layer.disconnect(self.display_change_id)
+ self.layer.disconnect(self.teardown_id)
+
+ self.sources = None
+ self.layer = None
+ self.destroy()
+
+ # Force GUI Refresh
+ def refresh_cb( self, widget, args ):
+ self.update_gui()
+
+def band_is_complex(layer,src_index):
+ """ Returns 1 if src_index'th band of layer is present
+ and complex; 0 otherwise.
+ """
+
+ try:
+ srctype=layer.get_data(src_index).get_band().DataType
+ ctypes=[gdal.GDT_CInt16, gdal.GDT_CInt32, gdal.GDT_CFloat32,
+ gdal.GDT_CFloat64]
+ if srctype in ctypes:
+ return 1
+
+ return 0
+ except:
+ return 0
+
+if __name__ == '__main__':
+ dialog = GvRasterPropDialog(None)
+ dialog.connect('delete-event', mainquit)
+
+ mainloop()
Added: packages/openev/branches/upstream/current/pymod/gvsdsdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvsdsdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvsdsdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,162 @@
+##############################################################################
+# $Id: gvsdsdlg.py,v 1.4 2003/09/09 15:18:46 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Subdataset Selection Dialog
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvsdsdlg.py,v $
+# Revision 1.4 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.3 2003/01/08 03:25:18 warmerda
+# avoid having any lines selected
+#
+# Revision 1.2 2003/01/07 03:38:09 warmerda
+# added better on/off icons
+#
+# Revision 1.1 2001/06/27 14:33:17 warmerda
+# New
+#
+#
+
+from gtk import *
+import gview
+import os.path
+import gvhtml
+
+
+class GvSDSDlg(GtkWindow):
+ def __init__(self, dataset, viewwindow):
+ GtkWindow.__init__(self)
+ self.set_title('SubDataset Selection')
+ self.set_usize(400, 300)
+ self.set_border_width(3)
+ self.set_policy(TRUE,TRUE,FALSE)
+ self.connect('delete-event',self.close)
+ shell = GtkVBox(spacing=3)
+ self.add(shell)
+ #gvhtml.set_help_topic(self, "layerdlg.html" );
+
+ # Layer list
+ layerbox = GtkScrolledWindow()
+ shell.pack_start(layerbox)
+ layerlist = GtkCList(cols=2)
+
+ layerbox.add_with_viewport(layerlist)
+ layerlist.set_shadow_type(SHADOW_NONE)
+ layerlist.set_selection_mode(SELECTION_SINGLE)
+ layerlist.set_row_height(30)
+ layerlist.set_column_width(0, 24)
+ #layerlist.connect('select-row', self.layer_selected)
+ layerlist.connect('button-press-event', self.list_clicked)
+
+ # buttons
+ button_box = GtkHButtonBox()
+ button_box.set_layout_default(BUTTONBOX_START)
+ ok_button = GtkButton('Accept')
+ ok_button.connect('clicked', self.accept)
+ apply_button = GtkButton('Cancel')
+ apply_button.connect('clicked', self.close)
+ cancel_button = GtkButton('Help')
+ cancel_button.connect('clicked', self.help_cb)
+ button_box.pack_start(ok_button, expand=FALSE)
+ button_box.pack_start(apply_button, expand=FALSE)
+ button_box.pack_start(cancel_button, expand=FALSE)
+ shell.pack_start(button_box,expand=FALSE)
+
+ self.connect('realize', self.realize)
+
+ self.sel_pixmap = \
+ GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'ck_on_l.xpm'))
+ self.not_sel_pixmap = \
+ GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'ck_off_l.xpm'))
+
+ shell.show_all()
+
+ self.dataset = dataset
+ self.viewwindow = viewwindow
+ self.layerlist = layerlist
+
+ self.sds = dataset.GetSubDatasets()
+ self.sds_sel = []
+ for entry in self.sds:
+ self.sds_sel.append( 0 )
+
+ self.show_all()
+
+ def help_cb(self,*args):
+ pass
+
+ def close(self,*args):
+ self.hide()
+ return TRUE
+
+ def accept(self,*args):
+ for i in range(len(self.sds_sel)):
+ if self.sds_sel[i]:
+ self.viewwindow.file_open_by_name( self.sds[i][0] )
+ self.close()
+
+ def realize(self, widget):
+ lst = self.layerlist
+ sds = self.sds
+
+ lst.freeze()
+ lst.clear()
+
+ i = 0
+ for entry in sds:
+ lst.append(('', entry[1]))
+
+ lst.set_pixmap(i, 0, self.not_sel_pixmap)
+
+ i = i + 1
+
+ lst.thaw()
+
+ def list_clicked(self, lst, event):
+ #print event.type
+
+ row, col = lst.get_selection_info(int(event.x), int(event.y))
+ lst.emit_stop_by_name('button-press-event')
+
+ if event.type is GDK._2BUTTON_PRESS:
+ for i in range(len(self.sds_sel)):
+ self.sds_sel[i] = 0
+
+ self.sds_sel[row] = 1
+ self.accept()
+ else:
+ self.sds_sel[row] = not self.sds_sel[row]
+
+ if self.sds_sel[row]:
+ lst.set_pixmap(row, 0, self.sel_pixmap)
+ else:
+ lst.set_pixmap(row, 0, self.not_sel_pixmap)
+
+
Added: packages/openev/branches/upstream/current/pymod/gvselbrowser.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvselbrowser.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvselbrowser.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,336 @@
+###############################################################################
+# $Id: gvselbrowser.py,v 1.4 2001/11/09 15:41:49 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: GUI component to show the current list of selected objects, and
+# to control a single sub-selection out of that set.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2001, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvselbrowser.py,v $
+# Revision 1.4 2001/11/09 15:41:49 warmerda
+# avoid using negative oids
+#
+# Revision 1.3 2001/04/23 15:22:47 warmerda
+# added callback on oid text field
+#
+# Revision 1.2 2001/04/19 22:07:53 warmerda
+# avoid use of +=
+#
+# Revision 1.1 2001/04/09 18:26:46 warmerda
+# New
+#
+#
+
+from gtk import *
+from string import *
+from gvsignaler import *
+import os.path
+import pgu
+import gview
+import gvutils
+
+class GvSelBrowser(GtkVBox):
+
+ def __init__(self, spacing=10):
+ GtkVBox.__init__(self, spacing=spacing)
+
+ self.updating = 0
+
+ self.sel_manager = gview.app.sel_manager
+
+ self.sel_manager.subscribe('active-layer-changed', self.update_gui)
+ self.sel_manager.subscribe('selection-changed', self.update_gui)
+ self.sel_manager.subscribe('subselection-changed', self.update_gui)
+
+ self.tooltips = GtkTooltips()
+
+ hbox = GtkHBox(spacing=3)
+ self.pack_start(hbox,expand=FALSE)
+ self.hbox = hbox
+
+ hbox.pack_start(GtkLabel('Shape:'),expand=FALSE)
+
+ self.oid_tb = GtkEntry(maxlen=7)
+ self.oid_tb.connect('activate', self.oid_cb)
+ self.oid_tb.connect('focus-out-event', self.oid_cb)
+ hbox.pack_start(self.oid_tb)
+
+ left_button = GtkButton()
+ left_button.add(GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'pan_left.xpm')))
+ self.tooltips.set_tip(left_button,'Cycle Selection Down')
+ left_button.connect('clicked', self.cycle_down)
+ hbox.pack_start(left_button,expand=FALSE)
+
+ self.n_of_n_label = GtkLabel('XXXX of XXXX')
+ hbox.pack_start(self.n_of_n_label)
+
+ right_button = GtkButton()
+ right_button.add(GtkPixmap(self,os.path.join(gview.home_dir,'pics',
+ 'pan_rght.xpm')))
+ self.tooltips.set_tip(left_button,'Cycle Selection Up')
+ right_button.connect('clicked', self.cycle_up)
+ hbox.pack_start(right_button, expand=FALSE)
+
+ hbox = GtkHBox(spacing=3)
+ self.pack_start(hbox)
+ self.layer_label = GtkLabel('XXXXXXXXXXXXXXXXXXXXXXXXXXX')
+ self.layer_label.set_justify( JUSTIFY_LEFT )
+ hbox.pack_start(self.layer_label, expand=FALSE)
+
+ self.connect('unrealize', self.close)
+
+ self.update_gui()
+ self.show_all()
+
+ def close(self, *args):
+ self.sel_manager.unsubscribe('active-layer-changed', self.update_gui)
+ self.sel_manager.unsubscribe('selection-changed', self.update_gui)
+ self.sel_manager.unsubscribe('subselection-changed', self.update_gui)
+
+ def update_gui(self, *args):
+ self.updating = 1
+ layer = self.sel_manager.get_active_layer()
+ if layer is None:
+ self.layer_label.set_text('Layer: <none selected>')
+ else:
+ self.layer_label.set_text('Layer: '+layer.get_name())
+
+ try:
+ layer = self.sel_manager.get_active_layer()
+ selected = layer.get_selected()
+ subsel = layer.get_subselected()
+ except:
+ self.n_of_n_label.set_text('0 of 0')
+ self.oid_tb.set_text('')
+ self.updating = 0
+ return
+
+ self.oid_tb.set_text(str(subsel))
+
+ index_of = self.get_sel_index(subsel,selected)
+
+ label = '%d of %d' % (index_of+1, len(selected))
+ self.n_of_n_label.set_text(label)
+
+ self.updating = 0
+
+ def oid_cb(self, *args):
+ if self.updating:
+ return
+
+ try:
+ new_oid = int(self.oid_tb.get_text())
+ layer = self.sel_manager.get_active_layer()
+ selected = layer.get_selected()
+ if new_oid in selected:
+ layer.subselect_shape( new_oid )
+ else:
+ layer.clear_selection()
+ if new_oid >= 0:
+ layer.select_shape( new_oid )
+
+ layer.display_change()
+ except:
+ pass
+
+ def cycle_down(self, *args):
+ try:
+ layer = self.sel_manager.get_active_layer()
+ selected = layer.get_selected()
+ except:
+ return
+
+ index_of = self.get_sel_index( layer.get_subselected(), selected )
+ if index_of > 0:
+ layer.subselect_shape( selected[index_of-1] )
+
+ def cycle_up(self, *args):
+ try:
+ layer = self.sel_manager.get_active_layer()
+ selected = layer.get_selected()
+ except:
+ return
+
+ index_of = self.get_sel_index( layer.get_subselected(), selected )
+ if index_of < len(selected)-1:
+ layer.subselect_shape( selected[index_of+1] )
+
+ def get_sel_index(self, subsel, selected):
+ index_of = 0
+ while index_of < len(selected) \
+ and selected[index_of] != subsel:
+ index_of = index_of + 1
+
+ if index_of >= len(selected):
+ return -1
+ else:
+ return index_of
+
+class GvSelectionManager(Signaler):
+
+ """
+ Convenient manager for view, layer, and shape selection tracking.
+
+ The GvSelectionManager provides a single object which can be easily
+ used to track changes in current view, layer, shape selection and shape
+ sub-selection. This is mainly useful because adding and removing
+ callbacks to individual layers and views is a hassle.
+
+ This class is normally accessed as "gview.app.sel_manager", and the
+ object instance is normally created by the openev.py startup. The
+ object publishes the following "gvsignaler.py" style signals. Use
+ the "subscribe" method to add a callback.
+
+ active-view-changed -- The current application view has changed (as
+ understood by openev.ViewManager).
+
+ active-layer-changed -- The current layer of the active view (as returned
+ by GvViewArea.active_layer()) has changed, possibly
+ as a result of the current view changing.
+
+ selection-changed -- The shape selection on the current layer (as
+ GvShapeLayer.get_selected()) has changed, possibly
+ as a result of a change of active layer or view.
+ Clearing selection, and selecting non-GvShapeLayers
+ can result in a selection-changed.
+
+ subselection-changed -- The item within the current selection has
+ changed, possible as the result of a change in
+ selection, active layer or active view.
+
+ """
+
+ def __init__(self, view_manager):
+
+ self.view_manager = view_manager
+ self.view_manager.subscribe('active-view-changed',self.view_change)
+
+ self.view = self.view_manager.get_active_view()
+ if self.view is not None:
+ self.view_cb_id \
+ = self.view.connect('active-changed', self.layer_change)
+ else:
+ self.view_cb_id = None
+
+ self.layer = None
+ self.layer_selcb_id = None
+ self.layer_sselcb_id = None
+
+ self.sel_len = 0
+ self.ssel = -1
+ self.ssel_layer = None
+
+ self.publish('active-view-changed')
+ self.publish('active-layer-changed')
+ self.publish('selection-changed')
+ self.publish('subselection-changed')
+
+ self.layer_change()
+
+ def view_change(self, *args):
+ if self.view == self.view_manager.get_active_view():
+ return
+
+ if self.view_cb_id is not None:
+ self.view.disconnect(self.view_cb_id)
+ self.view_cb_id = None
+
+ self.view = self.view_manager.get_active_view()
+
+ if self.view is not None:
+ self.view_cb_id \
+ = self.view.connect('active-changed', self.layer_change)
+
+ self.notify('active-view-changed')
+ self.layer_change()
+
+ def get_active_view_window(self):
+ """Fetch active GvViewWindow."""
+ return self.view_manager.get_active_view_window()
+
+ def get_active_view(self):
+ """Fetch active GvViewArea."""
+ return self.view_manager.get_active_view()
+
+ def layer_change(self, *args):
+ if self.view is None:
+ new_layer = None
+ else:
+ new_layer = self.view.active_layer()
+
+ if new_layer == self.layer:
+ return
+
+ if self.layer_selcb_id is not None:
+ self.layer.disconnect(self.layer_selcb_id)
+ self.layer.disconnect(self.layer_sselcb_id)
+ self.layer_selcb_id = None
+
+ self.layer = new_layer
+
+ if self.layer is not None \
+ and gvutils.is_of_class(self.layer.__class__, 'GvShapeLayer'):
+ self.layer_selcb_id = \
+ self.layer.connect('selection-changed',self.sel_change)
+ self.layer_sselcb_id = \
+ self.layer.connect('subselection-changed',self.ssel_change)
+
+ self.notify('active-layer-changed')
+ self.sel_change()
+ self.ssel_change()
+
+ def get_active_layer(self):
+ return self.layer
+
+ def sel_change(self,*args):
+ try:
+ new_len = len(self.layer.get_selected())
+ except:
+ new_len = 0
+
+ if new_len == 0 and self.sel_len == 0:
+ return
+
+ self.sel_len = new_len
+ self.notify('selection-changed')
+
+ def ssel_change(self,*args):
+
+ try:
+ new_ssel = self.layer.get_subselected()
+ except:
+ new_ssel = -1
+
+ if new_ssel == -1 and self.ssel == -1:
+ return
+
+ if self.ssel_layer == self.layer and new_ssel == self.ssel:
+ return
+
+ self.ssel_layer = self.layer
+ self.ssel = new_ssel
+
+ self.notify('subselection-changed')
+
+
+pgu.gtk_register('GvSelBrowser',GvSelBrowser)
Added: packages/openev/branches/upstream/current/pymod/gvshell.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvshell.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvshell.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,153 @@
+###############################################################################
+# $Id: gvshell.py,v 1.5 2003/07/30 15:31:12 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Extra intrinsics for OpenEV PyShell environment. Used from
+# gviewapp.pyshell().
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvshell.py,v $
+# Revision 1.5 2003/07/30 15:31:12 gmwalter
+# Update display() function so it can display 1-D arrays.
+#
+# Revision 1.4 2003/07/28 19:42:34 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.3 2002/09/12 15:02:54 warmerda
+# removed problematic import
+#
+# Revision 1.2 2001/11/12 18:47:47 warmerda
+# Fixed formatting of shape info in local_vars_list.
+#
+# Revision 1.1 2001/11/12 18:44:35 warmerda
+# New
+#
+
+import gview
+import gdalnumeric
+import gdal
+
+###############################################################################
+# define easy file view command
+def display(array, prototype_name = None):
+ import Numeric
+ if len(Numeric.shape(array)) == 1:
+ array=Numeric.reshape(array,(1,Numeric.shape(array)[0]))
+
+ array_name = gdalnumeric.GetArrayFilename(array)
+ ds = gview.manager.get_dataset( array_name )
+ if prototype_name is not None:
+ prototype_ds = gdal.Open( prototype_name )
+ gdalnumeric.CopyDatasetInfo( prototype_ds, ds )
+
+ gview.app.file_open_by_name( array_name )
+
+###############################################################################
+# Utility to get ROI marked with tool from array
+def get_roi(num_array):
+ roi = gview.app.toolbar.get_roi()
+
+ x1 = int(roi[0])
+ y1 = int(roi[1])
+ x2 = int(roi[0] + roi[2]) + 1
+ y2 = int(roi[1] + roi[3]) + 1
+
+ return num_array[...,y1:y2,x1:x2]
+
+###############################################################################
+def roi():
+ return gview.app.toolbar.get_roi()
+
+
+###############################################################################
+# local_vars_list()
+#
+# This function is invoked on locals() by entering "locals" in the
+# pyshell.py command window. The MyInteractiveConsole.push() method
+# intercepts the input line and replaces 'locals' with the call.
+#
+# This function attempts to print out a list of all local variables in the
+# command environment that have been defined since the shell was instantiated.
+# This is accomplished by keeping a list of variables (and methods) at the
+# startup time in the gview.shell_base_vars variable. This is done by
+# the GViewApp.pyshell() function.
+#
+# All objects existing at startup time are ignored, all others are listed for
+# the user.
+#
+# An attempt is made to distinguish between NumPy arrays, and other variables.
+# Numpy arrays will have their shape and type printed in a user friendly
+# (hopefully) manner, while other locals are printed with just their name,
+# and type.
+#
+def local_vars_list( var_list = None, typestrings=None ):
+ """local_vars_list( var_list = None, typestrings=None)
+ var_list: list of variables to search through
+ typestrings: list of types to include (strings
+ corresponding to type(var).__name__,
+ where var is a variable of the type
+ to search for).
+ """
+
+ import Numeric
+ img_type = type(Numeric.array((1,2)))
+
+ type_dict = {'b': 'UnsignedInt8', 'D': 'CFloat64', 'F':'CFloat32',
+ 'd': 'Float64', 'f': 'Float32', 'l': 'Int32',
+ '1': 'Int8', 's': 'Int16', 'i': 'Int32' }
+
+ list = var_list.keys()
+ txtlist=[]
+ for varname in list:
+ if varname in gview.shell_base_vars:
+ continue
+
+ var = var_list[varname]
+ t = type(var)
+
+ # Only show variables of type typestring
+ if ((typestrings is not None) and
+ (t.__name__ not in typestrings)):
+ continue
+
+ if t == img_type:
+ shape = Numeric.shape(var)
+ shape_str = None
+ for dim in shape:
+ if shape_str == None:
+ shape_str = ') '
+ else:
+ shape_str = 'x' + shape_str
+
+ shape_str = str(dim) + shape_str
+ shape_str = ' (' + shape_str
+
+ try:
+ txtlist.append(varname+ shape_str+ type_dict[var.typecode()])
+ except:
+ txtlist.append(varname+ shape_str+ var.typecode())
+ else:
+ txtlist.append('%s (%s)' % (varname, t.__name__))
+
+ return txtlist
+
Added: packages/openev/branches/upstream/current/pymod/gvsignaler.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvsignaler.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvsignaler.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,125 @@
+###############################################################################
+# $Id: gvsignaler.py,v 1.6 2003/01/07 18:44:32 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Signaler - implements subscription/notification system a bit like
+# Gtk signaling.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvsignaler.py,v $
+# Revision 1.6 2003/01/07 18:44:32 gmwalter
+# Changed a tuple to a list to fix a blocking bug.
+#
+# Revision 1.5 2001/04/03 02:30:38 warmerda
+# fixed signal name typo
+#
+# Revision 1.4 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.3 2000/08/09 01:04:13 warmerda
+# fixed bug in unsubscribe
+#
+# Revision 1.2 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+
+"""
+MODULE
+ gvsignaler
+
+DESCRIPTION
+ Provides an event subscription/notification mechanism a bit like
+ Gtk signal handling. Classes which derive from Signaler can
+ publish a list of named signals. These signals can then be
+ attached to arbitrary callback methods/functions using subscribe().
+ More than one callback function per signal can be attached.
+ The Signaler executes the callback functions with the notify()
+ method.
+
+ Arguments to the callback functions are (in order):
+ 1. The Signaler instance.
+ 2. Any signal specific arguments provided to notify().
+ 3. Subscriber baggage arguments provided to subscribe().
+ The baggage arguments act like the 'data' argument of Gtk signals.
+"""
+
+class UnpublishedSignalError(Exception): pass
+class SignalExistsError(Exception): pass
+
+class Signaler:
+ "Base class for objects with published signals"
+ signal = {} # Prevents AttributeErrors
+
+ def publish(self, *sigs):
+ "Publish one or more named signals"
+ if not self.__dict__.has_key('signal'):
+ self.signal = {}
+ for s in sigs:
+ if self.signal.has_key(s):
+ raise SignalExistsError
+ self.signal[s] = [0, []] # Blocked flag, handlers list
+
+ def subscribe(self, name, meth, *args):
+ "Attach a callback function/method to a signal"
+ try:
+ self.signal[name][1].append((meth, args))
+ except KeyError:
+ raise UnpublishedSignalError
+
+ def unsubscribe(self, name, meth):
+ "Remove a callback function/method for a named signal"
+ try:
+ l = len(self.signal[name][1])
+ for si in range(l):
+ if self.signal[name][1][si][0] == meth:
+ del self.signal[name][1][si]
+ break
+ except KeyError:
+ raise UnpublishedSignalError
+
+ def notify(self, name, *args):
+ "Execute callbacks attached to the named signal"
+ try:
+ sig = self.signal[name]
+ except KeyError:
+ raise UnpublishedSignalError
+ # Check for blocked signal
+ if sig[0] == 0:
+ for s in sig[1]:
+ apply(s[0], (self,) + args + s[1])
+
+ def block(self, name):
+ "Prevent a signal from being emitted"
+ try:
+ self.signal[name][0] = 1
+ except KeyError:
+ raise UnpublishedSignalError
+
+ def unblock(self, name):
+ "Allows a blocked signal to be emitted"
+ try:
+ self.signal[name][0] = 0
+ except KeyError:
+ raise UnpublishedSignalError
+
+
Added: packages/openev/branches/upstream/current/pymod/gvutils.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvutils.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvutils.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1147 @@
+###############################################################################
+# $Id: gvutils.py,v 1.29 2004/10/15 16:52:20 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Convenience widgets, and services built on Gtk widgets.
+# Note that these will eventually be moved into an Atlantis wide
+# set of utility classes in python.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvutils.py,v $
+# Revision 1.29 2004/10/15 16:52:20 gmwalter
+# Bug fix in GvEntryFrame default value setting.
+#
+# Revision 1.28 2004/10/12 14:25:21 gmwalter
+# Added forgotten import.
+#
+# Revision 1.27 2004/10/07 19:02:34 gmwalter
+# Extract generic code into gvutils.py.
+#
+# Revision 1.26 2004/07/05 08:47:02 dem
+# don't raise a top level exception when a deserialization
+# of a layer fails in projects reloading
+#
+# Revision 1.25 2004/07/02 16:37:09 dem
+# - Implement project files portability
+# - Change to don't crash OpenEV when a deserialization
+# of a layer fails in projects reloading.
+# Popup a gvutils.warning instead.
+#
+# Revision 1.24 2003/08/28 19:50:18 warmerda
+# added XMLSerializeSimpleObjAttributes (and deserialize)
+#
+# Revision 1.23 2003/05/22 18:38:28 desch-mosher
+#
+# return from parse_accerator incorrectly shifted
+#
+# Revision 1.22 2003/05/09 13:48:34 warmerda
+# don't read more than 20 bytes in is_project_file()
+#
+# Revision 1.21 2003/01/18 22:50:01 gmwalter
+# Change XMLInsert to allow top-level insertion.
+#
+# Revision 1.20 2002/11/26 16:16:41 gmwalter
+# Added a few more xml functions, extended XMLFind (default behaviour should
+# be unchanged). These functions may be rewritten/replaced later.
+#
+# Revision 1.19 2002/10/21 01:25:48 warmerda
+# avoid use of system tempnam() to avoid annoyying warning
+#
+# Revision 1.18 2002/07/15 18:43:06 pgs
+# modified XMLFindValue to take an empty path (operate on current node)
+#
+# Revision 1.17 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.16 2002/07/08 19:46:03 warmerda
+# added project save/load capability
+#
+# Revision 1.15 2002/07/07 21:06:15 warmerda
+# preliminary addition of project saving
+#
+# Revision 1.14 2002/04/25 15:19:58 gmwalter
+# Updated the menu extension mechanism to get rid of the extend_menu function and to allow the help menu to remain on the right side of the menubar. Got rid of some extra print statements and the gnuplot 0 y-range warning in the histogram tool initialization.
+#
+# Revision 1.13 2002/04/18 16:47:17 warmerda
+# Python2.0 doesn't have os.tempnam(), provide alternative
+#
+# Revision 1.12 2002/04/17 14:43:20 warmerda
+# added FindExecutable()
+#
+# Revision 1.11 2002/04/17 13:42:20 warmerda
+# added tempnam() method
+#
+# Revision 1.10 2002/02/28 18:52:22 gmwalter
+# Added a point-of-interest tool similar to the region-of-interest
+# tool (allows a user to select a temporary point without having to add a
+# new layer). Added a mechanism to allow some customization of openev
+# via a textfile defining external modules.
+#
+# Revision 1.9 2001/05/16 00:46:05 pgs
+# change tolower to lower in is_shapefile
+#
+# Revision 1.8 2001/05/15 14:14:49 warmerda
+# added is_shapefile() function
+#
+# Revision 1.7 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.6 2000/08/24 17:52:12 warmerda
+# added error and warning calls
+#
+# Revision 1.5 2000/06/14 15:13:38 warmerda
+# moved registering and color selector to pygtkutils
+#
+# Revision 1.4 2000/06/12 20:16:31 warmerda
+# added is_of_class test
+#
+# Revision 1.3 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+import gtk; _gtk = gtk; del gtk
+import GtkExtra
+import string
+import pgu
+import os
+import sys
+import pgufilesel
+
+def is_of_class(class_obj,class_name):
+ if class_obj.__name__ == class_name:
+ return 1
+ for c in class_obj.__bases__:
+ if is_of_class(c,class_name) == 1:
+ return 1
+ return 0
+
+class GvOptionMenu(_gtk.GtkOptionMenu):
+
+ def __init__(self, contents, callback = None):
+ _gtk.GtkOptionMenu.__init__(self)
+
+ menu = _gtk.GtkMenu()
+ self.callback = callback
+
+ item_widget = None
+ counter = 0
+ for item in contents:
+ item_widget = _gtk.GtkRadioMenuItem( item_widget, item )
+ item_widget.show()
+ item_widget.connect('activate', self.set_om_selection,
+ counter )
+ menu.append(item_widget)
+ counter = counter + 1
+
+ self.cur_selection = 0
+ menu.show()
+ self.set_menu(menu)
+
+ def set_history(self, item):
+ if item == self.cur_selection:
+ return
+
+ self.cur_selection = item
+ _gtk.GtkOptionMenu.set_history( self, item )
+
+ if self.callback is not None:
+ self.callback( self )
+
+ def get_history(self):
+ return self.cur_selection
+
+ def set_om_selection(self, widget, data ):
+ if widget.active:
+ self.set_history( data )
+
+pgu.gtk_register('GvOptionMenu',GvOptionMenu)
+
+#
+# Copied from GtkExtra
+#
+class _MessageBox(_gtk.GtkDialog):
+ def __init__(self, message="", buttons=(), pixmap=None,
+ modal=_gtk.TRUE):
+ _gtk.GtkDialog.__init__(self)
+ self.connect("destroy", self.quit)
+ self.connect("delete_event", self.quit)
+ self.modal = modal
+ if modal:
+ _gtk.grab_add(self)
+ hbox = _gtk.GtkHBox(spacing=5)
+ hbox.set_border_width(5)
+ self.vbox.pack_start(hbox)
+ hbox.show()
+ if pixmap:
+ self.realize()
+ pixmap = _gtk.GtkPixmap(self, pixmap)
+ hbox.pack_start(pixmap, expand=_gtk.FALSE)
+ pixmap.show()
+ label = _gtk.GtkLabel(message)
+ label.set_justify( _gtk.JUSTIFY_LEFT )
+ hbox.pack_start(label)
+ label.show()
+
+ for text in buttons:
+ b = _gtk.GtkButton(text)
+ b.set_flags(_gtk.CAN_DEFAULT)
+ b.set_data("user_data", text)
+ b.connect("clicked", self.click)
+ self.action_area.pack_start(b)
+ b.show()
+ self.ret = None
+
+ def quit(self, *args):
+ self.hide()
+ self.destroy()
+ if self.modal:
+ _gtk.mainquit()
+
+ def click(self, button):
+ self.ret = button.get_data("user_data")
+ self.quit()
+
+def warning( text ):
+ import gview
+ import os.path
+
+ warning_pixmap = os.path.join(gview.home_dir,'pics','warning.xpm')
+ win = _MessageBox(text, ('OK',), pixmap=warning_pixmap, modal=_gtk.FALSE )
+ win.set_title('Warning')
+ win.show()
+ return
+
+def error( text ):
+ import gview
+ import os.path
+
+ warning_pixmap = os.path.join(gview.home_dir,'pics','warning.xpm')
+ win = _MessageBox(text, ('OK',), pixmap=warning_pixmap, modal=_gtk.TRUE )
+ win.set_title('ERROR')
+ win.show()
+ _gtk.mainloop()
+
+ return
+
+def is_shapefile( filename ):
+ try:
+ ext = string.lower(filename[len(filename)-4:])
+ if ext == '.shp' or ext == '.shx' or ext == '.dbf':
+ return 1
+ else:
+ return 0
+ except:
+ return 0
+
+def is_project_file( filename ):
+ try:
+ ext = string.lower(filename[len(filename)-4:])
+ if ext == '.opf':
+ return 1
+
+ first_line = open(filename).read(20)
+ if first_line[:10] == '<GViewApp>':
+ return 1
+ else:
+ return 0
+ except:
+ return 0
+
+
+# GvMenuFactory is just GtkExtra.MenuFactory, with the
+# addition of a function to allow you to insert entries
+# after the fact...
+
+class GvMenuFactory:
+ def __init__(self, type=GtkExtra.MENU_FACTORY_MENU_BAR):
+ self.accelerator = _gtk.GtkAccelGroup()
+ if type == GtkExtra.MENU_FACTORY_MENU_BAR:
+ self.__w = _gtk.GtkMenuBar()
+ self.__ret = self.__w
+ elif type == GtkExtra.MENU_FACTORY_MENU:
+ self.__w = _gtk.GtkMenu()
+ self.__w.set_accel_group(self.accelerator)
+ self.__ret = self.__w
+ elif type == GtkExtra.MENU_FACTORY_OPTION_MENU:
+ self.__w = _gtk.GtkMenu()
+ self.__w.set_accel_group(self.accelerator)
+ self.__ret = GtkOptionMenu()
+ self.__ret.set_menu(self.__w)
+ self.__menus = {}
+ self.__items = {}
+ def __getattr__(self, key):
+ return getattr(self.__ret, key)
+ def add_entries(self, entries):
+ for entry in entries:
+ apply(self.create, tuple(entry))
+ def create(self, path, accelerator=None, callback=None, *args):
+ last_slash = string.rfind(path, '/')
+ if last_slash < 0:
+ parentmenu = self.__w
+ else:
+ parentmenu = self.get_menu(path[:last_slash])
+ label = path[last_slash+1:]
+ if label == '<separator>':
+ item = _gtk.GtkMenuItem()
+ elif label[:7] == '<check>':
+ item = _gtk.GtkCheckMenuItem(label[7:])
+ else:
+ item = _gtk.GtkMenuItem(label)
+ if label != '<nothing>':
+ item.show()
+ if accelerator:
+ key, mods = self.parse_accelerator(accelerator)
+ item.add_accelerator("activate", self.accelerator,
+ key, mods, 'visible')
+ if callback:
+ apply(item.connect, ("activate", callback) + args)
+ # right justify the help menu automatically
+ if string.lower(label) == 'help' and parentmenu == self.__w:
+ item.right_justify()
+ parentmenu.append(item)
+ self.__items[path] = item
+ return item
+ def get_menu(self, path):
+ if path == '':
+ return self.__w
+ if self.__menus.has_key(path):
+ return self.__menus[path]
+ wid = self.create(path)
+ menu = _gtk.GtkMenu()
+ menu.set_accel_group(self.accelerator)
+ wid.set_submenu(menu)
+ self.__menus[path] = menu
+ return menu
+ def parse_accelerator(self, accelerator):
+ key = 0
+ mods = 0
+ done = _gtk.FALSE
+ while not done:
+ if accelerator[:7] == '<shift>':
+ mods = mods | _gtk.GDK.SHIFT_MASK
+ accelerator = accelerator[7:]
+ elif accelerator[:5] == '<alt>':
+ mods = mods | _gtk.GDK.MOD1_MASK
+ accelerator = accelerator[5:]
+ elif accelerator[:6] == '<meta>':
+ mods = mods | _gtk.GDK.MOD1_MASK
+ accelerator = accelerator[6:]
+ elif accelerator[:9] == '<control>':
+ mods = mods | _gtk.GDK.CONTROL_MASK
+ accelerator = accelerator[9:]
+ else:
+ done = _gtk.TRUE
+ key = ord(accelerator[0])
+ return key, mods
+ def remove_entry(self, path):
+ if path not in self.__items.keys():
+ return
+ item = self.__items[path]
+ item.destroy()
+ length = len(path)
+ # clean up internal hashes
+ for i in self.__items.keys():
+ if i[:length] == path:
+ del self.__items[i]
+ for i in self.__menus.keys():
+ if i[:length] == path:
+ del self.__menus[i]
+
+ def get_entry(self, path):
+ result = []
+ if path not in self.__items.keys():
+ return result
+ item = self.__items[path]
+ result.append(item)
+ length = len(path)
+ # clean up internal hashes
+ for i in self.__items.keys():
+ if i[:length] == path:
+ result.append(self.__items[i])
+ for i in self.__menus.keys():
+ if i[:length] == path:
+ result.append(self.__menus[i])
+
+ return result
+ def remove_entries(self, paths):
+ for path in paths:
+ self.remove_entry(path)
+ def find(self, path):
+ return self.__items[path]
+
+ def insert_entry(self, pos, path, accelerator=None, callback=None, *args):
+ # like create, but lets you specify position in menu
+ last_slash = string.rfind(path, '/')
+ if last_slash < 0:
+ parentmenu = self.__w
+ else:
+ parentmenu = self.insert_get_menu(path[:last_slash])
+ label = path[last_slash+1:]
+ if label == '<separator>':
+ item = _gtk.GtkMenuItem()
+ elif label[:7] == '<check>':
+ item = _gtk.GtkCheckMenuItem(label[7:])
+ else:
+ item = _gtk.GtkMenuItem(label)
+ if label != '<nothing>':
+ item.show()
+ if accelerator:
+ key, mods = self.parse_accelerator(accelerator)
+ item.add_accelerator("activate", self.accelerator,
+ key, mods, 'visible')
+ if callback:
+ apply(item.connect, ("activate", callback) + args)
+ # right justify the help menu automatically
+ if string.lower(label) == 'help' and parentmenu == self.__w:
+ item.right_justify()
+ # all this copying for just the next few line...
+ if pos is not None:
+ parentmenu.insert(item, pos)
+ elif parentmenu == self.__w:
+ # Make sure Help retains far-right position
+ if self.__menus.has_key('Help'):
+ num_main_menus = 0
+ for current_path in self.__menus.keys():
+ # Check that it isn't a sub-menu...
+ temp_slash = string.rfind(current_path,'/')
+ if temp_slash < 0:
+ num_main_menus = num_main_menus + 1
+ parentmenu.insert(item,max(num_main_menus - 1,1))
+ else:
+ parentmenu.append(item)
+ else:
+ parentmenu.append(item)
+
+ self.__items[path] = item
+ return item
+
+ def insert_get_menu(self, path):
+ # Allows new menus to be placed before help on toolbar
+ # by using insert_entry to create parents instead of
+ # create.
+ if path == '':
+ return self.__w
+ if self.__menus.has_key(path):
+ return self.__menus[path]
+ wid = self.insert_entry(None,path)
+ menu = _gtk.GtkMenu()
+ menu.set_accel_group(self.accelerator)
+ wid.set_submenu(menu)
+ self.__menus[path] = menu
+ return menu
+
+
+def read_keyval( line ) :
+ import re
+ import string
+
+ # skip comments & lines that don't contain a '='
+ if line[0] == '#' : return [None,None]
+ if '=' not in line : return [None,None]
+
+ # Grab the key, val
+ [ key, val ] = re.compile( r"\s*=\s*" ).split( line )
+
+ # Strip excess characters from the key string
+ key_re = re.compile( r"\b\w+\b" )
+ key = key[key_re.search(key).start():]
+ key = key[:key_re.search(key).end()]
+
+ # Strip excess characters from the value string
+ val = string.strip( val )
+ i = string.find( val, ' ' )
+ if i > 0 : val = val[0:i]
+
+ return [ key, val ]
+
+
+def get_tempdir():
+ if os.environ.has_key('TMPDIR'):
+ tmpdir = os.environ['TMPDIR']
+ elif os.environ.has_key('TEMPDIR'):
+ tmpdir = os.environ['TEMPDIR']
+ elif os.environ.has_key('TEMP'):
+ tmpdir = os.environ['TEMP']
+ else:
+ if os.name == 'nt':
+ tmpdir = 'C:'
+ else:
+ tmpdir = '/tmp'
+
+ return tmpdir
+
+def tempnam( tdir = None, basename = None, extension = None ):
+ import os.path
+ import gview
+
+ if tdir is None:
+ plotfile = gview.get_preference('gvplot_tempfile')
+ if plotfile is not None and len(plotfile) > 0:
+ if os.path.isdir(plotfile):
+ tdir = plotfile
+ elif os.path.isdir(os.path.dirname(plotfile)):
+ tdir = os.path.dirname(plotfile)
+ else:
+ tdir = get_tempdir()
+ else:
+ tdir = get_tempdir()
+
+ if basename is None:
+ try:
+ pgu.pnm = pgu.pnm + 1
+ except:
+ pgu.pnm = 1
+ basename = 'OBJ_' + str(pgu.pnm)
+
+ if extension is None:
+ extension = 'tmp'
+
+ return os.path.join(tdir,basename + '.' + extension)
+
+def FindExecutable( exe_name ):
+ """Try to return full path to requested executable.
+
+ First checks directly, then searches $OPENEV_HOME/bin and the PATH.
+ Will add .exe on NT. Returns None on failure.
+ """
+
+ import os.path
+ import gview
+ import string
+
+ if os.name == 'nt':
+ (root, ext) = os.path.splitext(exe_name)
+ if ext != '.exe':
+ exe_name = exe_name + '.exe'
+
+ if os.path.isfile(exe_name):
+ return exe_name
+
+ if os.path.isfile(os.path.join(gview.home_dir,'bin',exe_name)):
+ return os.path.join(gview.home_dir,'bin',exe_name)
+
+ exe_path = os.environ['PATH']
+ if (os.name == 'nt'):
+ path_items = string.split(exe_path,';')
+ else:
+ path_items = string.split(exe_path,':')
+
+ for item in path_items:
+ exe_path = os.path.join(item,exe_name)
+ if os.path.isfile(exe_path):
+ return exe_path
+
+ return None
+
+def XMLFindValue( node, path, default = None ):
+ import gdal
+ if path == '' or path == None:
+ tnode = node
+ else:
+ tnode = XMLFind( node, path )
+ if tnode is None:
+ return default
+
+ for child in tnode[2:]:
+ if child[0] == gdal.CXT_Text:
+ return child[1]
+
+ return default
+
+def XMLFind( node, path, maxfind=1, attr=None,value=None ):
+ import gdal
+ broken_up = string.split( path, '.', 1 )
+ found_list=[]
+ if len(broken_up) == 2:
+ component, rest_of_path = broken_up
+ else:
+ component, rest_of_path = broken_up[0], None
+
+ for subnode in node[2:]:
+ if subnode[1] == component and \
+ (subnode[0] == gdal.CXT_Element or subnode[0] == gdal.CXT_Attribute):
+ if rest_of_path is None:
+ if ((attr is None) and (value is None)):
+ found_list.append(subnode)
+ if ((maxfind is not None) and (len(found_list) >= maxfind)):
+ break
+ else:
+ if XMLFindValue(subnode,attr) == value:
+ found_list.append(subnode)
+ if ((maxfind is not None) and (len(found_list) >= maxfind)):
+ break
+ else:
+ if maxfind is None:
+ submaxfind=maxfind
+ else:
+ submaxfind=maxfind-len(found_list)
+
+ sub_list = XMLFind( subnode, rest_of_path, submaxfind,attr, value )
+ if sub_list is not None:
+ if submaxfind > 1:
+ # If maxfind > 1, a list of lists is returned...
+ found_list.extend(sub_list)
+ else:
+ found_list.append(sub_list)
+
+ if len(found_list) == 0:
+ return None
+ elif maxfind == 1:
+ return found_list[0]
+ else:
+ return found_list
+
+def XMLInstantiate( node, parent, filename=None ):
+ import gdal
+
+ if len(node) < 2 or node[0] != gdal.CXT_Element:
+ raise AttributeError,'corrupt value passed to XMLInstantiate.'
+ return None
+
+ classname = node[1]
+ module = XMLFindValue( node, 'module', 'gview' )
+
+ try:
+ exec "import " + module
+ exec "func = %s.%sFromXML" % (module, classname)
+ instance = func( node, parent, filename=filename )
+ return instance
+ except:
+ warning( 'Failed to instantiate a %s:%s' % (module, classname) )
+ #raise
+ return None
+
+def XMLSerializeSimpleObjAttributes( obj, attrib_list, xml_list = [] ):
+ """
+ This method is used to serlialize a list of simple object attributes
+ as elements in a gdal compatible "pseudo-xml-list-tree". Each attribute
+ found on the source attribute will be converted to string type using the
+ str() function, and added to the XML tree as an element with the
+ element name being the attribute name, and the value being the
+ contents of the element.
+
+ This serialization approach (along with XMLDeserializeSimpleObjAttributes
+ is intended to make saving and restoring objects with lots of simple
+ attributes to and from a project file fairly easy.
+
+ obj -- the object instance from which attributes will be extracted.
+ attrib_list -- a list of attribute tuples. Each tuple contains the
+ attribute name and a function for converting a string into the
+ appropriate type (normally one of str, int or float).
+ xml_list -- the existing tree to which the new elements will be added.
+
+ Returns the modified xml_list.
+
+ Example attribute list:
+
+ attrib_list = [ (filename, str), (xsize, int), (ysize, int) ]
+
+
+ """
+ import gdal
+
+ for item in attrib_list:
+ if obj.__dict__.has_key( item[0] ):
+ text_value = str(obj.__dict__[item[0]])
+ xml_list.append( [gdal.CXT_Element, item[0],
+ [gdal.CXT_Text, text_value] ] )
+
+ return xml_list
+
+def XMLDeserializeSimpleObjAttributes( obj, attrib_list, xml_tree ):
+ failures = 0
+
+ for item in attrib_list:
+ text_value = XMLFindValue( xml_tree, item[0], None )
+ if text_value is not None:
+ try:
+ func = item[1]
+ typed_value = func( text_value )
+ obj.__dict__[item[0]] = typed_value
+ except:
+ failures = failures + 1
+ print 'Failed to decode %s attribute with text value (%s).' \
+ % ( item[0], text_value )
+
+ return failures
+
+# XMLPop, XMLInsert, XMLReplaceAttr: tools for manipulating xml files-
+# Might be changed or removed later.
+
+def XMLPop(node,path,maxpop=1,attr=None,value=None,overwrite='n'):
+ # Pop path from node if path has attr=value.
+ # pop up to maxpop instances, where maxpop is
+ # 1 by default. Set maxpop to None to return all
+ # instances.
+ # Returns (cnode,list of popped nodes), where cnode
+ # is a copy of node with the excess stuff removed
+ # if overwrite is set to 'y', node is altered and returned
+
+ import gdal
+
+
+ # avoid overwriting the contents of node
+ if overwrite=='n':
+ import copy
+ cnode=copy.deepcopy(node)
+ else:
+ cnode=node
+
+ broken_up = string.split( path, '.', 1 )
+ popped_list=[]
+ subpopped=[]
+ if len(broken_up) == 2:
+ component, rest_of_path = broken_up
+ else:
+ component, rest_of_path = broken_up[0], None
+
+ if ((maxpop is not None) and (maxpop < 1)):
+ return (cnode,[])
+
+ indx=1
+ indxlist=[]
+ count=0
+
+ for subnode in cnode[2:]:
+ indx=indx+1
+ if subnode[1] == component and \
+ (subnode[0] == gdal.CXT_Element or subnode[0] == gdal.CXT_Attribute):
+ if rest_of_path is None:
+ if ((attr is None) and (value is None)):
+ # Store index for later popping
+ indxlist.append(indx)
+ count=count+1
+ if ((maxpop is not None) and (count >= maxpop)):
+ break
+ else:
+ if XMLFindValue(subnode,attr) == value:
+ indxlist.append(indx)
+ count=count+1
+ if ((maxpop is not None) and (count >= maxpop)):
+ break
+ else:
+ if maxpop is None:
+ submaxpop=None
+ else:
+ submaxpop=maxpop-count
+ junk,sub_list = XMLPop(subnode,rest_of_path,submaxpop,attr,value,overwrite='y')
+ if len(sub_list) > 0:
+ count=count+len(sub_list)
+ subpopped.extend(sub_list)
+
+ if count >= maxpop:
+ break
+
+ # pop the top-level values now
+ pcount=0
+ for indx in indxlist:
+ popped_list.append(cnode.pop(indx-pcount))
+ # index should decrease with each pop...
+ pcount=pcount+1
+
+
+ return (cnode,popped_list)
+
+
+def XMLInsert(node,path,newnode,maxinsert=1,attr=None,value=None,overwrite='n'):
+ # Append newnode to all instances of path found within node
+ # that have attr=value, up to a maximum of maxinsert instances.
+ # Set maxinsert to None to insert in all path instances.
+ # Return the number of items inserted.
+ import gdal
+
+ # avoid overwriting the contents of node
+ if overwrite=='n':
+ import copy
+ cnode=copy.deepcopy(node)
+ else:
+ cnode=node
+
+ broken_up = string.split( path, '.', 1 )
+ if ((maxinsert is not None) and (maxinsert < 1)):
+ return (cnode,0)
+
+ insert_num=0
+ if len(broken_up) == 2:
+ component, rest_of_path = broken_up
+ else:
+ component, rest_of_path = broken_up[0], None
+
+ indx=1
+
+ if path == '' and attr is None:
+ # Insert at top level and return
+ cnode.append(newnode)
+ return (cnode,1)
+
+ for subnode in cnode[2:]:
+ indx=indx+1
+ if subnode[1] == component and \
+ (subnode[0] == gdal.CXT_Element or subnode[0] == gdal.CXT_Attribute):
+ if rest_of_path is None:
+ if ((attr is None) and (value is None)):
+ subnode.append(newnode)
+ insert_num=insert_num+1
+ if ((maxinsert is not None) and (insert_num >= maxinsert)):
+ return (cnode,insert_num)
+ else:
+ if XMLFindValue(subnode,attr) == value:
+ subnode.append(newnode)
+ insert_num=insert_num+1
+ if ((maxinsert is not None) and (insert_num >= maxinsert)):
+ return (cnode,insert_num)
+ else:
+ if maxinsert is None:
+ submaxinsert=None
+ else:
+ submaxinsert=maxinsert-insert_num
+ junk,subinsert=XMLInsert( subnode, rest_of_path,newnode,submaxinsert,attr,value,overwrite='y' )
+ insert_num=insert_num+subinsert
+ if ((maxinsert is not None) and (insert_num >= maxinsert)):
+ return (cnode,insert_num)
+ return (cnode,insert_num)
+
+def XMLReplaceAttr( node, path, pathvalue, maxreplace=1, attr=None, value=None, overwrite='n' ):
+ # path should end with the attribute to be replaced. attr and value, if entered, should be
+ # at the same level as the attribute to be replaced.
+ import gdal
+ import os.path
+
+ if overwrite == 'n':
+ import copy
+ cnode=copy.deepcopy(node)
+ else:
+ cnode=node
+ replaced=0
+ if ((maxreplace is not None) and (maxreplace < 1)):
+ return (cnode,replaced)
+
+ if path == '' or path == None:
+ print 'Error- No attribute to replace was entered...'
+ return
+ elif ((attr is None) and (value is None)):
+ tnode = XMLFind( cnode, path, maxreplace)
+ if tnode is None:
+ return (cnode,replaced)
+ else:
+ top_path,replace_attr=os.path.splitext(path)
+ if replace_attr == '':
+ replace_attr = top_path
+ top_path=''
+ else:
+ replace_attr=replace_attr[1:] # Get rid of .
+ inode = XMLFind( cnode, top_path, None,attr, value )
+ if inode is None:
+ return (cnode,replaced)
+ # Of the paths that have attr=value, see which ones also
+ # contain the replace_attr to be replaced.
+ tnode=[]
+ for item in inode:
+ temp=XMLFind( item, replace_attr)
+ if temp is not None:
+ if maxreplace is None:
+ tnode.append(temp)
+ elif (len(tnode)<maxreplace):
+ tnode.append(temp)
+
+ if len(tnode) < 1:
+ return (cnode, replaced)
+
+ if maxreplace == 1:
+ tnode=tnode[0]
+
+ if maxreplace == 1:
+ for child in tnode[2:]:
+ if child[0] == gdal.CXT_Text:
+ child[1] = pathvalue
+ replaced=replaced+1
+ return (cnode,replaced)
+ else:
+ for item in tnode:
+ for child in item[2:]:
+ if child[0] == gdal.CXT_Text:
+ child[1] = pathvalue
+ replaced=replaced+1
+ if ((maxreplace is not None) and (replaced >= maxreplace)):
+ return (cnode,replaced)
+
+ return (cnode,replaced)
+
+
+
+#-----------------------------------------------------------------
+# GvDataFilesFrame- function to create data file frame and entries
+#-----------------------------------------------------------------
+class GvDataFilesFrame(_gtk.GtkFrame):
+ def __init__(self,title='',sel_list=('Input','Output'),editable=_gtk.TRUE):
+ _gtk.GtkFrame.__init__(self)
+ self.set_label(title)
+ self.channels=sel_list
+
+ self.show_list = []
+ self.file_dict = {}
+ self.button_dict = {}
+ self.entry_dict = {}
+
+ # File options
+ file_table = _gtk.GtkTable(len(self.channels),5,_gtk.FALSE)
+ file_table.set_row_spacings(3)
+ file_table.set_col_spacings(3)
+ self.table = file_table
+ self.add(file_table)
+ self.show_list.append(file_table)
+
+ for idx in range(len(self.channels)):
+ ch = self.channels[idx]
+ self.button_dict[ch] = _gtk.GtkButton(ch)
+ self.button_dict[ch].set_usize(100,25)
+ self.show_list.append(self.button_dict[ch])
+ file_table.attach(self.button_dict[ch], 0,1, idx,idx+1)
+ self.entry_dict[ch] = _gtk.GtkEntry()
+ self.entry_dict[ch].set_editable(editable)
+ self.entry_dict[ch].set_usize(400, 25)
+ self.entry_dict[ch].set_text('')
+ self.show_list.append(self.entry_dict[ch])
+ self.set_dsfile('',ch)
+ file_table.attach(self.entry_dict[ch], 1,5, idx,idx+1)
+ if editable == _gtk.TRUE:
+ self.entry_dict[ch].connect('leave-notify-event',self.update_ds)
+
+
+ for bkey in self.button_dict.keys():
+ self.button_dict[bkey].connect('clicked',self.set_dsfile_cb,bkey)
+
+ def set_border_width(self,width):
+ self.table.set_border_width(width)
+
+ def set_spacings(self, rowspc, colspc):
+ self.table.set_row_spacings(rowspc)
+ self.table.set_col_spacings(colspc)
+
+ def update_ds(self,*args):
+ for ch in self.channels:
+ self.set_dsfile(self.entry_dict[ch].get_text(),ch)
+
+ def show(self,*args):
+ for item in self.show_list:
+ item.show()
+
+
+ def set_dsfile_cb(self,*args):
+ fkey = args[1]
+ file_str = 'Select ' + fkey + ' File'
+ pgufilesel.SimpleFileSelect(self.set_dsfile,
+ fkey,
+ file_str)
+
+ def set_dsfile(self,fname,fkey):
+ self.file_dict[fkey] = fname
+
+ # Save selected file directory
+ head = os.path.dirname(fname)
+ if len(head) > 0:
+ if os.access(head,os.R_OK):
+ pgufilesel.simple_file_sel_dir = head+os.sep
+
+ if self.entry_dict.has_key(fkey):
+ if self.file_dict[fkey] is None:
+ self.entry_dict[fkey].set_text('')
+ else:
+ self.entry_dict[fkey].set_text(
+ self.file_dict[fkey])
+
+ def get(self,fkey):
+ if self.file_dict.has_key(fkey):
+ return self.file_dict[fkey]
+ else:
+ return None
+
+#-----------------------------------------------------------------
+# GvEntryFrame- function to create a frame with a table of entries.
+# Input: a list, or list of list, of strings. initializing with
+# [['e1','e2'],['e3'],['e4','e5']] would create a table like this:
+#
+# e1: <entry> e2:<entry>
+# e3: <entry>
+# e4: <entry> e5:<entry>
+#
+# The strings in the list are used to index for returning entry
+# values, and must be unique.
+#
+# If some of the entries must have only certain values, a second
+# list of the same size may be supplied. This should contain
+# None where entries should be used, but a tuple of strings
+# where an option menu should be used.
+#-----------------------------------------------------------------
+class GvEntryFrame(_gtk.GtkFrame):
+ def __init__(self,title,entry_list,widget_list=None):
+ _gtk.GtkFrame.__init__(self)
+ self.set_label(title)
+ table_rows = len(entry_list)
+ cols = 1
+ for item in entry_list:
+ if type(item) in [type((1,)),type([1])]:
+ cols = max(cols,len(item))
+
+ # Note: the extra one column is because on windows,
+ # creating a gtk table with N columns sometimes only shows
+ # N-1 columns???
+ self.table = _gtk.GtkTable(table_rows,cols*2+1,_gtk.FALSE)
+ self.table.set_col_spacings(3)
+ self.table.set_row_spacings(3)
+ self.add(self.table)
+ self.entries = {}
+ if widget_list is None:
+ ridx=0
+ for item in entry_list:
+ if type(item) in [type((1,)),type([1])]:
+ cidx=0
+ for item2 in item:
+ label = _gtk.GtkLabel(item2)
+ label.set_alignment(0,0.5)
+ self.table.attach(label,cidx,cidx+1,ridx,ridx+1)
+ self.entries[item2] = _gtk.GtkEntry(maxlen=30)
+ self.entries[item2].set_editable(_gtk.TRUE)
+ cidx = cidx+1
+ self.table.attach(self.entries[item2],
+ cidx,cidx+1,ridx,ridx+1)
+ cidx = cidx+1
+ else:
+ label = _gtk.GtkLabel(item)
+ label.set_alignment(0,0.5)
+ self.table.attach(label,0,1,ridx,ridx+1)
+ self.entries[item] = _gtk.GtkEntry(maxlen=30)
+ self.entries[item].set_editable(_gtk.TRUE)
+ self.table.attach(self.entries[item],
+ 1,2,ridx,ridx+1)
+ ridx=ridx+1
+
+ else:
+ ridx=0
+ for item in entry_list:
+ wtype=widget_list[ridx]
+ if type(item) in [type((1,)),type([1])]:
+ cidx=0
+ widx=0
+ for item2 in item:
+ wtype2=wtype[widx]
+ label = _gtk.GtkLabel(item2)
+ label.set_alignment(0,0.5)
+ self.table.attach(label,cidx,cidx+1,ridx,ridx+1)
+ if wtype2 is None:
+ self.entries[item2] = _gtk.GtkEntry(maxlen=30)
+ self.entries[item2].set_editable(_gtk.TRUE)
+ else:
+ self.entries[item2] = GvOptionMenu(wtype2)
+ self.entries[item2].set_history(0)
+ self.entries[item2].contents = wtype2
+ cidx = cidx+1
+ self.table.attach(self.entries[item2],
+ cidx,cidx+1,ridx,ridx+1)
+ cidx = cidx+1
+ widx = widx+1
+ else:
+ label = _gtk.GtkLabel(item)
+ label.set_alignment(0,0.5)
+ self.table.attach(label,0,1,ridx,ridx+1)
+ if wtype is None:
+ self.entries[item] = _gtk.GtkEntry(maxlen=30)
+ self.entries[item].set_editable(_gtk.TRUE)
+ else:
+ self.entries[item] = GvOptionMenu(wtype)
+ self.entries[item].set_history(0)
+ self.entries[item].contents = wtype
+ self.table.attach(self.entries[item],
+ 1,2,ridx,ridx+1)
+ ridx=ridx+1
+
+
+ def get(self,fkey):
+ if self.entries.has_key(fkey):
+ if hasattr(self.entries[fkey],'get_text'):
+ return self.entries[fkey].get_text()
+ else:
+ hist=self.entries[fkey].get_history()
+ return self.entries[fkey].contents[hist]
+ else:
+ return None
+
+ def set_default_values(self,default_dict):
+ """Set default entry values. Input is default_dict,
+ a dictionary with keys corresponding to entries
+ (strings) and values corresponding to default
+ text or menu setting (also strings).
+ """
+ for ckey in default_dict.keys():
+ cval = default_dict[ckey]
+ if self.entries.has_key(ckey):
+ if hasattr(self.entries[ckey],'set_text'):
+ self.entries[ckey].set_text(cval)
+ else:
+ useidx=None
+ for idx in range(len(self.entries[ckey].contents)):
+ if self.entries[ckey].contents[idx] == cval:
+ useidx=idx
+ if useidx is not None:
+ self.entries[ckey].set_history(useidx)
+ else:
+ print cval+' not a valid entry for '+ckey
+
+ else:
+ print 'No entry '+ckey+'- skipping'
+
+ def set_default_lengths(self,default_dict):
+ """ Set the maximum entry lengths for non-menu entries.
+ Input is defalut_dict, a dictionary with keys
+ corresponding to entries (strings) and values
+ corresponding to entry lengths (integers)
+ """
+ for ckey in default_dict.keys():
+ cval = default_dict[ckey]
+ if self.entries.has_key(ckey):
+ if hasattr(self.entries[ckey],'set_text'):
+ self.entries[ckey].set_max_length(cval)
+ else:
+ print 'Length cannot be set for a menu ('+ckey+')'
+
+ else:
+ print 'No entry '+ckey+'- skipping'
+
+ def set_border_width(self,width):
+ self.table.set_border_width(width)
+
+ def set_spacings(self, rowspc, colspc):
+ self.table.set_row_spacings(rowspc)
+ self.table.set_col_spacings(colspc)
+
+
+if __name__ == '__main__':
+ dialog = _gtk.GtkWindow()
+
+ om = GvOptionMenu( ('Option 1', 'Option 2') )
+ om.show()
+ dialog.add( om )
+
+ dialog.connect('delete-event', _gtk.mainquit)
+ dialog.show()
+
+ _gtk.mainloop()
Added: packages/openev/branches/upstream/current/pymod/gvvectorpropdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvvectorpropdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvvectorpropdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,602 @@
+###############################################################################
+# $Id: gvvectorpropdlg.py,v 1.23 2003/02/14 23:03:35 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: GvShapesLayer Properties Dialog
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvvectorpropdlg.py,v $
+# Revision 1.23 2003/02/14 23:03:35 pgs
+# fixed typo in area_edge_width signal callback
+#
+# Revision 1.21 2002/03/21 15:48:51 warmerda
+# added support for geometry specific _ogr_ogrfs_... layer properties
+#
+# Revision 1.20 2001/04/16 17:06:49 warmerda
+# paul added symbol support to vector prop dialog
+#
+# Revision 1.19 2001/04/03 02:29:30 warmerda
+# improved some pane geometry
+#
+# Revision 1.18 2001/03/26 19:25:42 warmerda
+# fixed typo with font list
+#
+# Revision 1.17 2001/03/21 22:41:27 warmerda
+# added labels support under drawing style
+#
+# Revision 1.16 2000/08/10 15:59:29 warmerda
+# added help topic
+#
+# Revision 1.15 2000/08/08 20:12:21 warmerda
+# close on layer teardown
+#
+# Revision 1.14 2000/07/21 01:31:12 warmerda
+# added read_only flag for GvData, and utilize for vector layers
+#
+# Revision 1.13 2000/07/20 02:45:04 warmerda
+# avoid doing gui updates in response to signals if dialog destroyed
+#
+# Revision 1.12 2000/06/14 15:13:21 warmerda
+# updated pgu stuff
+#
+# Revision 1.11 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+from gtk import *
+from string import *
+import gvutils
+import pgucolorsel
+
+from gvconst import *
+import gview
+import gvhtml
+import gvogrfs
+import pgutogglebutton
+
+prop_dialog_list = []
+
+def LaunchVectorPropDialog(layer):
+ # Check list to see if dialog exists - make it visible
+ for test_dialog in prop_dialog_list:
+ if test_dialog.layer._o == layer._o:
+ test_dialog.update_gui()
+ test_dialog.show()
+ test_dialog.get_window()._raise()
+ return test_dialog
+
+ # Create new dialog if one doesn't exist already
+ new_dialog = GvVectorPropDialog(layer)
+ prop_dialog_list.append( new_dialog )
+ return new_dialog
+
+symbols = [ 'cross', 'x',
+ 'unfilled circle', 'filled circle',
+ 'unfilled square', 'filled square',
+ 'unfilled triangle', 'filled triangle',
+ 'unfilled star', 'filled star',
+ 'vertical bar' ]
+
+class GvVectorPropDialog(GtkWindow):
+
+ def __init__(self, layer):
+ GtkWindow.__init__(self)
+ self.set_title(layer.get_name()+' Properties')
+ self.layer = layer
+ self.updating = FALSE
+
+ if self.layer is not None:
+ self.display_change_id = layer.connect('display-change',
+ self.refresh_cb)
+ self.teardown_id = layer.connect('teardown',self.close)
+
+ # create the general layer properties dialog
+ self.create_notebook()
+ self.create_pane1()
+
+ # Setup Object Drawing Properties Tab
+ self.pane2 = GtkVBox(spacing=10)
+ self.pane2.set_border_width(10)
+ self.notebook.append_page( self.pane2, GtkLabel('Draw Styles'))
+
+ gvhtml.set_help_topic( self, "gvvectorpropdlg.html" )
+
+
+ # ANTIALIASING
+ box = GtkHBox(spacing=3)
+ self.pane2.pack_start(box)
+ box.pack_start( GtkLabel("Anti-alias:"), expand=FALSE )
+ self.antialias = pgutogglebutton.pguToggleButton()
+ self.antialias.connect('toggled', self.antialias_cb )
+ box.pack_start( self.antialias, expand=FALSE )
+
+ # POINT CONTROLS -----------------------------------------------------
+ frame = GtkFrame('Points')
+ self.pane2.pack_start(frame)
+
+ vbox = GtkVBox(spacing=10)
+ vbox.set_border_width(10)
+ frame.add(vbox)
+
+ #create a symbol control
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Symbol:'), expand=FALSE)
+ self.point_symbol = GtkCombo()
+ #add a default to symbol names
+ self.point_symbol.set_popdown_strings( tuple(symbols) )
+ self.point_symbol.entry.set_editable(FALSE)
+ #self.point_symbol.set_value_in_list(TRUE, FALSE)
+ self.point_symbol.entry.connect('changed', self.symbol_cb)
+ box.pack_start(self.point_symbol)
+
+ # Create Color control.
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Color:'),expand=FALSE)
+ self.point_color = pgucolorsel.ColorControl('Point Color',
+ self.symbol_cb)
+ box.pack_start(self.point_color)
+
+ # Point size
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Point Size:'),expand=FALSE)
+ self.point_size = GtkCombo()
+ self.point_size.set_popdown_strings(
+ ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '15', '20') )
+ self.point_size.entry.connect('changed', self.point_size_cb)
+ box.pack_start(self.point_size,expand=FALSE)
+
+ # LINE CONTROLS ------------------------------------------------------
+ frame = GtkFrame('Lines')
+ self.pane2.pack_start(frame)
+
+ vbox = GtkVBox()
+ vbox.set_border_width(10)
+ frame.add(vbox)
+
+ # Create Color control.
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Color:'),expand=FALSE)
+ self.line_color = pgucolorsel.ColorControl('Line Color',
+ self.color_cb,'_line_color')
+ box.pack_start(self.line_color)
+
+ #Line Width
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Width:'), expand=FALSE)
+ self.line_width = GtkEntry()
+ self.line_width.connect('changed', self.line_width_cb)
+ box.pack_start( self.line_width, expand=FALSE)
+
+
+ # AREA CONTROLS ------------------------------------------------------
+ frame = GtkFrame('Areas')
+ self.pane2.pack_start(frame)
+
+ vbox = GtkVBox(spacing=10)
+ vbox.set_border_width(10)
+ frame.add(vbox)
+
+ # Create Color controls
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Edge Color:'),expand=FALSE)
+ self.area_edge_color = pgucolorsel.ColorControl('Area Edge Color',
+ self.color_cb,'_area_edge_color')
+ box.pack_start(self.area_edge_color)
+
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Fill Color:'),expand=FALSE)
+ self.area_fill_color = pgucolorsel.ColorControl('Area Fill Color',
+ self.color_cb,'_area_fill_color')
+ box.pack_start(self.area_fill_color)
+
+ #Area Edge Width
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Edge Width:'), expand=FALSE)
+ self.area_edge_width = GtkEntry()
+ self.area_edge_width.connect('changed', self.area_edge_width_cb)
+ box.pack_start( self.area_edge_width, expand=FALSE)
+
+
+ # LABEL CONTROLS -----------------------------------------------------
+ frame = GtkFrame('Labels')
+ self.pane2.pack_start(frame)
+
+ vbox = GtkVBox(spacing=10)
+ vbox.set_border_width(10)
+ frame.add(vbox)
+
+ # collect candidate field names from the schema.
+ fnlist = [ 'disabled' ]
+ schema = self.layer.get_parent().get_schema()
+ for item in schema:
+ fnlist.append( item[0] )
+
+ # Field Name
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Label Field:'),expand=FALSE)
+ self.label_field = GtkCombo()
+ self.label_field.set_popdown_strings( fnlist )
+ self.label_field.entry.connect('changed', self.label_change_cb)
+ box.pack_start(self.label_field,expand=FALSE)
+
+ # Create Color control.
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Color:'),expand=FALSE)
+ self.label_color = pgucolorsel.ColorControl('Label Color',
+ self.label_change_cb)
+ box.pack_start(self.label_color)
+
+ # Font
+ font_list = self.layer.get_view().get_fontnames()
+ box = GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=FALSE)
+ box.pack_start(GtkLabel('Font:'),expand=FALSE)
+ self.label_font = GtkCombo()
+ self.label_font.set_popdown_strings(font_list)
+ self.label_font.entry.connect('changed', self.label_change_cb)
+ box.pack_start(self.label_font,expand=FALSE)
+
+ self.update_gui()
+
+ self.show_all()
+
+ def create_notebook(self):
+ self.set_border_width(3)
+ self.notebook = GtkNotebook()
+ self.add( self.notebook )
+ self.connect('delete-event', self.close)
+
+ def create_pane1(self):
+ # Setup General Properties Tab
+ self.pane1 = GtkVBox(spacing=10)
+ self.pane1.set_border_width(10)
+ self.notebook.append_page( self.pane1, GtkLabel('General'))
+
+ # Setup layer name entry box.
+ box = GtkHBox(spacing=5)
+ self.pane1.pack_start(box, expand=FALSE)
+ label = GtkLabel('Layer:' )
+ box.pack_start(label,expand=FALSE)
+ self.layer_name = GtkEntry()
+ self.layer_name.connect('changed', self.name_cb)
+ box.pack_start(self.layer_name)
+
+ # Setup Visibility radio buttons.
+ vis_box = GtkHBox(spacing=5)
+ self.pane1.pack_start(vis_box, expand=FALSE)
+ vis_box.pack_start(GtkLabel('Visibility:'),expand=FALSE)
+ self.vis_yes = GtkRadioButton(label='yes')
+ self.vis_yes.connect('toggled', self.visibility_cb)
+ vis_box.pack_start(self.vis_yes,expand=FALSE)
+ self.vis_no = GtkRadioButton(label='no',group=self.vis_yes)
+ self.vis_no.connect('toggled', self.visibility_cb)
+ vis_box.pack_start(self.vis_no,expand=FALSE)
+
+ # Setup Editability radio buttons.
+ edit_box = GtkHBox(spacing=5)
+ self.pane1.pack_start(edit_box, expand=FALSE)
+ edit_box.pack_start(GtkLabel('Editable:'),expand=FALSE)
+ self.edit_yes = GtkRadioButton(label='yes')
+ self.edit_yes.connect('toggled', self.edit_cb)
+ edit_box.pack_start(self.edit_yes,expand=FALSE)
+ self.edit_no = GtkRadioButton(label='no',group=self.edit_yes)
+ self.edit_no.connect('toggled', self.edit_cb)
+ edit_box.pack_start(self.edit_no,expand=FALSE)
+
+ # Initialize GUI state from underlying object state.
+ def update_gui(self):
+
+ if self.flags( DESTROYED ) > 0:
+ return
+
+ if self.layer is None or self.updating == TRUE:
+ return
+
+ self.updating = TRUE
+
+ # Layer name.
+ self.layer_name.set_text( self.layer.get_name() )
+
+ # Visibility radio buttons
+ self.vis_yes.set_active( self.layer.is_visible() )
+ self.vis_no.set_active( not self.layer.is_visible() )
+
+ # Editability radio buttons
+ self.edit_yes.set_active( not self.layer.is_read_only() )
+ self.edit_no.set_active( self.layer.is_read_only() )
+
+ # colors
+ self.set_color_or_default('_point_color', self.point_color)
+ self.set_color_or_default('_line_color', self.line_color)
+ self.set_color_or_default('_area_edge_color', self.area_edge_color)
+ self.set_color_or_default('_area_fill_color', self.area_fill_color)
+
+ # point size
+ self.point_size.entry.delete_text(0,-1)
+ if self.layer.get_property('_point_size') is None:
+ self.point_size.entry.insert_text('6')
+ else:
+ self.point_size.entry.insert_text(
+ self.layer.get_property('_point_size'))
+
+ #line and area edge width
+ self.line_width.delete_text( 0, -1 )
+ if self.layer.get_property('_line_width') is None:
+ self.line_width.insert_text('1.0')
+ else:
+ self.line_width.insert_text(
+ self.layer.get_property( '_line_width' ))
+
+ self.area_edge_width.delete_text( 0, -1 )
+ if self.layer.get_property('_area_edge_width') is None:
+ self.area_edge_width.insert_text('1.0')
+ else:
+ self.area_edge_width.insert_text(
+ self.layer.get_property( '_area_edge_width' ))
+
+ # antialiasing
+ if self.layer.get_property('_gl_antialias') is None:
+ self.antialias.set_active( FALSE )
+ elif self.layer.get_property('_gl_antialias') == "0":
+ self.antialias.set_active( FALSE )
+ else:
+ self.antialias.set_active( TRUE )
+
+ # font and symbol information
+
+ self.label_font.entry.delete_text(0,-1)
+ self.label_field.entry.delete_text(0,-1)
+
+ ogrfs = self.layer.get_property('_gv_ogrfs_point')
+ ogrfs_obj = gvogrfs.OGRFeatureStyle()
+ ogrfs_label = None
+ try:
+ ogrfs_obj.parse( ogrfs )
+ except:
+ print 'update_gui: error parsing ogrfs:'
+ print ogrfs
+
+ ogrfs_label = ogrfs_obj.get_part('LABEL')
+ if ogrfs_label is None:
+ self.label_font.entry.insert_text('Fixed')
+ self.label_field.entry.insert_text('disabled')
+ self.label_color.set_color( (0.5, 1.0, 0.5, 1.0) )
+ else:
+ self.label_font.entry.insert_text(ogrfs_label.parms['f'].value)
+ self.label_field.entry.insert_text(ogrfs_label.parms['t'].value)
+ ogr_color = ogrfs_label.parms['c'].value
+ gv_color = gvogrfs.ogr_to_gv_color(ogr_color)
+ self.label_color.set_color(gv_color)
+
+ ogrfs_symbol = ogrfs_obj.get_part('SYMBOL')
+ if ogrfs_symbol is None:
+ self.point_symbol.entry.set_text('cross')
+ else:
+ ogr_sym = ogrfs_symbol.parms['id'].value
+ try:
+ sym_num = int(ogr_sym[8:9])
+ sym_name = symbols[sym_num]
+ except:
+ sym_name = 'cross'
+ self.point_symbol.entry.set_text( sym_name )
+
+ self.updating = FALSE
+
+ def name_cb(self, *args):
+ if self.layer_name.get_text() != self.layer.get_name():
+ self.layer.set_name( self.layer_name.get_text() )
+
+ # Set color from property, or use default color.
+ def set_color_or_default(self, property_name, widget):
+ if self.layer.get_property( property_name ) is None:
+ widget.set_color( (0.5, 1.0, 0.5, 1.0) )
+ else:
+ widget.set_color_from_string(
+ self.layer.get_property( property_name ))
+
+ # Color of a feature type changed
+ def color_cb( self, color, type ):
+ if self.layer is None:
+ print 'set ' + type + ' to ', color
+ return
+
+ prop = str(color[0]) + ' ' + str(color[1]) + ' ' \
+ + str(color[2]) + ' ' + str(color[3])
+
+ old_prop = self.layer.get_property( type )
+ if old_prop is None or old_prop != prop:
+ self.layer.set_property( type, prop )
+ self.layer.display_change()
+
+ # Handle updates to the point size.
+ def point_size_cb(self, args):
+ if self.layer is None:
+ return
+
+ new_text = self.point_size.entry.get_chars(0,-1)
+ if len(new_text) == 0:
+ return
+
+ if self.layer.get_property('_point_size') is not None \
+ and self.layer.get_property('_point_size') == new_text:
+ return
+
+ self.layer.set_property( '_point_size', new_text)
+ self.layer.display_change()
+
+ #Handle changes to the line width
+ def line_width_cb( self, *args ):
+ if self.layer is None:
+ return
+
+ new_text = self.line_width.get_chars(0, -1)
+ if (len(new_text)) == 0:
+ return
+
+ if self.layer.get_property('_line_width') is not None \
+ and self.layer.get_property('_line_width') == new_text:
+ return
+
+ self.layer.set_property('_line_width', new_text)
+ self.layer.display_change()
+
+ #Handle changes to the area edge width
+ def area_edge_width_cb( self, *args ):
+ if self.layer is None:
+ return
+
+ new_text = self.area_edge_width.get_chars(0, -1)
+ if (len(new_text)) == 0:
+ return
+
+ if self.layer.get_property('_area_edge_width') is not None \
+ and self.layer.get_property('_area_edge_width') == new_text:
+ return
+
+ self.layer.set_property('_area_edge_width', new_text)
+ self.layer.display_change()
+
+ # Handle changes to antialiasing
+ def antialias_cb( self, *args ):
+ if self.layer is None:
+ return
+
+ antialias = self.layer.get_property( "_gl_antialias" )
+ if antialias is None:
+ antialias = "0"
+ elif antialias != "0":
+ antialias = "1"
+
+ if self.antialias.get_active() and antialias != "1":
+ self.layer.set_property( "_gl_antialias", "1" )
+ self.layer.display_change()
+ elif antialias != "0":
+ self.layer.set_property( "_gl_antialias", "0" )
+ self.layer.display_change()
+
+
+ # Handle updates to the label font.
+ def label_change_cb(self, *args):
+ if self.layer is None or self.updating:
+ return
+
+ font = self.label_font.entry.get_chars(0,-1)
+ field_name = self.label_field.entry.get_chars(0,-1)
+
+ color = self.label_color.current_color
+ color = gvogrfs.gv_to_ogr_color( color )
+
+ ogrfs = self.layer.get_property('_gv_ogrfs_point')
+ ogrfs_obj = gvogrfs.OGRFeatureStyle()
+ try:
+ ogrfs_obj.parse( ogrfs )
+ except:
+ print 'an error occurred parsing the ogrfs property:\n', ogrfs
+
+ #remove the old label
+ ogrfs_obj.remove_part('LABEL')
+
+ if field_name != 'disabled' and len(field_name) != 0:
+ ogrfs_label = gvogrfs.OGRFeatureStylePart()
+ ogrfs_label.parse(
+ 'LABEL(t:{%s},f:"%s",c:%s)' % (field_name, font, color) )
+ ogrfs_obj.add_part( ogrfs_label )
+
+ self.layer.set_property( '_gv_ogrfs_point', ogrfs_obj.unparse() )
+ self.layer.display_change()
+
+ # Visibility changing
+ def visibility_cb( self, widget ):
+ self.layer.set_visible( self.vis_yes.active )
+
+ # Visibility changing
+ def edit_cb( self, widget ):
+ self.layer.set_read_only( self.edit_no.active )
+
+ #symbol changing
+ def symbol_cb( self, widget, *args ):
+ """
+ update the symbol. This might have been called because the color
+ changed also, so update the _point_color property too.
+ """
+
+ if self.layer is None or self.updating:
+ return
+
+ symbol = self.point_symbol.entry.get_text()
+
+ ogrfs = self.layer.get_property('_gv_ogrfs_point')
+ ogrfs_obj = gvogrfs.OGRFeatureStyle()
+ try:
+ ogrfs_obj.parse( ogrfs )
+ except:
+ print 'an error occurred parsing the ogrfs property:\n', ogrfs
+
+ #remove the old symbol
+ ogrfs_obj.remove_part('SYMBOL')
+
+ point_sym_text = '"ogr-sym-%s"' % symbols.index(symbol)
+ color = self.point_color.current_color
+ #should this only be done on point layers?
+ point_ogr_color = gvogrfs.gv_to_ogr_color(color)
+ point_size = self.point_size.entry.get_text()
+ ogr_part = 'SYMBOL(c:' + point_ogr_color + ',id:' + \
+ point_sym_text + ')'
+ ogrfs_sym = gvogrfs.OGRFeatureStylePart()
+ ogrfs_sym.parse( ogr_part )
+ ogrfs_obj.add_part( ogrfs_sym )
+
+ self.layer.set_property('_gv_ogrfs_point', ogrfs_obj.unparse())
+
+ prop = str(color[0]) + ' ' + str(color[1]) + \
+ ' ' + str(color[2]) + ' ' + str(color[3])
+ self.layer.set_property( '_point_color', prop )
+ self.layer.display_change()
+
+ # Dialog closed, remove references to python object
+ def close( self, widget, args ):
+ self.layer.disconnect(self.teardown_id)
+ self.layer.disconnect(self.display_change_id)
+ prop_dialog_list.remove(self)
+ self.layer = None
+ self.destroy()
+
+ # Force GUI Refresh
+ def refresh_cb( self, widget, args ):
+ self.update_gui()
+
+if __name__ == '__main__':
+ dialog = GvVectorPropDialog(None)
+ dialog.connect('delete-event', mainquit)
+
+ mainloop()
+
Added: packages/openev/branches/upstream/current/pymod/gvviewwindow.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/gvviewwindow.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/gvviewwindow.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1726 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: gvviewwindow.py,v 1.96 2005/10/13 21:21:51 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: OpenEV General Purpose GvViewWindow class.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvviewwindow.py,v $
+# Revision 1.96 2005/10/13 21:21:51 gmwalter
+# Update for 3D RGB drapes.
+#
+# Revision 1.95 2005/08/07 18:23:19 warmerda
+# moved about box into oe_about.py
+#
+# Revision 1.94 2005/06/28 21:40:17 gmwalter
+# Avoid view title conflicts (saved projects)
+#
+# Revision 1.93 2005/06/28 18:14:25 gmwalter
+# Update Atlantis->Vexcel Canada; fix sizing for no scrollbar case
+#
+# Revision 1.92 2005/02/10 21:14:53 warmerda
+# Suppress terminal reporting of gdal errors while test-opening a file
+# as a raster. Otherwise we get a bunch of error noise from any OGR
+# files.
+#
+# Revision 1.91 2005/01/14 17:18:34 warmerda
+# save and restore menufile and iconfile
+#
+# Revision 1.90 2004/11/03 20:38:13 warmerda
+# updated to version 1.8 in about box
+#
+# Revision 1.89 2004/10/07 20:14:03 warmerda
+# added support to treat greyscale+alpha as RGBA
+#
+# Revision 1.88 2004/07/02 16:40:51 dem
+# - Implement project files portability
+# - last_strech restored in projects reloading
+# - add a "File/Save Project as..." menu
+#
+# Revision 1.87 2004/06/23 14:35:17 gmwalter
+# Added support for multi-band complex imagery.
+#
+# Revision 1.86 2004/04/21 14:35:27 andrey_kiselev
+# New option: save last visited directory.
+#
+# Revision 1.85 2004/04/05 05:32:25 warmerda
+# Updated about box version to 1.7.
+#
+# Revision 1.84 2004/02/23 16:09:54 warmerda
+# For some reason gview.manager.get_dataset() was return None for the
+# dataset, and 0 for GetLastErrorNo(). I changed to treat 0 as a non-fatal
+# error in file_open_by_name(). I'm not sure if this indicates a wider
+# problem.
+#
+# Revision 1.83 2004/02/10 15:47:56 andrey_kiselev
+# Added open_gdal_dataset method.
+#
+# Revision 1.82 2004/01/23 15:08:30 gmwalter
+# Add a few hooks for other applications to
+# use to alter closing behaviour of windows.
+#
+# Revision 1.81 2003/12/28 15:56:07 warmerda
+# removed unneeded openev import
+#
+# Revision 1.80 2003/09/30 16:40:50 gmwalter
+# Avoid errors when zoom icon is not present.
+#
+# Revision 1.79 2003/07/28 19:42:34 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.78 2003/06/25 17:08:58 warmerda
+# added rotate tool
+#
+# Revision 1.77 2003/04/15 15:03:25 gmwalter
+# Update Atlantis web address in Help/About dialog.
+#
+# Revision 1.76 2003/03/13 19:52:01 gmwalter
+# Make sure pop-up dialog appears rather than command line error message when
+# a file fails to open.
+#
+# Revision 1.75 2003/03/07 19:56:19 gmwalter
+# Fix goto dialog for raw layer case with row/col coordinates.
+#
+
+import gtk
+from gtk import FALSE, TRUE
+from GDK import *
+import gtkmissing
+import sys
+# import GtkExtra
+
+import gview
+import gvconst
+import layerdlg
+import gdal
+from gdalconst import *
+import gvutils
+import os
+import pgufilesel
+import pguprogress
+import math
+import gvhtml
+import string
+import glob
+import gviewapp
+
+ratio_list = ['250:1', '200:1', '150:1', '100:1', '80:1', '60:1', '45:1',
+ '35:1', '25:1', '18:1', '10:1', '8:1', '4:1', '2:1', '1:1',
+ '1:2', '1:4', '1:6', '1:8', '1:10', '1:12', '1:14','1:16',
+ '1:20', '1:25', '1:30', '1:40', '1:60', '1:80', '1:100',]
+
+def GvViewWindowFromXML( node, parent, filename=None ):
+ import gdal
+ instance = \
+ GvViewWindow( app = parent,
+ title = gvutils.XMLFindValue( node, "title", '' ),
+ show_menu = int(gvutils.XMLFindValue( node, "show_menu", "1")),
+ show_icons = int(gvutils.XMLFindValue( node, "show_icons", "1")),
+ show_tracker = int(gvutils.XMLFindValue( node, "show_tracker", "1")),
+ show_scrollbars = int(gvutils.XMLFindValue( node, "show_scrollbars", "1")),
+ menufile = gvutils.XMLFindValue( node, 'menufile', None),
+ iconfile = gvutils.XMLFindValue( node, 'iconfile', None))
+
+ if gvutils.XMLFindValue( node, "width", None ) is not None and \
+ gvutils.XMLFindValue( node, "height", None ) is not None:
+ instance.set_default_size(
+ int(gvutils.XMLFindValue( node, "width", "600")),
+ int(gvutils.XMLFindValue( node, "height", "600")) )
+
+ viewarea_tree = gvutils.XMLFind( node, "GvViewArea" )
+ if viewarea_tree != None:
+ instance.viewarea.initialize_from_xml( viewarea_tree,
+ filename=filename )
+
+ # Avoid multiple views with the same title when user opens
+ # new views after opening a project- same title causes
+ # problems in view management. Need to consider possibitity
+ # that user may have shut several views before saving the
+ # project, so next_viewnum may need to be > # views.
+ GvViewWindow.next_viewnum = GvViewWindow.next_viewnum + 1
+ title = gvutils.XMLFindValue( node, "title", '')
+ if len(title) > 5:
+ try:
+ vn = int(title[5:])
+ GvViewWindow.next_viewnum = max( GvViewWindow.next_viewnum,
+ vn + 1 )
+ except:
+ pass
+
+ instance.show()
+
+ # We can't move the window till after it is shown.
+ if gvutils.XMLFindValue( node, "x", None ) is not None and \
+ gvutils.XMLFindValue( node, "y", None ) is not None:
+ instance.window_move(
+ int(gvutils.XMLFindValue( node, "x", "0")),
+ int(gvutils.XMLFindValue( node, "y", "0")) )
+
+ return instance
+
+class GvViewWindow(gtk.GtkWindow):
+ next_viewnum = 1
+
+ def __init__(self, app=None, title=None, show_menu=1, show_icons=1,
+ show_tracker=1, show_scrollbars=1, menufile='DefaultMenuFile.xml',iconfile='DefaultIconFile.xml'):
+
+ gtk.GtkWindow.__init__(self)
+
+ if title is None:
+ title = 'View %d' % GvViewWindow.next_viewnum
+ GvViewWindow.next_viewnum = GvViewWindow.next_viewnum + 1
+
+ self.app = app
+ self.set_title('OpenEV: '+title)
+ gvhtml.set_help_topic(self, 'mainwindow.html')
+ self.title = title
+ self.file_sel = None
+ self.drape_file_sel = None
+ self.DEM_file_sel = None
+ shell = gtk.GtkVBox(spacing=0)
+ self.add(shell)
+ self.pref_dialog = None
+ self.position3D_dialog = None
+ self.set_policy(TRUE,TRUE,FALSE)
+ self.zoom = 0.0
+ self.zoom_flag = 'yes' # see set_zoom_factor_cb()
+ self.zoom_factor = None
+ self.position3D_dialog = None
+ self.menufile = menufile
+ self.iconfile = iconfile
+
+ # Menu bar
+ if show_menu > 0:
+ self.create_menubar(menufile)
+ shell.pack_start(self.menuf, expand=FALSE)
+ else:
+ self.menuf = None
+
+
+ if show_icons > 0:
+ self.create_iconbar(iconfile)
+ shell.pack_start(self.iconbar,expand=FALSE)
+ else:
+ self.iconbar = None
+
+ # Add the actual GvViewArea for drawing in
+ self.viewarea = gview.GvViewArea()
+
+ if gview.get_preference('view_background_color') is not None:
+ tokens = string.split(gview.get_preference('view_background_color'))
+ self.viewarea.set_background_color( [ float(tokens[0]),
+ float(tokens[1]),
+ float(tokens[2]),
+ float(tokens[3])] )
+
+ # Update Zoom ratio box in toolbar whenever view changes
+ # (actually, only when zoom changes)
+ self.view_state_changed_id = \
+ self.viewarea.connect("view-state-changed", self.update_zoom_cb)
+ self.viewarea.connect("active-changed", self.update_zoom_cb)
+
+ size = (620, 620)
+ if show_scrollbars:
+ self.scrolled_window = gtk.GtkScrolledWindow()
+ self.set_usize(size[0], size[1] + 60)
+ self.scrolled_window.add(self.viewarea)
+ shell.pack_start(self.scrolled_window, expand=TRUE)
+ else:
+ self.viewarea.size(size[0],size[1])
+ self.scrolled_window = None
+ shell.pack_start(self.viewarea, expand=TRUE)
+
+ if show_tracker:
+ statusbar = gtk.GtkHBox()
+ shell.pack_start(statusbar, expand=FALSE)
+ label = gtk.GtkLabel()
+ statusbar.pack_start(label, expand=FALSE, padding=3)
+ tracker = gview.GvTrackTool(label)
+ tracker.activate(self.viewarea)
+ self.tracker = tracker
+ else:
+ self.tracker = None
+
+ # End of widgets
+ self.viewarea.grab_focus()
+ shell.show_all()
+
+ self.show_rfl()
+
+ self.app.view_manager.add_view( self )
+
+ self.rawgeo_update()
+
+ self.viewarea.connect('key-press-event', self.key_press_cb)
+
+ # The close flag is meant to be used
+ # by other applications that use OpenEV's windows,
+ # but may want other closing behaviour for that
+ # particular window (eg. user
+ # unable to close, hiding instead of destroying,
+ # etc.). 0 is for default, 1 for not doing anything,
+ # 2 for hiding.
+ self.close_flag=0
+
+ # Trap window close event
+ self.connect('delete-event', self.close)
+
+
+ def serialize(self,base=None, filename=None ):
+ if base is None:
+ base = [gdal.CXT_Element, 'GvViewWindow']
+ base.append( [gdal.CXT_Attribute, 'module',
+ [gdal.CXT_Text, 'gvviewwindow']] )
+
+ if self.menuf is None:
+ base.append( [gdal.CXT_Attribute, 'show_menu',
+ [gdal.CXT_Text, '0']] )
+ if self.iconbar is None:
+ base.append( [gdal.CXT_Attribute, 'show_icons',
+ [gdal.CXT_Text, '0']] )
+ if self.tracker is None:
+ base.append( [gdal.CXT_Attribute, 'show_tracker',
+ [gdal.CXT_Text, '0']] )
+ if self.scrolled_window is None:
+ base.append( [gdal.CXT_Attribute, 'show_scrollbars',
+ [gdal.CXT_Text, '0']] )
+
+ geometry = self.get_allocation()
+
+ base.append( [gdal.CXT_Attribute, 'width',
+ [gdal.CXT_Text, str(geometry[2])]] )
+ base.append( [gdal.CXT_Attribute, 'height',
+ [gdal.CXT_Text, str(geometry[3])]] )
+
+ x_pos, y_pos = self.get_position()
+ base.append( [gdal.CXT_Attribute, 'x',
+ [gdal.CXT_Text, str(x_pos)]] )
+ base.append( [gdal.CXT_Attribute, 'y',
+ [gdal.CXT_Text, str(y_pos)]] )
+
+ base.append( [gdal.CXT_Element, 'title',
+ [gdal.CXT_Text, self.title]] )
+
+ if self.menufile is not None:
+ base.append( [gdal.CXT_Element, 'menufile',
+ [gdal.CXT_Text, self.menufile]] )
+
+ if self.iconfile is not None:
+ base.append( [gdal.CXT_Element, 'iconfile',
+ [gdal.CXT_Text, self.iconfile]] )
+
+ base.append( self.viewarea.serialize( filename=filename ) )
+
+ return base
+
+ def show_rfl(self, *args):
+ if self.menuf is None:
+ return
+
+ if ((self.app is None) or (hasattr(self.app,'get_rfl') == 0)):
+ return
+
+ try:
+ list = self.app.get_rfl()
+ for i in range(5):
+ menuitem = self.menuf.find('File/rfl'+str(i+1))
+ if i < len(list):
+ menuitem.children()[0].set_text(list[i])
+ menuitem.show()
+ else:
+ menuitem.children()[0].set_text('')
+ menuitem.hide()
+ except:
+ # Some menus don't have rfl
+ pass
+
+ def rfl_cb(self, menuitem, rfl_index, *args):
+ self.file_open_by_name(menuitem.children()[0].get(), sds_check=0)
+
+ def make_active(self, *args):
+ self.app.view_manager.set_active_view( self )
+
+ def key_press_cb( self, viewarea, event, *args ):
+ if event.keyval == F9:
+ gview.texture_cache_dump()
+
+ def busy_changed_cb(self,*args):
+ if gview.manager.get_busy():
+ self.idlebusy_pixmap.set( self.busy_icon[0], self.busy_icon[1] )
+ else:
+ self.idlebusy_pixmap.set( self.idle_icon[0], self.idle_icon[1] )
+
+ def print_cb(self, *args):
+ import gvprint
+ pd = gvprint.GvPrintDialog( self.viewarea )
+
+ def helpcb(self, item, topic='openevmain.html'):
+ gvhtml.LaunchHTML( topic )
+
+ def aboutcb(self, *args):
+ import oe_about
+
+ oe_about.ShowAboutBox( self )
+
+ def set_close_function(self,ctype=0):
+ """ Set the close behaviour for the view:
+ Input parameters:
+ ctype- 0 for default behaviour (close view,
+ exit when last one is shut); 1
+ so that window can't be closed
+ at all; 2 so that window will be
+ hidden rather than closed. Note
+ that the application will have to
+ reset the close function back again
+ for cases 1 and 2 if it wants to
+ close the window using the close function.
+
+ """
+ self.close_flag=ctype
+
+
+ def close(self, *args):
+ # first check for non-standard close settings
+ if self.close_flag == 1:
+ return TRUE
+ elif self.close_flag == 2:
+ self.hide()
+ return TRUE
+
+ # what else do we need to do?
+ if len(self.app.view_manager.get_views()) == 1:
+ if self.app.request_quit() > 0:
+ if self.menuf is not None:
+ self.app.unsubscribe('rfl-change',self.show_rfl)
+ # request_quit() sends out the order for the view
+ # to be shut. The destroy() and return FALSE are
+ # redundant and sometimes result in errors (project
+ # files).
+ #self.destroy()
+ #return FALSE
+ return TRUE
+ else:
+ return TRUE
+ else:
+ if self.menuf is not None:
+ self.app.unsubscribe('rfl-change',self.show_rfl)
+ self.destroy()
+ return TRUE
+
+ def hide_entry(self,entrystr='File/Exit'):
+ """Hide a menu entry (can be temporary)
+ Input: entrystr- eg. 'File/Exit', 'File/Close',...
+ Returns 1 for success, 0 for failure.
+ """
+ try:
+ item=self.menuf.find(entrystr)
+ if item is not None:
+ item.hide()
+ return 1
+ return 0
+ except:
+ return 0
+
+ def show_entry(self,entrystr='File/Exit'):
+ """Re-show a hidden menu entry
+ Input: entrystr- eg. 'File/Exit', 'File/Close',...
+ Returns 1 for success, 0 for failure.
+ """
+ try:
+ item=self.menuf.find(entrystr)
+ if item is not None:
+ item.show()
+ return 1
+ return 0
+ except:
+ return 0
+
+ def exit(self, *args ):
+ # should ask for confirmation at this point.
+ self.app.request_quit()
+
+ def undo(self, *args):
+ self.make_active()
+ gview.undo_pop()
+
+ def show_oeattedit(self, *args):
+ self.make_active()
+
+ import oeattedit
+
+ oeattedit.launch()
+
+ def show_layerdlg(self, *args):
+ self.layerdlg.show()
+ self.layerdlg.get_window()._raise()
+
+ def show_toolbardlg(self, *args):
+ self.make_active()
+ self.toolbar.show()
+ self.toolbar.get_window()._raise()
+
+ def goto_dlg(self, *args):
+ """ Create the GoTo Dialog box with coordinate system option menu and
+ text entry fields """
+ window = gtk.GtkWindow()
+ window.set_title('Go To...')
+ window.set_border_width(10)
+ vbox = gtk.GtkVBox(homogeneous=FALSE,spacing=15)
+ window.add(vbox)
+
+ # Make this a selection menu - doesn't work, yet!
+ box = gtk.GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=gtk.FALSE)
+ box.pack_start(gtk.GtkLabel('Coordinate System:'),expand=FALSE)
+ self.coord_system_om = gvutils.GvOptionMenu(('Row/Col','Native'),
+ self.set_coord_system)
+ box.pack_start(self.coord_system_om,expand=FALSE)
+
+ # Get current position in view native projection
+ # - changing Option Menu updates this in entry fields
+
+ current_pos = self.viewarea.get_translation()
+
+ # X Position
+ box = gtk.GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=gtk.FALSE)
+ box.pack_start(gtk.GtkLabel('X Position:'),expand=FALSE)
+ x_pos_entry = gtk.GtkEntry(maxlen=14)
+ x_pos_entry.set_text(str(-current_pos[0]))
+ box.pack_start(x_pos_entry,expand=FALSE)
+
+ # Y Position
+ box = gtk.GtkHBox(spacing=3)
+ vbox.pack_start(box, expand=gtk.FALSE)
+ box.pack_start(gtk.GtkLabel('Y Position:'),expand=FALSE)
+ y_pos_entry = gtk.GtkEntry(maxlen=14)
+ y_pos_entry.set_text(str(-current_pos[1]))
+ box.pack_start(y_pos_entry,expand=FALSE)
+
+ # Button to move
+ goto_button = gtk.GtkButton('Go To...')
+ goto_button.connect('clicked', self.goto_location )
+ vbox.pack_start(goto_button,expand=FALSE)
+
+ self.x_pos_entry = x_pos_entry
+ self.y_pos_entry = y_pos_entry
+
+ # set default to be native system - must be after x/y_pos_entry are setup
+ self.coord_system_om.set_history(1)
+
+ window.show_all()
+
+ def set_coord_system(self, om, *args):
+ """ Set coordinate system goto coordinates entered in GoTo dialog from
+ option menu. """
+ current_pos = self.viewarea.get_translation()
+
+ if om.get_history() == 0:
+ self.goto_coord_system = 'pixel'
+ # Lat/Long Not Working Yet!
+ elif om.get_history() == 9:
+ self.goto_coord_system = 'lat-long'
+ elif om.get_history() == 1:
+ self.goto_coord_system = 'native'
+ else:
+ self.goto_coord_system = 'native'
+
+ def goto_location(self, Button, *args):
+ """ Translate view to location specified in GoTo Dialog, using projection """
+ self.make_active()
+
+ coord_system = self.goto_coord_system
+ str_x = self.x_pos_entry.get_text()
+ str_y = self.y_pos_entry.get_text()
+
+ x = string.atof(str_x)
+ y = string.atof(str_y)
+
+ if coord_system == 'pixel':
+ # Get current raster
+ layer = self.viewarea.active_layer()
+
+ if (layer is None) or (gvutils.is_of_class( layer.__class__, 'GvRasterLayer' ) == 0):
+ gvutils.warning('Please select a raster layer using the layer dialog.\n')
+ return
+
+ raster = layer.get_parent()
+ if ((raster is not None) and (self.viewarea.get_raw(layer) == 0)):
+ # layer is georeferenced, coordinates are pixel/line
+ position = raster.pixel_to_georef(x,y)
+ elif (raster is not None):
+ # layer is in pixel/line coordinates, coordinates are pixel/line
+ position = (x,y)
+ else:
+ return
+
+ # Doesn't work Yet!
+ elif coord_system == 'lat-long':
+ position = self.viewarea.map_location((x,y))
+
+ elif coord_system == 'native':
+ # native - do nothing
+ position = (x,y)
+
+ else:
+ print 'Error in gvviewwindow.py function goto_location() passed invalid coordinate system'
+ # native - do nothing
+ position = (x,y)
+
+ self.viewarea.set_translation(-position[0],-position[1])
+
+ def menu_save_project(self, *args):
+ self.app.save_project()
+
+ def menu_save_project_as(self, *args):
+ self.app.save_project_as()
+
+ def menu_new_view(self, *args):
+ self.app.new_view()
+
+ def save_vector_layer_request( self, *args ):
+ self.make_active()
+
+ layer = self.viewarea.active_layer()
+ if layer is None or \
+ gvutils.is_of_class( layer.__class__, 'GvShapesLayer' ) == 0:
+ gvutils.warning('Please select a vector layer using the layer\n'+\
+ 'dialog before attempting to save.' )
+ return
+
+ pgufilesel.SimpleFileSelect( self.save_vector_layer_with_file,
+ cb_data = layer.get_parent(),
+ title = 'Shapefile To Save to',
+ default_filename = layer.get_name() )
+
+ def save_vector_layer_with_file( self, filename, shapes_data ):
+ if shapes_data.save_to( filename ) == 0:
+ gvutils.error('Unable to save vectors to:'+filename)
+
+ def destroy_preferences(self,*args):
+ self.pref_dialog = None
+
+ def file_open_shape_by_name(self, filename):
+ self.make_active()
+ shape_data = gview.GvShapes(shapefilename=filename)
+ if shape_data is None or shape_data._o is None:
+ gvutils.error('Unable to open '+filename+' for loading.')
+ return
+
+ self.app.add_to_rfl(filename)
+ gview.undo_register(shape_data)
+
+ layer = gview.GvShapesLayer( shape_data )
+ layer.set_name(filename)
+ self.viewarea.add_layer(layer)
+ self.viewarea.set_active_layer(layer)
+
+ def file_open_ogr_by_name(self, filename):
+ import ogr
+ import gvogrdlg
+
+ self.make_active()
+
+ hDS = ogr.Open( filename )
+ if hDS is None:
+ return FALSE
+
+ self.app.add_to_rfl(filename)
+
+ dlg = gvogrdlg.GvOGRDlg(hDS, self )
+
+ return TRUE
+
+ def file_open_ogr_by_layer(self, layer):
+
+ import _gv
+
+ raw_data = _gv.gv_shapes_from_ogr_layer( layer._o )
+ if raw_data is None:
+ return FALSE
+
+ shape_data = gview.GvShapes(_obj=raw_data)
+ if shape_data is None:
+ return
+
+ if len(shape_data) > 0:
+ gview.undo_register(shape_data)
+
+ layer = gview.GvShapesLayer( shape_data )
+ self.viewarea.add_layer(layer)
+ self.viewarea.set_active_layer(layer)
+ else:
+ # I am not sure how to blow away the GvShapes properly.
+ pass
+
+ return TRUE
+
+ def file_import_cb(self, *args):
+ self.make_active()
+ pgufilesel.SimpleFileSelect( self.file_import_by_name, None,
+ 'File To Import',
+ help_topic = 'files.html' )
+
+ def file_import_by_name( self, filename, *args ):
+ self.make_active()
+ dataset = gdal.Open( filename )
+ if dataset is None:
+ gvutils.error('Unable to open '+filename+' for import.')
+ return
+
+ geotiff = gdal.GetDriverByName("GTiff")
+ if geotiff is None:
+ gvutils.error("Yikes! Can't find GeoTIFF driver!")
+ return
+
+ newbase, ext = os.path.splitext(filename)
+ newfile = newbase + ".tif"
+ i = 0
+ while os.path.isfile(newfile):
+ i = i+1
+ newfile = newbase+"_"+str(i)+".tif"
+
+ progress = pguprogress.PGUProgressDialog( 'Import to '+newfile,
+ cancel = TRUE )
+ progress.SetDefaultMessage( "translated" )
+
+ old_cache_max = gdal.GetCacheMax()
+ if old_cache_max < 20000000:
+ gdal.SetCacheMax( 20000000 )
+
+ new_dataset = geotiff.CreateCopy( newfile, dataset, FALSE,
+ ['TILED=YES',],
+ callback = progress.ProgressCB )
+ dataset = None
+
+ if progress.cancelled:
+ progress.destroy()
+ if os.path.isfile(newfile):
+ os.unlink(newfile)
+ gdal.SetCacheMax( old_cache_max );
+ return
+
+ if new_dataset == None:
+ progress.destroy()
+ gvutils.error('Unable to translate '+filename+' to '+newfile)
+ if os.path.isfile(newfile):
+ os.unlink(newfile)
+ gdal.SetCacheMax( old_cache_max );
+ return
+
+ progress.SetDefaultMessage( "overviews built" )
+ new_dataset.BuildOverviews( "average", callback = progress.ProgressCB )
+ new_dataset = None
+
+ progress.destroy()
+
+ gdal.SetCacheMax( old_cache_max );
+
+ # open normally
+ self.file_open_by_name( newfile, sds_check=0 )
+
+
+ def file_open_cb(self, *args):
+ self.make_active()
+
+ if gview.get_preference('save_recent_directory') == 'on':
+ recent_dir = gview.get_preference('recent_directory')
+ else:
+ recent_dir = None
+
+ pgufilesel.SimpleFileSelect( ok_cb = self.file_open_name_check,
+ title = 'File Open',
+ default_filename = recent_dir,
+ help_topic = 'files.html' )
+
+# buffer function to check for wild cards in filename and then expand them
+ def file_open_name_check(self, filename, lut=None,*args):
+ if ('*' in filename)or('?' in filename):
+ for file in glob.glob(filename):
+ self.file_open_by_name(file)
+ else:
+ self.file_open_by_name(filename)
+
+ def open_subdataset_check( self, dataset ):
+ import gvsdsdlg
+ dlg = gvsdsdlg.GvSDSDlg(dataset, self)
+
+ def file_open_ap_envisat(self, dataset ):
+ options = []
+ if gview.get_preference('gcp_warp_mode') is not None \
+ and gview.get_preference('gcp_warp_mode') == 'no':
+ options.append(('raw','yes'))
+
+ md = dataset.GetMetadata()
+ try:
+ md1 = md['SPH_MDS1_TX_RX_POLAR']
+ md2 = md['SPH_MDS2_TX_RX_POLAR']
+ except:
+ md1 = ''
+ md2 = ''
+
+ raster1 = gview.manager.get_dataset_raster(dataset,1)
+ raster2 = gview.manager.get_dataset_raster(dataset,2)
+
+ rl1 = gview.GvRasterLayer(raster1, options, rl_mode=gview.RLM_AUTO )
+ rl1.set_name( 'MDS1: ' + md1 )
+ rl2 = gview.GvRasterLayer(raster2, options, rl_mode=gview.RLM_AUTO )
+ rl2.set_name( 'MDS2: ' + md2 )
+
+ # Add MDS1 to the current view window.
+
+ self.viewarea.add_layer(rl1)
+ self.viewarea.set_active_layer(rl1)
+ self.rawgeo_update()
+ self.set_title( self.title + ': MDS1- ' + md1 )
+
+ # Create a new view window and add MDS2 to it.
+
+ view2 = self.app.new_view()
+ view2.viewarea.add_layer(rl2)
+ view2.viewarea.set_active_layer(rl2)
+ view2.rawgeo_update()
+ view2.set_title( view2.title + ': MDS2- ' + md2 )
+
+ # Setup link between views.
+ link = gview.GvViewLink()
+ link.register_view( self.viewarea )
+ link.register_view( view2.viewarea )
+ link.enable()
+
+ def open_gdal_dataset(self, dataset, lut=None, sds_check=1, \
+ add_to_rfl=0, *args):
+ """Opens existing GDAL dataset."""
+
+ self.make_active()
+
+ dataset = gview.manager.add_dataset(dataset)
+ if dataset is None:
+ return
+
+ if sds_check and len(dataset.GetSubDatasets()) > 0:
+ self.open_subdataset_check( dataset )
+ return
+
+ if add_to_rfl:
+ self.app.add_to_rfl(dataset.GetDescription())
+
+ md = dataset.GetMetadata()
+ # special hack for displaying AP envisat specially.
+ if md.has_key('MPH_PHASE') and dataset.RasterCount == 2:
+ self.file_open_ap_envisat( dataset )
+ return
+
+ raster = gview.manager.get_dataset_raster(dataset,1)
+ options = []
+ if gview.get_preference('gcp_warp_mode') is not None \
+ and gview.get_preference('gcp_warp_mode') == 'no':
+ options.append(('raw','yes'))
+
+ if lut:
+ raster_layer = gview.GvRasterLayer(raster, options,
+ rl_mode = gview.RLM_SINGLE )
+ raster_layer.lut_put(lut)
+
+ elif dataset.RasterCount > 2:
+ raster_layer = gview.GvRasterLayer(raster, options,
+ rl_mode = gview.RLM_RGBA )
+ elif dataset.RasterCount == 2 and \
+ dataset.GetRasterBand(2).GetRasterColorInterpretation() == gdal.GCI_AlphaBand:
+ raster_layer = gview.GvRasterLayer(raster, options,
+ rl_mode = gview.RLM_RGBA )
+ else:
+ raster_layer = gview.GvRasterLayer(raster, options,
+ rl_mode = gview.RLM_AUTO )
+ raster_layer.set_name(dataset.GetDescription())
+
+ # Lots of logic to handle RGB and RGBA Layers
+ if raster_layer.get_mode() == gview.RLM_RGBA \
+ and dataset.RasterCount == 2:
+
+ alpha_band = gview.manager.get_dataset_raster(dataset,2)
+ raster_layer.set_source(1,raster)
+ raster_layer.set_source(2,raster)
+ raster_layer.set_source(3,alpha_band)
+
+ raster_layer.blend_mode_set( gview.RL_BLEND_FILTER )
+
+ if raster_layer.get_mode() == gview.RLM_RGBA \
+ and dataset.RasterCount > 2:
+
+ green_raster = gview.manager.get_dataset_raster(dataset,2)
+ blue_raster = gview.manager.get_dataset_raster(dataset,3)
+
+ raster_layer.set_source(1,green_raster)
+ raster_layer.set_source(2,blue_raster)
+
+ if dataset.RasterCount > 3:
+ band = dataset.GetRasterBand(4)
+ if band.GetRasterColorInterpretation() == gdal.GCI_AlphaBand:
+ raster_layer.blend_mode_set( gview.RL_BLEND_FILTER )
+ alpha_raster = \
+ gview.manager.get_dataset_raster(dataset, 4)
+ raster_layer.set_source(3,alpha_raster)
+
+ self.viewarea.add_layer(raster_layer)
+ self.viewarea.set_active_layer(raster_layer)
+ self.rawgeo_update()
+
+ def file_open_by_name(self, filename, lut=None, sds_check=1, *args):
+ head = os.path.dirname(filename)
+ if len(head) > 0:
+ if os.access(head,os.R_OK):
+ pgufilesel.simple_file_sel_dir = head+os.sep
+
+ if gview.get_preference('save_recent_directory') == 'on':
+ gview.set_preference('recent_directory', head+os.sep)
+
+ if gvutils.is_shapefile(filename):
+ self.file_open_shape_by_name(filename)
+ return
+
+ if gvutils.is_project_file(filename):
+ self.app.load_project(filename)
+ return
+
+ gdal.PushErrorHandler( 'CPLQuietErrorHandler' )
+ dataset = gview.manager.get_dataset(filename)
+ gdal.PopErrorHandler()
+ if dataset is None \
+ and gdal.GetLastErrorNo() != 4 \
+ and gdal.GetLastErrorNo() != 0:
+ gvutils.error( 'Unable to open '+filename+'\n\n' \
+ + gdal.GetLastErrorMsg() )
+ return
+
+ # catch ogr file open failure and pop up
+ # a warning rather than dumping to screen.
+ try:
+ if dataset is None and self.file_open_ogr_by_name(filename):
+ return
+
+ if dataset is None:
+ gvutils.error('Unable to open '+filename+'\n\n' \
+ + gdal.GetLastErrorMsg() )
+ return
+ except:
+ if dataset is None:
+ gvutils.error('Unable to open '+filename+'\n\n' \
+ + gdal.GetLastErrorMsg() )
+ return
+
+ self.open_gdal_dataset(dataset, lut, sds_check, add_to_rfl=1)
+
+ def init_custom_icons(self):
+ pass
+
+ def init_default_icons(self):
+ # Zoom ratio selection box
+ zoom_factor = gtk.GtkCombo()
+ zoom_factor.set_popdown_strings(ratio_list)
+ zoom_factor.entry.set_text('1:1')
+ zoom_factor.set_usize(70,20)
+ self.zoom_entry_changed_id = zoom_factor.entry.connect('changed', self.set_zoom_factor_cb)
+ zoom_factor.list.connect('selection-changed', self.set_zoom_factor_focus_cb)
+ self.zoom_factor = zoom_factor
+
+ # raw / georeferenced pixmap
+ self.raw_icon = gtk.create_pixmap_from_xpm(self,None,
+ os.path.join(gview.home_dir,'pics', 'worldg.xpm'))
+ self.geo_icon = gtk.create_pixmap_from_xpm(self,None,
+ os.path.join(gview.home_dir,'pics', 'worldrgb.xpm'))
+ self.rawgeo_pixmap = gtk.GtkPixmap(self.raw_icon[0],
+ self.raw_icon[1])
+
+ # idle / busy pixmap
+ self.idle_icon = gtk.create_pixmap_from_xpm(self,None,
+ os.path.join(gview.home_dir,'pics', 'idle.xpm'))
+ self.busy_icon = gtk.create_pixmap_from_xpm(self,None,
+ os.path.join(gview.home_dir,'pics', 'busy.xpm'))
+ self.idlebusy_pixmap = gtk.GtkPixmap(self.busy_icon[0],
+ self.busy_icon[1])
+ gview.manager.connect('busy-changed', self.busy_changed_cb)
+
+ def create_iconbar(self, iconfile='DefaultIconFile.xml'):
+ self.iconbar = gtk.GtkToolbar(gtk.ORIENTATION_HORIZONTAL,
+ gtk.TOOLBAR_ICONS)
+
+ self.init_default_icons()
+ self.init_custom_icons()
+
+ self.icon_cmds = None
+ if iconfile is not None:
+ # check that icon file exists. If not, use old values for
+ # backwards compatibility
+ fulliconfile = os.path.join(gview.home_dir,'xmlconfig',iconfile)
+ if os.path.isfile(fulliconfile) == 1:
+ if (self.app is not None) and hasattr(self.app,'load_icons_file_from_xml'):
+ icon_cmds=self.app.load_icons_file_from_xml( iconfile )
+ else:
+ icon_cmds = self.load_icons_file_from_xml( iconfile )
+ self.icon_cmds = icon_cmds
+ else:
+ raise AttributeError,'Unable to find view icon configuration file '+iconfile
+ else:
+ self.icon_cmds=self.old_icon_cmds()
+
+ for cmd in self.icon_cmds:
+ exec cmd
+
+ gview.manager.set_busy(TRUE)
+
+ def old_icon_cmds(self):
+ icon_cmds=[]
+ icon_cmds.append("self.add_icon_to_bar( 'openfile.xpm', None,'Open and Display Raster/Vector File',self.file_open_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'print.xpm', None,'Print Current View',self.print_cb, 'gvprint.html' )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'nonelut.xpm', None,'Revert to no Enhancement',self.nonelut_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'linear.xpm', None,'Linear Stretch/Enhancement',self.linear_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'equalize.xpm', None,'Apply Equalization Enhancement to Raster',self.equalize_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'log.xpm', None,'Logarithmic Enhancement to Raster',self.log_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'windowed.xpm', None,'Windowed Raster Re-enhancement',self.restretch_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'classify.xpm', None,'Classify Raster',self.classify_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'legend.xpm', None,'Show Legend',self.show_legend_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'seeall.xpm', None,'Fit All Layers',self.seeall_cb )")
+
+ # Zoom ratio selection box
+ icon_cmds.append("self.iconbar.append_widget(self.zoom_factor, 'Zoom Ratio', 'Zoom Ratio')")
+
+ icon_cmds.append("self.add_icon_to_bar( 'zoomin.xpm', None,'Zoom in x2',self.zoomin_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'zoomout.xpm', None,'Zoom out x2',self.zoomout_cb )")
+
+ icon_cmds.append("self.add_icon_to_bar( 'refresh.xpm', None,'Refresh Rasters From Disk',self.refresh_cb )")
+
+ # raw / georeferenced pixmap
+ icon_cmds.append("self.iconbar.append_item(None, 'Georeferenced','Georeferenced', self.rawgeo_pixmap,self.rawgeo_cb )")
+
+ # Help
+ icon_cmds.append("self.add_icon_to_bar( 'help.xpm', None,'Launch Online Help',self.helpcb )")
+
+ # idle / busy pixmap
+ icon_cmds.append("self.iconbar.append_item(None, 'Busy Indicator','Busy Indicator', self.idlebusy_pixmap,self.do_nothing )")
+
+ return icon_cmds
+
+ def create_menubar(self, menufile='DefaultMenuFile.xml'):
+ self.menuf = gvutils.GvMenuFactory()
+
+ self.menu_cmd = None
+ if menufile is not None:
+ # Check that menu file exists. If not, load old menu
+ # for backwards comaptibility.
+ fullmenufile = os.path.join(gview.home_dir,'xmlconfig',menufile)
+ if os.path.isfile(fullmenufile) == 1:
+ if ((self.app is not None) and hasattr(self.app,'load_menus_file_from_xml')):
+ # Application parses the xml file itself
+ menu_cmd=self.app.load_menus_file_from_xml( menufile, self.title )
+ else:
+ menu_cmd = self.load_menus_file_from_xml( menufile )
+ self.menu_cmd = menu_cmd
+ #print menu_cmd
+ else:
+ raise AttributeError,'Unable to find view menu configuration file '+menufile
+ else:
+ self.menu_cmd = self.old_menu_cmd()
+
+ exec self.menu_cmd
+ self.add_accel_group(self.menuf.accelerator)
+
+ if self.app is not None:
+ self.app.subscribe('rfl-change',self.show_rfl)
+
+
+ def old_menu_cmd(self):
+ menu_cmd = "self.menuf.add_entries([" + \
+ "('File/Import', None, self.file_import_cb )," + \
+ "('File/Open', '<control>O', self.file_open_cb )," + \
+ "('File/Open 3D', None, self.open_3D_request)," + \
+ "('File/Save Vector Layer', None, self.save_vector_layer_request)," + \
+ "('File/Save Project', None, self.menu_save_project)," + \
+ "('File/New View', None, self.menu_new_view)," + \
+ "('File/Print', None, self.print_cb)," + \
+ "('File/<separator>', None, None)," + \
+ "('File/rfl1', None, self.rfl_cb, 1)," + \
+ "('File/rfl2', None, self.rfl_cb, 2)," + \
+ "('File/rfl3', None, self.rfl_cb, 3)," + \
+ "('File/rfl4', None, self.rfl_cb, 4)," + \
+ "('File/rfl5', None, self.rfl_cb, 5)," + \
+ "('File/<separator>', None, None)," + \
+ "('File/Close', None, self.close)," + \
+ "('File/Exit', '<control>Q', self.exit)," + \
+ "('Edit/Undo', None, self.undo)," + \
+ "('Edit/Layers...', None, self.app.show_layerdlg)," + \
+ "('Edit/Vector Layer Attributes...', None, self.show_oeattedit)," + \
+ "('Edit/Edit Toolbar...', None, self.app.show_toolbardlg)," + \
+ "('Edit/Go To...', None, self.goto_dlg)," + \
+ "('Edit/Python Shell...', None, self.pyshell)," + \
+ "('Edit/3D Position...', None, self.position_3d)," + \
+ "('Edit/Preferences...', None, self.app.launch_preferences)," + \
+ "('Help/Help...', None, self.helpcb, 'openevmain.html')," + \
+ "('Help/<separator>', None, None)," + \
+ "('Help/Web Page...', None, self.helpcb,'http://OpenEV.Sourceforge.net/')," + \
+ "('Help/About...', None, self.aboutcb)])"
+
+ return menu_cmd
+
+ def load_menus_file_from_xml(self, menufile='DefaultMenuFile.xml'):
+ # load in menu file and populate menu entries
+ menufile = os.path.join(gview.home_dir,'xmlconfig',menufile)
+ menu_list = []
+ try:
+ raw_xml = open(menufile).read()
+ except:
+ raise AttributeError,"Unable to load " + menufile
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ raise AttributeError,"Problem occured parsing menu file " + menufile
+ return
+
+ if tree[1] != 'GViewAppMenu':
+ raise AttributeError,"Root of %s is not GViewAppMenu node " % menufile
+ return
+
+ # loop over entries getting path,accelerator,callback and arguments
+ menu_trees = gvutils.XMLFind( tree, 'Menu')
+ if menu_trees is None:
+ raise AttributeError,"Invalid menu file format"
+
+ for node in menu_trees[2:]:
+ if node[1] == 'entry':
+ node_path = gvutils.XMLFind( node, 'path')
+ if node_path is None:
+ raise AttributeError,"Invalid menu file format - missing path"
+
+ entry_type = gvutils.XMLFindValue( node_path, 'type', '')
+ entry_path = gvutils.XMLFindValue( node, 'path','')
+
+ if (string.find(entry_path,"/") == -1):
+ raise AttributeError,"Invalid menu file format - bad path:%s" % entry_path
+
+ if (entry_type != ''):
+ entry_type = "<" + entry_type + ">"
+ path_split=string.split(entry_path,"/")
+ path_split[-1] = entry_type + path_split[-1]
+ entry_path=string.join(path_split,"/")
+
+ entry_accelerator = gvutils.XMLFindValue( node, 'accelerator', 'None')
+ if (entry_accelerator != 'None'):
+ (key,mod) = string.split(entry_accelerator,'+')
+ entry_accelerator = "'<" + key + ">" + mod + "'"
+
+ entry_callback = gvutils.XMLFindValue( node, 'callback', 'None')
+ entry= "(" \
+ + string.join((entry_path,entry_accelerator, \
+ entry_callback),",")
+
+ arguments = gvutils.XMLFind( node, 'arguments')
+ if arguments is not None:
+ args_list = []
+ args = gvutils.XMLFind( arguments, 'arg','')
+ if args is not None:
+ for arg in args:
+ args_list.append(gvutils.XMLFindValue( arg, '',''))
+ entry = entry + "," + string.join(args_list,",")
+
+ entry = entry + ")"
+
+ menu_list.append(entry)
+ else:
+ raise AttributeError,"Invalid menu file format"
+
+ # create the menu command to populate the entries
+ menu_cmd = "self.menuf.add_entries([" + string.join(menu_list,',') + "])"
+ return menu_cmd
+
+
+ def load_icons_file_from_xml(self, iconfile='DefaultIconFile.xml'):
+ #print "LOADING ICONS"
+ # load in icon file and create icon commands
+ iconfile = os.path.join(gview.home_dir,'xmlconfig',iconfile)
+ icon_list = []
+ try:
+ raw_xml = open(iconfile).read()
+ except:
+ raise AttributeError,"Unable to load " + iconfile
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ raise AttributeError,"Problem occured parsing icon file " + iconfile
+ return
+
+ if tree[1] != 'GViewAppIconBar':
+ raise AttributeError,"Root of %s is not GViewAppIconBar node " % iconfile
+ return
+
+ # loop over entries getting icon,label,hint,callback and help
+ icon_trees = gvutils.XMLFind( tree, 'Iconbar')
+ if icon_trees is None:
+ raise AttributeError,"Invalid icon file format"
+
+ for node in icon_trees[2:]:
+ if node[1] == 'icon':
+ type = None
+ icon_label = gvutils.XMLFindValue( node, 'label','None')
+ icon_hint = gvutils.XMLFindValue( node, 'hint','None')
+ icon_callback = gvutils.XMLFindValue( node, 'callback','None')
+ icon_help = gvutils.XMLFindValue( node, 'help','None')
+ icon_file = gvutils.XMLFindValue( node, 'xpm','None')
+ # xpm files - need to add path and possible help
+ if (icon_file != 'None'):
+ type = 'xpm'
+ icon = "self.add_icon_to_bar(" \
+ + string.join((icon_file,icon_label,icon_hint, \
+ icon_callback,icon_help),",") \
+ + ")"
+
+ # pixmap files - not adding path or help
+ icon_file = gvutils.XMLFindValue( node, 'pixmap','None')
+ if (icon_file!= 'None'):
+ type = 'pixmap'
+ icon = "self.iconbar.append_item(" \
+ + string.join((icon_label,icon_hint,icon_hint, \
+ icon_file,icon_callback),",") \
+ + ")"
+
+ # widget
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ if (icon_file!= 'None'):
+ type = 'widget'
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ icon = "self.iconbar.append_widget(" \
+ + string.join((icon_file,icon_hint,icon_hint),",") \
+ + ")"
+ # none of the above
+ if type is None:
+ raise AttributeError,"Invalid icon file format - unknown type"
+
+ icon_list.append(icon)
+ else:
+ raise AttributeError,"Invalid icon file format"
+
+
+ return icon_list
+
+ def do_nothing(self, *args):
+ pass
+
+ def add_icon_to_bar(self, filename, text, hint_text, cb, help_topic=None):
+ full_filename = os.path.join(gview.home_dir,'pics',filename)
+ pix, mask = gtk.create_pixmap_from_xpm(self,None,full_filename)
+ item = self.iconbar.append_item(text,hint_text, hint_text,
+ gtk.GtkPixmap(pix,mask), cb)
+ if help_topic is not None:
+ gvhtml.set_help_topic(item, help_topic)
+
+ def insert_tool_icon(self, filename, text, hint_text, cb, help_topic=None, pos=0):
+ # Tool specifies full filename (file may not be in pics directory)
+
+ pix, mask = gtk.create_pixmap_from_xpm(self,None,filename)
+ item = self.iconbar.insert_item(text,hint_text, hint_text,
+ gtk.GtkPixmap(pix,mask), cb, pos )
+ if help_topic is not None:
+ gvhtml.set_help_topic(item, help_topic)
+
+ def classify_cb(self, *args):
+ self.make_active()
+ if hasattr(self.viewarea.active_layer(),'get_mode'):
+ if self.viewarea.active_layer().get_mode() == gview.RLM_COMPLEX:
+ gvutils.warning('Complex rasters cannot be classified!')
+ elif self.viewarea.active_layer().get_mode() == gview.RLM_RGBA:
+ gvutils.warning('Multiband rasters cannot be classified!')
+ else:
+ self.viewarea.active_layer().classify()
+ else:
+ self.viewarea.active_layer().classify()
+
+ def show_legend_cb(self, *args):
+ self.make_active()
+ self.viewarea.active_layer().show_legend()
+
+ def restretch_cb(self, *args):
+ self.make_active()
+ try:
+ self.viewarea.active_layer().window_restretch()
+ except:
+ gvutils.warning('This can only be applied to a raster layer.\n' \
+ + 'Select a raster layer for this view in the \nlayers dialog.' )
+
+ def equalize_cb(self, *args):
+ self.make_active()
+ try:
+ self.viewarea.active_layer().equalize()
+ except:
+ gvutils.warning('This can only be applied to a raster layer.\n' \
+ + 'Select a raster layer for this view in the \nlayers dialog.' )
+ #import traceback
+ #traceback.print_exc()
+
+ def linear_cb(self, *args):
+ self.make_active()
+ try:
+ self.viewarea.active_layer().linear()
+ except:
+ gvutils.warning('This can only be applied to a raster layer.\n' \
+ + 'Select a raster layer for this view in the \nlayers dialog.' )
+
+ def log_cb(self, *args):
+ self.make_active()
+ try:
+ self.viewarea.active_layer().log()
+ except:
+ gvutils.warning('This can only be applied to a raster layer.\n' \
+ + 'Select a raster layer for this view in the \nlayers dialog.' )
+
+ def nonelut_cb(self, *args):
+ self.make_active()
+ try:
+ self.viewarea.active_layer().none_lut()
+ except:
+ gvutils.warning('This can only be applied to a raster layer.\n' \
+ + 'Select a raster layer for this view in the \nlayers dialog.' )
+
+ def seeall_cb(self,*args):
+ self.make_active()
+ try:
+ self.viewarea.fit_all_layers()
+ except:
+ pass
+
+ def onetoone_cb(self,*args):
+ self.make_active()
+ try:
+ view = self.viewarea
+ layer = view.active_layer()
+ point1 = view.inverse_map_pointer(layer.pixel_to_view( 0, 0 ))
+ point2 = view.inverse_map_pointer(layer.pixel_to_view( 1, 1 ))
+ dist = math.sqrt(math.pow((point1[0]-point2[0]),2)
+ + math.pow((point1[1]-point2[1]),2))
+ factor = dist / math.sqrt(2)
+ view.zoom(-1 * (math.log(factor) / math.log(2)) )
+ except:
+ gvutils.warning('This operation can only be done if a raster layer is the\nactive layer. Please select a raster layer for this view in the layers dialog.')
+
+ def set_zoom_factor_focus_cb(self,*args):
+ """ Keep the focus in the view window when we selected a new zooming ratio from
+ the combo box. To ensure key events still recieved such as Home, and arrows """
+ self.viewarea.grab_focus()
+
+ def set_zoom_factor_cb(self,*args):
+ self.make_active()
+
+ if self.zoom_factor is None:
+ # if zoom factor icon doesn't exist (no iconbar)
+ return
+
+ try:
+ ratio_text = string.split(self.zoom_factor.entry.get_text(), ':')
+ ratio = [string.atof(ratio_text[0]), string.atof(ratio_text[1])]
+ except:
+ # if invalid text entered do nothing
+ return
+
+ # Make sure both values are positive
+ if (ratio[0] <= 0.0) or (ratio[1] <= 0.0):
+ return
+
+ try:
+ view = self.viewarea
+ layer = view.active_layer()
+ point1 = view.inverse_map_pointer(layer.pixel_to_view( 0, 0 ))
+ point2 = view.inverse_map_pointer(layer.pixel_to_view( 1, 1 ))
+ dist = math.sqrt(math.pow((point1[0]-point2[0]),2)
+ + math.pow((point1[1]-point2[1]),2))
+ factor = dist / math.sqrt(2)
+ self.zoom = factor
+
+ # Block view-state-changed signal while we update zoom factor
+ view.signal_handler_block(self.view_state_changed_id)
+ view.zoom(-1 * (math.log((ratio[1]/ratio[0])*factor) / math.log(2)) )
+ view.signal_handler_unblock(self.view_state_changed_id)
+
+ self.zoom_flag = 'yes'
+ except:
+ # To prevent multiple error messages use the zoom_flag to keep track if we
+ # have successfully zoomed since last error message, if not then we don't
+ # generate another one
+ if self.zoom_flag == 'yes':
+ self.zoom_flag = 'no'
+ gvutils.warning('This operation can only be done if a raster layer is the\nactive layer. Please select a raster layer for this view\nin the layers dialog.')
+
+ #self.viewarea.grab_focus()
+
+ def refresh_cb(self, *args):
+ self.make_active()
+ try:
+ layer = self.viewarea.active_layer()
+ for isource in range(4):
+ raster = layer.get_data(isource)
+ if raster is not None:
+ raster.changed()
+ except:
+ gvutils.warning('The refresh from disk operation can only be\n'+\
+ 'applied to raster layers. Select a raster\n'+\
+ 'layer for this view in the layers dialog.')
+ pass
+
+ def zoomin_cb(self,*args):
+ self.make_active()
+ try:
+ self.viewarea.zoom(1)
+ except:
+ pass
+
+ def zoomout_cb(self,*args):
+ self.make_active()
+ try:
+ self.viewarea.zoom(-1)
+ except:
+ pass
+
+ def update_zoom_cb(self, *args):
+ # Note: we do NOT use temp_zoom to get the zooming factor (doesn't work for
+ # geo-referenced images) we just use it as a way to check if the zoom
+ # has changed and therefore if we have to do the calculation
+ temp_zoom = self.viewarea.get_zoom()
+ layer = self.viewarea.active_layer()
+
+ if self.zoom_factor is None:
+ return gtk.FALSE
+
+ try:
+ # Check if zoom factor changed
+ if (temp_zoom != self.zoom) and (layer is not None):
+ self.zoom = temp_zoom
+ self.zoom_flag = 'yes'
+
+ point1 = self.viewarea.inverse_map_pointer(layer.pixel_to_view( 0, 0 ))
+ point2 = self.viewarea.inverse_map_pointer(layer.pixel_to_view( 1, 1 ))
+ dist = math.sqrt(math.pow((point1[0]-point2[0]),2)
+ + math.pow((point1[1]-point2[1]),2))
+ factor = dist / math.sqrt(2)
+
+ if (factor > 1):
+ ratio = str(round((factor/1.0),1)) + ':1'
+ else:
+ ratio = '1:' + str(round(1.0/factor,1))
+
+ # Block combo box changed signal while we update the text entry
+ self.zoom_factor.entry.signal_handler_block(self.zoom_entry_changed_id)
+ self.zoom_factor.entry.set_text(ratio)
+ self.zoom_factor.entry.signal_handler_unblock(self.zoom_entry_changed_id)
+ except:
+ self.zoom_factor.entry.signal_handler_block(self.zoom_entry_changed_id)
+ self.zoom_factor.entry.set_text('?:?')
+ self.zoom_factor.entry.signal_handler_unblock(self.zoom_entry_changed_id)
+
+ # Put focus back into view window
+ #self.viewarea.grab_focus()
+
+ # Return false to continue propogation of the view-state-changed signal
+ return gtk.FALSE
+
+
+ def pyshell(self, *args):
+ self.make_active()
+ self.app.pyshell()
+
+ # -------- 3D File Open and Setup --------
+ def open_3D_request(self, *args):
+ """ 3D File Open Dialog for selecting drape and height data """
+ self.make_active()
+ self.drape_dataset = None
+ self.DEM_dataset = None
+
+ # Create Dialog Window
+ dialog = gtk.GtkWindow()
+ dialog.set_title('Open 3D')
+ dialog.set_border_width(10)
+ # dialog.set_usize(500, 850)
+ dialog.set_policy(FALSE, FALSE, TRUE)
+ gvhtml.set_help_topic( dialog, 'open3d.html' )
+
+ box = gtk.GtkVBox(homogeneous=FALSE, spacing=5)
+ dialog.add(box)
+ self.file_dialog_3D = dialog
+
+ # Drape File Selector
+ drape_label = gtk.GtkLabel('Select Drape')
+ box.pack_start(drape_label)
+
+ self.drape_fileSelectWin = gtk.GtkFileSelection()
+ zsChildren = self.drape_fileSelectWin.children()[0].children()
+ for zsChild in zsChildren : zsChild.reparent(box)
+
+ # DEM File Selector
+ ruler1 = gtk.GtkHSeparator()
+ box.pack_start(ruler1)
+ DEM_label = gtk.GtkLabel('Select DEM')
+ box.pack_start(DEM_label)
+
+ self.DEM_fileSelectWin = gtk.GtkFileSelection()
+ zsChildren = self.DEM_fileSelectWin.children()[0].children()
+ for zsChild in zsChildren : zsChild.reparent(box)
+
+ # Mesh LOD and Height Scale
+ mesh_opts = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ lod_label = gtk.GtkLabel('Mesh Level of Detail')
+ spin_adjust = gtk.GtkAdjustment(value=3, lower=0, upper=8, step_incr=1)
+ self.lod_spin_button = gtk.GtkSpinButton(spin_adjust, climb_rate=1, digits=0)
+
+ hscale_label = gtk.GtkLabel('Height Scaling Factor:')
+ self.scale_value = gtk.GtkEntry(maxlen=7)
+ self.scale_value.set_text('1.0')
+
+ mesh_opts.pack_start(lod_label)
+ mesh_opts.pack_start(self.lod_spin_button)
+ mesh_opts.pack_start(hscale_label)
+ mesh_opts.pack_start(self.scale_value)
+ box.pack_start(mesh_opts)
+
+ # DEM height clamping options
+ min_clamp_opts = gtk.GtkHBox(homogeneous=TRUE,spacing=5)
+ self.min_heightclamp_entry = gtk.GtkEntry(maxlen=10)
+ self.min_heightclamp_entry.set_text('0.0')
+ min_clamp_label = gtk.GtkLabel('Minimum Height:')
+ self.min_heightclamp_toggle = gtk.GtkCheckButton('Clamp Minimum Height')
+ self.min_heightclamp_toggle.set_active(gtk.FALSE)
+ min_clamp_opts.pack_start(self.min_heightclamp_toggle)
+ min_clamp_opts.pack_start(min_clamp_label)
+ min_clamp_opts.pack_start(self.min_heightclamp_entry)
+ box.pack_start(min_clamp_opts)
+
+ max_clamp_opts = gtk.GtkHBox(homogeneous=TRUE,spacing=5)
+ self.max_heightclamp_entry = gtk.GtkEntry(maxlen=10)
+ self.max_heightclamp_entry.set_text('100000.0')
+ max_clamp_label = gtk.GtkLabel('Maximum Height:')
+ self.max_heightclamp_toggle = gtk.GtkCheckButton('Clamp Maximum Height')
+ self.max_heightclamp_toggle.set_active(gtk.FALSE)
+ max_clamp_opts.pack_start(self.max_heightclamp_toggle)
+ max_clamp_opts.pack_start(max_clamp_label)
+ max_clamp_opts.pack_start(self.max_heightclamp_entry)
+ box.pack_start(max_clamp_opts)
+
+ # Okay/Cancel Buttons
+ buttons = gtk.GtkHBox(homogeneous=FALSE, spacing=5)
+ okay = gtk.GtkButton('OK')
+ okay.set_usize(64, 32)
+ okay.connect('clicked', self.perform_3D_request)
+
+ cancel = gtk.GtkButton('Cancel')
+ cancel.set_usize(64, 32)
+ cancel.connect('clicked', dialog.destroy)
+
+ help = gtk.GtkButton('Help')
+ help.set_usize(64, 32)
+ help.connect('clicked', self.helpcb, 'open3d.html')
+
+ buttons.pack_end(help, expand=FALSE)
+ buttons.pack_end(cancel, expand=FALSE)
+ buttons.pack_end(okay, expand=FALSE)
+ box.pack_start(buttons, expand=FALSE)
+
+ # Show everything but unused fileselection buttons
+ dialog.show_all()
+ box.children()[1].hide() # Remove Drape Create/Delete/Rename
+ box.children()[6].hide() # Remove Drape Ok/Cancel
+ box.children()[9].hide() # Remove DEM Create/Delete
+ box.children()[14].hide() # Remove DEM Ok/Cancel
+
+
+ def perform_3D_request(self, *args):
+ """Tries to open selected files, then creates 3D Layer and switches to 3D mode"""
+ drape_filename = self.drape_fileSelectWin.get_filename()
+ dem_filename = self.DEM_fileSelectWin.get_filename()
+ mesh_lod = self.lod_spin_button.get_value_as_int()
+ hscale = float(self.scale_value.get_text())
+
+ if (self.min_heightclamp_toggle.get_active() == gtk.TRUE):
+ min_clamp = float(self.min_heightclamp_entry.get_text())
+ else:
+ min_clamp = None
+
+ if (self.max_heightclamp_toggle.get_active() == gtk.TRUE):
+ max_clamp = float(self.max_heightclamp_entry.get_text())
+ else:
+ max_clamp = None
+
+ # Do real work.
+ self.view3d_action( dem_filename, drape_filename, mesh_lod, hscale,
+ min_clamp, max_clamp )
+
+ # Clean up File Dialog Window
+ self.file_dialog_3D.destroy()
+
+ def view3d_action( self, dem_filename, drape_filename = None,
+ mesh_lod = None, hscale = None,
+ min_clamp = None, max_clamp = None ):
+
+ self.make_active()
+ gview.manager.set_busy(TRUE)
+
+ # Fill default parameters.
+ if drape_filename is None:
+ drape_filename = dem_filename
+ if mesh_lod is None:
+ mesh_lod = 3
+ if hscale is None:
+ hscale = 1.0
+
+ # Get Data
+ drape_dataset = gview.manager.get_dataset(drape_filename)
+ if drape_dataset is None or drape_dataset._o is None:
+ gvutils.error( 'Unable to open drape dataset: '+drape_filename)
+ return
+
+ DEM_dataset = self.raster_open_by_name(dem_filename)
+ if DEM_dataset is None or DEM_dataset._o is None:
+ return
+
+ if (drape_dataset is not None) and (DEM_dataset is not None):
+ # Get Current View & Prefs
+ view = self.viewarea
+
+ options = []
+ if gview.get_preference('_gcp_warp_mode') is not None \
+ and gview.get_preference('_gcp_warp_mode') == 'no':
+ options.append(('raw','yes'))
+
+ # Set Current View to 3D Mode
+ view.set_mode(gvconst.MODE_3D)
+ # view.height_scale(hscale)
+ options.append(('mesh_lod',str(mesh_lod)))
+
+ band = drape_dataset.GetRasterBand(1)
+ interp = band.GetRasterColorInterpretation()
+
+ # Create Drape Raster
+ drape_raster = gview.manager.get_dataset_raster(drape_dataset,1)
+ gview.undo_register(drape_raster)
+
+ # Create Drape Raster Layer
+ if drape_dataset.RasterCount > 2:
+ drape_raster_layer = gview.GvRasterLayer(drape_raster, options,
+ rl_mode = gview.RLM_RGBA )
+ else:
+ drape_raster_layer = gview.GvRasterLayer(drape_raster, options,
+ rl_mode = gview.RLM_AUTO )
+
+ # Logic to handle RGB and RGBA Layers
+ if drape_raster_layer.get_mode() == gview.RLM_RGBA:
+
+ green_raster= gview.manager.get_dataset_raster(drape_dataset,2)
+ blue_raster = gview.manager.get_dataset_raster(drape_dataset,3)
+
+ drape_raster_layer.set_source(1,green_raster)
+ drape_raster_layer.set_source(2,blue_raster)
+
+ if drape_dataset.RasterCount > 3:
+ band = drape_dataset.GetRasterBand(4)
+ if band.GetRasterColorInterpretation() == \
+ gdal.GCI_AlphaBand:
+ drape_raster_layer.blend_mode_set(
+ gview.RL_BLEND_FILTER )
+ drape_raster_layer.set_source(3,
+ gview.manager.get_dataset_raster(drape_dataset,4))
+
+ # Add to view
+ drape_raster_layer.set_name(drape_dataset.GetDescription() )
+ view.add_layer(drape_raster_layer)
+ view.set_active_layer(drape_raster_layer)
+
+ # Create DEM Raster and Add as Height
+ DEM_raster = gview.GvRaster(dataset=DEM_dataset)
+ DEM_raster.set_name(str(dem_filename))
+ drape_raster_layer.add_height(DEM_raster)
+
+ # perform clamping, if requested
+ if min_clamp is not None:
+ drape_raster_layer.clamp_height(1,0,min_clamp)
+
+ if max_clamp is not None:
+ drape_raster_layer.clamp_height(0,1,0,max_clamp)
+
+ # Modify hscale to be more reasonable in some geo-referenced cases
+ #[hscalex1,dummy] = DEM_raster.pixel_to_georef(0,0)
+ #[hscalex2,dummy] = DEM_raster.pixel_to_georef(DEM_dataset.RasterXSize - 1,0)
+ #hscale_georef = hscale*abs(hscalex2-hscalex1)/DEM_dataset.RasterXSize
+ #view.height_scale(hscale_georef)
+ view.height_scale(hscale)
+
+ # Try to make sure everything is visible.
+ self.seeall_cb()
+
+ def position_3d(self, *args):
+ self.make_active()
+ if self.position3D_dialog is None:
+ self.position3D_dialog = \
+ gviewapp.Position_3D_Dialog(self.app.view_manager)
+ self.position3D_dialog.connect('destroy', self.destroy_position_3d)
+ self.position3D_dialog.show()
+ self.position3D_dialog.get_window()._raise()
+
+ view = self.viewarea
+ self.position3D_dialog.update_cb(view)
+ view.connect('view-state-changed', self.position3D_dialog.update_cb)
+
+ def destroy_position_3d(self,*args):
+ self.position3D_dialog = None
+
+ def raster_open_by_name(self,filename):
+ self.make_active()
+ gdal.ErrorReset()
+ dataset = gdal.Open(filename)
+ if dataset is None:
+ gvutils.error('Unable to open: '+filename+'\n\n'+ \
+ gdal.GetLastErrorMsg())
+ return None
+
+ return dataset
+
+ def rawgeo_cb( self, *args ):
+ ref_layer = self.viewarea.active_layer()
+ self.viewarea.set_raw(ref_layer, not self.viewarea.get_raw(ref_layer))
+ self.rawgeo_update()
+
+ def rawgeo_update( self, *args ):
+ if self.iconbar is None:
+ return
+
+ ref_layer = self.viewarea.active_layer()
+ if self.viewarea.get_raw( ref_layer ):
+ self.rawgeo_pixmap.set( self.raw_icon[0], self.raw_icon[1] )
+ else:
+ self.rawgeo_pixmap.set( self.geo_icon[0], self.geo_icon[1] )
Added: packages/openev/branches/upstream/current/pymod/ibrowse.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/ibrowse.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/ibrowse.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+import gviewapp
+import gview
+import gtk
+from gtk import FALSE, TRUE
+import GDK
+import sys
+import random
+import os
+
+
+def force_load( filename ):
+ ds = gview.manager.get_dataset( filename )
+ if ds is None:
+ return ds
+
+ band_list = []
+ for band in range(0,ds.RasterCount):
+ band_list.append( ds.GetRasterBand(band+1) )
+
+ for line in range(0,ds.RasterYSize):
+ for band in range(0,ds.RasterCount):
+ band_list[band].ReadRaster( 0, line, ds.RasterXSize, 1 )
+
+ if ds.RasterCount >= 3:
+ rasters = (gview.manager.get_dataset_raster( ds, 1 ),
+ gview.manager.get_dataset_raster( ds, 2 ),
+ gview.manager.get_dataset_raster( ds, 3 ))
+ else:
+ rasters = [gview.manager.get_dataset_raster( ds, 1 )]
+
+ for rast in rasters:
+ rast.force_load()
+
+ gview.file_list_ds.append(rasters)
+ del gview.file_list_ds[0]
+
+ return ds
+
+def clean_old_layer():
+ view = gview.app.view_manager.get_active_view()
+
+ layers = view.list_layers()
+ if len(layers) > 1:
+ view.remove_layer( layers[0] )
+
+ gview.request_clean = 0
+
+ try:
+ ds = force_load( gview.file_list[gview.file_cur+1] )
+ except:
+ pass
+
+def request_clean( *args ):
+ gview.request_clean = 1
+
+def update_view():
+ view = gview.app.view_manager.get_active_view()
+
+ cur_file = gview.file_list[gview.file_cur]
+ print 'update_view:' + cur_file
+
+ ds = force_load( cur_file )
+ try:
+ ds = force_load( cur_file )
+ except:
+ os.system( 'ls -l ' + cur_file )
+ os.system( 'file ' + cur_file )
+ return
+
+ old_layer = view.active_layer()
+
+ gview.app.file_open_by_name( cur_file )
+ view.fit_extents( 0, 0, ds.RasterXSize, ds.RasterYSize )
+
+ layer = view.active_layer()
+ layer.set_property( 'force_load', '100' )
+ view.queue_draw()
+ if old_layer is not None:
+ gview.manager.queue_task( 'cleaner', 15, request_clean )
+
+ if old_layer is not None:
+ view.remove_layer( old_layer )
+
+def advance( step = 1 ):
+ gview.file_cur = gview.file_cur + step
+ if gview.file_cur < 0:
+ gview.file_cur = 0
+ if gview.file_cur >= len(gview.file_list):
+ gview.file_cur = len(gview.file_list)-1
+
+ update_view()
+
+def key_press_cb( viewarea, event, *args ):
+ print event.keyval
+ if event.keyval == GDK.space:
+ advance(1)
+
+ if event.keyval == GDK.minus:
+ advance(-1)
+
+ if event.keyval == GDK.q:
+ sys.exit()
+
+ if event.keyval == GDK.j:
+ advance(10)
+
+ if event.keyval == GDK.p:
+ advance(-10)
+
+ if event.keyval == GDK.d:
+ os.unlink( gview.file_list[gview.file_cur] )
+ advance()
+
+ if event.keyval == GDK.r:
+ gview.file_cur = int(random.random() * len(gview.file_list))
+ update_view()
+
+
+
+# #############################################################################
+# Main
+
+app = gviewapp.GViewApp()
+gview.app = app
+app.subscribe('quit',gtk.mainquit)
+app.show_layerdlg()
+app.new_view(None)
+app.do_auto_imports()
+
+view = gview.app.view_manager.get_active_view()
+view.connect('key-press-event', key_press_cb)
+
+gview.file_list = []
+gview.file_list_ds = [None, None, None]
+gview.file_cur = 0
+
+# Command line parser
+i = 1
+while i < len(sys.argv):
+ arg = sys.argv[i]
+ gview.file_list.append( arg )
+ i = i + 1
+
+update_view()
+
+gview.request_clean = 0
+while 1:
+ gtk.mainiteration()
+
+ if gview.request_clean == 1:
+ clean_old_layer()
Property changes on: packages/openev/branches/upstream/current/pymod/ibrowse.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/layerdlg.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/layerdlg.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/layerdlg.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,432 @@
+##############################################################################
+# $Id: layerdlg.py,v 1.33 2003/09/09 15:18:46 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Layer Management Dialog
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: layerdlg.py,v $
+# Revision 1.33 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.32 2003/07/28 19:42:34 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.31 2003/02/20 19:27:22 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.30 2001/06/22 13:33:29 warmerda
+# fix crash when last view removed from layerdlg
+#
+# Revision 1.29 2000/09/26 15:11:57 srawlin
+# changed get_selected_layer() to return the active view names as well as layer
+#
+# Revision 1.28 2000/09/25 14:08:28 srawlin
+# added get_selected_layer()
+#
+# Revision 1.27 2000/08/23 15:18:27 srawlin
+# changed window policy to allow resizing
+#
+# Revision 1.26 2000/08/15 21:24:37 srawlin
+# fixed list_layers to work if selected_view is None
+#
+# Revision 1.25 2000/08/10 15:59:29 warmerda
+# added help topic
+#
+# Revision 1.24 2000/08/08 20:59:36 warmerda
+# use SELECTION_SINGLE, don't force auto-selection of active layer
+#
+# Revision 1.23 2000/08/08 20:11:55 warmerda
+# don't reset active layer while updating display
+#
+# Revision 1.22 2000/07/17 17:12:57 warmerda
+# register new layers for undo
+#
+# Revision 1.21 2000/06/28 17:04:19 srawlin
+# dialog not visible when launched
+#
+# Revision 1.20 2000/06/20 15:29:58 warmerda
+# removed debugging statement
+#
+# Revision 1.19 2000/06/20 12:28:01 warmerda
+# fixed delete layer, made thumbnails optional
+#
+# Revision 1.18 2000/06/19 19:20:42 warmerda
+# implemented layer creation, attempted destruction
+#
+# Revision 1.17 2000/06/14 21:43:46 warmerda
+# slightly improve updating logic
+#
+# Revision 1.16 2000/06/12 19:23:10 warmerda
+# signal on view changes, allow outside setting of view
+#
+# Revision 1.15 2000/06/09 01:04:14 warmerda
+# added standard headers
+#
+
+from gtk import *
+import gview
+import os.path
+import gvsignaler
+import gvhtml
+
+THUMB_W = 24
+THUMB_H = 32
+EYE_W = 24
+
+# FIXME: Need a global tooltips object?
+tooltips = GtkTooltips()
+
+static_layer_dialog = None
+
+def Launch():
+ global static_layer_dialog
+
+ if static_layer_dialog is None:
+ static_layer_dialog = LayerDlg()
+
+ return static_layer_dialog
+
+class LayerDlg(GtkWindow,gvsignaler.Signaler):
+ def __init__(self):
+ GtkWindow.__init__(self)
+ self.set_title('Layers')
+ self.set_usize(250, 500)
+ self.set_border_width(3)
+ self.set_policy(TRUE,TRUE,FALSE)
+ self.connect('delete-event',self.close)
+ shell = GtkVBox(spacing=3)
+ self.add(shell)
+ gvhtml.set_help_topic(self, "layerdlg.html" );
+
+ # View chooser menu
+ hbox = GtkHBox(spacing=3)
+ shell.pack_start(hbox, expand=FALSE)
+ hbox.pack_start(GtkLabel('View:'), expand=FALSE, padding=3)
+ viewopt = GtkOptionMenu()
+ hbox.pack_start(viewopt)
+ viewmenu = GtkMenu()
+ viewopt.set_menu(viewmenu)
+
+ # Do we want to include a thumbnail? This is buggy on some platforms.
+ if gview.get_preference('layer_thumbnail') is None \
+ or gview.get_preference('layer_thumbnail') == 'off':
+ self.thumbnail = FALSE
+ else:
+ self.thumbnail = TRUE
+
+ self.updating = FALSE
+
+ # Layer list
+ layerbox = GtkScrolledWindow()
+ shell.pack_start(layerbox)
+ if self.thumbnail:
+ layerlist = GtkCList(cols=3)
+ else:
+ layerlist = GtkCList(cols=2)
+
+ layerbox.add_with_viewport(layerlist)
+ layerlist.set_shadow_type(SHADOW_NONE)
+ layerlist.set_selection_mode(SELECTION_SINGLE)
+ layerlist.set_row_height(THUMB_H + 4)
+ layerlist.set_column_width(0, EYE_W)
+ if self.thumbnail:
+ layerlist.set_column_width(1, THUMB_W + 4)
+ layerlist.connect('select-row', self.layer_selected)
+ layerlist.connect('button-press-event', self.list_clicked)
+
+ # Option buttons
+ opts = (('new.xpm', 'New layer', self.new_layer),
+ ('raise.xpm', 'Raise layer', self.raise_layer),
+ ('lower.xpm', 'Lower layer', self.lower_layer),
+ ('delete.xpm','Delete layer', self.delete_layer))
+ butbox = GtkHBox(spacing=1)
+ shell.pack_start(butbox, expand=FALSE)
+ for opt in opts:
+ but = GtkButton()
+ butbox.pack_start(but)
+ but.add(GtkPixmap(self,os.path.join(gview.home_dir,'pics',opt[0])))
+ tooltips.set_tip(but, opt[1])
+ but.connect('clicked', opt[2])
+
+ self.connect('realize', self.realize)
+
+ shell.show_all()
+ self.viewopt = viewopt
+ self.viewmenu = viewmenu
+ self.layerlist = layerlist
+ self.views = {}
+ self.menuitems = {}
+ self.selected_view = None
+
+ self.eye_pixmap = \
+ GtkPixmap(self,os.path.join(gview.home_dir,'pics','eye.xpm'))
+
+ # Publish signals
+ self.publish('active-view-changed')
+ self.publish('deleted-layer')
+
+
+ def close(self,*args):
+ self.hide()
+ return TRUE
+
+ def list_layers(self):
+ lst = []
+ if self.selected_view is not None:
+ lst = self.views[self.selected_view].list_layers()
+ # Reverse the list since we want the last draw layer listed first.
+ lst.reverse()
+ return lst
+
+ def add_view(self, name, view):
+ # FIXME: connect to view 'destroy' event ?
+ self.views[name] = view
+ menuitem = GtkMenuItem(name)
+ self.viewmenu.append(menuitem)
+ menuitem.connect('activate', self.view_selected, name)
+ menuitem.show()
+ self.menuitems[name] = menuitem
+ if self.viewmenu.get_active() == menuitem:
+ self.viewopt.set_history(0)
+ menuitem.activate()
+
+ def remove_view(self, name):
+ try:
+ view = self.views[name]
+ menuitem = self.menuitems[name]
+ except KeyError:
+ return
+ self.viewmenu.remove(menuitem)
+ self.viewopt.set_history(0)
+ del self.views[name]
+ del self.menuitems[name]
+ if len(self.menuitems) > 0:
+ newitem = self.viewmenu.get_active()
+ newitem.activate()
+
+ if len(self.views) == 0:
+ # FIXME: things get kind of screwed up here...
+ # there doesn't seem to be a way to tell GtkMenu/GtkOptionMenu
+ # that there is nothing active. This at least is stable...
+ # Possible solution: rebuild viewmenu on each view add/remove.
+ view.disconnect(self.active_change_id)
+ self.selected_view = None
+ self.layerlist.clear()
+
+ def view_selected(self, item, name):
+ # don't use item - view_selected() is called from gvapp with item=None
+ if name == self.selected_view: return
+ if self.selected_view:
+ self.views[self.selected_view].disconnect(self.active_change_id)
+ self.selected_view = name
+ i = 0
+ for x in self.viewmenu.children():
+ if x == self.menuitems[name]:
+ self.viewopt.set_history(i)
+ break
+ i = i + 1
+ self.notify('active-view-changed')
+
+ view = self.views[name]
+ self.active_change_id = view.connect('active-changed',
+ self.active_layer_changed)
+
+ self.update_layers()
+ self.active_layer_changed(view)
+
+ self.notify( 'active-view-changed')
+
+ def get_active_view(self):
+ if self.selected_view:
+ return self.views[self.selected_view]
+ else:
+ return None
+
+ def update_layers(self,*args):
+ if not self.flags() & REALIZED: return
+
+ self.updating = TRUE
+
+ lst = self.layerlist
+ view = self.views[self.selected_view]
+ layers = self.list_layers()
+
+ # get active layer so we can restore after
+ active = view.active_layer()
+ if active is not None and active in layers:
+ active_row = layers.index(active)
+ else:
+ active_row = None
+
+ if self.thumbnail:
+ thumbnail_mask = create_bitmap_from_data(
+ self.get_window(), '\xff' * (THUMB_W/8 * THUMB_H),
+ THUMB_W, THUMB_H)
+
+ lst.freeze()
+ lst.clear()
+
+ for i in range(len(layers)):
+ if self.thumbnail:
+ lst.append(('', '', layers[i].get_name()))
+ else:
+ lst.append(('', layers[i].get_name()))
+
+ if layers[i].is_visible():
+ lst.set_pixmap(i, 0, self.eye_pixmap)
+
+ if self.thumbnail:
+ try:
+ thumbnail = view.create_thumbnail(layers[i],
+ THUMB_W, THUMB_H)
+ lst.set_pixmap(i, 1, thumbnail, thumbnail_mask)
+ except:
+ pass
+
+ # restore active layer selection
+ if active_row is not None:
+ lst.select_row(active_row, -1)
+
+ lst.thaw()
+ self.updating = FALSE
+
+ def realize(self, widget):
+ if self.selected_view:
+ self.update_layers()
+
+ def active_layer_changed(self, view):
+ self.update_layers()
+ layers = self.list_layers()
+ active = view.active_layer()
+ if active is not None and active in layers:
+ self.layerlist.select_row(layers.index(active), -1)
+
+ def layer_selected(self, lst, row, col, event):
+ if self.updating:
+ return
+
+ view = self.views[self.selected_view]
+ layers = self.list_layers()
+ view.signal_handler_block(self.active_change_id)
+ view.set_active_layer(layers[row])
+ view.signal_handler_unblock(self.active_change_id)
+
+ def toggle_visibility(self, row):
+ layers = self.list_layers()
+ lst = self.layerlist
+ if lst.get_cell_type(row, 0) == CELL_PIXMAP:
+ layers[row].set_visible(FALSE)
+ else:
+ layers[row].set_visible(TRUE)
+
+ self.update_layers()
+
+ def launch_properties(self, row):
+ layers = self.list_layers()
+ layer = layers[row]
+ layer.launch_properties()
+
+ def list_clicked(self, lst, event):
+ try:
+ row, col = lst.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ if event.button == 1:
+ if col == 0:
+ lst.emit_stop_by_name('button-press-event')
+ self.toggle_visibility(row)
+
+ elif event.button == 3:
+ lst.emit_stop_by_name('button-press-event')
+ self.launch_properties(row)
+
+ def new_layer(self, *args):
+ if not self.selected_view:
+ return
+ view = self.views[self.selected_view]
+ layer_list = view.list_layers()
+ layer_map = {}
+ for layer in layer_list:
+ layer_map[layer.get_name()] = layer
+
+ counter = 1
+ name = 'UserShapes_'+str(counter)
+ while layer_map.has_key(name):
+ counter = counter + 1
+ name = 'UserShapes_'+str(counter)
+
+ shapes = gview.GvShapes(name=name)
+ gview.undo_register(shapes)
+ layer = gview.GvShapesLayer(shapes)
+ view.add_layer(layer)
+ view.set_active_layer(layer)
+
+
+ def raise_layer(self, *args):
+ if not self.selected_view: return
+ view = self.views[self.selected_view]
+ layers = self.list_layers()
+ row = layers.index(view.active_layer())
+ index = len(layers) - row - 1
+ if row == 0: return
+ self.layerlist.swap_rows(row-1, row)
+ view.swap_layers(index, index+1)
+
+ def lower_layer(self, *args):
+ if not self.selected_view: return
+ view = self.views[self.selected_view]
+ layers = self.list_layers()
+ row = layers.index(view.active_layer())
+ index = len(layers) - row - 1
+ if index == 0: return
+ self.layerlist.swap_rows(row, row+1)
+ view.swap_layers(index-1, index)
+
+ def delete_layer(self, *args):
+ if not self.selected_view: return
+ view = self.views[self.selected_view]
+ layer = view.active_layer()
+ layername = layer.get_name()
+ if layer is not None:
+ view.remove_layer(layer)
+
+ self.notify('deleted-layer',view,layername)
+
+
+ def get_selected_layer(self, *args):
+ """ Returns a tuple with the name of the active view and the object with the currently selected layer
+ in that view. From the layer you can get the layer name another other useful properties of the
+ layer. """
+ if not self.selected_view: return
+ view = self.views[self.selected_view]
+ return (self.selected_view, view.active_layer())
Added: packages/openev/branches/upstream/current/pymod/makefile.vc
===================================================================
--- packages/openev/branches/upstream/current/pymod/makefile.vc (rev 0)
+++ packages/openev/branches/upstream/current/pymod/makefile.vc 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,49 @@
+GVIEW_ROOT=..
+
+!INCLUDE ..\nmake.opt
+
+PKG_SRCDIR = $(NM_ROOT)
+PYGTKDIR = $(NM_ROOT)\pygtk-0.6.6
+GTKDIR = $(NM_GTK_DIR)
+GLIBDIR = $(NM_GLIB_DIR)
+
+PYGVIEW_DLL = _gv.dll
+PYGTKMISSING_DLL = _gtkmissing.dll
+
+INC = /I$(GLIBDIR) /I$(NM_GLIB_DIR)/gmodule /I$(GTKDIR) /I$(GTKDIR)/gdk \
+ /I$(NM_GTKGLAREA_DIR) /I$(NM_GTKGLAREA_DIR) \
+ /I$(GDAL_HOME)\port /I$(GDAL_HOME)\gcore /I$(GDAL_HOME)/ogr \
+ /I.. /I. -I$(NM_PY_DIR)/include -I$(PYGTKDIR)
+
+CFLAGS = $(INC) $(GV_OPTFLAGS) /nologo
+
+LIBS = $(GDAL_HOME)/gdal_i.lib $(NM_GTKGLAREA_DIR)/gtkglarea.lib \
+ $(GTKDIR)/gtk/gtk-1.3.lib \
+ $(GTKDIR)/gdk/gdk-1.3.lib $(GLIBDIR)/glib-1.3.lib \
+ comdlg32.lib GLU32.lib opengl32.lib gdi32.lib user32.lib shell32.lib
+
+default: $(PYGVIEW_DLL) $(PYGTKMISSING_DLL)
+
+$(PYGVIEW_DLL): gvmodule.obj ../gv.lib
+ link /dll /debug \
+ /def:_gview.def gvmodule.obj ../gv.lib $(LIBS) \
+ /LIBPATH:$(NM_PY_DIR)/libs \
+ /out:$(PYGVIEW_DLL)
+
+$(PYGTKMISSING_DLL): gtkmissing.obj
+ link /dll /debug \
+ /def:_gtkmissing.def gtkmissing.obj $(LIBS) \
+ /LIBPATH:$(NM_PY_DIR)/libs \
+ /out:$(PYGTKMISSING_DLL)
+
+.c.obj:
+ $(CC) $(CFLAGS) /c $*.c
+
+clean:
+ -del *.obj
+ -del *.dll
+ -del *.lib
+
+install: default
+ copy *.dll $(NM_PYMOD_DIR)
+ copy *.py $(NM_PYMOD_DIR)
Added: packages/openev/branches/upstream/current/pymod/mkgv.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/mkgv.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/mkgv.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,6 @@
+import generate
+
+p = generate.FilteringParser(input='gv.defs',
+ prefix='gvmodule',
+ typeprefix='&')
+p.startParsing()
Added: packages/openev/branches/upstream/current/pymod/nls.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/nls.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/nls.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,207 @@
+###############################################################################
+# $Id: nls.py,v 1.6 2005/03/16 18:57:04 zjamesatdm Exp $
+#
+# Project: OpenEV
+# Purpose: NLS localisation module
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: nls.py,v $
+# Revision 1.6 2005/03/16 18:57:04 zjamesatdm
+# allow leading space in localised strings
+#
+# Revision 1.5 2003/04/03 21:57:05 pgs
+# added a method to put values into the nls dictionary
+#
+# Revision 1.4 2002/08/16 18:58:58 pgs
+# fixed typo.
+#
+# Revision 1.3 2002/08/16 17:49:56 pgs
+# changed prints for gdal.Debug
+#
+# Revision 1.2 2001/03/21 04:30:05 pgs
+# handle \\n in input file
+#
+# Revision 1.1 2001/03/11 21:52:30 pgs
+# new file
+#
+#
+
+"""
+OpenEV Localization Module.
+
+This module is designed to provide the programmer with a simplified interface
+to provided customizable or multi-lingual interfaces.
+
+After this module is imported, call get_locales() to determine which modules
+are available and set_locale(name) to set the current locale. If no locale
+is set, the module will always return the default value from
+get(key, default).
+
+Variables:
+----------
+
+_locales - dictionary, a mapping of locale names to locale files
+_locale - the current locale dictionary
+
+Methods:
+--------
+
+_load_locale(fname) - loads the locale file as the current locale
+get_locales() - returns the names of the locales that can be selected
+set_locale(name) - sets the current locale to name
+get(key, default) - gets the localized value of key or default if not found
+"""
+
+_locales = {}
+_locale = None
+
+
+
+#load locale files from the locale directory and parse them for locale
+#names ... this only happens on the first import in any particular
+#python run-time
+
+import gview
+import os
+import string
+import gdal
+
+gdal.Debug( "nls", 'initializing localization module' )
+
+locale_dir = os.path.join(gview.find_gview(), "locales")
+
+if os.path.isdir(locale_dir):
+ gdal.Debug( "nls", 'loading localization files from %s' % locale_dir )
+ fnames = os.listdir(locale_dir)
+ for fname in fnames:
+ fname = os.path.join(locale_dir, fname)
+ gdal.Debug( "nls", 'processing file %s' % fname )
+ if os.path.isfile(fname):
+ file = open(fname, 'r')
+ loc_dict = {}
+ lines = file.readlines()
+ for line in lines:
+ if string.find(line, '=') >= 0:
+ key, value = string.split(line, '=')
+
+ if key == 'locale-name':
+ value = string.strip(value)
+ gdal.Debug( "nls", 'loading %s locale' % value )
+ _locales[value] = fname
+ break
+ file.close()
+ lines = None
+ else:
+ print '%s is not a file' % fname
+ gdal.Debug( "nls", 'localization initialization complete' )
+else:
+ gdal.Debug( "nls", 'cannot locate localization files' )
+
+def _load_locale(fname):
+ """
+ open a locale file and set the internal locale
+
+ fname - string, the name of the locale file to load
+ """
+ global _locale
+ try:
+ file = open(fname, 'r')
+ except:
+ gdal.Debug( "nls", 'load locale failed' )
+ _locale = None
+ return
+
+ loc_dict = {}
+ lines = file.readlines()
+ for line in lines:
+ if line[0] == '#':
+ continue
+ try:
+ if string.find(line, '=') >= 0:
+ key, value = string.split(line, '=')
+ #take care with CR-LF
+ #does this work on UNIX?
+ value = string.rstrip(value)
+ value = string.replace(value, '\\n', '\n')
+ loc_dict[key] = value
+ except:
+ gdal.Debug( "nls", 'an exception occurred in nls.py' )
+ pass
+
+ file.close()
+ _locale = loc_dict
+ try:
+ gdal.Debug( "nls", 'locale changed to %s' % loc_dict['locale-name'] )
+ except:
+ gdal.Debug( "nls", 'unknown locale loaded' )
+
+def set_locale(locale_name):
+ """
+ change locales to the specified locale name
+
+ locale_name - string, the name of the locale (must be one of the
+ keys in 'locales'
+ """
+ global _locales
+ try:
+ fname = _locales[locale_name]
+ _load_locale(fname)
+ except:
+ gdal.Debug( "nls", 'locale %s not found' % locale_name )
+
+def get_locales():
+ """
+ Return a list of available locales
+ """
+ global _locales
+ return _locales.keys()
+
+def get(key, default):
+ """
+ Return a localized value from the current locale or the default
+ value if the the value isn't localized in the current locale
+
+ key - the name of the value to get
+ default - the value to return if the key isn't found
+ """
+ global _locale
+
+ if _locale is None:
+ return default
+
+ try:
+ return _locale[key]
+ except:
+ return default
+
+def set( key, value ):
+ """
+ add a value to the locale
+
+ key - the key to add
+ value - the value to add
+ """
+ global _locale
+ if _locale is None:
+ return
+
+ _locale[key] = value
Added: packages/openev/branches/upstream/current/pymod/oe_about.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/oe_about.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/oe_about.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: oe_about.py,v 1.1 2005/08/07 18:22:57 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Subscript for OpenEV About Box
+# Author: Frank Warmerdam <warmerdam at pobox.com>
+# Gillian Walter <gillian.walter at vexcel.com>
+#
+###############################################################################
+# Copyright (c) 2005, Vexcel Canada Inc. (www.vexcel.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: oe_about.py,v $
+# Revision 1.1 2005/08/07 18:22:57 warmerda
+# New
+#
+#
+
+import gtk
+from gtk import FALSE, TRUE
+from GDK import *
+import sys
+import os
+import gview
+import gvconst
+
+def ShowAboutBox( viewwindow ):
+
+ window = gtk.GtkWindow()
+ window.set_title('About OpenEV')
+ vbox = gtk.GtkVBox(homogeneous=FALSE,spacing=15)
+ window.add(vbox)
+
+ vbox.pack_start(gtk.GtkPixmap(viewwindow,
+ os.path.join(gview.home_dir,'pics',
+ 'openev.xpm')))
+
+ # Contributors
+ contrib = gtk.GtkVBox(homogeneous=FALSE,spacing=3)
+ contrib.pack_start(gtk.GtkLabel('Contributors:'))
+ contrib.pack_start(gtk.GtkLabel('Frank Warmerdam (warmerdam at pobox.com),'))
+ contrib.pack_start(gtk.GtkLabel('Gillian Walter (gillian.walter at vexcel.com),'))
+ contrib.pack_start(gtk.GtkLabel('Peter Farris-Manning (peter.farris-manning at vexcel.com),'))
+ contrib.pack_start(gtk.GtkLabel('Paul Spencer (pagemeba at magma.ca),'))
+ contrib.pack_start(gtk.GtkLabel('Steve Rawlinson,'))
+ contrib.pack_start(gtk.GtkLabel('Steve Taylor,'))
+ contrib.pack_start(gtk.GtkLabel('Paul Lahaie,'))
+ contrib.pack_start(gtk.GtkLabel('and others'))
+ vbox.pack_start(contrib)
+
+ # Funded By
+ funding = gtk.GtkVBox(homogeneous=FALSE,spacing=3)
+ funding.pack_start(gtk.GtkLabel('Funding provided by:'))
+ funding.pack_start(gtk.GtkPixmap(viewwindow,
+ os.path.join(gview.home_dir, 'pics', 'vexcel_logo.xpm')))
+ funding.pack_start(gtk.GtkLabel('Vexcel Canada Inc.'))
+ funding.pack_start(gtk.GtkPixmap(viewwindow,
+ os.path.join(gview.home_dir,'pics','geo_innovation.xpm')))
+ funding.pack_start(gtk.GtkLabel('GeoInnovations'))
+ vbox.pack_start(funding)
+
+ # Other Info
+ vbox.pack_start(gtk.GtkLabel('Version: 1.8'))
+ vbox.pack_start(gtk.GtkLabel('Web Site: http://OpenEV.sourceforge.net'))
+ vbox.pack_start(gtk.GtkLabel('(C) Copyright 2000 Vexcel Canada Inc. www.vexcel.com'))
+
+ window.show_all()
+
Added: packages/openev/branches/upstream/current/pymod/oeattedit.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/oeattedit.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/oeattedit.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,302 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: oeattedit.py,v 1.9 2003/02/20 19:27:23 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Shape attribute display, and editing.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: oeattedit.py,v $
+# Revision 1.9 2003/02/20 19:27:23 gmwalter
+# Updated link tool to include Diana's ghost cursor code, and added functions
+# to allow the cursor and link mechanism to use different gcps
+# than the display for georeferencing. Updated raster properties
+# dialog for multi-band case. Added some signals to layerdlg.py and
+# oeattedit.py to make it easier for tools to interact with them.
+# A few random bug fixes.
+#
+# Revision 1.8 2002/11/14 15:43:14 gmwalter
+# Fixed a few bugs in the closing/reopening code.
+#
+# Revision 1.7 2002/09/12 17:08:45 gmwalter
+# *** empty log message ***
+#
+# Revision 1.6 2002/09/12 13:08:14 gmwalter
+# Updated oeattedit.py so that new fields can be added to shapefiles via the
+# gui. Minor changes to aclocal.m4/configure to ensure that specified
+# libraries are picked up rather than defaults.
+#
+# Revision 1.5 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.4 2001/04/09 18:27:45 warmerda
+# upgraded to support subselection
+#
+# Revision 1.3 2000/08/11 20:46:48 warmerda
+# get rid of horizontal scrollbar, fix original width
+#
+# Revision 1.2 2000/08/04 14:10:48 warmerda
+# report shapeid in titlebar
+#
+# Revision 1.1 2000/07/10 20:59:04 warmerda
+# New
+#
+#
+
+from gtk import *
+import gview
+import string
+import gvselbrowser
+import gvutils
+import GtkExtra
+import gvsignaler
+
+def launch():
+ try:
+ gview.oeattedit.get_window()._raise()
+ gview.oeattedit.show()
+ gview.oeattedit.reconnect()
+ gview.oeattedit.gui_update()
+ except:
+ try:
+ # oeattedit has been created,
+ # but not shown
+ gview.oeattedit.show()
+ gview.oeattedit.reconnect()
+ gview.oeattedit.gui_update()
+ except:
+ gview.oeattedit = OEAttEdit()
+ gview.oeattedit.show()
+
+ return gview.oeattedit
+
+def launch_hidden():
+ if not hasattr(gview,'oeattedit'):
+ gview.oeattedit = OEAttEdit()
+
+class OEAttEdit(GtkWindow,gvsignaler.Signaler):
+
+ def __init__(self):
+ GtkWindow.__init__(self)
+
+ self.set_title('Shape Attributes')
+ gview.app.sel_manager.subscribe( 'selection-changed',
+ self.gui_update )
+ gview.app.sel_manager.subscribe( 'subselection-changed',
+ self.gui_update )
+
+ # signal for external tools to connect to
+ self.publish('hidden')
+ self.publish('shown')
+
+ self.text_contents = ''
+ self.selected_shape = None
+ self.layer = None
+ self.create_gui()
+
+ self.visibility_flag = 0
+ self.gui_update()
+ self.connect('delete-event', self.close)
+
+ def show(self):
+ GtkWindow.show(self)
+ self.visibility_flag = 1
+ self.notify('shown')
+
+ def close(self, *args):
+ gview.app.sel_manager.unsubscribe( 'selection-changed',
+ self.gui_update )
+ gview.app.sel_manager.unsubscribe( 'subselection-changed',
+ self.gui_update )
+ self.hide()
+ self.visibility_flag = 0
+ self.notify('hidden')
+
+ return TRUE
+
+ def reconnect(self, *args):
+ gview.app.sel_manager.subscribe( 'selection-changed',
+ self.gui_update )
+ gview.app.sel_manager.subscribe( 'subselection-changed',
+ self.gui_update )
+
+ def create_gui(self):
+ box1 = GtkVBox()
+ self.add(box1)
+ box1.show()
+
+ self.selbrowser = gvselbrowser.GvSelBrowser()
+ self.selbrowser.set_border_width(10)
+ box1.pack_start( self.selbrowser, expand=FALSE )
+
+ box2 = GtkVBox(spacing=10)
+ box2.set_border_width(10)
+ box1.pack_start(box2)
+ box2.show()
+
+ table = GtkTable(2, 2)
+ table.set_row_spacing(0, 2)
+ table.set_col_spacing(0, 2)
+ box2.pack_start(table)
+ table.show()
+
+ text = GtkText()
+ text.set_usize(400,100)
+ text.set_line_wrap(FALSE)
+ text.set_word_wrap(FALSE)
+ text.set_editable(TRUE)
+ table.attach(text, 0,1, 0,1)
+ text.show()
+ self.text = text
+ self.text.connect('activate', self.att_update_cb)
+ self.text.connect('leave-notify-event', self.att_update_cb)
+
+ vscrollbar = GtkVScrollbar(text.get_vadjustment())
+ table.attach(vscrollbar, 1,2, 0,1, xoptions=FILL)
+ vscrollbar.show()
+
+
+ separator = GtkHSeparator()
+ box1.pack_start(separator, expand=FALSE)
+ separator.show()
+
+ box2 = GtkVBox(spacing=10)
+ box2.set_border_width(10)
+ box1.pack_start(box2, expand=FALSE)
+ box2.show()
+
+ # new field options
+ box3 = GtkHBox(spacing=10)
+ box3.set_border_width(10)
+ nf_frame = GtkFrame('New field properties: type/width/precision')
+ nf_frame.add(box3)
+ self.new_field_width_entry = GtkEntry(2)
+ self.new_field_width_entry.set_text('20')
+ self.new_field_width_entry.set_editable(TRUE)
+ self.new_field_precision_entry = GtkEntry(2)
+ self.new_field_precision_entry.set_text('0')
+ self.new_field_precision_entry.set_editable(FALSE)
+ self.new_field_precision_entry.set_sensitive(FALSE)
+
+ self.new_field_types = ('string','integer','float')
+ self.new_field_type_menu = gvutils.GvOptionMenu(self.new_field_types, self.new_field_precision_cb)
+ self.new_field_type_menu.set_history(0)
+ box3.pack_start(self.new_field_type_menu)
+ box3.pack_start(self.new_field_width_entry,expand=FALSE,fill=FALSE)
+ box3.pack_start(self.new_field_precision_entry,expand=FALSE,fill=FALSE)
+ box2.pack_start(nf_frame)
+ nf_frame.show_all()
+
+ button = GtkButton("close")
+ button.connect("clicked", self.close)
+ box2.pack_start(button)
+ button.set_flags(CAN_DEFAULT)
+ button.grab_default()
+ button.show()
+
+ def new_field_precision_cb(self,*args):
+ if self.new_field_types[self.new_field_type_menu.get_history()] == 'float':
+ # precision is only relevant for float
+ self.new_field_precision_entry.set_editable(TRUE)
+ self.new_field_precision_entry.set_sensitive(TRUE)
+ else:
+ self.new_field_precision_entry.set_text('0')
+ self.new_field_precision_entry.set_editable(FALSE)
+ self.new_field_precision_entry.set_sensitive(FALSE)
+
+ def gui_update(self,*args):
+ self.text_contents = ''
+ self.text.freeze()
+ self.text.delete_text(0,-1)
+
+ self.selected_shape = None
+
+ try:
+ self.layer = gview.app.sel_manager.get_active_layer()
+ shapes = self.layer.get_parent()
+ self.selected_shape = self.layer.get_subselected()
+ properties = shapes[self.selected_shape].get_properties()
+ for att_name in properties.keys():
+ self.text_contents = self.text_contents + \
+ att_name + ': ' + properties[att_name] + '\n'
+ self.text.insert_defaults(self.text_contents)
+ except:
+ pass
+
+ self.text.thaw()
+
+ def att_update_cb(self,*args):
+ if self.text_contents == self.text.get_chars(0,-1):
+ return
+
+ if self.selected_shape is None:
+ return
+
+ shapes = self.layer.get_parent()
+ shape = shapes[self.selected_shape]
+ if shape is None:
+ return
+
+ shape = shape.copy()
+
+ lines = string.split(self.text.get_chars(0,-1),'\n')
+ for line in lines:
+ tokens = string.split(line,':',1)
+ if len(tokens) == 2:
+ value = string.strip(tokens[1])
+ shape.set_property(tokens[0],value)
+ property_exists=0
+ for cprop in shapes.get_schema():
+ if cprop[0] == tokens[0]:
+ property_exists=1
+ if property_exists != 1:
+ ftype = self.new_field_types[self.new_field_type_menu.get_history()]
+
+ response = \
+ GtkExtra.message_box('Confirmation',
+ 'Create new ' + ftype + '-type property ' + tokens[0] + '?' ,
+ ('Yes','No'))
+ if response == 'Yes':
+ try:
+ fwidth = int(self.new_field_width_entry.get_text())
+ except:
+ gvutils.error('Field width must be an integer!')
+ continue
+
+ if ftype == 'float':
+ try:
+ fprec = int(self.new_field_width_entry.get_text())
+ except:
+ gvutils.error('Precision width must be an integer!')
+ continue
+ else:
+ fprec = 0
+
+ shapes.add_field(tokens[0],ftype,fwidth,fprec)
+
+ shapes[self.selected_shape] = shape
+ self.gui_update()
+
+ def insert_text_cb(self,new_text,*args):
+ if new_text[0] == '\n':
+ self.att_update_cb()
+ return FALSE
Added: packages/openev/branches/upstream/current/pymod/openev.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/openev.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/openev.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: openev.py,v 1.46 2005/01/14 17:17:18 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: OpenEV Application Mainline
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: openev.py,v $
+# Revision 1.46 2005/01/14 17:17:18 warmerda
+# pass base config file names, not full path, to new_view()
+#
+# Revision 1.45 2003/10/29 14:58:00 gmwalter
+# Force floating point to use "." instead of "," to avoid problems on
+# foreign language windows.
+#
+# Revision 1.44 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.43 2003/07/28 19:42:34 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.42 2002/02/28 18:52:22 gmwalter
+# Added a point-of-interest tool similar to the region-of-interest
+# tool (allows a user to select a temporary point without having to add a
+# new layer). Added a mechanism to allow some customization of openev
+# via a textfile defining external modules.
+#
+# Revision 1.41 2001/11/12 18:42:56 warmerda
+# GViewApp moved to gviewapp.py
+#
+# Revision 1.40 2001/10/25 20:30:46 warmerda
+# added interp_mode preference to control default subpixel interp
+#
+# Revision 1.39 2001/10/19 16:08:57 warmerda
+# dont put NUMPY:: files in RFL list
+#
+# Revision 1.38 2001/10/16 18:52:40 warmerda
+# added active_layer
+#
+# Revision 1.37 2001/08/15 13:05:57 warmerda
+# modified default autoscale std_dev to 2.5
+#
+# Revision 1.36 2001/08/14 17:03:24 warmerda
+# added standard deviation autoscaling support
+#
+# Revision 1.35 2001/06/27 14:32:56 warmerda
+# added subdataset selection support
+#
+# Revision 1.34 2001/04/24 14:23:33 warmerda
+# added label tool
+#
+# Revision 1.33 2001/04/09 18:33:24 warmerda
+# instantiate a GvSelectionManager
+#
+
+import gviewapp
+import gview
+import gtk
+import sys
+import os
+import getopt
+
+# Force standard c settings for floating point (. rather than ,)
+import locale
+locale.setlocale(locale.LC_NUMERIC,'C')
+
+
+if __name__ == '__main__':
+
+ # get command line options and args
+ # openev -m menufile -i iconfile -t toolfile image1 image2 ......
+ (options, ifiles) = getopt.getopt(sys.argv[1:], 'm:i:t:p:')
+
+ if os.path.isdir(os.path.join(gview.home_dir, 'xmlconfig')):
+ mfile = 'DefaultMenuFile.xml'
+ if not os.path.isfile(os.path.join(gview.home_dir, 'xmlconfig',mfile)):
+ mfile = None
+
+ ifile = 'DefaultIconFile.xml'
+ if not os.path.isfile(os.path.join(gview.home_dir, 'xmlconfig',ifile)):
+ ifile = None
+
+ pfile = 'DefaultPyshellFile.xml'
+ if not os.path.isfile(os.path.join(gview.home_dir, 'xmlconfig',pfile)):
+ pfile = None
+
+ else:
+ mfile=None
+ ifile=None
+ pfile=None
+
+ tfile = None
+
+ for opt in options[0:]:
+ if opt[0] == '-m':
+ mfile=opt[1]
+ elif opt[0] == '-i':
+ ifile=opt[1]
+ elif opt[0] == '-p':
+ pfile=opt[1]
+ elif opt[0] == '-t':
+ tfile=opt[1]
+
+ app = gviewapp.GViewApp(toolfile=tfile,menufile=mfile,iconfile=ifile,pyshellfile=pfile)
+ gview.app = app
+ app.subscribe('quit',gtk.mainquit)
+ app.show_layerdlg()
+ app.new_view(title=None)
+ app.do_auto_imports()
+
+ for item in ifiles:
+ app.file_open_by_name(item)
+
+ gtk.mainloop()
Property changes on: packages/openev/branches/upstream/current/pymod/openev.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/pathutils.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pathutils.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pathutils.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,148 @@
+###############################################################################
+#
+# Project: OpenEV
+# Purpose: Paths utilities
+# Author: Julien Demaria, demaria.julien at free.fr
+#
+###############################################################################
+# Copyright (c) 2004, Julien Demaria <demaria.julien at free.fr>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+
+
+import os.path
+
+try:
+ real_path = os.path.realpath
+except:
+ real_path = os.path.abspath
+
+def split_all( path ):
+ """
+ Return a list (whithout any '') corresponding to the splitted path.
+ """
+ splitted_path = []
+ (h, t) = os.path.split( path )
+ old_h = h + 'dummy'
+ while h != old_h:
+ old_h = h
+ if t != '':
+ splitted_path.insert( 0, t )
+ (h, t) = os.path.split( h )
+ if h != '':
+ splitted_path.insert( 0, h )
+ return splitted_path
+
+def join_all( path ):
+ """
+ Return a path from its corresponding splitted list form.
+ """
+ return apply( os.path.join, path )
+
+def relative_path( path, ref_path ):
+ """
+ Return the relative form of path, with ref_path as reference.
+ If path and ref_path don't have any common prefix,
+ raise ValueError, 'Not any common prefix'
+ The function internally works on os.path.realpath() forms
+ of path and ref_path.
+ """
+ realpath = real_path( path )
+ basepath = ''
+ basepath = os.path.basename( realpath )
+ realpath = os.path.dirname( realpath )
+
+ real_ref_path = real_path( ref_path )
+ real_ref_path = os.path.dirname( real_ref_path )
+
+ split_path = split_all( realpath )
+ split_ref_path = split_all( real_ref_path )
+
+ # Find common prefix
+ for i, v in enumerate( zip( split_path, split_ref_path ) ):
+ if v[0] != v[1]:
+ if i == 0:
+ # Case where the 2 paths don't have any common prefix
+ # (Note the under Unix platform there is always at least
+ # '/' as common prefix...).
+ raise ValueError, 'Not any common prefix'
+ else:
+ break
+
+ if split_path[i] == split_ref_path[i]:
+ # Handle the case of one of the path is the prefix of the other
+ i += 1
+ path_tail = split_path[i:]
+ ref_path_tail = split_ref_path[i:]
+ rel_path = ['..'] * len( ref_path_tail )
+ rel_path.extend( path_tail )
+ if basepath != '':
+ rel_path.append( basepath )
+
+ return join_all( rel_path )
+
+def PortablePathFromXML( str ):
+ t = eval( str )
+ p = PortablePath( join_all( t[0] ) )
+ p.rel_path = t[1]
+ return p
+
+class PortablePath:
+
+ def __init__( self, path, ref_path = None ):
+ """
+ Create a portable path from a path and optionnaly a reference path.
+ A portable path contains :
+ - the normalized absolutized splitted form of the given path ;
+ - the relativized (with ref_path as reference) splitted form of
+ the given path if it exists.
+ A portable path internally uses os.path.realpath() forms of path and
+ ref_path.
+ """
+ self.abs_path = split_all( real_path( path ) )
+ try:
+ self.rel_path = split_all( relative_path( path, ref_path ) )
+ except:
+ self.rel_path = None
+
+ def local_path( self, ref_path = None ):
+ """
+ Return the path corresponding to the portable path for the current
+ local platform.
+ The method tests in the portable path the existence of, in this order :
+ - the normalized absolutized form of the original path ;
+ - the relativized (with ref_path as reference) form of
+ the original path ;
+ and then returns the first existing (in os.path.realpath() form).
+ If none of them exists,
+ raise ValueError, 'Cannot compute a local path from the portable path'
+ The method internally works on os.path.realpath() form of ref_path.
+ """
+ p = join_all( self.abs_path )
+ if os.path.exists( p ):
+ return p
+ else:
+ if self.rel_path is None:
+ raise ValueError, 'Cannot compute a local path from the portable path'
+ r = os.path.dirname( real_path( ref_path ) )
+ p = real_path( os.path.join( r, join_all( self.rel_path ) ) )
+ if os.path.exists( p ):
+ return p
+ raise ValueError, 'Cannot compute a local path from the portable path'
+
+ def serialize( self ):
+ return repr( [self.abs_path, self.rel_path] )
Property changes on: packages/openev/branches/upstream/current/pymod/pathutils.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/pgu.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgu.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgu.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,38 @@
+###############################################################################
+# $Id: pgu.py,v 1.1 2000/06/14 15:12:39 warmerda Exp $
+#
+# Project: Python Gtk Utility Widgets
+# Purpose: Core PGU stuff, such as registering new PyGtk classes.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgu.py,v $
+# Revision 1.1 2000/06/14 15:12:39 warmerda
+# New
+#
+#
+
+import gtk; _gtk = gtk; del gtk
+from string import *
+
+def gtk_register(name,class_obj):
+ _gtk._name2cls[name] = class_obj
+
Added: packages/openev/branches/upstream/current/pymod/pgucolor.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgucolor.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgucolor.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,423 @@
+###############################################################################
+# $Id: pgucolor.py,v 1.12 2003/09/09 15:18:46 gmwalter Exp $
+#
+# Project: Python Gtk Utility Widgets
+# Purpose: Color-related widgets and utilities.
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgucolor.py,v $
+# Revision 1.12 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.11 2002/08/09 21:04:48 pgs
+# added support for DISCRETE color ramps
+#
+# Revision 1.10 2001/09/17 15:26:33 pgs
+# moved more GtkColorWell code into gtkmissing.
+#
+# Revision 1.9 2001/09/17 03:44:40 pgs
+# added get_color to ColorButton
+#
+# Revision 1.8 2001/09/17 03:41:52 pgs
+# removed GtkColorWell (moved to gtkmissing) and added __init__ to
+# ColorButton to initialize a standard color button.
+#
+# Revision 1.7 2001/09/16 03:28:37 pgs
+# Added GtkColorWell class (should be in GtkMissing?) and modified ColorButton
+# to derive from it.
+#
+# Revision 1.6 2001/05/08 23:37:07 pgs
+# fixed bug allowing multiple color choosers for a single color button
+#
+# Revision 1.5 2001/04/14 14:52:28 pgs
+# added color_string_to_tuple
+#
+# Revision 1.4 2001/04/11 03:04:51 pgs
+# added get_color() to color swatch and opacity to ColorDialog
+#
+# Revision 1.3 2000/09/28 22:45:15 pgs
+# fixed up ColorRamp
+#
+# Revision 1.1 2000/09/27 13:32:33 warmerda
+# New
+#
+#
+
+MIN_COLOR=0
+MAX_COLOR = 65535
+
+import gtk
+from gtk import TRUE, FALSE
+import GDK
+from gvsignaler import Signaler
+import _gv
+from gtkmissing import GtkColorWell
+
+def color_string_to_tuple(s):
+ from string import replace, split
+ s = replace(s, '(', '')
+ s = replace(s, ')', '')
+ s = replace(s, ',', '')
+ r, g, b, a = split(s, None)
+ return (float(r), float(g), float(b), float(a))
+
+
+class ColorSwatch(gtk.GtkDrawingArea, Signaler):
+ """
+ Class ColorSwatch is a simple widget that
+ displays a color.
+
+ The color attribute is an RGBA tuple. Internally, however,
+ a GdkColor object is used that has values in the range 0-65535
+ for red, green and blue. The color display doesn't support
+ the alpha channel (yet?)
+
+ Don't use GdkColor(red, green, blue) to allocate colors ... use
+ GdkColormap.alloc instead and get a reference to the GdkColormap
+ from the widget (self.get_colormap())
+ """
+ def __init__(self, color=(0,0,0,0)):
+ gtk.GtkDrawingArea.__init__(self)
+ self.size(20, 15)
+ self.connect('configure-event', self.configure_event)
+ self.connect('expose-event', self.expose_event)
+ self.connect('realize', self.realize_event)
+ self.connect('unrealize', self.unrealize_event)
+ self.color = color
+ #the color - use GdkColorMap's alloc method to get it
+ cm = self.get_colormap()
+ self.icolor = cm.alloc(int(color[0] * MAX_COLOR), \
+ int(color[1] * MAX_COLOR), \
+ int(color[2] * MAX_COLOR))
+ self.publish('color-changed')
+ #cached graphics context
+ self.gc = None
+
+ def realize_event(self, *args):
+ self.gc = self.get_window().new_gc(foreground=self.icolor)
+
+ def unrealize_event(self, *args):
+ #remove references to the gc to prevent leaks?
+ self.gc = None
+
+ def configure_event(self, *args):
+ #is this required?
+ return gtk.FALSE
+
+ def expose_event(self, *args):
+ #get the window and graphic context
+ win = self.get_window()
+ self.draw_rectangle(self.get_style().black_gc, gtk.FALSE, 0, 0, win.width-1, win.height-1)
+ self.draw_rectangle(self.gc, gtk.TRUE, 1, 1, win.width-2, win.height-2)
+ return gtk.FALSE
+
+ def set_color(self, color=(0,0,0,0)):
+ self.color = color
+ #the color - use GdkColorMap's alloc method to get it
+ cm = self.get_colormap()
+ self.icolor = cm.alloc(int(color[0] * 65535), int(color[1] * 65535),
+ int(color[2] * 65535))
+ if self.gc is not None:
+ self.gc.foreground = self.icolor
+ self.queue_draw()
+ self.notify('color-changed')
+
+ def get_color(self):
+ return self.color
+
+
+class ColorButton(GtkColorWell):
+ """
+ Class ColourButton extends GtkColorWell
+ """
+
+ def __init__(self, color=(0,0,0,0), title='', use_alpha=TRUE, continuous=FALSE, _obj=None):
+ GtkColorWell.__init__(self, _obj)
+ self.set_color( color )
+ self.set_use_alpha( use_alpha )
+ self.set_continuous( continuous )
+
+class ColorDialog(gtk.GtkWindow):
+ """used with a ColorButton when it is clicked"""
+
+ def __init__(self, ok_cb = None, cancel_cb = None, cb_data = None):
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Select a Color')
+ vbox = gtk.GtkVBox(spacing=3)
+ self.add(vbox)
+ self.user_ok_cb = ok_cb
+ self.user_cancel_cb = cancel_cb
+ self.user_cb_data = cb_data
+
+ self.connect('delete-event', self.user_cancel_cb)
+ #add the color selection widget
+ self.colorsel = gtk.GtkColorSelection()
+ self.colorsel.set_opacity(gtk.TRUE)
+ vbox.pack_start(self.colorsel)
+ #add the ok and cancel buttons
+ button_box = gtk.GtkHButtonBox()
+ ok_button = gtk.GtkButton("OK")
+ ok_button.connect('clicked', self.ok_cb, cb_data)
+ cancel_button = gtk.GtkButton("Cancel")
+ cancel_button.connect('clicked', self.cancel_cb, cb_data)
+ button_box.pack_start(ok_button)
+ button_box.pack_start(cancel_button)
+ vbox.pack_start(button_box, expand=gtk.FALSE)
+ vbox.show_all()
+ ok_button.set_flags(gtk.CAN_DEFAULT)
+ ok_button.grab_default()
+
+ def ok_cb(self, *args):
+ if self.user_ok_cb is not None:
+ self.user_ok_cb(self.user_cb_data, self)
+ self.hide()
+ self.destroy()
+
+ def cancel_cb(self, *args):
+ if self.user_cancel_cb is not None:
+ self.user_cancel_cb(self.user_cb_data, self)
+ self.hide()
+ self.destroy()
+
+RAMP_GRADIENT = 0
+RAMP_DISCRETE = 1
+
+class ColorRamp(gtk.GtkFrame, Signaler):
+ """encapsulate the functionality of a color ramp that
+ can apply itself in a linearly interpolated number of
+ steps between several colors positioned along the ramp
+
+ Colors can be returned from the ramp by calling apply_ramp
+ with a callback and the number of colors to calculate.
+ """
+ def __init__(self):
+ """initialize the ramp
+ """
+ gtk.GtkFrame.__init__(self)
+ self.set_shadow_type(gtk.SHADOW_NONE)
+ self.colors = []
+ self.gradient = ColorGradientSwatch(self)
+ self.title = gtk.GtkLabel('Ramp')
+ fix = gtk.GtkFixed()
+ fix.put(self.gradient, 1, 0)
+ fix.put(self.title, 84, 0)
+ self.add(fix)
+ self.type = RAMP_GRADIENT
+
+ def serialize(self, fname = None):
+ """save to a file
+ """
+
+ result = "%s\n" % self.title.get()
+ result = result + "%s\n" % self.type
+ for n in self.colors:
+ if self.type == RAMP_GRADIENT:
+ result = result + "%s %s\n" % (str(n[0]), str(n[1]))
+ else:
+ result = result + "%s\n" % str(n[1])
+
+ if fname is not None:
+ f = open(fname, 'w')
+ f.write( result )
+ f.close()
+ else:
+ return result
+
+ def deserialize(self, fname):
+ """read from a file"""
+ import string
+ fp = open(fname, 'r')
+ lines = fp.readlines()
+ self.title.set_text(lines[0].strip())
+ self.type = int(lines[1].strip())
+ n_colors = len( lines[2:] )
+ for i in range(n_colors):
+ line = lines[2+i]
+ line = string.replace(line, '(', '')
+ line = string.replace(line, ')', '')
+ line = string.replace(line, ',', '')
+ if self.type == RAMP_GRADIENT:
+ pos, r, g, b, a = line.split()
+ else:
+ r, g, b, a = line.split()
+ #assume equally spaced for DISCRETE
+ pos = float(i)/float(n_colors - 1)
+ self.add_color((float(r), float(g), float(b), float(a)), float(pos))
+
+ fp.close()
+ self.queue_draw()
+
+ def add_color(self, color, position):
+ """add a color to the ramp at the given position.
+ color - an rgba tuple
+ position - between 0.0 and 1.0
+ """
+ for i in range(len(self.colors)):
+ if position <= self.colors[i][0]:
+ self.colors.insert(i, (position, color))
+ break
+ else:
+ self.colors.append((position, color))
+
+ def apply_ramp(self, color_cb, ncolors):
+ """
+ return ncolors spread over the ramp by
+ calling the color_cb callback with the
+ current position (in the range 0 to
+ ncolors-1) and color
+ """
+ if len(self.colors) == 0:
+ return
+
+ #insert false entries at 0 and 1 if necessary
+ bLow = gtk.FALSE
+ bHi = gtk.FALSE
+
+ if self.colors[0][0] <> 0.0:
+ self.add_color(self.colors[0][1], 0.0)
+ bLow = gtk.TRUE
+ if self.colors[len(self.colors) - 1][0] <> 1.0:
+ self.add_color(self.colors[len(self.colors)-1][1], 1.0)
+ bHi = gtk.TRUE
+
+ if ncolors > 1:
+ for i in range(ncolors):
+ if self.type == RAMP_GRADIENT:
+ color_cb(i, self.calculate_color(float(float(i)/float(ncolors - 1))))
+ elif self.type == RAMP_DISCRETE:
+ pos = i % len(self.colors)
+ color_cb(i, self.colors[pos][1] )
+
+ else:
+ color_cb( 0, self.calculate_color( 0 ) )
+
+ #clean up
+ if bLow:
+ del self.colors[0]
+ if bHi:
+ del self.colors[len(self.colors)-1]
+
+ def calculate_color(self, pos):
+ """calculate the color at the given position. If a color
+ exists at the position, return it. Otherwise get the color
+ before and after it and calculate a linear interpolation
+ between them.
+ """
+ for i in range(len(self.colors)-1):
+ below = self.colors[i]
+ above = self.colors[i+1]
+ if below[0] <= pos and above[0] >= pos:
+ fr = below[1][0]
+ fg = below[1][1]
+ fb = below[1][2]
+ fa = below[1][3]
+ tr = above[1][0]
+ tg = above[1][1]
+ tb = above[1][2]
+ ta = above[1][3]
+ delta = (pos - below[0]) / (above[0] - below[0])
+ cr = fr + ( tr - fr ) * delta
+ cg = fg + ( tg - fg ) * delta
+ cb = fb + ( tb - fb ) * delta
+ ca = fa + ( ta - fa ) * delta
+ return (cr, cg, cb, ca)
+
+ def get_color_list(self, ncolors):
+ self.color_list = []
+ self.apply_ramp(self.color_list_cb, ncolors)
+ return self.color_list
+
+ def color_list_cb(self, num, color):
+ self.color_list.insert(num, color)
+
+class ColorGradientSwatch(ColorSwatch):
+ """
+ Class ColorGradientSwatch extends ColorSwatch to n colors
+ and draws itself as a gradient between the various colors.
+
+ This class is intended primarily to provide a GUI element for
+ ColorRamps
+ """
+ def __init__(self, ramp):
+ ColorSwatch.__init__(self)
+ self.size(80, 15)
+ self.ramp = ramp
+
+ def expose_event(self, *args):
+ #get the window and graphic context
+ win = self.get_window()
+ self.width = win.width
+ self.height = win.height
+ self.cm = self.get_colormap()
+ if self.ramp.type == RAMP_GRADIENT:
+ colors = self.ramp.get_color_list(self.width)
+ else:
+ colors = self.ramp.get_color_list( len(self.ramp.colors) - 1 )
+ bar_width = self.width / len(colors)
+ i = 0
+ for color in colors:
+ self.gc.foreground = self.cm.alloc(int(color[0] * MAX_COLOR),
+ int(color[1] * MAX_COLOR),
+ int(color[2] * MAX_COLOR))
+ self.draw_rectangle(self.gc, gtk.TRUE, i, 0, bar_width, self.height)
+ i = i + bar_width
+ self.draw_rectangle(self.get_style().black_gc, gtk.FALSE, 0, 0, win.width-1, win.height-1)
+ return gtk.FALSE
+
+
+def test_cb(num, color):
+ print num, ' - ', color
+
+def color_set( widget, obj ):
+ print 'color set to ', widget.get_color()
+
+if __name__ == '__main__':
+ a = ColorRamp()
+ a.add_color((0.0,1.0,0.0,1.0), 0.0)
+ a.add_color((1.0,1.0,0.0,1.0), 0.50)
+ a.add_color((1.0,0.0,0.0,1.0), 1.0)
+ print a.colors
+ a.apply_ramp(test_cb, 5)
+ print a.colors
+ a.serialize('c:\\test_ramp')
+ b = ColorRamp()
+ b.deserialize('c:\\test_ramp')
+ print b.colors
+
+ c = ColorButton((1.0, 0.0, 0.0, 1.0))
+ c.connect('color-set', color_set)
+
+ dlg = gtk.GtkDialog()
+ btn = gtk.GtkButton('OK')
+ btn.connect('clicked', gtk.mainquit)
+
+ dlg.vbox.pack_start(a)
+ dlg.vbox.pack_start(b)
+ dlg.vbox.pack_start(c)
+ dlg.action_area.pack_start(btn)
+ dlg.show_all()
+ dlg.show()
+
+ gtk.mainloop()
Added: packages/openev/branches/upstream/current/pymod/pgucolorsel.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgucolorsel.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgucolorsel.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,201 @@
+###############################################################################
+# $Id: pgucolorsel.py,v 1.1 2000/06/14 15:12:43 warmerda Exp $
+#
+# Project: Python Gtk Utility Widgets
+# Purpose: Embeddable color selector.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgucolorsel.py,v $
+# Revision 1.1 2000/06/14 15:12:43 warmerda
+# New
+#
+#
+
+from gtk import *
+from string import *
+import pgu
+from pgucolourswatch import ColourSwatch
+
+
+class ColorControl(GtkHBox):
+
+ """Embeddable Color Selector Control
+
+ The pgucolorsel.ColorControl widget is intended to provide a simple
+ color selection widget that can be embedded in dialogs and that will
+ launch a fill GtkColorSelectionDialog if the user doesn't select one of
+ the list of predefined colors.
+
+ At this time the ColorControl's main widgetry is just an option menu, but
+ it is expected in the future to also include some sort of color swatch
+ showing the currently selected color graphically.
+
+ The application supplies a single callback which is involved when the
+ selected color changes. All colors are handled as RGBA tuples, with the
+ values being in the range of 0-1 (rather than 0-255).
+
+ Arguments:
+
+ title -- the title used for the color selection dialog, if displayed.
+
+ callback -- the application function to call when the color changes. It
+ should take a color tuple (RGBA) and a callback data object as arguments.
+
+ cb_data -- callback data to pass to callback.
+
+ Example:
+
+ self.mod_color = pgucolorsel.ColorControl('Modulation Color',
+ self.color_cb,None)
+ self.mod_color.set_color(tcolor)
+
+ def color_cb( self, color, cb_data ):
+ print color[0], color[1], color[2], color[3]
+ """
+
+ color_list = [ ('Red', ( 1, 0, 0, 1)),
+ ('Green', ( 0, 1, 0, 1)),
+ ('Blue', ( 0, 0, 1, 1)),
+ ('White', ( 1, 1, 1, 1)),
+ ('Black', ( 0, 0, 0, 1)),
+ ('Transparent', ( 0, 0, 0, 0))]
+
+ def __init__(self, title, callback = None, cb_data = None):
+ GtkHBox.__init__(self)
+
+ self.callback = callback
+ self.cb_data = cb_data
+ self.current_color = (1,0,0,1)
+ self.mixer = None
+ self.title = title
+
+ self.swatch = ColourSwatch(self.current_color)
+
+ self.om = GtkOptionMenu()
+
+ menu = GtkMenu()
+ self.om.set_menu(menu)
+
+ item = None
+ for cinfo in self.color_list:
+ name, value = cinfo
+ item = GtkRadioMenuItem(item,name)
+ item.connect('activate', self.set_color_cb, value)
+ item.show()
+ menu.append(item)
+
+ item = GtkRadioMenuItem(item,'Custom')
+ item.connect('activate', self.launch_mixer_cb)
+ item.show()
+ menu.append(item)
+
+ item = GtkRadioMenuItem(item,'Mixer')
+ item.connect('activate', self.launch_mixer_cb)
+ item.show()
+ menu.append(item)
+
+ self.om.set_history(0)
+
+ self.pack_start(self.swatch, expand=FALSE)
+ self.pack_start(self.om)
+
+ def launch_mixer_cb(self,item):
+ if not item.active:
+ return
+
+ if self.mixer is not None and self.mixer.get_window() is not None:
+ self.mixer.colorsel.set_color( self.current_color )
+ self.mixer.colorsel.set_opacity( self.current_color[3] )
+ self.mixer.get_window()._raise()
+ return
+
+ self.mixer = GtkColorSelectionDialog(self.title)
+ self.mixer.connect('delete-event',self.mixer_delete)
+ self.mixer.colorsel.set_opacity( 1 )
+ self.mixer.colorsel.set_color( self.current_color )
+ self.mixer.ok_button.connect('clicked',self.mixer_ok_cb )
+ self.mixer.ok_button.children()[0].set_text('Apply')
+ self.mixer.cancel_button.connect('clicked',self.mixer_cancel )
+ self.mixer.cancel_button.children()[0].set_text('Close')
+ self.mixer.help_button.hide()
+ self.mixer.show()
+ self.update_om()
+
+ def mixer_delete(self, widget, args):
+ self.mixer = None
+
+ def mixer_cancel(self, args):
+ self.mixer.hide()
+ self.mixer.destroy()
+ self.mixer = None
+
+ def mixer_ok_cb(self, args):
+ rgb = self.mixer.colorsel.get_color()
+ self.set_color( (rgb[0], rgb[1], rgb[2], rgb[3] ) )
+
+ def set_color(self, new_color):
+ if len(new_color) == 3:
+ new_color = (new_color[0],new_color[1],new_color[2],1.0)
+
+ if new_color[0] > 1 or new_color[1] > 1 \
+ or new_color[2] > 1 or new_color[3] > 1:
+ new_color = (new_color[0] / 255.0,
+ new_color[1] / 255.0,
+ new_color[2] / 255.0,
+ new_color[3] / 255.0)
+
+ if new_color == self.current_color:
+ return
+
+ self.current_color = new_color
+ self.swatch.set_colour(self.current_color)
+ self.invoke_callback()
+ self.update_om()
+
+ def update_om(self):
+ for ci_index in range(len(self.color_list)):
+ name, value = self.color_list[ci_index]
+ if value == self.current_color:
+ self.om.set_history(ci_index)
+ return
+
+ # Mark as custom
+ self.om.set_history(len(self.color_list))
+
+ def set_color_from_string(self, new_color):
+ if new_color is None:
+ return
+
+ red, green, blue, alpha = split(new_color,' ')
+ self.set_color((atof(red), atof(green), atof(blue), atof(alpha)))
+
+ def invoke_callback(self):
+ if self.callback == None:
+ return
+ self.callback( self.current_color, self.cb_data )
+
+ def set_color_cb(self, item, color):
+ if item.active:
+ self.set_color( color )
+
+pgu.gtk_register('ColorControl',ColorControl)
+
Added: packages/openev/branches/upstream/current/pymod/pgucolourswatch.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgucolourswatch.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgucolourswatch.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,102 @@
+###############################################################################
+# $Id: pgucolourswatch.py,v 1.3 2003/09/09 15:18:46 gmwalter Exp $
+#
+# Project: Python Gtk Utility Widgets
+# Purpose: Embeddable color swatch.
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgucolourswatch.py,v $
+# Revision 1.3 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.2 2001/03/19 21:57:14 warmerda
+# expand tabs
+#
+# Revision 1.1 2000/07/26 21:20:01 warmerda
+# New
+#
+#
+
+import gtk
+from gvsignaler import Signaler
+
+class ColourSwatch(gtk.GtkDrawingArea, Signaler):
+ '''
+ Class ColourSwatch is a simple widget that
+ displays a colour.
+
+ The colour attribute is an RGBA tuple. Internally, however,
+ a GdkColour object is used that has values in the range 0-65535
+ for red, green and blue.
+ '''
+ def __init__(self, colour=(0,0,0,0)):
+ gtk.GtkDrawingArea.__init__(self)
+ self.size(30, 15)
+ self.connect('configure-event', self.configure_event)
+ self.connect('expose-event', self.expose_event)
+ self.connect('realize', self.realize_event)
+ self.connect('unrealize', self.unrealize_event)
+ self.colour = colour
+ #the color - use GdkColourMap's alloc method to get it
+ cm = self.get_colormap()
+ self.icolour = cm.alloc(int(colour[0] * 65535),
+ int(colour[1] * 65535),
+ int(colour[2] * 65535))
+ self.publish('colour-changed')
+ #cached graphics context
+ self.gc = None
+
+ def realize_event(self, *args):
+ self.gc = self.get_window().new_gc(foreground=self.icolour)
+
+ def unrealize_event(self, *args):
+ #don't know the correct way to destroy a gc yet
+ #self.gc.destroy()
+ pass
+
+ def configure_event(self, *args):
+ #is this required?
+ return gtk.FALSE
+
+ def expose_event(self, *args):
+ #get the window and graphic context
+ win = self.get_window()
+ self.draw_rectangle(self.get_style().black_gc, gtk.FALSE, 2, 2, win.width-2, win.height-2)
+ self.draw_rectangle(self.gc, gtk.TRUE, 3, 3, win.width-3, win.height-3)
+ return gtk.FALSE
+
+ def set_colour(self, colour=(0,0,0,0)):
+ self.colour = colour
+ #the color - use GdkColourMap's alloc method to get it
+ cm = self.get_colormap()
+ self.icolour = cm.alloc(int(colour[0] * 65535),
+ int(colour[1] * 65535),
+ int(colour[2] * 65535))
+ if self.gc is not None:
+ self.gc.foreground = self.icolour
+ self.notify('colour-changed')
+ if self.flags() & gtk.REALIZED:
+ self.expose_event()
+
Added: packages/openev/branches/upstream/current/pymod/pgucombo.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgucombo.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgucombo.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,230 @@
+###############################################################################
+# $Id: pgucombo.py,v 1.7 2005/11/08 15:51:44 andrey_kiselev Exp $
+#
+# Project: CIET Map
+# Purpose: CIET Map
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgucombo.py,v $
+# Revision 1.7 2005/11/08 15:51:44 andrey_kiselev
+# Properly import gtkextra module, should work on Debian system now.
+#
+# Revision 1.6 2004/09/28 17:50:42 warmerda
+# change fallback for how pygtkextra is imported
+#
+# Revision 1.5 2003/11/19 15:20:53 warmerda
+# try looking in alternate location for pygtkextra if import fails
+#
+# Revision 1.4 2002/08/13 12:44:15 pgs
+# made dropdown list scrollable and added capture of esc key to
+# close dropdown
+#
+# Revision 1.3 2002/08/09 21:04:24 pgs
+# fixed bug in set_popdown_strings (make copy of list)
+#
+# Revision 1.2 2002/08/01 14:49:37 pgs
+# modified, now dependent on gtkextra but much nicer control
+#
+# Revision 1.1 2001/04/29 15:24:38 pgs
+# new file
+#
+#
+
+import gtk
+try:
+ from pygtkextra import GtkComboBox
+except:
+ from gtkextra import GtkComboBox
+
+"""
+pgucombo contains a single class, pguCombo, which implements a better combobox
+based on gtkextra's GtkComboBox (and the python bindings)
+"""
+
+class pguCombo(GtkComboBox):
+ """
+ this class mimics GtkCombo but the selection process is somewhat simpler
+ and the entry box only changes when you actually select an item, not when
+ you drag through it.
+ """
+
+ def __init__(self, strings = [ "" ]):
+ """Initialize the combo box, default strings can be passed.
+ """
+ GtkComboBox.__init__(self)
+
+ self.items = strings
+ self.current_item = 0
+
+ #widgets to go into the combo box
+ self.list = gtk.GtkCList( cols=1 )
+ self.list.set_selection_mode( gtk.SELECTION_SINGLE )
+
+ self.entry = gtk.GtkEntry()
+ self.entry.set_editable( gtk.FALSE )
+
+ #fix up the style of the entry
+ #style = self.entry.get_style().copy()
+
+ #fake a background color the same as the button widget
+ #for i in range(5):
+ # style.base[i] = self.button.get_style().bg[i]
+ #self.entry.set_style( style )
+
+ self._scrolled_win = gtk.GtkScrolledWindow()
+ self._scrolled_win.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC )
+ self._scrolled_win.add( self.list )
+
+ #################################
+ #
+ # TODO: figure out how to resize this on the fly
+ #
+ #################################
+ self._scrolled_win.set_usize( 150, 175 )
+ self._scrolled_win.show_all()
+ #frame is the popdown window frame
+ self.frame.add( self._scrolled_win )
+
+ #button is the main area to the left of the dropdown arrow
+ self.button.add( self.entry )
+
+ #initialize the widgets
+ self.set_popdown_strings( self.items )
+ self.select_item( self.current_item )
+
+ #connect up signals
+ self.list.connect( 'select-row', self.list_row_selected )
+
+ self.list.add_events(gtk.GDK.KEY_PRESS_MASK)
+ self.list.connect('key-press-event', self.key_press_cb)
+
+ self.arrow.connect( 'toggled', self.toggle_cb )
+
+
+ #make sure they all get shown
+ self.show_all()
+
+
+ def toggle_cb( self, widget, *args ):
+ if widget.get_active():
+ self.list.grab_focus()
+ else:
+ self.entry.grab_focus()
+
+ def key_press_cb( self, widget, event, *args ):
+ """
+ The user pressed a key. Find out if we should respond to it
+ """
+ if event.keyval == gtk.GDK.Escape:
+ self.hide_popdown_window()
+
+ def list_row_selected( self, widget, row, col, event, *args ):
+ """private callback for list selections
+ """
+ self.select_item( row )
+ self.hide_popdown_window()
+
+ def get_text( self ):
+ """Return the text associated with the currently selected item
+ """
+ return self.items[ self.current_item ]
+
+ def get_selected_item( self ):
+ """Return the index of the selected item
+ """
+ return self.current_item
+
+ def select_item( self, item = 0 ):
+ """Select an item by it's index
+ """
+ if item >= 0 and item < len(self.items):
+ self.current_item = item
+ self.entry.set_text( self.items[self.current_item] )
+ return gtk.TRUE
+ else:
+ return gtk.FALSE
+ def select_string( self, string = "" ):
+ """Cause an item to be selected by a string value
+ """
+ try:
+ idx = self.items.index( string )
+ self.select_item( idx )
+ return gtk.TRUE
+ except:
+ return gtk.FALSE
+
+ ############################################################################
+ #
+ # GtkCombo API
+ #
+ ############################################################################
+ def set_popdown_strings( self, items ):
+ """set the strings to display
+ """
+ del self.items
+ self.items = []
+ for item in items:
+ self.items.append( item )
+ self.list.clear()
+ for item in self.items:
+ self.list.append( [item] )
+ self.list.set_column_width( 0, self.list.optimal_column_width( 0 ) )
+ self.list.show_all()
+ self.select_item( 0 )
+
+ def disable_activate( self ):
+ pass
+
+ def set_use_arrows( self, val):
+ pass
+
+ def set_use_arrows_always( self, val ):
+ pass
+
+ def set_case_sensitive( self, val ):
+ pass
+
+ def set_value_in_list( self, val, ok_if_empty ):
+ pass
+
+class TestWindow( gtk.GtkWindow ):
+
+ def __init__(self):
+ gtk.GtkWindow.__init__(self)
+
+ vbox = gtk.GtkVBox()
+ self.add(vbox)
+
+ self.cmb = pguCombo([ 'test1', 'test2', 'long test string' ])
+ self.cmb.entry.connect( 'changed', self.item_changed )
+
+ vbox.pack_start( self.cmb )
+
+ self.connect( 'delete-event', gtk.mainquit )
+ self.show_all()
+
+ def item_changed( self, *args ):
+ print self.cmb.get_text()
+
+if __name__ == "__main__":
+ win = TestWindow()
+ gtk.mainloop()
Added: packages/openev/branches/upstream/current/pymod/pguentry.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pguentry.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pguentry.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,12 @@
+import gtk
+
+class pguEntry( gtk.GtkEntry ):
+
+ def __init__(self):
+ gtk.GtkEntry.__init__(self)
+ self.add_events(gtk.GDK.FOCUS_CHANGE_MASK)
+ self.connect('focus-out-event', self.cleanup)
+
+ def cleanup(self, *args):
+ self.select_region(0, 0)
+ self.queue_draw()
Added: packages/openev/branches/upstream/current/pymod/pgufilesel.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgufilesel.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgufilesel.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,202 @@
+###############################################################################
+# $Id: pgufilesel.py,v 1.1 2000/06/14 13:57:30 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Simplified File Selection API.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgufilesel.py,v $
+# Revision 1.1 2000/06/14 13:57:30 warmerda
+# New
+#
+#
+
+import gtk; _gtk = gtk; del gtk
+from string import *
+import os.path
+
+simple_file_sel = None
+simple_file_sel_dir= None
+
+def SFSOkCB( item, cb, cb_data ):
+ global simple_file_sel
+
+ simple_file_sel.hide()
+ cb( os.path.normpath(simple_file_sel.get_filename()), cb_data )
+
+def SFSCancelCB( item, cb, cb_data ):
+ global simple_file_sel
+
+ simple_file_sel.hide()
+ if cb is not None:
+ cb( cb_data )
+
+def SFSDestroyCB( item, cb, cb_data ):
+ global simple_file_sel
+
+ simple_file_sel = None
+ if cb is not None:
+ cb( cb_data )
+
+def SimpleFileSelect( ok_cb,
+ cb_data = None,
+ title = None,
+ default_filename = None,
+ cancel_cb = None,
+ help_topic = None ):
+
+ """Simplified File Selection
+
+ This method launches a file selector, and calls the caller supplied
+ OK callback when the user selects a file. Creation, tailoring and
+ cleanup of the GtkFileselection is managed internally.
+
+ Arguments:
+
+ ok_cb -- callback to call when user selects a file. It should take
+ a filename and cb_data argument.
+
+ cb_data -- extra data to pass to ok, and cancel callbacks. Defaults to
+ None.
+
+ title -- the title to use for the dialog. Defaults to nothing.
+
+ default_filename -- the initial filename to be shown in the file selector.
+ Defaults to no file, and the current (or last accessed) directory.
+
+ cancel_cb -- callback called when the user hits the cancel button or
+ closes the file selection dialog. If defaulted the caller isn't notified
+ of cancels. If supplied, the callback should take one argument which is
+ the callback data.
+
+ Example:
+
+ The following code launches a simple file selector, and does an action
+ in the callback. The title, and default filename are set, but
+ pgufilesel.SimpleFileSelect( self.save_vector_layer_with_file,
+ cb_data = layer.get_parent(),
+ title = 'Shapefile To Save to',
+ default_filename = layer.get_name() )
+
+ def save_vector_layer_with_file( self, filename, shapes_data ):
+ shapes_data.save_to( filename )
+
+ """
+
+ global simple_file_sel
+
+ if simple_file_sel is not None:
+ simple_file_sel.destroy()
+
+ simple_file_sel = _gtk.GtkFileSelection()
+ simple_file_sel.hide_fileop_buttons()
+ simple_file_sel.ok_button.connect('clicked', SFSOkCB, ok_cb, cb_data )
+ simple_file_sel.cancel_button.connect('clicked', SFSCancelCB, cancel_cb, cb_data )
+ simple_file_sel.connect('destroy', SFSDestroyCB, cancel_cb, cb_data)
+
+ if title is not None:
+ simple_file_sel.set_title( title )
+
+ if default_filename is not None:
+ simple_file_sel.set_filename( default_filename )
+ else:
+ if simple_file_sel_dir is not None:
+ simple_file_sel.set_filename(simple_file_sel_dir)
+
+ if help_topic is not None:
+ import gvhtml
+ gvhtml.set_help_topic( simple_file_sel, help_topic )
+
+
+ simple_file_sel.show()
+
+
+def SimpleFileSelectCB( item, ok_cb, *args ):
+
+ """Simple file selection suitable to use as a callback.
+
+ This function is suitable to be used as a callback from a menu item,
+ and will launch a file selector, using the SimpleFileSelect() API.
+ See that function for details on meaning of arguments.
+
+ The callback should be passed one, two or three arguments which
+ would be the SimpleFileSelect() arguments ok_cb, cb_data and title.
+
+ Example:
+
+ The following fragment passed to GtkExtra.MenuFactory creates a File
+ Open menu item, and it launches a file selector. When a file is called
+ the caller supplied self.file_open_by_name() method is called.
+
+ ('File/Open', '<control>O', pgufilesel.SimpleFileSelectCB,
+ self.file_open_by_name ),
+
+ def file_open_by_name(self, filename, *args):
+ ...
+
+ """
+
+ if len(args) == 0:
+ SimpleFileSelect( ok_cb )
+ elif len(args) == 1:
+ SimpleFileSelect( ok_cb, cb_data = args[0] )
+ else:
+ SimpleFileSelect( ok_cb, cb_data = args[2], title = args[0] )
+
+
+# For directly grabbing a filename within a single callback
+class pguFileSelection(_gtk.GtkFileSelection):
+ def __init__(self, title, default_filename = None):
+ _gtk.GtkFileSelection.__init__(self)
+ self.set_title(title)
+ if default_filename is not None:
+ self.set_filename(default_filename)
+
+ elif simple_file_sel_dir is not None:
+ self.set_filename(simple_file_sel_dir)
+
+ self.ok_button.connect ("clicked", self.ok_cb)
+ self.cancel_button.connect("clicked", self.cancel_cb)
+ self.connect("delete_event", self.cancel_cb)
+ self.ret = None
+ self.set_modal(_gtk.TRUE)
+
+ def ok_cb(self, *args):
+ self.ret = self.get_filename()
+ self.hide()
+ self.destroy()
+ _gtk.mainquit()
+
+ def cancel_cb(self, *args):
+ self.ret = None
+ self.selected = None
+ self.hide()
+ self.destroy()
+ _gtk.mainquit()
+
+
+def GetFileName(title = 'Select File', default_filename = None):
+ win = pguFileSelection(title, default_filename)
+ win.show_all()
+ _gtk.mainloop()
+ return win.ret
+
Added: packages/openev/branches/upstream/current/pymod/pgufont.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgufont.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgufont.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,440 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: pgufont.py,v 1.4 2004/07/20 12:26:43 pgs Exp $
+#
+# Project: OpenEV Python GTK Utility classes
+# Purpose: Embeddable Font class and font utility classes
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgufont.py,v $
+# Revision 1.4 2004/07/20 12:26:43 pgs
+# added ability to load font and report statistics on it
+#
+# Revision 1.3 2002/08/28 18:44:17 pgs
+# fixed typo from last change :(
+#
+# Revision 1.2 2002/08/28 18:07:35 pgs
+# removed sys.stdout.flush() to prevent problems on windows with no console
+#
+# Revision 1.1 2001/04/29 15:23:40 pgs
+# new file
+#
+#
+
+import gtk
+from gtk import TRUE, FALSE
+import gview
+from gvsignaler import Signaler
+import string
+import sys
+import gdal
+
+
+"""
+pgufont contains utility classes for manipulating and selecting fonts
+"""
+
+class XLFDFontSpec:
+ """
+ encapsulate an X Logical Font Description (XLFD) font specification
+
+ -adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1
+
+ The fields in the XLFD are:
+
+ Foundry the company or organization where the font originated.
+ Family the font family (a group of related font designs).
+ Weight A name for the font's typographic weight For example,
+ 'bold' or 'medium').
+ Slant The slant of the font. Common values are 'R' for Roman,
+ 'I' for italoc, and 'O' for oblique.
+ Set Width A name for the width of the font. For example,
+ 'normal' or 'condensed'.
+ Add Style Additional information to distinguish a font from other
+ fonts of the same family.
+ Pixel Size The body size of the font in pixels.
+ Point Size The body size of the font in 10ths of a point. (A point
+ is 1/72.27 inch)
+ Resolution X The horizontal resolution that the font was designed for.
+ Resolution Y The vertical resolution that the font was designed for .
+ Spacing The type of spacing for the font - can be 'p' for
+ proportional, 'm' for monospaced or 'c' for charcell.
+ Average Width The average width of a glyph in the font. For monospaced
+ and charcell fonts, all glyphs in the font have this width
+ Charset Registry The registration authority that owns the encoding for the
+ font. Together with the Charset Encoding field, this
+ defines the character set for the font.
+ Charset Encoding An identifier for the particular character set encoding.
+ """
+
+ xlfd_field_names = ['Foundry','Family','Weight',
+ 'Slant','Set','Add Style','Pixel Size',
+ 'Point Size','Resolution X','Resolution Y',
+ 'Spacing','Average Width','Charset Registry',
+ 'Charset Encoding']
+
+ def __init__(self, fontspec = None):
+ """
+ initialize, optionally parsing a font spec
+ """
+ self.gdk_font = None
+ self.parts = []
+ for i in range(14):
+ self.parts.append('*')
+ if fontspec is not None:
+ self.parse_font_spec(fontspec)
+
+ def parse_font_spec(self, font_spec):
+ """
+ parse a font specification
+ """
+ self.gdk_font = None
+ result = ''
+
+ #coerce XLFDFontSpec classes into strings to parse them
+ font_spec = str(font_spec)
+
+ if font_spec[0:1] != '-':
+ gdal.Debug( "pgufont", "invalid XLFD(%s), should start with -" % font_spec )
+ return
+
+ new_parts = string.split(font_spec, '-')
+ del new_parts[0] #remove first (empty) part produced by split
+
+ if len(new_parts) != 14:
+ gdal.Debug( "pgufont", 'invalid XLFD(%s), should have 14 parts' % font_spec )
+ return
+
+ else:
+ self.parts = new_parts
+
+ def get_font_part(self, field_name=None, field_number=None):
+ """
+ Get one part of the font description by field name or number. If
+ both are specified, the result of the field name will be returned
+ if it is valid, or if invalid, the field number, or if that is also
+ invalid, the an empty string.
+ """
+ result = ''
+ if field_number is not None:
+ if field_number < 1 or field_number > 14:
+ gdal.Debug( "pgufont", 'invalid field number (%s), should be 1-14' % field_number)
+ else:
+ result = self.parts[field_number]
+
+ if field_name is not None:
+ if self.xlfd_field_names.count(field_name) == 0:
+ gdal.Debug( "pgufont", 'invalid field name (%s), should be one of %s' \
+ % (field_name, self.xlfd_field_names) )
+ else:
+ result = self.parts[self.xlfd_field_names.index(field_name)]
+
+ return result
+
+ def set_font_part(self, field_name, value):
+ """
+ set a part of the font description
+ """
+ self.gdk_font = None
+ if self.xlfd_field_names.count(field_name) != 0:
+ self.parts[self.xlfd_field_names.index(field_name)] = value
+ else:
+ gdal.Debug( "pgufont", 'invalid field name (%s), should be one of %s' \
+ % (field_name, self.xlfd_field_names) )
+
+ def get_display_string(self):
+ """
+ return a human readable display string for this font
+ """
+ family = self.get_font_part('Family') + ' '
+ weight = self.get_font_part('Weight') + ' '
+ if weight == '* ' or weight == 'normal ': weight = ''
+ slant = self.get_font_part('Slant') + ' '
+ if slant == '* ': slant = ''
+ elif slant == 'r ': slant = ''
+ elif slant == 'i ' or slant == 'o ': slant = 'Italic '
+
+ unit = ' pt'
+ size = self.get_font_part('Point Size')
+ if size == '*' or size == '':
+ size = self.get_font_part('Pixel Size')
+ unit = ' px'
+ else:
+ size = size[0:len(size)-1]
+ return family + weight + slant + size + unit
+
+ def get_font_string(self):
+ """
+ return this font as a string (for cases where automatic coercion
+ doesn't work ...)
+ """
+ return str(self)
+
+ def __str__(self):
+ """
+ return a representation of this xfld as a string
+ """
+ result = ''
+ for val in self.parts:
+ result = result + '-' + val
+
+ return result
+
+ def load_font( self ):
+ """
+ load the real GDK font associated with this font spec so
+ we can do calculations on it.
+ """
+ if self.gdk_font is not None:
+ return
+ self.gdk_font = gtk.load_font(str(self))
+
+ def text_size( self, text ):
+ """
+ return the size (w,h) of a text string in the current font
+ """
+ self.load_font()
+ w = self.gdk_font.width(text)
+ h = self.gdk_font.height(text)
+ return (w, h)
+
+class pguFontDisplay(gtk.GtkDrawingArea):
+ """
+ a widget for displaying some text in a given font.
+ """
+
+ def __init__(self, text='Sample', font=None):
+ """
+ """
+ gtk.GtkDrawingArea.__init__(self)
+ self.size(10, 10)
+ self.connect('expose-event', self.expose_event)
+ self.connect('configure-event', self.configure_event)
+ self.connect('realize', self.realize_event)
+ self.connect('unrealize', self.unrealize_event)
+ self.text = text
+ self.font = font
+ if font is not None:
+ self.gdk_font = gtk.load_font(font)
+ else:
+ self.gdk_font = None
+
+ self.set_events(gtk.GDK.BUTTON_PRESS_MASK)
+
+ def realize_event(self, *args):
+ pass
+
+ def unrealize_event(self, *args):
+ self.gdk_font = None
+ pass
+
+ def configure_event(self, *args):
+ #is this required?
+ return gtk.FALSE
+
+ def expose_event(self, *args):
+ #get the window and graphic context
+ resize = FALSE
+
+ if self.gdk_font is None:
+ resize = TRUE
+ if self.font is None:
+ self.gdk_font = self.get_style().font
+ else:
+ self.gdk_font = gtk.load_font(self.font)
+
+ w = self.gdk_font.width(self.text)
+ h = self.gdk_font.height(self.text)
+
+ if resize:
+ self.set_usize(w + 6, h + 6)
+ self.queue_draw()
+
+ win = self.get_window()
+ #self.draw_rectangle(self.get_style().black_gc, gtk.FALSE, 0, 0, win.width-1, win.height-1)
+ self.draw_rectangle(self.get_style().white_gc, gtk.TRUE, 0, 0, win.width-1, win.height-1)
+ self.draw_string(self.gdk_font, self.get_style().black_gc, 3, h+3, self.text)
+ return gtk.FALSE
+
+ def set_text(self, text):
+ """
+ set the text for this widget and resize if appropriate
+ """
+ if self.text == text:
+ return
+
+ self.text = text
+ #try to resize. If no font, wait for the next redraw
+ if self.gdk_font is not None:
+ w = self.gdk_font.width(self.text)
+ h = self.gdk_font.height(self.text)
+ self.set_usize(w + 6, h + 6)
+ self.queue_draw()
+
+ def set_font(self, font):
+ self.font = font
+ self.gdk_font = None
+ self.queue_draw()
+
+class pguFontControl(gtk.GtkHBox, Signaler):
+ """
+ an embeddable control for selecting fonts. It displays the current
+ font in a pguFontDisplay widget and provides a button to click to
+ change the font. If the widget is double-clicked, the displayed
+ text will toggle between the default font and the selected font.
+
+ Uses gvsignaler.Signaler to provide a 'font-changed' signal ... use
+ font_control.subscribe('font-changed', call_back)
+
+ Use font_control.get_font to retrieve an XLFDFontSpec object or
+ font_control.get_font_string to get a font string.
+ """
+
+ def __init__(self, fontspec=None, use_font=FALSE):
+ """
+ Initialize the font selector and optionally load a previous
+ font spec
+ """
+ gtk.GtkHBox.__init__(self)
+
+ self.use_font = use_font
+ self.font = XLFDFontSpec()
+
+ tips = gtk.GtkTooltips()
+
+ if fontspec is not None:
+ self.font.parse_font_spec( fontspec )
+ else:
+ self.font.set_font_part('Family', 'Arial')
+ self.font.set_font_part('Point Size', '100')
+
+ table = gtk.GtkTable()
+ self.pack_start(table)
+
+ table.set_row_spacings(6)
+ table.set_col_spacings(6)
+ table.set_border_width(6)
+
+ self.font_label = pguFontDisplay()
+ self.font_label.set_text(self.font.get_display_string())
+ table.attach(self.font_label, 0, 1, 0, 1, xoptions=gtk.SHRINK,
+ yoptions=gtk.SHRINK)
+ tips.set_tip(self.font_label, 'double click to toggle sample mode')
+
+ font_button = gtk.GtkButton('...')
+ font_button.connect('clicked', self.show_font_dialog)
+ table.attach(font_button, 1, 2, 0, 1, xoptions=gtk.SHRINK,
+ yoptions=gtk.SHRINK)
+ tips.set_tip(font_button, 'click to select a different font')
+
+ self.show_all()
+
+ self.font_label.set_events(gtk.GDK.BUTTON_PRESS_MASK)
+ self.font_label.connect('button-press-event', self.label_clicked)
+
+ self.update_gui()
+ self.publish('font-changed')
+
+ def show_font_dialog(self, *args):
+ """
+ show the font selection dialog
+ """
+ dlg = gtk.GtkFontSelectionDialog('Select a font')
+ dlg.set_font_name(str(self.font))
+ dlg.ok_button.connect('clicked', self.update_font, dlg)
+ dlg.cancel_button.connect('clicked', dlg.destroy)
+ dlg.show()
+
+ def update_font(self, widget, dlg):
+ """
+ update the font as a result of the user selecting a new one
+ """
+ self.set_font(dlg.get_font_name())
+ dlg.destroy()
+
+ def update_gui(self, *args):
+ """
+ update the GUI to reflect the state of the current font spec
+ """
+ #style = self.font_label.get_style().copy()
+ #if self.use_font:
+ # style.font = gtk.load_font(str(self.font))
+ #else:
+ # style.font = self.get_style().font
+ if self.use_font:
+ self.font_label.set_font(str(self.font))
+ else:
+ self.font_label.set_font(None)
+ self.font_label.set_text(self.font.get_display_string())
+ self.queue_resize()
+
+ def set_font(self, fontspec):
+ """
+ set the font from the fontspec and update the gui
+ """
+ self.font.parse_font_spec(fontspec)
+ self.update_gui()
+ self.notify('font-changed')
+
+ def get_font(self):
+ """
+ return the current font specification
+ """
+ #should this be a string or a font spec?
+ return self.font
+
+ def get_font_string(self):
+ return str(self.font)
+
+ def label_clicked(self, widget, event):
+ """
+ toggle the sample mode if the user double clicks on the label
+ """
+ if event.type == gtk.GDK._2BUTTON_PRESS:
+ self.use_font = (self.use_font == FALSE)
+ self.update_gui()
+
+
+def print_font(widget,font_selector):
+ """
+ test case
+ """
+ font = font_selector.get_font()
+ print font
+
+if __name__ == '__main__':
+ """
+ test case
+ """
+
+ dlg = gtk.GtkDialog()
+
+ font_selector = pguFontControl(use_font=FALSE)
+ font_selector.subscribe('font-changed', print_font, font_selector)
+ dlg.vbox.pack_start(font_selector)
+
+ ok = gtk.GtkButton('ok')
+ dlg.action_area.pack_start(ok)
+ ok.connect('clicked', gtk.mainquit)
+ dlg.connect('delete-event', gtk.mainquit)
+ dlg.show_all()
+ gtk.mainloop()
\ No newline at end of file
Added: packages/openev/branches/upstream/current/pymod/pgugrid.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgugrid.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgugrid.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,6251 @@
+#! /usr/bin/env python
+###############################################################################
+# $Id: pgugrid.py,v 1.17 2005/10/17 14:32:28 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: General purpose grid widget.
+# Author: Gillian Walter, gillian.walter at atlantis-scientific.com
+#
+###############################################################################
+# Copyright (c) 2003, Atlantis Scientific Inc. (www.atlantis-scientific.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgugrid.py,v $
+# Revision 1.17 2005/10/17 14:32:28 gmwalter
+# Merge in Bi's changes.
+#
+# Revision 1.16 2005/04/06 15:56:52 gmwalter
+# Add ability to set row titles.
+#
+# Revision 1.15 2005/03/01 20:53:34 gmwalter
+# Fix some bugs with scrollbars and configuration.
+#
+# Revision 1.14 2004/12/15 17:29:26 gmwalter
+# Fix bug that occurs when user deletes
+# a cell as it is being edited.
+#
+# Revision 1.13 2004/09/09 15:22:16 gmwalter
+# Fix bug for variant case.
+#
+# Revision 1.12 2004/08/31 19:11:56 gmwalter
+# Added ability to control line drawing
+# to some degree.
+#
+# Revision 1.11 2004/08/30 22:20:32 gmwalter
+# Added another variant, cleaned up a few problems
+# with drawing, added ability to set scrollbar-showing
+# policy and a few functions for default style setting.
+#
+# Revision 1.10 2004/06/27 20:18:14 gmwalter
+# Fixed xspc/xtics bug in vecplot, added
+# character-based field width option to
+# pgugrid.py.
+#
+# Revision 1.9 2004/03/23 18:08:25 gmwalter
+# Add another variant to pgugrid and update
+# comments; update shapesgrid tool to start
+# editing on single left click.
+#
+# Revision 1.8 2004/01/19 18:46:35 gmwalter
+# Add checks for None in _get_data.
+#
+# Revision 1.7 2004/01/14 19:55:46 gmwalter
+# Fixes for empty source list.
+#
+# Revision 1.6 2004/01/13 20:53:36 gmwalter
+# Fix typo.
+#
+# Revision 1.5 2004/01/08 22:33:07 gmwalter
+# Minor fixes for column text justification
+# and data type checking.
+#
+# Revision 1.4 2004/01/08 21:55:41 gmwalter
+# Add ability to delete rows (backspace
+# or delete key) and to force a column
+# to be a particular width.
+#
+# Revision 1.3 2004/01/07 22:44:46 gmwalter
+# Add text justification settings to set_source, add
+# tuples/lists of integers or floats or complex
+# or strings to allowable sources.
+#
+# Revision 1.2 2003/11/19 16:46:55 gmwalter
+# Checked into main branch.
+#
+#
+
+# To do soon:
+# - Simplify default window startup
+#
+#
+# To do later (maybe):
+# - Ability to dump entire or visible grid to printer or file
+# - column resizing
+# - row and column title user configuration
+# - per-row editability options (some rows deletable/changeable, some not)
+# - data input checking (may need to be externally influenced)
+# - add up/down/left/right arrow actions.
+
+# NOTE: This grid has to simulate double click behaviour by tracking the
+# last clicked row/column/cell because on windows a) the gtk double click
+# event is not sent out if the callback on the single click event is too
+# long (this can happen for row selection when there are a large number
+# of shapes- on the order of 50000- and the expose event demands a lot
+# of the cpu),
+# and b) even if the double click event is sent out, the associated
+# single press events are sent out in different orders on windows than
+# they are on linux/unix. The sequence of events sent out for a double
+# click is as follows:
+# linux/unix: BUTTON_PRESS, BUTTON_PRESS, _2BUTTON_PRESS
+# windows: BUTTON_PRESS, BUTTON_PRESS (if single press callback is too long)
+# BUTTON_PRESS, _2BUTTON_PRESS, BUTTON_PRESS
+#
+# GTK's double click behaviour is reasonable for linux/unix, but for
+# consistency the approach for all platforms has been to treat the
+# double click event as a single click event and track the last
+# clicked cell/row/column internally. Internally, the grid only uses the
+# simulated double click event to launch cell editing.
+#
+# The better alternative would be to fix gtk itself for windows, but this
+# could be complicated and would require new users to build a special
+# version of gtk for windows...
+#
+# THIS SHOULD BE REVISITED IF OPENEV IS UPGRADED TO GTK2, AS GTK2 MAY
+# NOT SUFFER THESE PROBLEMS.
+
+import gtk
+import gvsignaler
+import Numeric
+import gview
+import gvutils
+import string
+
+
+# Allowable data sources for pgugrid
+SRC_NONE=0 # no source
+SRC_NUMERIC=1 # 2 dimensional python array
+SRC_SHAPES=2 # Shapes
+SRC_SHAPESLAYER=3 # Shapes layer (layer selection follows grid's)
+SRC_LISTLIST=4 # List of lists
+SRC_LISTOBJ=5 # List of objects
+SRC_LISTUNDEF=6 # Empty list (will be updated with either lists or objects)
+
+# scrollbar sizes
+SCROLL_DIM1=18
+SCROLL_DIM2=45
+
+# Internal supporting classes
+class _column_info:
+ """ Class to manage display-related information for
+ a single column in the pgugrid.
+
+ Members:
+
+ member- Reference to the source being displayed:
+ SRC_NUMERIC- data column
+ SRC_SHAPES- property name
+ SRC_SHAPESLAYER- property name
+ SRC_LISTLIST- index within sub list
+ SRC_LISTOBJ- variable name within object
+
+ title- Column display title.
+
+ type- type of value: 'string','integer','float', or 'complex'.
+
+ format- a string to indicate how values should be
+ displayed in the column. Format string also
+ determines text justification (left, right,
+ or center) within the cell
+
+ editable- editable status of the column. Indicates
+ whether or not the values in the column
+ can be changed other than row addition/
+ deletion.
+ 0- not editable
+ 1- editable
+
+ Note: The editability of a given cell is determined by
+ the intersection of the column and row editability
+ parameters. Add/delete is determined entirely
+ by the row add/delete settings. The contents of
+ the cell can only be altered (aside from add/delete)
+ if both the row and the column permit change.
+ Editable status of rows can currently only be set
+ on the grid as a whole, not per-row (though
+ this may be added later). Row editability
+ follows these rules:
+ 0- not editable (000)
+ 1- rows can be deleted, but not added/changed (001)
+ 2- rows can be added, but not deleted/changed (010)
+ 4- rows can be changed, but not deleted/added (100)
+ 3- rows can be deleted/added, but not changed (011)
+ 5- rows can be changed or deleted, but not added (101)
+ 6- rows can be changed or added, but not deleted (110)
+ 7- rows can be changed and added/deleted (111)
+
+
+ nodata- string to display if no data is available
+
+ width- width of the column
+
+ start_x- x location of top left corner of column header
+
+ justification- text justification in the column: 0
+ for right, 1 for left, 2 for center.
+
+ title_justification- text justification of column title: 0
+ for right, 1 for left, 2 for center.
+
+ force_width- force a column to be a particular width.
+
+ force_width_chars- force a column to be a particular number
+ of characters wide. If active, will overwrite
+ force_width with force_width_chars * maximum
+ character width for the current font. Set
+ to -1 to inactivate, or an integer >= 0
+ corresponding to number of characters
+ to allow to activate. Defaults to -1.
+
+ entry_chars- number of characters to allow user to type
+ (only relevant if column is editable). 90
+ by default.
+
+
+
+
+ """
+ def __init__(self,member,title,type,format=None,editable=0,
+ nodata='',width=0,start_x=0,justification=0,
+ title_justification=2,force_width=None,
+ force_width_chars=-1, entry_chars=0):
+
+ self.title=title
+ self.member=member
+ self.type=type
+ self.format=format
+ self.editable=editable
+ self.nodata=nodata
+ self.width=width
+ self.start_x=start_x
+ self.justification=justification
+ self.title_justification=title_justification
+ # force_width is used to limit a column's width
+ # width for display (set to None to auto-choose).
+ self.force_width=force_width
+ self.force_width_chars=force_width_chars
+ self.entry_chars=entry_chars
+
+
+
+# Configurable events that grid can respond to
+
+
+# Cell area has been clicked on
+_cell_clickevents=('cell-left','cell-shift-left','cell-ctrl-left',\
+ 'cell-double-left','cell-right',\
+ 'cell-shift-right','cell-ctrl-right',\
+ 'cell-double-right')
+
+# Row title has been clicked on
+_row_clickevents=('row-left','row-shift-left','row-ctrl-left',\
+ 'row-double-left','row-right','row-shift-right',\
+ 'row-ctrl-right','row-double-right')
+
+# Column title has been clicked on
+_column_clickevents=('column-left','column-shift-left','column-ctrl-left',\
+ 'column-double-left','column-right','column-shift-right',\
+ 'column-ctrl-right','column-double-right')
+
+_cell_keyevents=()
+
+
+_row_select=[(),\
+ ('select-single-row','unselect-single-row','toggle-single-row'),\
+ ('select-single-row','unselect-single-row','toggle-single-row',\
+ 'toggle-block-rows','toggle-multiple-rows','select-block-rows',
+ 'select-multiple-rows')]
+
+_cell_select=[(),\
+ ('select-single-cell','unselect-single-cell',\
+ 'toggle-single-cell'),\
+ ('select-single-cell','unselect-single-cell',\
+ 'toggle-single-cell','toggle-block-cells',\
+ 'toggle-multiple-cells')]
+
+_column_select=[(),
+ ('select-single-column','unselect-single-column',\
+ 'toggle-single-column'),\
+ ('select-single-column','unselect-single-column',\
+ 'toggle-single-column','toggle-block-columns',\
+ 'toggle-multiple-columns','select-block-columns',
+ 'select-multiple-columns')]
+
+
+class _selection_info:
+ """Selection behaviour parameters:
+
+ Several parameters must be defined in order to indicate the selection
+ behaviour within the grid. Here, row selection refers to the selection
+ of an entire row or rows, column selection refers to the selection of
+ an entire column or columns, and cell selection refers to the
+ selection of a single or multiple individual cells. The possible
+ values of each are 0 (no selection), 1 (single selection), or
+ 2 (multiple selection). The combination parameters indicate whether
+ or not different types of selection can be present at the same time
+ For instance, setting the row-cell selection
+ parameter to 2 indicates that the last selected row can remain
+ selected while a cell within that row or another row is selected.
+ Setting it to 1 indicates that the last selected row can only remain
+ selected if the cell just selected is within that row. Setting it
+ to 0 indicates that the row will be unselected when a cell is
+ selected. Setting it to 3 indicates that selecting a cell should
+ force selection of that row if it is not already selected.
+ For row-column selection, the two are orthogonal, so only
+ 0 (rows/columns can't be selected at the same time) and
+ 1 (rows/columns can be selected at the same time) are available.
+
+ Note: a cell, row, or column must be selected in order to be
+ changed or deleted through the pgugrid.
+
+ 1) row selection- 0, 1, or 2
+ 2) column selection- 0, 1, or 2
+ 3) cell selection- 0, 1, or 2
+ 4) row-cell selection- 0, 1, 2, 3
+ 5) column-cell selection- 0, 1, 2, 3
+ 6) row-column selection- 0 or 1
+
+ Currently, this class just keeps track of which selection
+ actions should be permitted for a given selection configuration
+ (verified through the get_allowed_actions function).
+ """
+
+ def __init__(self,row_selection=1,column_selection=1,cell_selection=0,
+ row_cell=0, column_cell=0, row_column=0):
+
+ if row_selection not in [0,1,2]:
+ raise AttributeError,'row_selection must be 0, 1, or 2'
+
+ if cell_selection not in [0,1,2]:
+ raise AttributeError,'cell_selection must be 0, 1, or 2'
+
+ if column_selection not in [0,1,2]:
+ raise AttributeError,'column_selection must be 0, 1, or 2'
+
+ if row_cell not in [0,1,2,3]:
+ raise AttributeError,'row_cell must be 0, 1, 2, or 3'
+
+ if column_cell not in [0,1,2,3]:
+ raise AttributeError,'column_cell must be 0, 1, 2, or 3'
+
+ if row_column not in [0,1]:
+ raise AttributeError,'row_column must be 0 or 1'
+
+ self.row=row_selection
+ self.cell=cell_selection
+ self.column=column_selection
+ self.row_cell=row_cell
+ self.column_cell=column_cell
+ self.row_column=row_column
+
+ def get_allowed_actions(self):
+ select_actions=[]
+ for item in _row_select[self.row]:
+ select_actions.append(item)
+
+ for item in _cell_select[self.cell]:
+ select_actions.append(item)
+
+ for item in _column_select[self.column]:
+ select_actions.append(item)
+
+ return select_actions
+
+
+class _pgugrid_options:
+
+ """Class to set up pgugrid configuration.
+ Stores whether or not row and column titles will be shown,
+ and configures event mapping within the grid.
+ Input parameter is a tuple of 9 values indicating configuration
+ information.
+
+ NOTE 1: These parameters control selection through clicking on the grid.
+ In cases where selection can be done from outside (eg.
+ shapes layer through selection tool, or by directly calling
+ a grid function), it is the responsibility of the calling
+ application to ensure that selection consistency is maintained.
+ For instance, if row selection is single, the layer's
+ selection mode (for select tool) should also be set to
+ single; otherwise the grid may end up with multiple
+ selected rows (it stays consistent with the layer selection
+ regardless of parameter settings).
+
+ NOTE 2: NOT ALL CONFIGURATIONS HAVE BEEN IMPLEMENTED/TESTED YET,
+ AND SOME MAY NOT BE IMPLEMENTED EVER.
+
+ SUPPORTED/VALID CONFIGURATIONS:
+
+ Parameter: 0 1 2 3 4 5 6 7
+
+ 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0
+ 1 4
+ 2
+
+ 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0
+ 1 1 4 1
+ 2 2 2
+
+ 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0
+ 1 1 4
+ 2 2
+
+ 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0
+ 1 1 1 4 1
+ 2 2 2 2
+
+
+ 0 - 1 - 0 - 1 - 0 - 3 - 0 - 0
+ 1 4
+ 2
+ 3
+
+ 0 - 2 - 0 - 2 - 0 - 3 - 0 - 0
+ 1 4
+ 2
+ 3
+
+
+ Parameters:
+
+ [0]: Row/Column titles
+
+ 0- no row or column titles
+ 1- row titles only
+ 2- column titles only
+ 3- row and column titles
+
+ [1]: Row selection mode
+
+ 0- rows may not be selected
+
+ If row titles are present:
+ 1- rows may be singly selected
+ 2- multiple rows may be selected
+
+ [2]: Column selection mode
+
+ 0- columns may not be selected
+
+ If column titles are present:
+ 1- columns may be singly selected
+ 2- multiple columns may be selected
+
+ [3]: Cell selection mode
+
+ 0- cells may not be selected
+ 1- cells may be singly selected
+ 2- cells may be multiply selected
+
+ [4]: Row editability
+
+ 0- rows are not editable (000)
+ 1- rows can be deleted, but not added/changed (001)
+ 2- rows can be added, but not deleted/changed (010)
+ 4- rows can be changed, but not deleted/added (100)
+ 3- rows can be deleted/added, but not changed (011)
+ 5- rows can be changed or deleted, but not added (101)
+ 6- rows can be changed or added, but not deleted (110)
+ 7- rows can be changed and added/deleted (111)
+
+ Note: column editability is set by the user using define_columns
+ (if user doesn't set it, defaults are used).
+
+
+ [5]: Row/Cell cross selection behaviour
+
+ 0- rows and cells may not remain simultaneously selected
+ 1- rows and cells can remain selected if the selected cell
+ is in the selected row
+ 2- rows and cells can remain selected simultaneously even
+ if the cell isn't in the row
+ 3- selecting a cell forces selection of that row, clearing
+ rows that do not contain selected cells, and vice versa
+ (row selection is synchronized with cell selection).
+ NOTE: IN THIS MODE, LEFT CLICKING A CELL TOGGLES ITS
+ SELECTION STATE RATHER THAN ALWAYS FORCING IT TO BE
+ SELECTED IF THE EDITING PARAMETER IS TURNED OFF.
+
+ [6]: Column/Cell cross selection behaviour
+
+ 0- columns and cells may not remain simultaneously selected
+ 1- columns and cells can remain selected if the selected cell
+ is in the selected column
+ 2- columns and cells can remain selected simultaneously even
+ if the cell isn't in the column
+ 3- selecting a cell forces selection of that column, clearing
+ columns that do not contain selected cells. Note:
+ in this case cell selection parameter is ignored (when
+ a column is selected, all cells in that column are selected).
+
+ [7]: Row/Column cross selection behaviour
+
+ 0- rows and columns may not remain simultaneously selected
+ 1- rows and columns may be simultaneously selected
+
+ [8] Variant parameter. Used to do slight variations on the above
+ configuration parameters (eg. turning column sorting on/off,
+ alterations to which events trigger selection/editing etc.,
+ turning off grid lines). ALL variants must be documented here:
+
+ 0 or None: No variation
+ 1,3,...: No column sorting (note: some configurations don't anyway)
+ 2,3,5,6,..: For configurations where cells are editable and cell
+ selection does not trigger row selection, have cell editing
+ trigger on double left click rather than single click.
+ IE. This only has an effect if config[5] is not 3, and
+ config[4] is one of 4,5,6, or 7.
+ 4,5,...: For configurations where row and/or column selection
+ is enabled, unselection using a second click is disabled
+ (it just triggers selection again).
+
+ Variant parameter= (column sorting off)*1 +
+ (start editing on double left click)*2 +
+ (second click unselects)*4
+
+ Input parameters: configuration
+
+ Valid options for configuration:
+
+ - click events:
+
+ Row selection (if enabled): NOTE: REQUIRES THAT ROW TITLES
+ BE PRESENT!
+ single left click on a row title- toggle row's selection
+
+ shift left click on row title-
+ multiple consecutive row selection
+
+ control left click on row title-
+ multiple nonconsecutive row selection
+
+ control right click on row title- If the source is a
+ shapes layer, translate the view to that row and
+ add that row to the current selection if possible
+ (clear other selections if only single selection
+ is enabled).
+
+ Cell selection (if enabled):
+ if self.config[5] is 3:
+
+ control right click on cell- If the source is a
+ shapes layer, translate the view to that row and
+ add that row to the current selection if possible
+ (clear other selections if only single selection
+ is enabled).
+
+ if self.config[5] is not 3:
+
+ single left click a cell- select a cell. If self.config[4] is
+ in [4,5,6,7], enable cell editing if
+ appropriate. Press escape or select another
+ cell to unselect (and stop editing, if
+ editing).
+
+ if self.config[5] is 3 and self.config[4] is not in
+ [4,5,6,7]:
+ single left click a cell- toggle a cell/row's selection.
+
+
+ Column selection (if enabled): NOTE: REQUIRES THAT COLUMN TITLES
+ BE PRESENT!
+
+ single left click on column title- toggle column's selection
+
+ shift left click on column title-
+ multiple consecutive column selection
+
+ control left click on column title-
+ multiple nonconsecutive column selection
+
+ Cell editing (if enabled):
+
+ left clicking a cell-
+ Start cell editing.
+ Pressing Enter or Tab, or selecting
+ another cell will finish editing
+ and store the changes. Enter will
+ finish by unselecting the cell
+ and selecting the next one down
+ in the column for editting.
+ Tab will finish by unselecting the
+ cell and selecting the one in the
+ next column for editting. Pressing
+ Escape will exit editing mode, clear
+ the cell selection, and cancel the
+ changes.
+
+ If Variant parameter is 2, 3,
+ 5, 6, ... etc., start editing on double
+ left click rather than single click
+ (single click will just select).
+
+ Other behaviours:
+ alt left click on table- if the source is SRC_SHAPESLAYER,
+ recenter the view on the selected
+ shape.
+
+ single right click on column title- sort by the values in
+ that column (reverse at
+ each click)
+
+
+ arrow keys: (NOT IMPLEMENTED YET)
+ up/down:
+ - if a single row is selected, move the selected row up/down
+ - if a cell is selected, unselect the cell, move up/down,
+ and select the next cell. If the cell is being edited,
+ store the changes before unselecting and moving on, and
+ select the next cell for editing as well.
+
+ right/left:
+ - if a cell is selected, unselect the cell, move right/left,
+ and select the next cell.
+ - if a cell is selected and being edited, move right/left
+ within the entry.
+
+ Note on row-cell selection behaviour (column-cell is analogous):
+
+ row-cell row selected cell selected
+ parameter
+
+ 0 unselect all cells, unselect all rows
+ cancel cell editing
+
+ 1 unselect all cells unselect all rows that
+ not in a selected don't contain a
+ row, cancel cell selected cell
+ editing if edited cell
+ is unselected
+
+ 2 no effect on cells no effect on rows
+
+ 3 select first cell in add cell's row to selected
+ the row if no cell in row list
+ that row is selected yet
+
+
+ row-cell row unselected cell unselected
+ parameter
+
+ 0 no effect on cells no effect on rows
+
+ 1 if # rows is still if # cells is still
+ > 0, unselect any > 0, unselect any
+ cells in the unselected rows that don't
+ row and cancel cell contain a selected
+ editing of unselected cell
+ cells
+
+ 2 no effect on cells no effect on rows
+
+ 3 unselect all selected unselect that row
+ cells in that row if no selected cells
+ remain in the row
+
+
+ """
+
+ def __init__(self,configuration=None):
+
+ # Set defaults where user has not specified anything
+ cfg_defaults=(2,2,0,0,0,2,0,0,0)
+ if configuration is None:
+ configuration=cfg_defaults
+ else:
+ cfg=[]
+ for idx in range(9):
+ if len(configuration) <= idx:
+ cfg.append(cfg_defaults[idx])
+ elif configuration[idx] is None:
+ cfg.append(cfg_defaults[idx])
+ else:
+ cfg.append(configuration[idx])
+
+ configuration=tuple(cfg)
+
+ self.config=configuration
+
+ # Check configuration
+ _ranges=[]
+ _ranges.append([0,1,2,3])
+ _ranges.append([0,1,2])
+ _ranges.append([0,1,2])
+ _ranges.append([0,1,2])
+ _ranges.append([0,1,2,3,4,5,6,7])
+ _ranges.append([0,1,2,3])
+ _ranges.append([0,1,2,3])
+ _ranges.append([0,1])
+ _names=['display','row select','column select','cell select','edit',
+ 'row-cell cross selection','column-cell cross selection',
+ 'row-column cross selection']
+
+ _invalid=[(0,None,1,None,None,None,None,None),
+ (0,None,2,None,None,None,None,None)]
+
+ for idx in range(len(_ranges)):
+ if self.config[idx] not in _ranges[idx]:
+ txt="_pgugrid_options: invalid configuration specification"+\
+ ".\nValid ranges are (0-3,0-2,0-2,0-2,0-7,0-3,0-3,0-1)."
+ raise AttributeError,txt
+
+ for cfgtype in _invalid:
+ matches=0
+ idx=0
+ for item in cfgtype:
+ if item is None:
+ matches=matches+1
+ elif item == self.config[idx]:
+ matches=matches+1
+ idx=idx+1
+ if matches == 8:
+ txt="_pgugrid_options: invalid configuration combination.\n"
+ idx=0
+ for item in cfgtype:
+ if item is not None:
+ txt=txt+_names[idx]+": "+str(self.config[idx])+"\n"
+ raise AttributeError,txt
+
+ self.events={}
+ self._allowed_events=[]
+
+ for item in _cell_clickevents:
+ self._allowed_events.append(item)
+
+ for item in _cell_keyevents:
+ self._allowed_events.append(item)
+
+ # row title type: only used if row titles are shown
+ # Should be 'grid' to show grid row, 'source' to show
+ # underlying source index.
+
+ self.row_title_type = 'grid'
+
+ if self.config[0] in [1,3]:
+ self.show_row_titles=1
+ for item in _row_clickevents:
+ self._allowed_events.append(item)
+ else:
+ self.show_row_titles=0
+
+ if self.config[0] in [2,3]:
+ self.show_column_titles=1
+ for item in _column_clickevents:
+ self._allowed_events.append(item)
+ else:
+ self.show_column_titles=0
+
+ self._set_selection_info()
+ self._set_event_mapping()
+
+ def set_row_title_type(self,type):
+ """Define whether row titles should reflect grid
+ row number, or underlying source index.
+ Parameters:
+ type- either 'grid' (to show grid row) or
+ 'source' (to show source row index) or
+ 'user-defined' (user specifies row titles
+ as a list).
+ """
+ if type not in ['grid','source','user-defined']:
+ raise AttributeError,"_pgugrid_options: row title type must be "+\
+ "either 'grid' or 'source'"
+
+ self.row_title_type = type
+
+ def _set_selection_info(self):
+ s1=self.config[1]
+ s2=self.config[2]
+ s3=self.config[3]
+ s4=self.config[5]
+ s5=self.config[6]
+ s6=self.config[7]
+ self.selection_info=_selection_info(s1,s2,s3,s4,s5,s6)
+
+ def _extract_variant_options(self):
+ """ Extract the variant parameters and return a tuple
+ of which ones are turned on (0 if they're off,
+ 1 if they're on:
+ (column sorting, editing starts on single left click,
+ second click unselects)
+ """
+ leftover = self.config[8]
+ if (leftover >= 4):
+ par2 = 1
+ leftover = leftover - 4
+ else:
+ par2 = 0
+
+ if (leftover >= 2):
+ par1 = 1
+ leftover = leftover - 2
+ else:
+ par1 = 0
+
+ par0 = leftover
+
+ return (par0, par1, par2)
+
+ def _set_event_mapping(self):
+ """Map events onto behaviours."""
+
+ # NOTE: the setting of some events to both double and single
+ # clicks is because of the hacky way double clicks are detected
+ # here (two consecutive clicks on the same thing any time
+ # apart) because of problems on windows. These ensure that
+ # single click events behave okay, but still allows user have
+ # a pseudo-double click event. NEEDS TO BE FIXED UP!!!
+ vopts = self._extract_variant_options()
+ # row selection
+ if self.show_row_titles == 1:
+ if self.selection_info.row > 0:
+ if vopts[2] == 1:
+ self.events['row-left']='select-single-row'
+ self.events['row-double-left']='select-single-row'
+ else:
+ self.events['row-left']='toggle-single-row'
+ self.events['row-double-left']='toggle-single-row'
+ self.events['row-ctrl-right']='translate-view-to-row'
+ if self.selection_info.row > 1:
+ if vopts[2] == 1:
+ self.events['row-shift-left']='select-block-rows'
+ self.events['row-ctrl-left']='select-multiple-rows'
+ else:
+ self.events['row-shift-left']='toggle-block-rows'
+ self.events['row-ctrl-left']='toggle-multiple-rows'
+
+ # column sorting and selection
+ if ((self.show_column_titles == 1) and
+ (vopts[0] == 0)):
+ self.events['column-right']='toggle-sort-by-column'
+ self.events['column-double-right']='toggle-sort-by-column'
+
+ if self.selection_info.column > 0:
+ if vopts[2] == 1:
+ self.events['column-left']='select-single-column'
+ self.events['column-double-left']='select-single-column'
+ else:
+ self.events['column-left']='toggle-single-column'
+ self.events['column-double-left']='toggle-single-column'
+
+ if self.selection_info.column > 1:
+ if vopts[2] == 1:
+ self.events['column-shift-left']='select-block-columns'
+ self.events['column-ctrl-left']='select-multiple-columns'
+ else:
+ self.events['column-shift-left']='toggle-block-columns'
+ self.events['column-ctrl-left']='toggle-multiple-columns'
+
+ # cell selection and editing
+ if self.selection_info.cell > 0:
+ if self.config[5] == 3:
+ if self.config[4] in [4,5,6,7]:
+ self.events['cell-left']='select-single-cell'
+ self.events['cell-double-left']='start-cell-edit'
+ else:
+ if vopts[2] == 1:
+ self.events['cell-left']='select-single-cell'
+ self.events['cell-double-left']='select-single-cell'
+ else:
+ self.events['cell-left']='toggle-single-cell'
+ self.events['cell-double-left']='toggle-single-cell'
+ self.events['cell-ctrl-right']='translate-view-to-row'
+ else:
+ if vopts[1] == 1:
+ self.events['cell-left']='select-single-cell'
+ if self.config[4] in [4,5,6,7]:
+ # Note: cell editing function needs to check that
+ # column is editable before altering anything.
+ self.events['cell-double-left']='start-cell-edit'
+ else:
+ if self.config[4] in [4,5,6,7]:
+ # Note: cell editing function needs to check that
+ # column is editable before altering anything.
+ self.events['cell-left']='start-cell-edit'
+ else:
+ self.events['cell-left']='select-single-cell'
+
+ if self.selection_info.cell > 1:
+ self.events['cell-shift-left']='toggle-block-cells'
+ self.events['cell-ctrl-left']='toggle-multiple-cells'
+
+
+ # The remaining code in this function is used to
+ # validate a new configuration.
+ # It can be commented out for run-time.
+
+ # get allowable selection actions
+ allowed=self.selection_info.get_allowed_actions()
+
+ # sorting columns is always permitted
+ allowed.extend(['sort-by-column','reverse-sort-by-column',
+ 'toggle-sort-by-column'])
+
+ allowed.extend(['translate-view-to-row'])
+
+ # edit-related actions
+ if self.config[4] in [4,5,6,7]:
+ allowed.extend(['start-cell-edit'])
+
+ # check that this configuration does not define
+ # invalid actions (eg. editing in non-editable grid)
+ for action in self.events.values():
+ if action not in allowed:
+ raise 'Invalid action mapping in pgugrid configuration'
+
+ # check that configuration doesn't define callbacks
+ # for events that won't happen
+ for cevent in self.events.keys():
+ if cevent not in self._allowed_events:
+ raise 'Invalid event in pgugrid configuration'
+
+# Grid
+class pguGrid(gtk.GtkHBox,gvsignaler.Signaler):
+ def __init__(self,config):
+ """ Class to create a tabular display grid.
+
+ Parameters:
+ config- configuration to use (controls
+ whether row and column titles
+ are displayed, and how rows
+ and columns can be selected).
+ See _pgugrid_options class
+ documentation for more.
+ """
+
+ #gtk.GtkTable.__init__(self,rows=2,cols=3)
+ gtk.GtkHBox.__init__(self)
+ self.set_spacing(0)
+ self.vshell = gtk.GtkVBox()
+ self.vshell.set_spacing(0)
+ self.pack_start(self.vshell)
+
+
+ self.opts=_pgugrid_options(config)
+ self._ColumnDefs=[]
+
+ # GUI setup
+
+ # default style
+ self.default_style = None
+ self.default_style_reset_flag = 0
+ self.default_row_title_style = None
+ self.default_row_title_style_reset_flag = 0
+ self.default_col_title_style = None
+ self.default_col_title_style_reset_flag = 0
+
+ #add flag for numeric range check
+ self.doRangeCheck = False
+ self.numericRange = None
+
+ self.draw_row_lines = 2
+ self.draw_col_lines = 2
+
+ #fonts for drawing titles and cells put here
+ self.title_font = None
+ self.cell_font = None
+
+ # Message to display when there is no data
+ self.empty_msg= "NO DATA TO DISPLAY"
+
+ # The height of a single row (not including the
+ # line between rows) and column title row (if present),
+ # width of row titles column (if present). These
+ # get reset in configure.
+ self.row_height = 0
+ self.column_title_height=0
+ self.row_title_width = 0
+
+ # padding between lines and text in cells
+ # (included in column width/row heights)
+ self.pad=4
+
+ # Build GUI
+ self.hadj = gtk.GtkAdjustment()
+ self.vadj = gtk.GtkAdjustment()
+
+ self._hscroll = gtk.GtkHScrollbar( adj = self.hadj )
+ self._vscroll = gtk.GtkVScrollbar( adj = self.vadj )
+ self.hsframe = gtk.GtkFrame()
+ self.hsframe.set_shadow_type(gtk.SHADOW_NONE)
+ self.vsframe = gtk.GtkFrame()
+ self.vsframe.set_shadow_type(gtk.SHADOW_NONE)
+ self.hsframe.add(self._hscroll)
+ self.vsframe.add(self._vscroll)
+ self.hscroll_shown=1
+ self.vscroll_shown=1
+ self.hscroll_policy = 0
+ self.vscroll_policy = 0
+
+ self._area = gtk.GtkDrawingArea()
+ self._pixmap = None
+
+ #this mask also seems to enable scrolling???
+ evt_mask = gtk.GDK.BUTTON_PRESS_MASK | gtk.GDK.BUTTON_RELEASE_MASK | \
+ gtk.GDK.KEY_RELEASE_MASK | \
+ gtk.GDK.FOCUS_CHANGE_MASK | gtk.GDK.EXPOSURE_MASK
+ self._area.set_events( evt_mask )
+ self._area.set_flags( gtk.CAN_FOCUS | gtk.HAS_GRAB )
+
+ #flag to recalculate the adjustments
+ self.bCalcAdjustments = gtk.TRUE
+
+ #set to true if changing some value that would end up causing multiple
+ #expose events or an endless loop even.
+ self.updating = gtk.FALSE
+
+ #frm = gtk.GtkFrame()
+ #frm.set_shadow_type(gtk.SHADOW_ETCHED_OUT)
+ #frm.add(self._area)
+ self._area.set_usize(300,400)
+
+ self._layout=gtk.GtkLayout()
+ self._layout.put(self._area,0,0)
+ self._layout.show_all()
+
+ #self.attach( frm, 0, 1, 0, 1,
+ # xoptions=gtk.FILL, yoptions=gtk.FILL )
+ self.vshell.pack_start(self._layout,expand=gtk.TRUE)
+ self.vshell.pack_start(self.hsframe,expand=gtk.FALSE)
+ self.pack_start(self.vsframe,expand=gtk.FALSE)
+ #self.attach( self._layout, 0, 1, 0, 1,
+ # xoptions=gtk.FILL, yoptions=gtk.FILL )
+ #self.attach( self._vscroll, 1, 2, 0, 1, xoptions=gtk.SHRINK)
+ #self.attach( self._hscroll, 0, 1, 1, 2, yoptions=gtk.SHRINK )
+
+ # floating editing entry box
+ self.editbox = gtk.GtkEntry()
+ self.editbox.connect( 'key_press_event', self.entry_key_press )
+ self.editbox.hide()
+
+ self.editing_cell=None
+
+
+ dw=300
+ dh=400
+ self.set_usize(dw,dh)
+
+ #self._layout=gtk.GtkLayout()
+ self._layout.put(self.editbox,5000,5000)
+ #self.add(self._layout)
+ self.show_all()
+
+ # Style list: used to colour rows. Initially
+ # empty except for default style placeholders
+ # (filled in upon first expose).
+ self.style_list=[None,None,None]
+
+ # new styles can't actually be added until expose.
+ # Use this to store info up until then
+ self.styles_to_add=None
+
+ # Initialize parameters relating to source displayed in grid
+ self._initialize_settings()
+
+ # User defined row titles (only used if row title type
+ # is reset to 'user-defined')
+ self.row_titles = []
+
+ # signals: Note that the right-click (button 3) event
+ # is a special case used internally to select cells for
+ # editing.
+ self.publish('row-selection-changed')
+ #self.publish('row-changed')
+ #self.publish('row-added')
+ self.publish('rows-deleted')
+ self.publish('cell-selection-changed')
+ self.publish('cell-changed')
+ self.publish('column-selection-changed')
+ #self.publish('column-changed')
+ #self.publish('column-added')
+ #self.publish('column-deleted')
+
+ # Pass on click events with grid row and column
+ # (-1 if title clicked)
+ self.publish('clicked')
+
+
+ self._area.connect( 'expose-event', self.expose )
+ self._area.connect( 'configure-event', self.configure )
+ self._area.connect( 'button-press-event', self.click )
+ self._area.connect( 'key_press_event', self.area_key_press )
+ self.hadj.connect( 'value-changed', self.changed )
+ self.vadj.connect( 'value-changed', self.changed )
+ self.connect( 'style-set', self.expose )
+ self.connect('size-allocate',self.size_allocate)
+
+
+ def reset_configuration(self,config):
+ """ Reset the grid configuration. """
+ self.opts=_pgugrid_options(config)
+
+ self._update_column_title_height()
+ self._update_row_title_width()
+
+ self.expose()
+
+
+ def set_empty_message(self,msg):
+ """ Set the message to display when there is no data. """
+ self.empty_msg=msg
+
+ def set_source(self,source,view=None,subset=None,members=None,titles=None,
+ editables=None,formats=None,types=None,nodata=None,
+ justify=None,title_justify=None,force_width=None,
+ force_width_chars=None, entry_chars=None, expose=0,
+ redefine_columns=1):
+ """ Set the source for the grid.
+ Note: for Numeric arrays, the
+ grid operates on a copy of the
+ source data. For all other
+ types, it operates on the
+ original.
+
+ Parameters:
+ source- one of:
+ a) 1 or 2-D Numeric python array
+ b) List of same-length lists
+ c) List of objects
+ d) GvShapes object
+ e) GvShapesLayer object (requires view)
+ f) None (to clear the grid or just show titles)
+
+ view- only supplied for GvShapesLayer
+
+ subset- subset to initialize the display with (a list of
+ source row indices). [optional]
+
+ members, titles, editables, formats, types,
+ nodata, justify, title_justify, force_width,
+ force_width_chars, entry_chars- initial defining
+ column information (see define_columns). [optional].
+
+ expose- whether or not to expose the grid immediately (1
+ to expose, 0 not to). Defaults to 0.
+
+ redefine_columns- set to 0 if column definitions should not
+ change (if it is 0, then members, titles,
+ etc. will be ignored). If this is set to
+ 0, it is the calling function's
+ responsibility to ensure that the columns
+ are still valid for the new source.
+ Defaults to 1.
+
+
+ """
+ if self.src is not None:
+ self.clear()
+
+ self.subset=subset
+ self.bCalcAdjustments = gtk.TRUE
+
+ if ((source is None) or
+ ((type(source) == type((1,))) and (len(source) == 0))):
+ # put tuples in with None rather than LISTUNDEF because
+ # a tuple cannot be updated, so an empty tuple is
+ # equivalent to None for display.
+ self.src=None
+ self.src_type=SRC_NONE
+ if redefine_columns == 1:
+ self._ColumnDefs=[]
+ if members is not None:
+ self.define_columns(members,titles,editables,formats,types,
+ nodata,justify,title_justify,force_width,
+ force_width_chars, entry_chars,
+ expose=0)
+ else:
+ # Reset g_columns to previous number
+ # of columns so titles are displayed
+ self.g_columns=len(self._ColumnDefs)
+ self._update_column_widths(expose=0)
+
+ if expose == 1:
+ self.expose()
+ return
+
+ if (type(source) == type([1,])) and (len(source) == 0):
+ self.src=source
+ self.src_type = SRC_LISTUNDEF
+ if redefine_columns == 1:
+ self._ColumnDefs=[]
+ if (members is not None):
+ self.define_columns(members,titles,editables,formats,types,
+ nodata,justify,title_justify,force_width,
+ force_width_chars, entry_chars,
+ expose=expose)
+ else:
+ # Reset g_cols to previous number
+ # of columns so titles are displayed
+ self.g_columns=len(self._ColumnDefs)
+ self._update_column_widths(expose=0)
+
+ if expose == 1:
+ self.expose()
+ return
+
+ if type(source) == type((1,)):
+ source=list(source)
+
+ if type(source) == type(Numeric.ones((4,4))):
+ shp=Numeric.shape(source)
+ if len(shp) == 1:
+ self.src=Numeric.reshape(source,(1,shp[0]))
+ elif len(shp) == 2:
+ self.src=source
+ else:
+ txt='pgugrid: only 1 or 2-D Numeric arrays are supported'
+ raise AttributeError,txt
+ self.src_type=SRC_NUMERIC
+ elif ((type(source) == type([])) and
+ (type(source[0]) == type([]))):
+ self.src=source
+ self.src_type=SRC_LISTLIST
+ elif ((type(source) == type([])) and
+ (type(source[0]) == type((1,)))):
+ osrc=source
+ source=[]
+ for nexttuple in osrc:
+ source.append(list(nexttuple))
+ self.src=source
+ self.src_type=SRC_LISTLIST
+ elif type(source) == type([]):
+ self.src=source
+ self.src_type=SRC_LISTOBJ
+ elif hasattr(source,'__len__'):
+ self.src=source
+ self.src_type=SRC_SHAPES
+ self.source_changed_id=self.src.connect('changed',
+ self.refresh)
+ else:
+ try:
+ self.src=source.get_parent()
+ self.src_type=SRC_SHAPESLAYER
+
+ self.source_changed_id=self.src.connect('changed',
+ self.refresh)
+ self.layer=source
+ self.layer_selection_changed_id = \
+ self.layer.connect('selection-changed',
+ self.layer_selection_cb)
+ self.layer_subselection_changed_id = \
+ self.layer.connect('subselection-changed',
+ self.layer_subselection_cb)
+ self.layer_teardown_id = \
+ self.layer.connect('teardown',self.clear_and_expose)
+
+ if view is None:
+ txt='pgugrid: if source is a shapeslayer, a viewarea\n'
+ txt=txt+'must be supplied.'
+ raise AttributeError,txt
+
+ self.view=view
+ except:
+ txt='pgugrid: source must be one of:\n'
+ txt=txt+'a) 1 or 2-D Numeric python array\n'
+ txt=txt+'b) List of same-length lists\n'
+ txt=txt+'c) List of objects with common elements\n'
+ txt=txt+'d) GvShapes object\n'
+ txt=txt+'e) GvShapesLayer object\n'
+ raise AttributeError,txt
+
+
+ if ((view is not None) and (self.src_type != SRC_SHAPESLAYER)):
+ txt='pgugrid: view updates are only supported for\n'
+ txt=txt+'the shapeslayer source datatype.'
+ raise AttributeError,txt
+
+
+ self._generate_row_indices()
+
+ if redefine_columns == 1:
+ self.define_columns(members,titles,editables,formats,types,
+ nodata,justify,title_justify,force_width,
+ force_width_chars, entry_chars,
+ expose=expose)
+ else:
+ self._update_column_widths(expose=expose)
+
+
+ if self.src_type == SRC_SHAPESLAYER:
+ # Make sure grid is initialized
+ # to proper selection settings
+ self.layer_selection_cb(self.layer)
+ self.layer_subselection_cb(self.layer)
+
+ def set_subset(self,indices=None,expose=1):
+ """ Only display a subset of the items in the
+ grid.
+
+ Parameters:
+ indices- a list of indices to source
+ for display. Set to None
+ to display all rows.
+
+ expose- 0 (do not redisplay grid) or
+ 1 (redisplay grid). Defaults
+ to 1.
+ """
+
+ if indices is not None:
+ # Store a copy of the list so it cannot
+ # be updated from outside
+ self.subset=list(indices)
+ else:
+ self.subset=None
+
+ self._generate_row_indices()
+
+ # clear any selections not in the current subset
+ if self.subset is not None:
+ usrows=[]
+ uscells=[]
+ for item in self.selected_rows:
+ if item not in self.subset:
+ usrows.append(item)
+ for cell in self.selected_cells:
+ if cell[0] not in self.subset:
+ uscells.append(cell)
+
+ if len(usrows) > 0:
+ self.unselect_rows(usrows,expose=0)
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ if len(uscells) > 0:
+ self.unselect_cells(uscells,expose=0)
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if expose == 1:
+ self.expose()
+
+ def get_selected_row_indices(self,*args):
+ return tuple(self.selected_rows)
+
+ def get_unselected_row_indices(self,*args):
+ unsel=1-self.row_selectstate
+ unselected=Numeric.compress(unsel > 0, Numeric.arange(len(unsel)))
+ return tuple(unselected)
+
+ def get_selected_column_indices(self,*args):
+ return tuple(self.selected_columns)
+
+ def get_unselected_column_indices(self,*args):
+ unsel=1-self.column_selectstate
+ unselected=Numeric.compress(unsel > 0, Numeric.arange(len(unsel)))
+ return tuple(unselected)
+
+ def get_selected_cell_indices(self,*args):
+ return tuple(self.selected_cells)
+
+ def get_source(self,*args):
+ """ Use to get the underlying source. This returns the
+ original source, not a copy, so should normally only be used
+ in read-only fashion.
+ """
+ return self.src
+
+ def start_cell_edit(self,cell):
+ """ Start editing new cell. """
+ if self.editing_cell is not None:
+ self.end_cell_edit()
+
+ if self._ColumnDefs[cell[1]].editable == 0:
+ # Column is not editable.
+ self.editing_cell=None
+ self._layout.move(self.editbox,5000,5000)
+ return
+
+ if self.opts.config[4] not in [4,5,6,7]:
+ # Rows are not changeable.
+ self.editing_cell=None
+ self._layout.move(self.editbox,5000,5000)
+ return
+
+ self.editing_cell=cell
+ self.reset_startrow(cell[0])
+ self.reset_startcolumn(cell[1])
+
+ # Make sure only currently edited cell is selected
+ if ((len(self.selected_cells) == 0) or
+ (len(self.selected_cells) > 1) or
+ (self.selected_cells[0][0] != cell[0]) or
+ (self.selected_cells[0][1] != cell[1])):
+ self.select_cell(cell,clearfirst=1,expose=1)
+
+ cwidth=self._ColumnDefs[cell[1]].width
+ self.editbox.set_usize(cwidth,self.row_height)
+ self.editbox.set_max_length(self._ColumnDefs[cell[1]].entry_chars)
+ self.editbox.set_text(self._get_datastr(cell[0],cell[1]))
+ self.editbox.set_position(len(self._get_datastr(cell[0],cell[1])))
+ locx=self._ColumnDefs[cell[1]].start_x-\
+ self._ColumnDefs[self.start_column].start_x+\
+ self.row_title_width+1
+ locy=self.column_title_height+2+\
+ ((self.src2row[cell[0]]-self.start_row)*(self.row_height+1))
+ if self.opts.show_row_titles == 1:
+ locy=locy+1
+
+ self._layout.move(self.editbox,locx,locy)
+
+ def cancel_cell_edit(self):
+ """ Cancel the current cell edit, not saving changes. """
+ self.editing_cell=None
+ self._layout.move(self.editbox,5000,5000)
+
+ def end_cell_edit(self):
+ """ End current cell edit, saving changes. """
+ if self.editing_cell is not None:
+ newval=self.editbox.get_text()
+ # TO DO: type checking (probably in set datastr itself though)
+ self._set_datastr(self.editing_cell[0],self.editing_cell[1],newval)
+ self.notify('cell-changed',tuple(self.editing_cell))
+
+ self.editing_cell=None
+ self._layout.move(self.editbox,5000,5000)
+
+ def entry_key_press(self,entry,event):
+ """ Edit box had a key press event. If enter was pressed,
+ save changes to source and go on to next cell down (if
+ there is one). If tab was pressed, save and go on to next
+ cell across. If escape was pressed, cancel cell editing without
+ saving changes.
+ """
+
+ # If a key was pressed, clear the information used
+ # to detect "double" click (hack- see info in _initialize_settings
+ # function)
+ self.last_click_cell=None
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+ # End of hack
+
+ if self.editing_cell is None:
+ return
+
+ if event.keyval == gtk.GDK.Return:
+ last_cell=self.editing_cell
+ self.end_cell_edit()
+ next_cell=(self.src2row[last_cell[0]]+1,last_cell[1])
+ if next_cell[0] < len(self.row2src):
+ next_cell=(self.row2src[next_cell[0]],last_cell[1])
+ self.start_cell_edit(next_cell)
+ else:
+ self.unselect_all_cells()
+ self._area.grab_focus()
+ elif event.keyval == gtk.GDK.Tab:
+ last_cell=self.editing_cell
+ self.end_cell_edit()
+ next_cell=(last_cell[0],last_cell[1]+1)
+ if next_cell[1] >= len(self._ColumnDefs):
+ n_row=self.src2row[last_cell[0]]+1
+ if n_row >= len(self.row2src):
+ next_row=self.row2src[0]
+ else:
+ next_row=self.row2src[n_row]
+ next_cell=(next_row,0)
+
+ if self._ColumnDefs[next_cell[1]].editable == 1:
+ self.start_cell_edit(next_cell)
+ else:
+ self.unselect_all_cells()
+
+ # This next line avoids the next tab
+ # being treated as part of the text
+ # on alternate tabs (ie. jumping
+ # from start to end within text
+ # rather than resetting the
+ # editable cell
+ self._area.grab_focus()
+
+ elif event.keyval == gtk.GDK.Escape:
+ self.cancel_cell_edit()
+ self.unselect_all_cells()
+ self._area.grab_focus()
+
+ def area_key_press(self,area,event):
+ """ If escape is pressed, clear all current cell selections
+ and cancel any editing."""
+ # If a key was pressed, clear the information used
+ # to detect "double" click (hack- see info in _initialize_settings
+ # function)
+ self.last_click_cell=None
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+ # End of hack
+
+ if event.keyval == gtk.GDK.Escape:
+ self.cancel_cell_edit()
+ self.unselect_all_cells()
+ elif ((event.keyval == gtk.GDK.BackSpace) or
+ (event.keyval == gtk.GDK.Delete)):
+ if self.opts.config[4] in [1,3,5,7]:
+ # row deletion supported by configuration
+ rows=self.get_selected_row_indices()
+ if len(rows) > 0:
+ self.delete_rows(rows)
+
+ def _generate_row_indices(self):
+
+ """ Create row index mappings.
+ Source and grid are both indexed
+ from 0. Initially, all non-None source rows
+ are displayed. If a subset is specified,
+ row2src will be subset minus any None's
+ contained within the subset list. Otherwise,
+ row2src will map all non-None rows of source
+ onto the grid.
+ """
+
+ # TO DO: Incorporate sorting property, select logic
+ # (want to retain selections where possible)
+ self.src2row=[]
+ self.row2src=[]
+
+ if self.src_type in [SRC_NONE,SRC_LISTUNDEF]:
+ return
+
+ if self.src_type == SRC_NUMERIC:
+ # Numeric arrays don't have rows of None
+ if self.subset is None:
+ self.src2row=range(Numeric.shape(self.src)[0])
+ self.row2src=range(Numeric.shape(self.src)[0])
+ else:
+ grididx=0
+ for idx in range(Numeric.shape(self.src)[0]):
+ if idx in self.subset:
+ self.src2row.append(grididx)
+ grididx=grididx+1
+ self.row2src.append(idx)
+ else:
+ self.src2row.append(-1)
+
+ else:
+ if self.subset is None:
+ grididx=0
+ for idx in range(len(self.src)):
+ if self.src[idx] != None:
+ self.src2row.append(grididx)
+ grididx=grididx+1
+ self.row2src.append(idx)
+ else:
+ self.src2row.append(-2)
+ else:
+ grididx=0
+ for idx in range(len(self.src)):
+ if idx in self.subset:
+ if self.src[idx] is None:
+ self.src2row.append(-2)
+ else:
+ self.src2row.append(grididx)
+ grididx=grididx+1
+ self.row2src.append(idx)
+ elif self.src[idx] != None:
+ # row is not None, but it
+ # isn't in subset
+ self.src2row.append(-1)
+ else:
+ self.src2row.append(-2)
+
+ self.s_rows=len(self.src2row)
+ self.g_rows=len(self.row2src)
+
+ # If selection state has not been specified, initialize
+ # to zeros. If selection state has been specified and
+ # source is the same length as before,
+ # leave select state alone. Otherwise,
+ # reset row and cell matrices.
+ if ((self.row_selectstate is None) or
+ (len(self.row_selectstate) != self.s_rows)):
+ self.row_selectstate=Numeric.zeros((self.s_rows,))
+ self.cell_selectstate=Numeric.zeros((self.s_rows,self.g_columns))
+ self.last_selected_row=None
+ self.last_toggled_row=None
+ self.last_selected_cell=None
+ self.last_toggled_cell=None
+
+ # If a sort column has been specified, do sorting
+ if self.sort_column != -1:
+ self.sort_by_column()
+
+ if self.last_selected_row is not None:
+ self.reset_startrow(self.last_selected_row)
+
+ self._update_row_title_width()
+
+ # Row colouring:
+ # If no style index exists already, initialize
+ # all rows to the default style.
+ #
+ # If the source is a shapes or shapes layer
+ # object and a row style index exists that is
+ # less than the length of the length of the
+ # source, some rows have been added to the end
+ # of the source (new shapes are always appended
+ # to gvshapes; there are no functions for
+ # inserting) so keep the existing row colours
+ # the same and add more of the default colour
+ # to the end (shapes are always appended).
+ # In the shapes/shapeslayer cases, the rows of the
+ # source are just set to None when they are
+ # deleted, and the list only shrinks if the
+ # last shape is deleted (it shrinks until it
+ # encounters a non-None shape). This means that
+ # if the row style index is longer than the source,
+ # the row style index will still be valid for the
+ # length of the source, and can just be truncated.
+ #
+ # For all the other types of objects (lists, tuples,
+ # arrays), no assumptions can be made about how to
+ # update the row style index if its length differs
+ # from that of the source because rows can be
+ # deleted/inserted at any point. In these cases,
+ # the row style index will be reset to the default
+ # values for the length of the source if the two
+ # differ in length; if they are the same, the
+ # colours are left alone. For these objects,
+ # internal pgugrid functions such as delete_rows
+ # should update the style list appropriately before
+ # the row indices are regenerated so that
+ # colours are maintained; if the source is updated
+ # externally, the colours will be reset to the
+ # default.
+ if self.src_type in [SRC_SHAPES,SRC_SHAPESLAYER]:
+ if (self.row_style_index is None):
+ self.row_style_index=Numeric.zeros((self.s_rows,))
+ elif (len(self.row_style_index) > self.s_rows):
+ self.row_style_index=self.row_style_index[:self.s_rows]
+ elif (len(self.row_style_index) < self.s_rows):
+ temp=self.row_style_index
+ self.row_style_index=Numeric.zeros((self.s_rows,))
+ self.row_style_index[:len(temp)]=temp
+ else:
+ if ((self.row_style_index is None) or
+ (len(self.row_style_index) != self.s_rows)):
+ self.row_style_index=Numeric.zeros((self.s_rows,))
+
+ # Below: if row title styles are set, add code here:
+
+ self.bCalcAdjustments=gtk.TRUE
+
+ def add_style(self,style_or_tuple):
+ """ Add a style to the list of styles available to
+ expose in the grid. style_or_tuple may be either
+ a GtkStyle, or a tuple consisting of
+ (bg_gc_normal,fg_gc_normal,bg_gc_selected,fg_gc_selected,
+ bg_gc_insensitive,fg_gc_insensitive),
+ where bg=background, fg=foreground. Not all
+ of these are used yet (may never be).
+ Currently, the grid only distinguishes between
+ selected and unselected rows and columns.
+ Cell selection colours follow the ROW selection
+ colours. If a row and column are simultaneously
+ selected, the column selection colours will override the
+ row selection colours.
+ Each of these entries should be either None
+ (then the default value is used) or a tuple
+ of 3 integer (0-65535) values.
+ Returns the index of the new style.
+ """
+
+ if type(style_or_tuple) == type(self.get_style()):
+ self.style_list.append(style_or_tuple.copy())
+ return len(self.style_list)-1
+ else:
+ # Style will be created at next expose (can't
+ # be created if no expose has taken place)
+ idx=len(self.style_list)
+ if self.styles_to_add is None:
+ self.styles_to_add=[]
+
+ self.styles_to_add.append((idx,style_or_tuple))
+ self.style_list.append(None)
+ return idx
+
+ def _add_style(self,cidx,ctuple):
+ """ Internal function that actually creates the requested
+ style.
+ """
+ if self.style_list[cidx] is None:
+ style=self.get_style()
+ else:
+ # use existing style for defaults if it is
+ # present
+ style = self.style_list[cidx]
+
+ nstyle=style.copy()
+ for idx in range(max(len(ctuple),6)):
+ item=ctuple[idx]
+ if item is None:
+ if (idx == 0) and (style.bg_gc[gtk.STATE_NORMAL] is not None):
+ nstyle.bg_gc[gtk.STATE_NORMAL] = \
+ style.bg_gc[gtk.STATE_NORMAL]
+ elif (idx == 1) and (style.fg_gc[gtk.STATE_NORMAL] is not None):
+ nstyle.fg_gc[gtk.STATE_NORMAL] = \
+ style.fg_gc[gtk.STATE_NORMAL]
+ elif (idx == 2) and (style.bg_gc[gtk.STATE_SELECTED] is not None):
+ nstyle.bg_gc[gtk.STATE_SELECTED] = \
+ style.bg_gc[gtk.STATE_SELECTED]
+ elif (idx == 3) and (style.fg_gc[gtk.STATE_SELECTED] is not None):
+ nstyle.fg_gc[gtk.STATE_SELECTED] = \
+ style.fg_gc[gtk.STATE_SELECTED]
+ elif (idx == 4) and (style.bg_gc[gtk.STATE_INSENSITIVE] is not None):
+ nstyle.bg_gc[gtk.STATE_INSENSITIVE] = \
+ style.bg_gc[gtk.STATE_INSENSITIVE]
+ elif (idx == 5) and (style.fg_gc[gtk.STATE_INSENSITIVE] is not None):
+ nstyle.fg_gc[gtk.STATE_INSENSITIVE] = \
+ style.fg_gc[gtk.STATE_INSENSITIVE]
+
+ continue
+
+ if idx == 0:
+ ngc=self._get_new_gc(item,style.bg_gc[gtk.STATE_NORMAL])
+ nstyle.bg_gc[gtk.STATE_NORMAL]=ngc
+ elif idx == 1:
+ ngc=self._get_new_gc(item,style.fg_gc[gtk.STATE_NORMAL])
+ nstyle.fg_gc[gtk.STATE_NORMAL]=ngc
+ elif idx == 2:
+ ngc=self._get_new_gc(item,style.bg_gc[gtk.STATE_SELECTED])
+ nstyle.bg_gc[gtk.STATE_SELECTED]=ngc
+ elif idx == 3:
+ ngc=self._get_new_gc(item,style.fg_gc[gtk.STATE_SELECTED])
+ nstyle.fg_gc[gtk.STATE_SELECTED]=ngc
+ elif idx == 4:
+ ngc=self._get_new_gc(item,
+ style.bg_gc[gtk.STATE_INSENSITIVE])
+ nstyle.bg_gc[gtk.STATE_INSENSITIVE]=ngc
+ elif idx == 5:
+ ngc=self._get_new_gc(item,
+ style.fg_gc[gtk.STATE_INSENSITIVE])
+ nstyle.fg_gc[gtk.STATE_INSENSITIVE]=ngc
+
+ # None placeholder was created when user called add_style to
+ # request the new style. Here, just replace the None.
+ self.style_list[cidx]=nstyle
+
+ def _get_new_gc(self,color_tuple, ref_gc):
+ """ Get a new graphics context for a style. """
+ # WARNING: Don't try printing out the gc's foreground and
+ # background values- it seems that the printed values are
+ # unrelated to the actual set values. Setting them does
+ # seem to work though.
+ cmap=self.get_colormap()
+ new_color=cmap.alloc(color_tuple[0],color_tuple[1],color_tuple[2])
+ if ref_gc is None:
+ ref_gc=self.get_style().white_gc
+
+ ngc=self.get_window().new_gc(foreground=new_color,
+ # background=new_color)
+ background=new_color,font=ref_gc.font, fill=ref_gc.fill,
+ subwindow_mode=ref_gc.subwindow_mode,
+ ts_x_origin=ref_gc.ts_x_origin, ts_y_origin=ref_gc.ts_y_origin,
+ clip_x_origin=ref_gc.clip_x_origin,
+ clip_y_origin=ref_gc.clip_y_origin,
+ line_width=ref_gc.line_width, line_style=ref_gc.line_style,
+ cap_style=ref_gc.cap_style,
+ join_style=ref_gc.join_style)
+
+ return ngc
+
+ def set_line_drawing(self,rlines=2, clines=2, expose=1):
+ """ Set which lines in the grid are drawn:
+ Inputs:
+ rlines- 0 for no lines between rows
+ 1 for lines between row titles
+ 2 for lines under whole rows
+
+ clines- 0 for no lines between columns
+ 1 for lines between column titles
+ 2 for lines under whole columns
+
+
+ """
+ self.draw_row_lines = rlines
+ self.draw_col_lines = clines
+ if expose == 1:
+ self.expose()
+
+ def set_default_style(self,tuple):
+ """ Set the default style: a tuple consisting of
+ (bg_gc_normal,fg_gc_normal,bg_gc_selected,fg_gc_selected,
+ bg_gc_insensitive,fg_gc_insensitive),
+ where bg=background, fg=foreground. Not all
+ of these are used yet (may never be).
+ Each of these entries should be either None
+ (then the default value is used) or a tuple
+ of 3 integer (0-65535) values.
+ """
+ self.default_style_reset_flag = 1
+ self.default_style = tuple
+
+ def set_default_row_title_style(self,tuple):
+ """ Set the default row title style: a tuple consisting of
+ (bg_gc_normal,fg_gc_normal,bg_gc_selected,fg_gc_selected,
+ bg_gc_insensitive,fg_gc_insensitive),
+ where bg=background, fg=foreground. Not all
+ of these are used yet (may never be).
+ Each of these entries should be either None
+ (then the default value is used) or a tuple
+ of 3 integer (0-65535) values.
+ """
+ self.default_row_title_style_reset_flag = 1
+ self.default_row_title_style = tuple
+
+ def set_default_col_title_style(self,tuple):
+ """ Set the default column title style: a tuple consisting of
+ (bg_gc_normal,fg_gc_normal,bg_gc_selected,fg_gc_selected,
+ bg_gc_insensitive,fg_gc_insensitive),
+ where bg=background, fg=foreground. Not all
+ of these are used yet (may never be).
+ Each of these entries should be either None
+ (then the default value is used) or a tuple
+ of 3 integer (0-65535) values.
+ """
+ self.default_col_title_style_reset_flag = 1
+ self.default_col_title_style = tuple
+
+ def set_default_selection_colour(self,ctuple):
+ """ Set the default selection colour: a tuple
+ of three integers.
+ """
+ self.set_default_style((None,None,ctuple,None,None,None))
+
+ def set_row_style(self,row_index,style_index):
+ """ Assign a style index to a row. row_index
+ is either a single integer index or a list
+ of indices. If it is -1, all rows will
+ be set to have style style_index. If it is
+ a list, the rows (in source coordinates) in
+ that list will have that style. If it is
+ a single integer that is > -1, only that
+ row will be set to have that style.
+ style_index is always an integer.
+ """
+
+ if type(row_index) == type([]):
+ for row in row_index:
+ self.row_style_index[row]=style_index
+ elif row_index == -1:
+ self.row_style_index=\
+ style_index*Numeric.ones((self.s_rows,))
+ else:
+ self.row_style_index[row_index]=style_index
+
+
+ def set_column_style(self,column_index,style_index):
+ """ Assign a style index to a column. column_index
+ is either a single integer index or a list
+ of indices. If it is -1, all columns will
+ be set to have style style_index. If it is
+ a list, the columns (in grid coordinates) in
+ that list will have that style. If it is
+ a single integer that is > -1, only that
+ column will be set to have that style.
+ style_index is always an integer. Note that
+ only the selected states of column styles
+ will be seen- in drawing, the unselected
+ row color overrides the unselected column
+ color.
+ """
+
+ if type(column_index) == type([]):
+ for column in column_index:
+ self.column_style_index[column]=style_index
+ elif column_index == -1:
+ self.column_style_index=\
+ style_index*Numeric.ones((self.g_columns,))
+ else:
+ self.column_style_index[column_index]=style_index
+
+
+
+ def set_row_title_type(self,type='grid',expose=1,titles=None):
+ """Define whether row titles should reflect grid
+ row number, or underlying source index.
+ NOTE: If len(titles) doesn't match the source length,
+ the first len(source) values will be used. If
+ len(titles) < len(source), '' will be used for
+ source indices > len(titles)-1.
+
+ Parameters:
+ type- either 'grid' (to show grid row) or
+ 'source' (to show source row index) or
+ 'user-defined' (user specifies row
+ titles as a list). In the 'user-defined'
+ case, the title list is indexed
+ as the source row indices (ie. title[0]
+ corresponds to source[0] as opposed
+ to grid[0]). Default type is 'grid'.
+ expose- 1 if pgugrid should be redrawn
+ immediately; 0 if not. Defaults
+ to 1.
+ titles- None for 'grid' or 'source'; a list
+ of the same length as the source
+ for 'user-defined'.
+ """
+ self.opts.set_row_title_type(type)
+
+ if self.opts.show_row_titles != 1:
+ print 'Warning- setting row title type on a grid that\n'+\
+ ' is not configured to display row titles!'
+
+ if type == 'user-defined':
+ if titles is None:
+ raise AttributeError,'User-defined row titles must be a list!'
+
+ self.row_titles = titles
+ self._update_row_title_width()
+
+ if expose == 1:
+ self.expose()
+
+ def define_columns(self,members=None,titles=None,editables=None,
+ formats=None,types=None,nodata=None,
+ justify=None,title_justify=None,
+ force_width=None,force_width_chars=None,
+ entry_chars=None,expose=1):
+ """ Define which columns to include in display.
+ Parameters:
+ members- Relates the column to the underlying source.
+ Is either None (use defaults) or a list.
+ List contains elements described here:
+ SRC_NUMERIC: column index (integer)
+ SRC_SHAPES: shape property
+ SRC_SHAPESLAYER: shape property
+ SRC_LISTLIST: sublist index
+ SRC_LISTOBJ: object member, or None if the
+ object is a string, float, integer,
+ or complex.
+
+ title- Describes the display title for each column.
+ Is either None or a list of strings. If list, the
+ list must have a one-to-one correspondence
+ to the members list (if members list is None,
+ the length of this list must be the same as
+ the number of members detected by default).
+
+ editables- Is either None (use global editable parameter
+ used in initial grid definition), 0 (no
+ editable columns), 1 (all editable columns),
+ or a list of 1's and zeros that has a one-to-one
+ correspondence with the members list.
+
+ formats- Is either None (use default formatting), a single
+ expression that should be used to format all
+ columns, or a list of expressions that has a
+ one-to-one correspondence with the members
+ list.
+
+ types- Is either None (try to auto-detect type), a
+ single type describing members of all columns,
+ or a list of types that has a one-to-one
+ correspondence with the members list.
+
+ nodata- Is either None, a single string describing
+ the nodata string for members of all columns,
+ or a list of nodata strings that has a one-to-one
+ correspondence with the members list.
+
+ justify- Is either None, a single integer to describe
+ all column justifications (0=right, 1=left,
+ 2=center), or a list of integers (0-2)
+ that has a one-to-one correspondence with the
+ members list. Defaults to 0.
+
+ title_justify- Is either None, a single integer to describe
+ all column title justifications (0=right,
+ 1=left, 2=center), or a list of integers (0-2)
+ that has a one-to-one correspondence with the
+ members list. Defaults to 2.
+
+ force_width- Used to force a particular column's width.
+ Is either None, a single width to describe
+ all column widths, or a list of widths
+ that has a one-to-one correspondence with the
+ members list. Defaults to None (auto-select
+ column widths).
+
+ force_width_chars- whether width is specified in terms of
+ pixels (-1) or characters (> 0). Is either
+ None, a single value to describe all
+ columns, or a list of values with a
+ one-to-one correspondence with the
+ members list. Defaults to -1.
+
+ entry_chars- number of characters to allow user to type
+ (only relevant if column is editable). Is
+ either None, a single value to describe all
+ columns, or a list of values with a one-to-one
+ correspondence with the members list. Defaults
+ to 90.
+ """
+
+
+ self._ColumnDefs=[]
+
+ if (self.src_type in [SRC_NONE,SRC_LISTUNDEF]) and (members is None):
+ return
+
+ if type(members) == type((1,)):
+ members=list(members)
+ if type(titles) == type((1,)):
+ titles=list(titles)
+ if type(editables) == type((1,)):
+ editables=list(editables)
+ if type(formats) == type((1,)):
+ formats=list(formats)
+ if type(types) == type((1,)):
+ types=list(types)
+ if type(nodata) == type((1,)):
+ nodata=list(nodata)
+ if type(justify) == type((1,)):
+ justify=list(justify)
+ if type(title_justify) == type((1,)):
+ title_justify=list(title_justify)
+ if type(force_width) == type((1,)):
+ force_width=list(force_width)
+ if type(force_width_chars) == type((1,)):
+ force_width_chars=list(force_width_chars)
+ if type(entry_chars) == type((1,)):
+ entry_chars=list(entry_chars)
+
+ startx=self.row_title_width+1
+ if self.opts.show_row_titles == 1:
+ startx=startx+1
+
+ if members is None:
+ if self.src_type == SRC_NUMERIC:
+ # Default: one column per array column, with
+ # column number as the title
+ ci_mems=range(Numeric.shape(self.src)[1])
+ elif ((self.src_type == SRC_SHAPES) or
+ (self.src_type == SRC_SHAPESLAYER)):
+ ci_mems=[]
+ schema=self.src.get_schema()
+ if len(schema) > 0:
+ for item in schema:
+ ci_mems.append(item[0])
+ else:
+ if len(self.src) > 0:
+ props=self.src[0].get_properties()
+ for ckey in props.keys():
+ ci_mems.append(ckey)
+ elif (self.src_type == SRC_LISTLIST):
+ ci_mems=range(len(self.src[0]))
+ elif (self.src_type == SRC_LISTOBJ):
+ if type(self.src[0]) == type(''):
+ ci_mems=[None]
+ elif type(self.src[0]) == type(1):
+ ci_mems=[None]
+ elif type(self.src[0]) == type(5.2):
+ ci_mems=[None]
+ elif type(self.src[0]) == type(complex(1,1)):
+ ci_mems=[None]
+ else:
+ members=dir(self.src[0])
+ ci_mems=[]
+ for ckey in members:
+ cmem=eval('self.src[0].'+ckey)
+ oktypes=[type(''),type(1),type(5.2),type(complex(1,1))]
+ if type(cmem) in oktypes:
+ ci_mems.append(ckey)
+ else:
+ ci_mems=members
+
+ ci_titles=[]
+ if titles is None:
+ if self.src_type in [SRC_NUMERIC,SRC_LISTLIST]:
+ for idx in ci_mems:
+ ci_titles.append('Column '+str(idx))
+ elif (self.src_type in
+ [SRC_SHAPES,SRC_SHAPESLAYER,SRC_LISTOBJ,SRC_NONE,SRC_LISTUNDEF]):
+ for mem in ci_mems:
+ if mem is not None:
+ ci_titles.append(mem)
+ else:
+ ci_titles.append('Column 0')
+
+ elif type(titles) == type(''):
+ for idx in ci_mems:
+ ci_titles.append(titles)
+ elif type(titles) == type([]):
+ ci_titles=titles
+ if len(ci_titles) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'title per member!'
+ else:
+ raise RuntimeError,'define_columns: titles must be either '+\
+ 'None, a string, or a list.'
+
+ ci_edit=[]
+ if editables is None:
+ if self.opts.config[4] in [4,5,6,7]:
+ editopts=1
+ else:
+ editopts=0
+
+ for idx in ci_mems:
+ ci_edit.append(editopts)
+
+ elif editables in [0,1]:
+ for idx in ci_mems:
+ ci_edit.append(editables)
+ elif type(editables) == type([]):
+ ci_edit=editables
+ if len(ci_edit) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'edit property per member if editables is a list!'
+ else:
+ raise RuntimeError,'define_columns: editables must be either '+\
+ 'None, 0, 1, or a list.'
+
+
+ ci_fmts=[]
+ if formats is None:
+ if ((self.src_type == SRC_SHAPES) or
+ (self.src_type == SRC_SHAPESLAYER)):
+ schema=self.src.get_schema()
+ schema_fmts={}
+ for item in schema:
+ if item[1] == 'integer':
+ schema_fmts[item[0]]="%"+str(item[2])+"d"
+ elif item[1] == 'float':
+ schema_fmts[item[0]]="%"+str(item[2])+"."+\
+ str(item[3])+"f"
+
+ for idx in ci_mems:
+ if schema_fmts.has_key(idx):
+ ci_fmts.append(schema_fmts[idx])
+ else:
+ ci_fmts.append(None)
+
+ else:
+ for idx in ci_mems:
+ ci_fmts.append(None)
+ elif type(formats) == type(''):
+ for idx in ci_mems:
+ ci_fmts.append(formats)
+ elif type(formats) == type([]):
+ ci_fmts=formats
+ if len(ci_fmts) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'format per member if formats is a list!'
+ else:
+ raise RuntimeError,'define_columns: formats must be either '+\
+ 'None, a string, or a list.'
+
+ ci_types=[]
+ if types is None:
+ if self.src_type == SRC_NUMERIC:
+ #inttypes=['1','l','s','i','u','b','w']
+ inttypes=[Numeric.Int,Numeric.Int0,Numeric.Int8,Numeric.Int16,
+ Numeric.Int32,Numeric.UnsignedInteger,Numeric.UInt8,
+ Numeric.UInt16,Numeric.UInt32]
+ #complextypes=['D','F']
+ complextypes=[Numeric.Complex,Numeric.Complex0,
+ Numeric.Complex8,
+ Numeric.Complex16,Numeric.Complex32,
+ Numeric.Complex64]
+ if self.src.typecode() in inttypes:
+ ctype='integer'
+ elif self.src.typecode() in complextypes:
+ ctype='complex'
+ else:
+ ctype='float'
+
+ for mem in ci_mems:
+ ci_types.append(ctype)
+
+ elif self.src_type in [SRC_SHAPES,SRC_SHAPESLAYER]:
+ schema=self.src.get_schema()
+ sd={}
+ for item in schema:
+ sd[item[0]]=item[1]
+ sdkeys=sd.keys()
+ for mem in ci_mems:
+ if mem in sdkeys:
+ ci_types.append(sd[mem])
+ else:
+ ci_types.append('string')
+
+ elif self.src_type == SRC_LISTLIST:
+ for idx in ci_mems:
+ if type(self.src[0][idx]) == type(1.2):
+ ctype='float'
+ elif type(self.src[0][idx]) == type(1):
+ ctype='integer'
+ elif type(self.src[0][idx]) == type(complex(1,1)):
+ ctype='complex'
+ else:
+ ctype='string'
+ ci_types.append(ctype)
+
+ elif self.src_type == SRC_LISTOBJ:
+ if ci_mems[0] is None:
+ if type(self.src[0]) == type(''):
+ ci_types.append('string')
+ elif type(self.src[0]) == type(1):
+ ci_types.append('integer')
+ elif type(self.src[0]) == type(5.2):
+ ci_types.append('float')
+ elif type(self.src[0]) == type(complex(1,1)):
+ ci_types.append('complex')
+ else:
+ for mem in ci_mems:
+ cmem=eval('self.src[0].'+mem)
+ if type(cmem) == type(complex(1,1)):
+ ci_types.append('complex')
+ elif type(cmem) == type(5.3):
+ ci_types.append('float')
+ elif type(cmem) == type(1):
+ ci_types.append('integer')
+ else:
+ ci_types.append('string')
+ elif self.src_type in [SRC_NONE,SRC_LISTUNDEF]:
+ for mem in ci_mems:
+ ci_types.append(None)
+
+ elif type(types) == type(''):
+ for idx in ci_mems:
+ ci_types.append(types)
+ elif type(types) == type([]):
+ ci_types=list(types)
+ if len(ci_types) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'type per member if types is a list!'
+ else:
+ raise RuntimeError,'define_columns: types must be either '+\
+ 'None, a string, or a list.'
+
+
+ ci_nodata=[]
+ if nodata is None:
+ for idx in ci_mems:
+ ci_nodata.append('')
+ elif type(nodata) == type(''):
+ for idx in ci_mems:
+ ci_nodata.append(nodata)
+ elif type(nodata) == type([]):
+ ci_nodata=nodata
+ if len(ci_nodata) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'string per member if nodata is a list!'
+ else:
+ raise RuntimeError,'define_columns: nodata must be either '+\
+ 'None, a string, or a list.'
+
+
+ ci_just=[]
+ if justify is None:
+ for idx in ci_mems:
+ ci_just.append(0)
+ elif type(justify) == type(1):
+ for idx in ci_mems:
+ ci_just.append(justify)
+ elif type(justify) == type([]):
+ ci_just=justify
+ if len(ci_just) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'integer per member if justify is a list!'
+ else:
+ raise RuntimeError,'define_columns: justify must be either '+\
+ 'None, a string, or a list.'
+
+
+ ci_tjust=[]
+ if title_justify is None:
+ for idx in ci_mems:
+ ci_tjust.append(2)
+ elif type(title_justify) == type(1):
+ for idx in ci_mems:
+ ci_tjust.append(title_justify)
+ elif type(title_justify) == type([]):
+ ci_tjust=title_justify
+ if len(ci_tjust) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'integer per member if title_justify is a list!'
+ else:
+ raise RuntimeError,'define_columns: title_justify must be '+\
+ 'either None, a string, or a list.'
+
+ ci_fwidth=[]
+ if force_width is None:
+ for idx in ci_mems:
+ ci_fwidth.append(None)
+ elif type(force_width) == type(1):
+ for idx in ci_mems:
+ ci_fwidth.append(force_width)
+ elif type(force_width) == type([]):
+ ci_fwidth=force_width
+ if len(ci_fwidth) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'integer per member if force_width is a list!'
+ else:
+ raise RuntimeError,'define_columns: force_width must be '+\
+ 'either None, a string, or a list.'
+
+ ci_fwidthc=[]
+ if force_width_chars is None:
+ for idx in ci_mems:
+ ci_fwidthc.append(-1)
+ elif type(force_width_chars) == type(1):
+ for idx in ci_mems:
+ ci_fwidthc.append(force_width_chars)
+ elif type(force_width_chars) == type([]):
+ ci_fwidthc=force_width_chars
+ if len(ci_fwidthc) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'integer per member if force_width_chars is a list!'
+ else:
+ raise RuntimeError,'define_columns: force_width_chars must be '+\
+ 'either None, a string, or a list.'
+
+ ci_entryc=[]
+ if entry_chars is None:
+ for idx in ci_mems:
+ ci_entryc.append(90)
+ elif type(entry_chars) == type(1):
+ for idx in ci_mems:
+ ci_entryc.append(entry_chars)
+ elif type(entry_chars) == type([]):
+ ci_entryc=entry_chars
+ if len(ci_entryc) != len(ci_mems):
+ raise RuntimeError,'define_columns: must specify one '+\
+ 'integer per member if entry_chars is a list!'
+ else:
+ raise RuntimeError,'define_columns: entry_chars must be '+\
+ 'either None, a string, or a list.'
+
+ style = self.get_style()
+
+ if self.title_font is None:
+ try:
+ self.title_font = gtk.load_font( self.title_font_spec )
+ except:
+ self.title_font = style.font
+
+ self._update_column_title_height()
+ self._update_row_title_width()
+
+ if self.cell_font is None:
+ try:
+ self.cell_font = gtk.load_font( self.cell_font_spec )
+ except:
+ self.cell_font = style.font
+ self.row_height = self.cell_font.ascent + 2*self.pad
+
+ for idx in range(len(ci_mems)):
+ cwidth=30
+ cnew=_column_info(ci_mems[idx],ci_titles[idx],ci_types[idx],
+ ci_fmts[idx],ci_edit[idx],ci_nodata[idx],
+ cwidth,startx,ci_just[idx],ci_tjust[idx],
+ ci_fwidth[idx], ci_fwidthc[idx], ci_entryc[idx])
+ self._ColumnDefs.append(cnew)
+ # Cycle though first few rows to update column width
+ if ((self._ColumnDefs[idx].force_width is not None) or
+ (self._ColumnDefs[idx].force_width_chars > -1)):
+ if self._ColumnDefs[idx].force_width_chars == -1:
+ cwidth = self._ColumnDefs[idx].force_width
+ else:
+ # This assumes that 'W' has pretty much the maximum
+ # width for most fonts (rather than cycling through
+ # all possible characters). May need to update...
+ cwidth = (max(self.title_font.width('W'),
+ self.cell_font.width('W'))*
+ self._ColumnDefs[idx].force_width_chars) + 2*self.pad
+ self._ColumnDefs[idx].force_width = cwidth
+
+ else:
+ cwidth=self.title_font.width(self._ColumnDefs[idx].title)+\
+ 2*self.pad
+ tmprows=min([10,len(self.row2src)])
+ for cr in range(tmprows):
+ cwidth=max([cwidth,self.cell_font.width(
+ self._get_datastr(cr,idx))+2*self.pad])
+ cwidth=max(cwidth,30)
+ self._ColumnDefs[idx].width=cwidth
+ startx=startx+cwidth+1
+
+
+ self.g_rows=len(self.row2src)
+ self.g_columns=len(self._ColumnDefs)
+
+ self.column_widths=[]
+ for item in self._ColumnDefs:
+ self.column_widths.append(item.width)
+
+ self.column_selectstate=Numeric.zeros((self.g_columns,))
+ self.cell_selectstate=Numeric.zeros((self.s_rows,self.g_columns))
+ self.last_selected_column=None
+ self.last_selected_cell=None
+ self.last_toggled_column=None
+ self.last_toggled_cell=None
+
+ self.column_style_index=Numeric.zeros((self.g_columns,))
+ # Below: not used yet, but will be later
+ #self.columntitle_style_index=Numeric.ones((self.g_columns,))
+
+ self.bCalcAdjustments = gtk.TRUE
+
+ if expose == 1:
+ self.expose()
+
+
+ def _update_column_widths(self,expose=1):
+ """ Update column widths for new source with same column defs. """
+
+ style = self.get_style()
+
+ if self.title_font is None:
+ try:
+ self.title_font = gtk.load_font( self.title_font_spec )
+ except:
+ self.title_font = style.font
+
+ self._update_column_title_height()
+ self._update_row_title_width()
+
+ if self.cell_font is None:
+ try:
+ self.cell_font = gtk.load_font( self.cell_font_spec )
+ except:
+ self.cell_font = style.font
+ self.row_height = self.cell_font.ascent + 2*self.pad
+
+ cwidth=30
+ startx=self.row_title_width+1
+ if self.opts.show_row_titles == 1:
+ startx=startx+1
+ for idx in range(len(self._ColumnDefs)):
+ if (( self._ColumnDefs[idx].force_width is not None) or
+ (self._ColumnDefs[idx].force_width_chars > -1)):
+ if self._ColumnDefs[idx].force_width_chars == -1:
+ cwidth = self._ColumnDefs[idx].force_width
+ else:
+ # This assumes that 'W' has pretty much the maximum
+ # width for most fonts (rather than cycling through
+ # all possible characters). May need to update...
+ cwidth = (max(self.title_font.width('W'),
+ self.cell_font.width('W'))*
+ self._ColumnDefs[idx].force_width_chars) + 2*self.pad
+ self._ColumnDefs[idx].force_width = cwidth
+ else:
+ cwidth=self.title_font.width(self._ColumnDefs[idx].title)+\
+ 2*self.pad
+ tmprows=min([10,len(self.row2src)])
+ for cr in range(tmprows):
+ cwidth=max([cwidth,self.cell_font.width(
+ self._get_datastr(cr,idx))+2*self.pad])
+ cwidth=max(cwidth,30)
+ self._ColumnDefs[idx].width=cwidth
+ self._ColumnDefs[idx].start_x=startx
+ startx=startx+cwidth+1
+
+ self.bCalcAdjustments = gtk.TRUE
+ if expose == 1:
+ self.expose()
+
+ def _get_datastr(self,row,column):
+ """ Get the underlying source data in cell row,column as a string. """
+ cdata=self._get_data(row,column)
+
+ if cdata is None:
+ cdata=self._ColumnDefs[column].nodata
+ return cdata
+
+ if self._ColumnDefs[column].format in ['',None]:
+ return str(cdata)
+ else:
+ return self._ColumnDefs[column].format % cdata
+
+ def _get_data(self,row,column):
+ """ Get the source data in cell row,column. """
+ if self.src_type == SRC_NUMERIC:
+ return self.src[row,self._ColumnDefs[column].member]
+ elif self.src_type == SRC_SHAPES:
+ if self.src[row] is not None:
+ datastr = self.src[row].get_property(
+ self._ColumnDefs[column].member)
+ else:
+ return None
+
+ if datastr is None:
+ return None
+
+ if self._ColumnDefs[column].type == 'float':
+ data=float(datastr)
+ elif self._ColumnDefs[column].type == 'integer':
+ data=int(datastr)
+ else:
+ data=datastr
+
+ return data
+
+ elif self.src_type == SRC_SHAPESLAYER:
+ if self.src[row] is not None:
+ datastr = self.src[row].get_property(
+ self._ColumnDefs[column].member)
+ else:
+ return None
+
+ if datastr is None:
+ return None
+
+ if self._ColumnDefs[column].type == 'float':
+ data=float(datastr)
+ elif self._ColumnDefs[column].type == 'integer':
+ data=int(datastr)
+ else:
+ data=datastr
+
+ return data
+
+ elif self.src_type == SRC_LISTLIST:
+ if self.src[row] is not None:
+ datastr= self.src[row][self._ColumnDefs[column].member]
+ else:
+ return None
+
+ if self._ColumnDefs[column].type == 'float':
+ data=float(datastr)
+ elif self._ColumnDefs[column].type == 'integer':
+ data=int(datastr)
+ elif self._ColumnDefs[column].type == 'complex':
+ data=complex(datastr)
+ else:
+ data=datastr
+
+ return data
+
+ elif self.src_type == SRC_LISTOBJ:
+ if self._ColumnDefs[column].member is None:
+ datastr=self.src[row]
+ else:
+ datastr = eval('self.src[row].'+
+ self._ColumnDefs[column].member)
+
+ if self._ColumnDefs[column].type == 'float':
+ data=float(datastr)
+ elif self._ColumnDefs[column].type == 'integer':
+ data=int(datastr)
+ elif self._ColumnDefs[column].type == 'complex':
+ data=complex(datastr)
+ else:
+ data=datastr
+
+ return data
+
+ def get_cell_data(self,row,column):
+ """ Get the source data in cell (source) row, (grid) column. """
+ return self._get_data(row,column)
+
+ def get_cell_data_string(self,row,column):
+ """ Get the source data in cell (source) row,(grid) column
+ as a string. """
+ return self._get_datastr(row,column)
+
+ def set_cell_data(self,row,column,value):
+ """ Set the source data in cell (source) row, (grid) column. """
+ return self._set_data(row,column,value)
+
+ def set_cell_data_string(self,row,column,value):
+ """ Set the source data string in cell (source) row,(grid) column. """
+ return self._set_datastr(row,column,value)
+
+ def set_rangeCheck(self,flag= False):
+ """Set range check flag """
+ self.doRangeCheck = flag
+
+ def set_numericRange(self,range):
+ """Set valid range[min,max] for range check of input value """
+ if range is None or type(range) != type([1,]):
+ gvutils.error('Invalid range input. [min,max]')
+ return
+ else:
+ self.numericRange = range
+
+ def _set_datastr(self,row,column,value):
+ """ Set the source data in cell row,column to value.
+ Note that value is entered as a string that
+ must be converted to the required type."""
+
+ if self._ColumnDefs[column].type == 'string':
+ nvalue=value
+ elif self._ColumnDefs[column].type == 'integer':
+ try:
+ nvalue=int(value)
+ if self.doRangeCheck and self.numericRange is not None:
+ if nvalue <self.numericRange[0] or nvalue>self.numericRange[1]:
+ gvutils.error('Input out of range. '+str(nvalue)+" "+str(self.numericRange))
+ return
+
+ except:
+ # If empty string was entered, user may have
+ # clicked on an empty cell and not typed
+ # anything, so don't set the value or send
+ # an error
+ if len(value) == 0:
+ return
+
+ gvutils.error('Invalid data entry. Integer required.')
+ return
+
+ elif self._ColumnDefs[column].type == 'float':
+ try:
+ nvalue=float(value)
+ if self.doRangeCheck and self.numericRange is not None:
+ if nvalue <self.numericRange[0] or nvalue>self.numericRange[1]:
+ gvutils.error('Input out of range. '+str(nvalue)+" "+str(self.numericRange))
+ return
+ except:
+ if len(value) == 0:
+ return
+
+ gvutils.error('Invalid data entry. Float required.')
+ return
+
+ elif self._ColumnDefs[column].type == 'complex':
+ try:
+ nvalue=complex(value)
+ except:
+ if len(value) == 0:
+ return
+
+ gvutils.error('Invalid data entry. Complex required.')
+ return
+
+ self._set_data(row,column,nvalue)
+
+ def _set_data(self,row,column,value):
+ """ Set the source data in cell row,column to value.
+ Necessary conversions have already taken
+ place (use _set_datastr if value is still a
+ string that needs to be converted).
+ """
+ if self.src_type == SRC_NUMERIC:
+ try:
+ self.src[row,self._ColumnDefs[column].member]=value
+ except:
+ dtype=self.src.typecode()
+ txt='Invalid entry for array of typecode '+dtype
+ gvutils.error(txt)
+ elif self.src_type == SRC_SHAPES:
+ s1=string.strip(str(value))
+ pval=self.src[row].get_property(
+ self._ColumnDefs[column].member)
+ if pval is not None:
+ s2=string.strip(pval)
+ else:
+ s2=None
+ if s1 == '':
+ return
+
+ if s1 != s2:
+ # The copying is necessary for undo to work properly
+ shape=self.src[row].copy()
+ shape.set_property(self._ColumnDefs[column].member,
+ s1)
+ # avoid regenerating row indices
+ self.src.signal_handler_block(self.source_changed_id)
+ self.src[row]=shape
+ self.src.signal_handler_unblock(self.source_changed_id)
+ elif self.src_type == SRC_SHAPESLAYER:
+ s1=string.strip(str(value))
+ pval=self.src[row].get_property(
+ self._ColumnDefs[column].member)
+ if pval is not None:
+ s2=string.strip(pval)
+ else:
+ s2=None
+ if s1 == '':
+ return
+
+ if s1 != s2:
+ shape=self.src[row].copy()
+ shape.set_property(self._ColumnDefs[column].member,
+ s1)
+ self.src.signal_handler_block(self.source_changed_id)
+ self.src[row]=shape
+ self.src.signal_handler_unblock(self.source_changed_id)
+ elif self.src_type == SRC_LISTLIST:
+ self.src[row][self._ColumnDefs[column].member]=value
+ elif self.src_type == SRC_LISTOBJ:
+ if self._ColumnDefs[column].member is None:
+ self.src[row]=value
+ else:
+ setattr(self.src[row],self._ColumnDefs[column].member,value)
+
+
+ def translate_view_to_row(self,row):
+ """ If source is a shapeslayer, translate the view
+ to center on the row'th source shape and select
+ that row if it isn't already selected and selection
+ is enabled.
+ """
+
+ if self.view is not None:
+ if row > (len(self.src)-1):
+ raise RuntimeError,'translate_row_to_view: tried to '+\
+ 'translate view to center on non-existent node.'
+
+ cnode=self.src[row].get_node()
+ self.view.set_translation(-cnode[0],-cnode[1])
+ if self.row_selectstate[row] == 0:
+ if self.opts.selection_info.row == 1:
+ self.select_row(row,clearfirst=1,expose=1)
+ elif self.opts.selection_info.row == 2:
+ self.select_row(row,clearfirst=0,expose=1)
+
+ def delete_row(self,row):
+ """ Delete source row row. Note: this function will
+ reset the source in the Numerical array case
+ (necessary because array must be re-allocated when
+ it changes size).
+ """
+
+ self.delete_rows([row])
+
+ def delete_rows(self,row_list):
+ """ Delete source rows in row_list. Note: this function will
+ reset the source in the Numerical array case
+ (necessary because array must be re-allocated when
+ it changes size).
+ """
+
+ if type(row_list) == type((1,)):
+ row_list=list(row_list)
+
+ if len(row_list) == 0:
+ return
+
+ self.bCalcAdjustments=gtk.TRUE
+
+ if self.src_type in [SRC_SHAPES,SRC_SHAPESLAYER]:
+ self.src.delete_shapes(row_list)
+
+ elif self.src_type in [SRC_LISTLIST,SRC_LISTOBJ]:
+ # sort the row list in descending order so that
+ # deleting one row won't alter the indices
+ # of the next one.
+ row_list.sort()
+ row_list.reverse()
+ rstyle_index=list(self.row_style_index)
+ for item in row_list:
+ self.src.pop(item)
+ rstyle_index.pop(item)
+
+ self.row_style_index=Numeric.array(rstyle_index)
+
+ self.refresh()
+ else:
+ row_list.sort()
+ newrows=self.src.shape[0]-len(row_list)
+ cols=self.src.shape[1]
+ rm_rows=0
+ first_row=0
+ newarr=Numeric.zeros((newrows,cols),self.src.typecode())
+ for item in row_list:
+ newarr[first_row:item-rm_rows,:]=\
+ self.src[first_row+rm_rows:item,:]
+ first_row=item-rm_rows
+ rm_rows=rm_rows+1
+
+ newarr[first_row:newrows,:]=self.src[first_row+rm_rows:]
+
+ # Update row style list (colours)
+ row_list.reverse()
+ rstyle_index=list(self.row_style_index)
+
+ for item in row_list:
+ rstyle_index.pop(item)
+
+ self.row_style_index=Numeric.array(rstyle_index)
+
+ self.src=newarr
+ self.refresh()
+
+ self.notify('rows-deleted',row_list)
+
+ def select_rows(self,row_list,clearfirst=0,expose=1):
+ """ Trigger row selection in the grid.
+
+ Parameters:
+ row_list- list of integers corresponding
+ to source (not grid or subset) index
+ coordinate to select
+
+ clearfirst- 0 (don't clear existing selections before
+ selecting new ones) or 1 (clear exisiting
+ selections). Defaults to 0.
+
+ expose- 0 (redraw grid), or 1 (do not redraw grid).
+ Defaults to 1.
+ """
+
+ self._flags['selecting-rows']=1
+ if self.src_type == SRC_SHAPESLAYER:
+ # block so that grid doesn't refresh until the end.
+ self.layer.signal_handler_block(self.layer_selection_changed_id)
+ self.layer.signal_handler_block(self.layer_subselection_changed_id)
+ if clearfirst == 1:
+ self.layer.clear_selection()
+ for idx in range(len(row_list)-1):
+ self.layer.select_shape(row_list[idx])
+ self.layer.signal_handler_unblock(
+ self.layer_selection_changed_id)
+ self.layer.signal_handler_unblock(
+ self.layer_subselection_changed_id)
+ # The layer's selection-changed signal should
+ # trigger a callback that calls _select_rows
+ if len(row_list) > 0:
+ self.layer.select_shape(row_list[len(row_list)-1])
+ else:
+ if clearfirst == 1:
+ self._unselect_all_rows()
+ self._select_rows(row_list)
+
+ self._flags['selecting-rows']=0
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ if len(row_list) > 0:
+ self.reset_startrow(row_list[len(row_list)-1])
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+
+ def unselect_rows(self,row_list,clearfirst=0,expose=1):
+ """ Trigger row selection in the grid.
+
+ Parameters:
+ row_list- list of integers corresponding
+ to source (not grid or subset) index
+ coordinate to select
+
+ clearfirst- 0 (don't alter existing selections before
+ unselecting) or 1 (clear all values to
+ selected before unselecting requested
+ rows). Defaults to 0.
+
+ expose- 0 (redraw grid), or 1 (do not redraw grid).
+ Defaults to 1.
+ """
+
+ self._flags['selecting-rows']=1
+ if self.src_type == SRC_SHAPESLAYER:
+ # block so that grid doesn't refresh until the end.
+ self.layer.signal_handler_block(self.layer_selection_changed_id)
+ self.layer.signal_handler_block(self.layer_subselection_changed_id)
+ if clearfirst == 1:
+ self.layer.select_all()
+ for idx in range(len(row_list)-1):
+ self.layer.deselect_shape(row_list[idx])
+ self.layer.signal_handler_unblock(
+ self.layer_selection_changed_id)
+ self.layer.signal_handler_unblock(
+ self.layer_subselection_changed_id)
+ # The layer's selection-changed signal should
+ # trigger a callback that calls _select_rows
+ if len(row_list) > 0:
+ self.layer.deselect_shape(row_list[len(row_list)-1])
+ else:
+ if clearfirst == 1:
+ self._select_all_rows()
+
+ self._unselect_rows(row_list)
+
+ self._flags['selecting-rows']=0
+
+ if len(row_list) > 0:
+ self.last_toggled_row=row_list[len(row_list)-1]
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+ def select_row(self,row,clearfirst=0,expose=1):
+ """Select a single row."""
+
+ self.select_rows([row],clearfirst,expose)
+
+ def unselect_row(self,row,clearfirst=0,expose=1):
+ """Unselect a single row."""
+
+ self.unselect_rows([row],clearfirst,expose)
+
+ def toggle_row(self,row,expose=1):
+ """Toggle a single row."""
+
+ if self.row_selectstate[row] == 0:
+ self.select_row(row,0,expose)
+ else:
+ self.unselect_row(row,0,expose)
+
+ def toggle_rows(self,row_list,expose=1):
+ """Toggle multiple rows."""
+
+ select=[]
+ unselect=[]
+
+ for row in row_list:
+ if self.row_selectstate[row] == 0:
+ select.append(row)
+ else:
+ unselect.append(row)
+
+ if len(unselect) > 0:
+ self.unselect_rows(unselect,0,0)
+
+ if len(select) > 0:
+ self.select_rows(select,0,0)
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def toggle_block_rows(self,end_row,expose=1):
+ """Toggle a block of rows between self.last_toggled_row
+ and end_row.
+
+ Parameters:
+ end_row- last row to include in toggle block
+
+ expose- 0 (don't redraw grid) or 1 (redraw grid).
+ Defaults to 1.
+
+ """
+
+ if self.last_toggled_row is None:
+ return
+
+ g1=self.src2row[self.last_toggled_row]
+ g2=self.src2row[end_row]
+ if g1 < g2:
+ tlist=list(self.row2src[g1+1:g2+1])
+ else:
+ tlist=list(self.row2src[g2:g1])
+
+ self.toggle_rows(tlist,expose=0)
+ self.last_toggled_row=end_row
+ if self.row_selectstate[end_row] == 1:
+ self.last_selected_row=end_row
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.reset_startrow(end_row)
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def select_block_rows(self,end_row,expose=1):
+ """Select a block of rows between self.last_toggled_row
+ and end_row.
+
+ Parameters:
+ end_row- last row to include in toggle block
+
+ expose- 0 (don't redraw grid) or 1 (redraw grid).
+ Defaults to 1.
+
+ """
+
+ if self.last_toggled_row is None:
+ return
+
+ g1=self.src2row[self.last_toggled_row]
+ g2=self.src2row[end_row]
+ if g1 < g2:
+ tlist=list(self.row2src[g1+1:g2+1])
+ else:
+ tlist=list(self.row2src[g2:g1])
+
+ self.select_rows(tlist,expose=0)
+ self.last_toggled_row=end_row
+ self.last_selected_row=end_row
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.reset_startrow(end_row)
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def select_all_rows(self,expose=1):
+ """Select all rows (updates internal matrices,
+ triggers layer selection if relevant,
+ and redraws grid if requested).
+ """
+
+ # TO DO: ADD CODE TO CHECK PGUGRID OPTIONS
+ # AND MAKE SURE NO ILLEGAL SELECTION
+ # IS PERMITTED (RAISE ERROR IF IT TRIES)
+
+ self._flags['selecting-rows']=1
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.select_all()
+ else:
+ self._select_all_rows()
+
+ self._flags['selecting-rows']=0
+
+ self.last_toggled_row=None
+ self.last_selected_row=None
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def unselect_all_rows(self,expose=1):
+ """Unselect all rows (updates internal matrices,
+ triggers layer selection if relevant,
+ and redraws grid if requested).
+ """
+
+ self._flags['selecting-rows']=1
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.clear_selection()
+ else:
+ self._unselect_all_rows()
+
+ self._flags['selecting-rows']=0
+
+ self.last_toggled_row=None
+ self.last_selected_row=None
+
+ if expose == 1:
+
+ nlist=self._rows_updated()
+
+ self.expose()
+
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def _select_all_rows(self):
+ """ Update internal selection matrices. """
+ if self.row_selectstate is None:
+ return 0
+
+ self.row_selectstate[:] = 1
+ self.selected_rows=range(len(self.row_selectstate))
+
+ # check for cross-selection
+ if self.opts.selection_info.row_cell == 0:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ self.notify('cell-selection-changed',())
+
+ if self.opts.selection_info.row_column == 0:
+ if len(self.selected_columns) > 0:
+ self.unselect_all_columns(expose=0)
+ self.notify('column-selection-changed',())
+
+
+ return 1
+
+ def _unselect_all_rows(self):
+ """ Update internal selection matrices. """
+ if self.row_selectstate is None:
+ return 0
+
+ self.row_selectstate[:] = 0
+ self.selected_rows=[]
+
+ return 1
+
+ def _select_rows(self,row_list):
+ """ Helper function for select_rows. Updates
+ the selection matrices internally.
+ """
+ if self.row_selectstate is None:
+ # No source is set
+ return 0
+
+ for row in row_list:
+ if (len(self.row_selectstate) <= row):
+ raise RuntimeError,'pgugrid: tried to select nonexistent row'
+ else:
+ if self.row_selectstate[row] == 0:
+ self.row_selectstate[row]=1
+ self.selected_rows.append(row)
+
+
+ if len(row_list) > 0:
+ self.last_selected_row=row_list[len(row_list)-1]
+ self.last_toggled_row=row_list[len(row_list)-1]
+
+ # check for cross-selection
+ if self.opts.selection_info.row_cell == 0:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ self.notify('cell-selection-changed',())
+ elif self.opts.selection_info.row_cell == 1:
+ if len(self.selected_cells) > 0:
+ uscells=[]
+ for item in self.selected_cells:
+ if self.row_selectstate[item[0]] == 0:
+ uscells.append(item)
+ if len(uscells) > 0:
+ self.unselect_cells(uscells,expose=0)
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if self.opts.selection_info.row_column == 0:
+ if len(self.selected_columns) > 0:
+ self.unselect_all_columns(expose=0)
+ self.notify('column-selection-changed',())
+
+ return 1
+
+ def _unselect_rows(self,row_list):
+ """ Helper function for unselect_rows. Updates
+ the selection matrices internally.
+ """
+ if self.row_selectstate is None:
+ # No source is set
+ return 0
+
+ for row in row_list:
+ if (len(self.row_selectstate) <= row):
+ raise RuntimeError,'pgugrid: tried to select nonexistent row'
+ else:
+ if self.row_selectstate[row] == 1:
+ self.row_selectstate[row]=0
+ self.selected_rows.remove(row)
+
+ return 1
+
+ def select_column(self,column,clearfirst=0,expose=1):
+ """Select a single column."""
+
+ rval = self.select_columns([column],clearfirst,expose)
+ return rval
+
+ def select_columns(self,column_list,clearfirst=0,expose=1):
+ """Select multiple columns."""
+
+ if self.column_selectstate is None:
+ # No source is set
+ return 0
+
+ if clearfirst == 1:
+ self.unselect_all_columns(expose=0)
+
+ for column in column_list:
+ if (len(self.column_selectstate) <= column):
+ raise RuntimeError,'pgugrid: tried to select nonexistent '+\
+ 'column'
+ else:
+ self.column_selectstate[column]=1
+
+ if column not in self.selected_columns:
+ self.selected_columns.append(column)
+
+
+ if len(column_list) > 0:
+ self.last_selected_column=column_list[len(column_list)-1]
+ self.last_toggled_column=column_list[len(column_list)-1]
+
+
+ if expose == 1:
+
+ nlist=self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+ def select_all_columns(self,expose=1):
+ """Select all columns."""
+
+ if self.column_selectstate is None:
+ return 0
+
+ self.column_selectstate[:]=1
+ self.selected_columns=range(len(self.column_selectstate))
+
+ self.last_toggled_column=None
+ self.last_selected_column=None
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+ def unselect_column(self,column,clearfirst=0,expose=1):
+ """Unselect a single column."""
+
+ rval = self.unselect_columns([column],clearfirst,expose)
+ return rval
+
+
+ def unselect_columns(self,column_list,clearfirst=0,expose=1):
+ """Unselect multiple columns."""
+
+ if self.column_selectstate is None:
+ # No source is set
+ return 0
+
+ if clearfirst == 1:
+ self.select_all_columns(expose=0)
+
+ for column in column_list:
+ if (len(self.column_selectstate) <= column):
+ raise RuntimeError,'pgugrid: tried to select nonexistent '+\
+ 'column'
+ else:
+ self.column_selectstate[column]=0
+
+ if column in self.selected_columns:
+ self.selected_columns.remove(column)
+
+ if len(column_list) > 0:
+ self.last_toggled_column=column_list[len(column_list)-1]
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+ def unselect_all_columns(self,expose=1):
+ """Unselect all columns."""
+
+ if self.column_selectstate is None:
+ return 0
+
+ self.column_selectstate[:]=0
+ self.selected_columns=[]
+
+ self.last_toggled_column=None
+ self.last_selected_column=None
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+
+ def toggle_column(self,column,expose=1):
+ """Toggle a single column."""
+
+ if self.column_selectstate[column] == 0:
+ self.select_column(column,0,expose)
+ else:
+ self.unselect_column(column,0,expose)
+
+
+ def toggle_columns(self,column_list,expose=1):
+ """Toggle multiple columns."""
+
+ select=[]
+ unselect=[]
+
+ for column in column_list:
+ if self.column_selectstate[column] == 0:
+ select.append(column)
+ else:
+ unselect.append(column)
+
+ if len(unselect) > 0:
+ self.unselect_columns(unselect,0,0)
+
+ if len(select) > 0:
+ self.select_columns(select,0,0)
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+
+ def toggle_block_columns(self,end_column,expose=1):
+ """Toggle a block of columns between self.last_toggled_column
+ and end_column.
+
+ Parameters:
+ end_column- last column to include in toggle block
+
+ expose- 0 (don't redraw grid) or 1 (redraw grid).
+ Defaults to 1.
+
+ """
+
+ if self.last_toggled_column is None:
+ return
+
+ if self.last_toggled_column < end_column:
+ tlist=range(self.last_toggled_column+1,end_column+1)
+ else:
+ tlist=range(end_column,self.last_toggled_column)
+
+ self.toggle_columns(tlist,expose=0)
+ self.last_toggled_column=end_column
+ if self.column_selectstate[end_column] == 1:
+ self.last_selected_column=end_column
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+
+ def select_block_columns(self,end_column,expose=1):
+ """Select a block of columns between self.last_toggled_column
+ and end_column.
+
+ Parameters:
+ end_column- last column to include in toggle block
+
+ expose- 0 (don't redraw grid) or 1 (redraw grid).
+ Defaults to 1.
+
+ """
+
+ if self.last_toggled_column is None:
+ return
+
+ if self.last_toggled_column < end_column:
+ tlist=range(self.last_toggled_column+1,end_column+1)
+ else:
+ tlist=range(end_column,self.last_toggled_column)
+
+ self.select_columns(tlist,expose=0)
+ self.last_toggled_column=end_column
+ self.last_selected_column=end_column
+
+ if expose == 1:
+
+ nlist = self._columns_updated()
+
+ self.expose()
+
+ self.notify('column-selection-changed',
+ tuple(self.selected_columns))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def select_cell(self,cell,clearfirst=0,expose=1):
+ """Select a single cell."""
+ rval = self.select_cells([cell],clearfirst,expose=expose)
+ return rval
+
+
+ def select_cells(self,cell_list,clearfirst=0,expose=1):
+ """Select multiple cells. cell_list is a list of
+ (source row, grid column) tuples.
+ """
+
+ if self.cell_selectstate is None:
+ # No source is set
+ return 0
+
+ if clearfirst == 1:
+ self.unselect_all_cells(expose=0)
+
+ for cell in cell_list:
+ if ((self.cell_selectstate.shape[0] <= cell[0]) or
+ (self.cell_selectstate.shape[1] <= cell[1])):
+ raise RuntimeError,'pgugrid: tried to select nonexistent '+\
+ 'cell'
+ else:
+ if self.cell_selectstate[cell[0],cell[1]] == 0:
+ self.cell_selectstate[cell[0],cell[1]]=1
+ self.selected_cells.append(cell)
+
+
+ if len(cell_list) > 0:
+ self.last_selected_cell=cell_list[len(cell_list)-1]
+ self.last_toggled_cell=cell_list[len(cell_list)-1]
+
+
+ if expose == 1:
+ nlist=self._cells_updated()
+
+ self.expose()
+
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+
+ def select_all_cells(self,expose=1):
+ """Select all cells.
+ NOT USED YET- MAY NOT EVER BE.
+ """
+
+ if self.cell_selectstate is None:
+ return 0
+
+ self.cell_selectstate[:,:]=1
+ # NOTE: it would be more efficient to implement
+ # selected cells so that it could be a tuple of
+ # slices or a tuple of indices, but this is
+ # simpler to implement (the indices method, that
+ # is). This also applies to row and column
+ # selection. May want to revisit later.
+ self.selected_cells = []
+
+ for i in range(self.cell_selectstate.shape[0]):
+ for j in range(self.cell_selectstate.shape[1]):
+ self.selected_cells.append((i,j))
+
+
+ self.last_toggled_cell=None
+ self.last_selected_cell=None
+
+ if expose == 1:
+
+ nlist=self._cells_updated()
+
+ self.expose()
+
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+
+ return 1
+
+
+ def unselect_cell(self,cell,clearfirst=0,expose=1):
+ """Unselect a single cell."""
+
+ rval = self.unselect_cells([cell],clearfirst,expose)
+ return rval
+
+
+ def unselect_cells(self,cell_list,clearfirst=0,expose=1):
+ """Unselect multiple cells. cell_list is a list of
+ (source row, grid column) tuples.
+ """
+
+ if self.cell_selectstate is None:
+ # No source is set
+ return 0
+
+ if clearfirst == 1:
+ self.select_all_cells(expose=0)
+
+ for cell in cell_list:
+ if ((self.cell_selectstate.shape[0] <= cell[0]) or
+ (self.cell_selectstate.shape[1] <= cell[1])):
+ raise RuntimeError,'pgugrid: tried to select nonexistent '+\
+ 'cell'
+ else:
+ if self.cell_selectstate[cell[0],cell[1]] == 1:
+ self.cell_selectstate[cell[0],cell[1]]=0
+ self.selected_cells.remove(cell)
+
+ # TO DO: check this!!!
+ if len(cell_list) > 0:
+ self.last_toggled_cell=cell_list[len(cell_list)-1]
+
+
+ if expose == 1:
+
+ nlist = self._cells_updated()
+
+ self.expose()
+
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+
+ def unselect_all_cells(self,expose=1):
+ """Unselect all cells."""
+
+ if self.cell_selectstate is None:
+ return 0
+
+ self.cell_selectstate[:,:]=0
+ self.selected_cells = []
+
+ self.last_toggled_cell=None
+ self.last_selected_cell=None
+
+ if expose == 1:
+
+ nlist=self._cells_updated()
+
+ self.expose()
+
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ return 1
+
+
+ def toggle_cell(self,cell,expose=1):
+ """Toggle a single cell."""
+
+ if self.cell_selectstate[cell[0],cell[1]] == 0:
+ self.select_cell(cell,0,expose)
+ else:
+ self.unselect_cell(cell,0,expose)
+
+
+ def toggle_cells(self,cell_list,expose=1):
+ """Toggle multiple cells."""
+
+ select=[]
+ unselect=[]
+
+ for cell in cell_list:
+ if self.cell_selectstate[cell] == 0:
+ select.append(cell)
+ else:
+ unselect.append(cell)
+
+ if len(unselect) > 0:
+ self.unselect_cells(unselect,0,0)
+
+ if len(select) > 0:
+ self.select_cells(select,0,0)
+
+ if expose == 1:
+
+ nlist = self._cells_updated()
+
+ self.expose()
+
+ self.notify('cell-selection-changed',
+ tuple(self.selected_cells))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+
+
+ def toggle_block_cells(self,end_cell,expose=1):
+ """Toggle a block of cells between self.last_toggled_cell
+ and end_cell.
+
+ Parameters:
+ end_cell- last cell to include in toggle block,
+ a (row,column) tuple.
+
+ expose- 0 (don't redraw grid) or 1 (redraw grid).
+ Defaults to 1.
+
+ """
+
+ if self.last_toggled_cell is None:
+ return
+
+ g1=self.src2row[self.last_toggled_cell[0]]
+ g2=self.src2row[end_cell[0]]
+ if g1 < g2:
+ rlist=list(self.row2src[g1:g2+1])
+ else:
+ rlist=list(self.row2src[g2:g1+1])
+
+ if self.last_toggled_cell[1] < end_cell[1]:
+ clist=range(self.last_toggled_cell[1],end_cell[1]+1)
+ else:
+ clist=range(end_cell[1],self.last_toggled_cell[1]+1)
+
+ tlist=[]
+ for row in rlist:
+ for column in clist:
+ ncell=(row,column)
+ if ncell != self.last_toggled_cell:
+ tlist.append(ncell)
+
+ self.toggle_cells(tlist,expose=expose)
+
+ self.last_toggled_cell=end_cell
+ if self.cell_selectstate[end_cell[0],end_cell[1]] == 1:
+ self.last_selected_cell=end_cell
+
+ def _cells_updated(self):
+ """ Internal function called when cell selection has
+ changed. Ensures that row/column selections is
+ consistent with current cross-selection settings.
+ Returns notifications that should be sent out
+ after expose event.
+ """
+
+ notifylist=[]
+ if len(self.selected_cells) > 0:
+ if self.opts.selection_info.row_cell == 0:
+ if len(self.selected_rows) > 0:
+ self.unselect_all_rows(expose=0)
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+ notifylist.append(('row-selection-changed',
+ tuple(self.selected_rows)))
+ elif self.opts.selection_info.row_cell == 1:
+ # find rows that have selected cells in them,
+ # unselect any selected rows that don't have
+ # selected cells in them
+ rstate=Numeric.where(Numeric.sum(self.cell_selectstate,1)>0,
+ 1,0)
+ unselect=Numeric.where(
+ self.row_selectstate*2+rstate == 2,
+ Numeric.arange(self.s_rows),-1)
+ ulist=list(Numeric.compress(unselect > -1, unselect))
+ if len(ulist) > 0:
+ self.unselect_rows(ulist,expose=0)
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+ notifylist.append(('row-selection-changed',
+ tuple(self.selected_rows)))
+ elif self.opts.selection_info.row_cell == 3:
+ # rows that contain selected cells should be
+ # selected; those that don't should not be
+ # selected
+ rstate=Numeric.where(Numeric.sum(self.cell_selectstate,1)>0,
+ 1,0)
+ unselect=Numeric.where(
+ self.row_selectstate*2+rstate == 2,
+ Numeric.arange(self.s_rows),-1)
+ ulist=list(Numeric.compress(unselect > -1, unselect))
+ if len(ulist) > 0:
+ self.unselect_rows(ulist,expose=0)
+
+ select=Numeric.where(
+ self.row_selectstate*2+rstate == 1,
+ Numeric.arange(self.s_rows),-1)
+ slist=list(Numeric.compress(select > -1, select))
+ if len(slist) > 0:
+ self.select_rows(slist,expose=0)
+
+ if ((len(ulist) > 0) or (len(slist) > 0)):
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+ notifylist.append(('row-selection-changed',
+ tuple(self.selected_rows)))
+
+ if self.opts.selection_info.column_cell == 0:
+ if len(self.selected_columns) > 0:
+ self.unselect_all_columns(expose=0)
+ notifylist.append(('column-selection-changed',
+ tuple(self.selected_columns)))
+ elif self.opts.selection_info.column_cell == 1:
+ cstate=Numeric.where(Numeric.sum(self.cell_selectstate,0)>0,
+ 1,0)
+ unselect=Numeric.where(
+ self.column_selectstate*2+cstate == 2,
+ Numeric.arange(self.g_columns),-1)
+ ulist=list(Numeric.compress(unselect > -1, unselect))
+ if len(ulist) > 0:
+ self.unselect_columns(ulist,expose=0)
+ notifylist.append(('column-selection-changed',
+ tuple(self.selected_columns)))
+ elif self.opts.selection_info.column_cell == 3:
+ cstate=Numeric.where(Numeric.sum(self.cell_selectstate,0)>0,
+ 1,0)
+ unselect=Numeric.where(
+ self.column_selectstate*2+cstate == 2,
+ Numeric.arange(self.g_columns),-1)
+ ulist=list(Numeric.compress(unselect > -1, unselect))
+ if len(ulist) > 0:
+ self.unselect_columns(ulist,expose=0)
+
+ select=Numeric.where(
+ self.column_selectstate*2+cstate == 1,
+ Numeric.arange(self.g_columns),-1)
+ slist=list(Numeric.compress(select > -1, select))
+ if len(slist) > 0:
+ self.select_columns(slist,expose=0)
+
+ if ((len(ulist) > 0) or (len(slist) > 0)):
+ notifylist.append(('column-selection-changed',
+ tuple(self.selected_columns)))
+
+ else:
+ if self.opts.selection_info.row_cell == 3:
+ if len(self.selected_rows) > 0:
+ self.unselect_all_rows(expose=0)
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+ notifylist.append(('row-selection-changed',()))
+
+ if self.opts.selection_info.column_cell == 3:
+ if len(self.selected_columns) > 0:
+ self.unselect_all_columns(expose=0)
+ notifylist.append(('column-selection-changed',()))
+
+ if ((self.editing_cell is not None) and
+ (self.cell_selectstate[self.editing_cell[0],
+ self.editing_cell[1]] == 0)):
+ self.end_cell_edit()
+
+ return notifylist
+
+ def _rows_updated(self):
+ """ Internal function called when row selection has
+ changed. Ensures that cell/column selections is
+ consistent with current cross-selection settings.
+ Returns a list of notifications to send out.
+ """
+
+ notifylist=[]
+ if self.g_columns == 0:
+ # No columns are defined yet, so
+ # there must be no column/cell selections
+ return notifylist
+
+ if len(self.selected_rows) > 0:
+ if self.opts.selection_info.row_cell == 0:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+ elif self.opts.selection_info.row_cell == 1:
+ # unselect any selected cells that aren't contained
+ # in selected rows
+ rvec=Numeric.repeat(Numeric.reshape(self.row_selectstate,
+ (self.s_rows,1)),self.g_columns,1)
+
+ unselect=Numeric.reshape(Numeric.where(
+ self.cell_selectstate > rvec,1,0),
+ (self.s_rows*self.g_columns,))
+ cind=Numeric.indices((self.s_rows,self.g_columns))
+ rarr=Numeric.reshape(cind[0],(self.s_rows*self.g_columns,))
+ carr=Numeric.reshape(cind[1],(self.s_rows*self.g_columns,))
+
+ rcarr=Numeric.compress(unselect > 0,rarr)
+ ccarr=Numeric.compress(unselect > 0,carr)
+ uarr=Numeric.zeros((rcarr.shape[0],2))
+ uarr[:,0]=rcarr
+ uarr[:,1]=ccarr
+
+ ulist=map(tuple,uarr)
+ if len(ulist) > 0:
+ self.unselect_cells(ulist,expose=0)
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+
+ elif self.opts.selection_info.row_cell == 3:
+ # unselect any selected cells that aren't contained
+ # in selected rows. Force selection of first cell
+ # in any row that doesn't contain any selected cells
+ # (ensures that row can be unselected again through
+ # grid in shapeslayer case if no row titles are shown)
+
+ rvec=Numeric.repeat(Numeric.reshape(self.row_selectstate,
+ (self.s_rows,1)),self.g_columns,1)
+
+ unselect=Numeric.reshape(Numeric.where(
+ self.cell_selectstate > rvec,1,0),
+ (self.s_rows*self.g_columns,))
+ cind=Numeric.indices((self.s_rows,self.g_columns))
+ urarr=Numeric.reshape(cind[0],(self.s_rows*self.g_columns,))
+ ucarr=Numeric.reshape(cind[1],(self.s_rows*self.g_columns,))
+
+ urcarr=Numeric.compress(unselect > 0,urarr)
+ uccarr=Numeric.compress(unselect > 0,ucarr)
+ uarr=Numeric.zeros((urcarr.shape[0],2))
+ uarr[:,0]=urcarr
+ uarr[:,1]=uccarr
+
+ ulist=map(tuple,uarr)
+ if len(ulist) > 0:
+ self.unselect_cells(ulist,expose=0)
+
+ sumc=Numeric.sum(self.cell_selectstate,1)
+ select=Numeric.where(sumc < self.row_selectstate,
+ Numeric.arange(self.s_rows),-1)
+ srcarr=Numeric.compress(select > -1,select)
+ sarr=Numeric.zeros((srcarr.shape[0],2))
+ sarr[:,0]=srcarr
+ sarr[:,1]=Numeric.zeros((srcarr.shape[0],))
+
+ slist=map(tuple,sarr)
+ if len(slist) > 0:
+ self.select_cells(slist,expose=0)
+
+ if (len(ulist) > 0) or (len(slist) > 0):
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+
+ if self.opts.selection_info.row_column == 0:
+ if len(self.selected_columns) > 0:
+ self.unselect_all_columns(expose=0)
+ notifylist.append(('column-selection-changed',
+ tuple()) )
+
+ else:
+ if self.opts.selection_info.row_cell == 3:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ notifylist.append(('cell-selection-changed',()))
+
+ # If row selection changes while a cell is being edited,
+ # cancel editing and clear cell selections.
+ if (self.editing_cell is not None):
+ self.cancel_cell_edit()
+ self.unselect_all_cells()
+
+ return notifylist
+
+
+ def _columns_updated(self):
+ """ Internal function called when column selection has
+ changed. Ensures that row/cell selections is
+ consistent with current cross-selection settings.
+ Returns a list of notifications to send out.
+ """
+
+ notifylist=[]
+ if len(self.selected_columns) > 0:
+ if self.opts.selection_info.column_cell == 0:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+ elif self.opts.selection_info.column_cell == 1:
+ # unselect any selected cells that aren't contained
+ # in selected columns
+ if self.s_rows > 0:
+ rvec=Numeric.repeat(Numeric.reshape(
+ self.column_selectstate,
+ (1,self.g_columns)),self.s_rows,0)
+
+ unselect=Numeric.reshape(Numeric.where(
+ self.cell_selectstate > rvec,1,0),
+ (self.s_rows*self.g_columns,))
+ cind=Numeric.indices((self.s_rows,self.g_columns))
+ rarr=Numeric.reshape(cind[0],(self.s_rows*self.g_columns,))
+ carr=Numeric.reshape(cind[1],(self.s_rows*self.g_columns,))
+
+ rcarr=Numeric.compress(unselect > 0,rarr)
+ ccarr=Numeric.compress(unselect > 0,carr)
+ uarr=Numeric.zeros((rcarr.shape[0],2))
+ uarr[:,0]=rcarr
+ uarr[:,1]=ccarr
+
+ ulist=map(tuple,uarr)
+ if len(ulist) > 0:
+ self.unselect_cells(ulist,expose=0)
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+
+ elif self.opts.selection_info.column_cell == 3:
+ # unselect any selected cells that aren't contained
+ # in selected columns. Force selection of first cell
+ # in any column that doesn't contain any selected cells
+ # (ensures that column can be unselected again through
+ # grid in shapeslayer case if no column titles are shown)
+
+ if self.s_rows > 0:
+ rvec=Numeric.repeat(Numeric.reshape(
+ self.column_selectstate,
+ (1,self.g_columns)),self.s_rows,0)
+
+ unselect=Numeric.reshape(Numeric.where(
+ self.cell_selectstate > rvec,1,0),
+ (self.s_rows*self.g_columns,))
+ cind=Numeric.indices((self.s_rows,self.g_columns))
+ urarr=Numeric.reshape(cind[0],
+ (self.s_rows*self.g_columns,))
+ ucarr=Numeric.reshape(cind[1],
+ (self.s_rows*self.g_columns,))
+
+ urcarr=Numeric.compress(unselect > 0,urarr)
+ uccarr=Numeric.compress(unselect > 0,ucarr)
+ uarr=Numeric.zeros((urcarr.shape[0],2))
+ uarr[:,0]=urcarr
+ uarr[:,1]=uccarr
+
+ ulist=map(tuple,uarr)
+ if len(ulist) > 0:
+ self.unselect_cells(ulist,expose=0)
+
+ sumc=Numeric.sum(self.cell_selectstate,1)
+ select=Numeric.where(sumc < self.row_selectstate,
+ Numeric.arange(self.s_rows),-1)
+ srcarr=Numeric.compress(select > -1,select)
+ sarr=Numeric.zeros((srcarr.shape[0],2))
+ sarr[:,0]=srcarr
+ sarr[:,1]=Numeric.zeros((srcarr.shape[0],))
+
+ slist=map(tuple,sarr)
+ if len(slist) > 0:
+ self.select_cells(slist,expose=0)
+
+ if (len(ulist) > 0) or (len(slist) > 0):
+ notifylist.append(('cell-selection-changed',
+ tuple(self.selected_cells)))
+
+ if self.opts.selection_info.row_column == 0:
+ if len(self.selected_rows) > 0:
+ self.unselect_all_rows(expose=0)
+ if self.src_type == SRC_SHAPESLAYER:
+ self.layer.display_change()
+ notifylist.append(('row-selection-changed',
+ tuple()) )
+
+ else:
+ if self.opts.selection_info.column_cell == 3:
+ if len(self.selected_cells) > 0:
+ self.unselect_all_cells(expose=0)
+ notifylist.append(('cell-selection-changed',()))
+
+
+
+ if ((self.editing_cell is not None) and
+ (self.cell_selectstate[self.editing_cell[0],
+ self.editing_cell[1]] == 0)):
+ self.end_cell_edit()
+
+ return notifylist
+
+ def _update_row_title_width(self):
+ if self.opts.show_row_titles == 1:
+ if ( (self.title_font is not None) and
+ (self.opts.row_title_type == 'user-defined') ):
+ width = 0
+ for item in self.row_titles:
+ width = max( self.title_font.width(item)+2*self.pad,
+ width )
+ self.row_title_width = width
+ elif (self.title_font is not None) and (self.src is not None):
+ self.row_title_width=self.title_font.width(
+ str(len(self.src2row)))+2*self.pad
+ else:
+ self.row_title_width=0
+ else:
+ self.row_title_width=0
+
+ def _update_column_title_height(self):
+ if self.opts.show_column_titles == 1:
+ if self.title_font is not None:
+ self.column_title_height = self.title_font.ascent + 2*self.pad
+ else:
+ self.column_title_height=0
+ else:
+ self.column_title_height = 0
+
+ def _update_column_width(self,column,cell_width):
+ """Reset a column's width, and update other
+ columns' start positions accordingly.
+ """
+
+ self._ColumnDefs[column].width=cell_width
+
+ startx=self._ColumnDefs[column].start_x +\
+ self._ColumnDefs[column].width + 1
+
+ for idx in range(column+1,self.g_columns):
+ self._ColumnDefs[idx].start_x=startx
+ startx=startx+self._ColumnDefs[idx].width+1
+
+ def reset_startrow(self, row):
+ """ Check if row is visible. If it is,
+ return without doing anything. If it
+ isn't, update the GUI so that it
+ is visible. row should be in source
+ coordinates. Does nothing if row
+ is None or isn't in the current subset.
+ """
+ if not (self.flags() & gtk.REALIZED):
+ return
+
+ c_row = self.src2row[row]
+ if c_row < 0:
+ # requested row is either None, or is not
+ # part of the currently displayed subset.
+ return
+
+ win = self._area.get_window()
+ height = win.height
+
+ base_height = height
+ column_title_height = self.column_title_height
+
+ # The extra 1's account for the 1-pixel wide lines drawn
+ # between cells.
+ data_height = base_height - column_title_height -1
+ if self.opts.show_column_titles == 1:
+ data_height=data_height - 1
+
+ disp_rows = int(data_height / ( self.row_height + 1 )) + 1
+ first_row = self.start_row
+ last_row = first_row + disp_rows - 1
+
+ if ((c_row >= self.start_row) and (c_row < last_row)):
+ return
+
+ # If c_row isn't in current window, scroll
+ # so it is the new start row.
+ vmax = self.vadj.__getattr__('upper')
+ if c_row >= vmax:
+ self.vadj.set_value(vmax)
+ elif c_row < 0:
+ self.vadj.set_value(0)
+ else:
+ self.vadj.set_value(c_row)
+
+ self.vadj.value_changed()
+
+
+ def reset_startcolumn(self, column):
+ """ Check if column is visible. If it is,
+ return without doing anything. If it
+ isn't, update the GUI so that it
+ is visible. Does nothing if column
+ is outside the range of columns.
+ """
+ if not (self.flags() & gtk.REALIZED):
+ return
+
+
+ win = self._area.get_window()
+ width = win.width
+
+ base_width = width
+ row_title_width = self.row_title_width
+
+ # The extra 1's account for the 1-pixel wide lines drawn
+ # between cells.
+ data_width = base_width - row_title_width -1
+ if self.opts.show_row_titles == 1:
+ data_width=data_width - 1
+
+ cstartx = self._ColumnDefs[self.start_column].start_x
+ cendx=cstartx+data_width
+
+ ccolumn=column
+ if ccolumn < 0:
+ ccolumn=0
+ elif ccolumn >= self.g_columns:
+ ccolumn=self.g_columns-1
+
+ nstartx=self._ColumnDefs[ccolumn].start_x
+ nendx=nstartx+self._ColumnDefs[ccolumn].width
+
+ if ((nstartx >= cstartx) and (nendx < cendx)):
+ return
+
+ # If ccolumn isn't in current window, scroll
+ # so it is the new start column.
+ self.hadj.set_value(ccolumn)
+ self.hadj.value_changed()
+
+
+ def click( self, widget, event ):
+ """ User has clicked on the widget.
+ """
+
+ if len(self.column_widths) < 1:
+ return
+
+ self._area.grab_focus()
+ #
+ # determine the column that the user clicked in by first offsetting
+ # for the current start column (accounts for columns scrolled off the
+ # left edge).
+ #
+ # After this if-block, nColumn should be -1 if a row title
+ # was clicked, None if the user clicked off the right
+ # edge of the grid, and the column number if a user
+ # clicked on a cell.
+ #
+
+ if ((self.opts.show_row_titles == 1) and
+ (event.x < self.row_title_width+2)):
+ # clicked on row title column
+ gColumn = -1
+ else:
+ #
+ # now actually look for the right column.
+ # If gColumn is None at the end
+ # then the user clicked off the right edge.
+ #
+ gColumn = None
+ current = 1
+ if self.opts.show_row_titles == 1:
+ current = self.row_title_width+2
+
+ for i in range(self.start_column,len(self.column_widths)):
+ current = current + self.column_widths[i] + 1
+ if event.x < current:
+ gColumn = i
+ break
+
+
+ #
+ # Determine the row. If its -1 then they clicked a 'title'. If it
+ # is None then they clicked off the bottom edge.
+ #
+ gRow = None
+ if ((self.opts.show_column_titles == 1) and
+ (event.y < (self.column_title_height + 2))):
+ gRow = -1
+ else:
+ # NOTE: the max(self.start_row-1,0) below is a kludge to
+ # avoid an offset problem after scrolling (first scroll
+ # click doesn't seem to actually cause the window to scroll,
+ # even though vadj updates)
+ current=1
+ if self.opts.show_column_titles == 1:
+ current = self.column_title_height+2
+
+ row = self.start_row+\
+ int(Numeric.floor((event.y-current) /(self.row_height + 1)))
+
+ if row < self.g_rows:
+ gRow = row
+
+ if ((gColumn is None) or (gRow is None) or
+ ((gColumn == -1) and (gRow == -1))):
+ # User did not click on a cell or
+ # row/column header
+ return
+
+ if gRow != -1:
+ sRow=self.row2src[gRow]
+ else:
+ sRow = -1
+
+ clickstr=None
+ clickarg=None
+
+ if (event.state & gtk.GDK.SHIFT_MASK):
+ # last click information only applies
+ # if the click was not modified by
+ # shift or control (for the purposes
+ # of pgugrid). Last click is not
+ # related to last selected.
+ self.last_click_cell=None
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+
+ if event.button == 1:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-shift-left'
+ clickarg=(gColumn,)
+ elif gColumn == -1:
+ clickstr='row-shift-left'
+ clickarg=(sRow,)
+ else:
+ clickstr='cell-shift-left'
+ clickarg=(sRow,gColumn)
+ elif event.button == 3:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-shift-right'
+ clickarg=(gColumn,)
+ elif gColumn == -1:
+ clickstr='row-shift-right'
+ clickarg=(sRow,)
+ else:
+ clickstr='cell-shift-right'
+ clickarg=(sRow,gColumn)
+
+ elif (event.state & gtk.GDK.CONTROL_MASK):
+ self.last_click_cell=None
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+
+ if event.button == 1:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-ctrl-left'
+ clickarg=(gColumn,)
+ elif gColumn == -1:
+ clickstr='row-ctrl-left'
+ clickarg=(sRow,)
+ else:
+ clickstr='cell-ctrl-left'
+ clickarg=(sRow,gColumn)
+ elif event.button == 3:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-ctrl-right'
+ clickarg=(gColumn,)
+ elif gColumn == -1:
+ clickstr='row-ctrl-right'
+ clickarg=(sRow,)
+ else:
+ clickstr='cell-ctrl-right'
+ clickarg=(sRow,gColumn)
+ else:
+ # Current click event is not modified
+ # by shift or control. First, establish
+ # if this is a double click event or not.
+
+ if self.last_click_button == event.button:
+ if event.button == 1:
+ if ((sRow == self.last_click_row) and
+ (gColumn == -1)):
+ clickstr='row-double-left'
+ clickarg=(sRow,)
+ elif ((gColumn == self.last_click_column) and
+ (gRow == -1)):
+ clickstr='column-double-left'
+ clickarg=(gColumn,)
+ elif ((sRow == self.last_click_cell[0]) and
+ (gColumn == self.last_click_cell[1])):
+ clickstr='cell-double-left'
+ clickarg=(sRow,gColumn)
+ elif event.button == 3:
+ if ((sRow == self.last_click_row) and
+ (gColumn == -1)):
+ clickstr='row-double-right'
+ clickarg=(sRow,)
+ elif ((gColumn == self.last_click_column) and
+ (gRow == -1)):
+ clickstr='column-double-right'
+ clickarg=(gColumn,)
+ elif ((sRow == self.last_click_cell[0]) and
+ (gColumn == self.last_click_cell[1])):
+ clickstr='cell-double-right'
+ clickarg=(sRow,gColumn)
+
+ if clickstr is not None:
+ # a double click event has been detected.
+ # clear the last_click values
+ self.last_click_cell=(None,None)
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+ else:
+ self.last_click_cell=(None,None)
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=event.button
+ if event.button == 1:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-left'
+ clickarg=(gColumn,)
+ self.last_click_column=gColumn
+ elif gColumn == -1:
+ clickstr='row-left'
+ clickarg=(sRow,)
+ self.last_click_row=sRow
+ else:
+ clickstr='cell-left'
+ clickarg=(sRow,gColumn)
+ self.last_click_cell=(sRow,gColumn)
+ elif event.button == 3:
+ if gRow == -1:
+ # A column header was clicked
+ clickstr='column-right'
+ clickarg=(gColumn,)
+ self.last_click_column=gColumn
+ elif gColumn == -1:
+ clickstr='row-right'
+ clickarg=(sRow,)
+ self.last_click_row=sRow
+ else:
+ clickstr='cell-right'
+ clickarg=(sRow,gColumn)
+ self.last_click_cell=(sRow,gColumn)
+
+
+ if ((clickstr is not None) and
+ (self.opts.events.has_key(clickstr))):
+ # click event is recognized, and current
+ # configuration has defined an event for it.
+ self._perform_click_action(clickstr,clickarg)
+
+ # Pass clicked event with grid row, column
+ self.notify('clicked',gRow,gColumn,event)
+
+
+
+ def _perform_click_action(self,clickstr,clickarg):
+ """Map the click event and arguments onto the
+ correct function call for the current configuration.
+ """
+ # Find out what this action is supposed to do
+ clickfunc=self.opts.events[clickstr]
+
+ if clickfunc == 'select-single-row':
+ # Select a single row at a time, clearing all
+ # previous selections.
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.select_row(clickarg[0],clearfirst=1,expose=1)
+ elif clickfunc == 'unselect-single-row':
+ # Unselect the current row (and only that row)
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.unselect_row(clickarg[0],clearfirst=0,expose=1)
+ elif clickfunc == 'toggle-single-row':
+ # Toggle a single row, making sure all other rows
+ # are unselected.
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ if self.row_selectstate[clickarg[0]] == 1:
+ self.unselect_all_rows()
+ else:
+ self.unselect_all_rows(expose=0)
+ self.select_row(clickarg[0])
+
+ elif clickfunc == 'toggle-block-rows':
+ # Toggle a block of rows between the last selected
+ # row and the current one.
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.toggle_block_rows(clickarg[0],expose=1)
+ elif clickfunc == 'toggle-multiple-rows':
+ # Toggle a single row without affecting other rows
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.toggle_row(clickarg[0],expose=1)
+
+ elif clickfunc == 'select-block-rows':
+ # Select a block of rows between the last selected
+ # row and the current one.
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.select_block_rows(clickarg[0],expose=1)
+ elif clickfunc == 'select-multiple-rows':
+ # Select a single row without affecting other rows
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.select_row(clickarg[0],expose=1)
+ elif clickfunc == 'select-single-column':
+ # Select a single column at a time, clearing all
+ # previous selections.
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.select_column(clickarg[0],clearfirst=1,expose=1)
+ elif clickfunc == 'unselect-single-column':
+ # Unselect the current column
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.unselect_column(clickarg[0],clearfirst=0,expose=1)
+ elif clickfunc == 'toggle-single-column':
+ # Toggle a single column, making sure all other columns
+ # are unselected.
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ if self.column_selectstate[clickarg[0]] == 1:
+ self.unselect_all_columns()
+ else:
+ self.unselect_all_columns(expose=0)
+ self.select_column(clickarg[0])
+
+ elif clickfunc == 'toggle-block-columns':
+ # Toggle a block of columns between the last selected
+ # column and the current one.
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.toggle_block_columns(clickarg[0],expose=1)
+
+ elif clickfunc == 'toggle-multiple-columns':
+ # Toggle a single column without affecting other columns
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.toggle_column(clickarg[0],expose=1)
+
+ elif clickfunc == 'select-block-columns':
+ # Select a block of columns between the last selected
+ # column and the current one.
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.select_block_columns(clickarg[0],expose=1)
+
+ elif clickfunc == 'select-multiple-columns':
+ # Toggle a single column without affecting other columns
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.select_column(clickarg[0],expose=1)
+
+ elif clickfunc == 'select-single-cell':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+
+ self.select_cell(clickarg,clearfirst=1,expose=1)
+
+ elif clickfunc == 'unselect-single-cell':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+
+ self.unselect_cell(clickarg,clearfirst=0,expose=1)
+
+ elif clickfunc == 'toggle-single-cell':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+
+ if self.cell_selectstate[clickarg[0],clickarg[1]] == 1:
+ self.unselect_all_cells()
+ else:
+ self.unselect_all_cells(expose=0)
+ self.select_cell(clickarg)
+
+ elif clickfunc == 'toggle-block-cells':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+
+ self.toggle_block_cells(clickarg,expose=1)
+
+ elif clickfunc == 'toggle-multiple-cells':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+
+ self.toggle_cell(clickarg,expose=1)
+
+ elif clickfunc == 'start-cell-edit':
+ if clickstr not in _cell_clickevents:
+ txt='pgugrid: cell cannot be selected in response\n'
+ txt=txt+' to a row or column click event.'
+ raise RuntimeError,txt
+ self.start_cell_edit(clickarg)
+
+ elif clickfunc == 'sort-by-column':
+ # Sort by column (ascending)
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.sort_reverse=0
+ if clickstr in _column_clickevents:
+ self.sort_by_column(clickarg[0],expose=1)
+ else:
+ self.sort_by_column(clickarg[1],expose=1)
+
+ elif clickfunc == 'reverse-sort-by-column':
+ # Sort by column (descending)
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.sort_reverse=1
+ if clickstr in _column_clickevents:
+ self.sort_by_column(clickarg[0],expose=1)
+ else:
+ self.sort_by_column(clickarg[1],expose=1)
+ elif clickfunc == 'toggle-sort-by-column':
+ # Sort by column (alternate between ascending
+ # and descending with consecutive calls). If
+ # a new column is being sorted, start with
+ # ascending sort regardless of the ascending/descending
+ # state for the last column sorted.
+ if clickstr in _row_clickevents:
+ txt='pgugrid: column cannot be selected in response\n'
+ txt=txt+' to a row click event'
+ raise RuntimeError,txt
+
+ self.sort_reverse=abs(self.sort_reverse-1)
+ if clickstr in _column_clickevents:
+ if self.sort_column != clickarg[0]:
+ self.sort_reverse=0
+ self.sort_by_column(clickarg[0],expose=1)
+ else:
+ if self.sort_column != clickarg[1]:
+ self.sort_reverse=0
+ self.sort_by_column(clickarg[1],expose=1)
+ elif clickfunc == 'translate-view-to-row':
+ # If source type is shapes layer, translate view
+ # to that row.
+ if clickstr in _column_clickevents:
+ txt='pgugrid: row cannot be selected in response\n'
+ txt=txt+' to a column click event'
+ raise RuntimeError,txt
+
+ self.translate_view_to_row(clickarg[0])
+
+ else:
+ raise '_perform_click_action: unrecognized click function'
+
+
+ def changed( self, widget ):
+ """Track changes to the scrollbars and record the row/column
+ """
+ self.start_row = int(self.vadj.value)
+ self.start_column = int(self.hadj.value)
+ self.expose()
+
+ def refresh( self, *args ):
+ """ Refresh grid from source (use if source has been
+ internally or externally changed).
+ """
+ # cancel any editing operations
+ if self.editing_cell is not None:
+ self.cancel_cell_edit()
+ self.unselect_all_cells(expose=0)
+
+ if self.src_type == SRC_LISTUNDEF:
+ if len(self.src) == 0:
+ self.expose()
+ return
+
+ if type(self.src[0]) == type([]):
+ self.src_type=SRC_LISTLIST
+ elif type(self.src[0]) == type((1,)):
+ self.src_type=SRC_LISTLIST
+ else:
+ self.src_type=SRC_LISTOBJ
+
+ self._generate_row_indices()
+
+ self.expose()
+
+
+ def resize_to_default(self,max_width=400,max_height=300):
+ """ Resize to the default size calculated by
+ get_default_size, tp a maximum width of max_width
+ and maximum height of max_height.
+ """
+
+ newsize=self.get_default_size(max_width,max_height)
+ self.set_usize(newsize[0],newsize[1])
+
+ def select_next_row(self,clearfirst=1,expose=1):
+ """If a row is selected, select the next
+ row in the current sorting scheme. If no row
+ is currently selected, do nothing. Uses the
+ last selected row if multiple rows are selected.
+ Clears all other selections if clearfirst is 1.
+ """
+ if len(self.selected_rows) == 0:
+ return
+
+ srow=self.selected_rows[len(self.selected_rows)-1]
+
+ if srow not in self.row2src:
+ # selected row is not in the display. do nothing.
+ return
+
+ g_row=self.src2row[srow]
+ g_row=g_row+1
+ if g_row >= len(self.row2src):
+ g_row=0
+
+ nsrow=self.row2src[g_row]
+ self.select_row(nsrow,clearfirst,expose)
+
+ def grid2src(self,grid_row):
+ """ Convert grid row to source row (returns -1 if the
+ row is out of range)
+ """
+
+ if type(grid_row) in [type([]),type(())]:
+ if len(grid_row) == 0:
+ return ()
+
+ garr=Numeric.array(grid_row)
+ mask=Numeric.where(garr >= len(self.row2src),
+ -1,
+ Numeric.where(garr<0,-1,1))
+ garr=Numeric.where(garr >= len(self.row2src),
+ 0,
+ Numeric.where(garr<0,0,garr))
+ sarr=Numeric.where(mask>0,Numeric.take(self.row2src,list(garr)),
+ mask)
+ return tuple(sarr)
+ else:
+ if (grid_row > -1) and (grid_row < len(self.row2src)):
+ return self.row2src[grid_row]
+ else:
+ return -1
+
+ def src2grid(self,src_row):
+ """ Convert source row to grid row (returns -1 if source
+ row is not in grid- this may be the case if a subset
+ is specified or if the source row is None or if the
+ row is out of range)
+ """
+
+ if type(src_row) in [type([]),type(())]:
+ if len(src_row) == 0:
+ return ()
+
+ sarr=Numeric.array(src_row)
+ mask=Numeric.where(sarr >= len(self.src2row),
+ -1,
+ Numeric.where(sarr<0,-1,1))
+ sarr=Numeric.where(sarr >= len(self.src2row),
+ 0,
+ Numeric.where(sarr<0,0,sarr))
+ garr=Numeric.where(mask>0,Numeric.take(self.src2row,list(sarr)),
+ mask)
+ garr=Numeric.maximum(garr,-1)
+
+ return tuple(garr)
+ else:
+ if (src_row > -1) and (src_row < len(self.src2row)):
+ return max(self.src2row[src_row],-1)
+ else:
+ return -1
+
+ def get_current_columns(self):
+ """ Return the current column info. Is a tuple
+ of lists:
+ (members,titles,editables,formats,types,
+ nodatas,justifys,title_justifys,widths,start_x's,force_widths,
+ force_width_chars, entry_chars)
+ """
+ members=[]
+ titles=[]
+ editables=[]
+ formats=[]
+ types=[]
+ nodatas=[]
+ justifys=[]
+ title_justifys=[]
+ widths=[]
+ start_xs=[]
+ force_widths=[]
+ force_width_chars=[]
+ entry_chars=[]
+ for item in self._ColumnDefs:
+ members.append(item.member)
+ titles.append(item.title)
+ editables.append(item.editable)
+ formats.append(item.format)
+ types.append(item.type)
+ nodatas.append(item.nodata)
+ justifys.append(item.justification)
+ title_justifys.append(item.title_justification)
+ widths.append(item.width)
+ start_xs.append(item.start_x)
+ force_widths.append(item.force_width)
+ force_width_chars.append(item.force_width_chars)
+ entry_chars.append(item.entry_chars)
+
+ return (members,titles,editables,formats,types,nodatas,
+ justifys,title_justifys,widths,start_xs,force_widths,
+ force_width_chars, entry_chars)
+
+
+ def get_default_size(self,max_width=400,max_height=300):
+ """ Calculate a sensible size to allocate for the grid.
+ If size is greater than max_width x max_height,
+ try to break on column and row boundaries.
+ Returns a (width,height) tuple.
+ """
+
+ if len(self._ColumnDefs) == 0:
+ return (max_width,max_height)
+
+ # offsets account for scrollbars and finite line width
+ if self.vscroll_shown == 1:
+ cwidth=self._ColumnDefs[self.g_columns-1].start_x+\
+ self._ColumnDefs[self.g_columns-1].width+20
+ else:
+ cwidth=self._ColumnDefs[self.g_columns-1].start_x+\
+ self._ColumnDefs[self.g_columns-1].width+2
+
+ idx=self.g_columns-1
+ while ((cwidth > max_width) and (idx > 0)):
+ cwidth=cwidth-self._ColumnDefs[idx].width-1
+ idx=idx-1
+
+ cwidth=min([cwidth,max_width])
+
+ if self.hscroll_shown == 1:
+ cheight=(self.row_height+1)*len(self.row2src)+20
+ else:
+ cheight=(self.row_height+1)*len(self.row2src)+2
+
+ if self.opts.show_column_titles == 1:
+ cheight=cheight+self.column_title_height+1
+
+ if (cheight > max_height):
+ cheight=cheight-((self.row_height+1)*(int(
+ Numeric.ceil(float((cheight-max_height))/(self.row_height+1)))))
+
+ # Make sure that minimum height accounts for vertical
+ # scrollbar, minimum width for horizontal, if shown
+ # (if grid is small enough, scrollbars will determine
+ # minimum size)
+ mswidth=0
+ msheight=0
+
+ if self.hscroll_shown == 1:
+ mswidth = mswidth + SCROLL_DIM2
+ msheight = msheight + SCROLL_DIM1
+
+ if self.vscroll_shown == 1:
+ mswidth = mswidth + SCROLL_DIM1
+ msheight = msheight + SCROLL_DIM2
+
+ cwidth = max(cwidth, mswidth)
+ cheight = max(cheight, msheight)
+
+
+ return (cwidth,cheight)
+
+ def expose( self, *args ):
+ """Draw the widget
+ """
+ if not (self.flags() & gtk.REALIZED):
+ return
+
+ if self._flags['frozen'] == 1:
+ return
+
+ #
+ # create a memory pixmap to render into
+ #
+ try:
+ win=self._area.get_window()
+ width = win.width
+ height = win.height
+ except:
+ return
+
+ pix = self._pixmap
+
+ #
+ # prefetch the style
+ #
+ style = self.get_style()
+
+ if self.style_list[0] is None:
+ # Start by creating default styles. Note that before,
+ # gtk.STATE_PRELIGHT was used to indicate selected cells,
+ # and gtk.STATE_SELECTED was used for titles (regardless
+ # of selection). By default, revert back to this
+ # convention.
+ cellstyle=style.copy()
+ cellstyle.bg_gc[gtk.STATE_NORMAL]=style.white_gc
+
+ cellstyle.bg_gc[gtk.STATE_SELECTED]=style.bg_gc[gtk.STATE_PRELIGHT]
+ self.style_list[0]=cellstyle
+
+ # row titles
+ titlestyle=style.copy()
+ titlestyle.bg_gc[gtk.STATE_NORMAL]=style.bg_gc[gtk.STATE_NORMAL]
+ self.style_list[1]=titlestyle
+
+ # column titles
+ titlestyle=style.copy()
+ titlestyle.bg_gc[gtk.STATE_NORMAL]=style.bg_gc[gtk.STATE_NORMAL]
+ self.style_list[2]=titlestyle
+
+ if self.default_style_reset_flag == 1:
+ # User has reset default style
+ self._add_style(0,self.default_style)
+ self.default_style_reset_flag = 0
+
+ if self.default_row_title_style_reset_flag == 1:
+ # User has reset default row title style
+ self._add_style(1,self.default_row_title_style)
+ self.default_row_title_style_reset_flag = 0
+
+ if self.default_col_title_style_reset_flag == 1:
+ # User has reset default column title style
+ self._add_style(2,self.default_col_title_style)
+ self.default_col_title_style_reset_flag = 0
+
+ if self.styles_to_add is not None:
+ for item in self.styles_to_add:
+ self._add_style(item[0],item[1])
+
+ self.styles_to_add=None
+
+ # Note on drawing order:
+ #
+ # - background (cell style default background)
+ # - empty message (if relevant): returns
+ # - If row titles present, draw the rectangle
+ # background covering all row titles, then
+ # text row number of first row title, second
+ # row title, etc.
+ # - For i in range (first column, last column+1)
+ # - If column titles are present, draw the
+ # rectangle for the current column title
+ # background, then the text.
+ # - For each cell in the column, draw the background
+ # rectangle, then the text.
+ #
+
+ #
+ # clear the pixmap
+ #
+ gtk.draw_rectangle( pix, self.style_list[0].bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE, 0, 0, width, height )
+
+ #print 'exposing...'
+ #print 'pix: ',self._pixmap
+ if ((self.src_type in [SRC_NONE, SRC_LISTUNDEF]) and
+ (len(self._ColumnDefs) == 0)):
+ msg = self.empty_msg
+ if (msg is not None) and (len(msg) > 0):
+ msg_width = self.title_font.width( msg )
+ msg_height = self.title_font.height( msg )
+ msg_x = (width / 2) - (msg_width / 2)
+ msg_y = (height / 2) + (msg_height / 2 )
+ gtk.draw_text( pix, self.title_font,
+ style.fg_gc[gtk.STATE_INSENSITIVE],
+ msg_x, msg_y, msg )
+ self._area.draw_pixmap(style.white_gc, self._pixmap,
+ 0, 0, 0, 0,
+ width, height )
+
+ if self.bCalcAdjustments:
+ self.calc_adjustments()
+
+ return gtk.FALSE
+
+
+ #
+ # track changes in column width because of wide columns
+ #
+ bResetAdj = gtk.FALSE
+
+ #
+ # calculate the number of rows to draw
+ #
+ base_height = height
+ column_title_height = self.column_title_height
+ data_height = base_height - column_title_height - 1
+ if self.opts.show_column_titles == 1:
+ data_height=data_height-1
+
+ disp_rows = int(Numeric.floor(
+ data_height / ( self.row_height + 1 ))) + 1
+
+ first_row = self.start_row
+ last_row = first_row + disp_rows - 1
+ if last_row > self.g_rows-1:
+ last_row = self.g_rows-1
+ disp_rows=last_row-first_row+1
+
+ first_column = self.start_column
+ last_column = self.g_columns
+
+ sum_row_heights=disp_rows*(self.row_height+1)
+
+ if self.opts.show_row_titles == 1:
+ rt_height= disp_rows*( self.row_height + 1 ) + \
+ self.column_title_height
+ rt_offset=self.column_title_height + self.row_height + 1 - \
+ self.pad
+
+ if self.opts.show_column_titles == 1:
+ rt_height = rt_height + 1
+ rt_offset = rt_offset + 1
+
+ gtk.draw_rectangle(pix,self.style_list[1].bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE,0,0,
+ self.row_title_width+1,
+ rt_height+1)
+
+ for c_row in range(first_row,last_row+1):
+ if self.opts.row_title_type == 'user-defined':
+ idx=self.row2src[c_row]
+ if idx > len(self.row_titles)-1:
+ txt = ''
+ else:
+ txt=self.row_titles[idx]
+ gtk.draw_text(pix,self.title_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ self.pad,rt_offset,txt)
+ elif self.opts.row_title_type == 'source':
+ gtk.draw_text(pix,self.title_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ self.pad,rt_offset,str(self.row2src[c_row]))
+ else:
+ gtk.draw_text(pix,self.title_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ self.pad,rt_offset,str(c_row))
+
+ rt_offset = rt_offset + self.row_height + 1
+
+
+ #
+ # starting x for the the first column (far left line)
+ #
+ x = self.row_title_width
+ if self.opts.show_row_titles == 1:
+ x = x+1
+
+
+ #
+ # loop through a column at a time
+ #
+ row_is_selected=[]
+
+ rstyles=[] # Draw styles
+ cstyles=[]
+ cjust=[] # Column justification
+ ctjust=[] # Column title justification
+ for i in range( first_column, last_column ):
+ #
+ # don't bother drawing if we're going to start past the right edge
+ #
+ if x > width:
+ continue
+
+ cells=[]
+ # Info on whether or not shapes are selected (1 if selected)
+ cell_is_selected = []
+ cstyles.append(self.style_list[self.column_style_index[i]])
+ cjust.append(self._ColumnDefs[i].justification)
+ ctjust.append(self._ColumnDefs[i].title_justification)
+ force_width=self._ColumnDefs[i].force_width
+
+ for j in range( first_row, last_row+1 ):
+ idx = self.row2src[j]
+
+ if idx == -1:
+ continue
+
+ txt=self._get_datastr(idx,i)
+
+ if txt is None:
+ txt = ""
+
+ if force_width is not None:
+ cell_width = force_width
+ real_cell_width = min(force_width,
+ self.cell_font.width( txt ) + 2*self.pad)
+ else:
+ cell_width = self.cell_font.width( txt ) + 2*self.pad
+ real_cell_width = cell_width
+
+ cells.append( (txt, real_cell_width) )
+ cell_is_selected.append(
+ self.cell_selectstate[idx,i])
+
+ if i == first_column:
+ row_is_selected.append(self.row_selectstate[idx])
+ rstyles.append(self.style_list[self.row_style_index[idx]])
+
+ if cell_width > self.column_widths[i]:
+ bResetAdj = gtk.TRUE
+ self.column_widths[i] = cell_width
+ self._update_column_width(i,cell_width)
+
+ #
+ # figure out the size and placement of the title text
+ #
+ y = 1
+ if force_width is not None:
+ title_width=force_width
+ real_title_width = min(force_width,
+ self.title_font.width(self._ColumnDefs[i].title ) +
+ 2*self.pad)
+ else:
+ title_width = self.title_font.width(
+ self._ColumnDefs[i].title ) + 2*self.pad
+ real_title_width = title_width
+
+ if title_width > self.column_widths[i]:
+ bResetAdj=gtk.TRUE
+ self.column_widths[i]=title_width
+ self._update_column_width(i,title_width)
+
+ #
+ # draw the 'button'
+ #
+ bx = x
+ by = 0
+ bw = self.column_widths[i]+1
+ if self.opts.show_column_titles == 1:
+ bh = self.column_title_height+1
+ else:
+ bh = 0
+
+ if self.opts.show_column_titles == 1:
+ gtk.draw_rectangle( pix,
+ self.style_list[2].bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE, bx, by, bw, bh)
+
+ #
+ # draw the title
+ #
+ if ctjust[i-first_column] == 0:
+ tx = x + ( self.column_widths[i] - real_title_width )
+ elif ctjust[i-first_column] == 1:
+ tx = x
+ else:
+ tx = x + ( ( self.column_widths[i] -
+ real_title_width ) / 2 )
+
+ gtk.draw_text( pix, self.title_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ tx+self.pad,
+ y + self.column_title_height - self.pad,
+ self._ColumnDefs[i].title )
+
+ y = y+self.column_title_height + 1
+
+ #
+ # draw the horizontal line below the title
+ #
+
+
+ for j in range( len(cells) ):
+ if cell_is_selected[j]:
+ gtk.draw_rectangle( pix,
+ rstyles[j].bg_gc[gtk.STATE_SELECTED],
+ gtk.TRUE,
+ x,
+ y,
+ self.column_widths[i]+1,
+ self.row_height+1)
+ elif self.column_selectstate[i]:
+ gtk.draw_rectangle( pix,
+ cstyles[i-first_column].bg_gc[gtk.STATE_SELECTED],
+ gtk.TRUE,
+ x,
+ y,
+ self.column_widths[i]+1,
+ self.row_height+1)
+ elif row_is_selected[j]:
+ gtk.draw_rectangle( pix,
+ rstyles[j].bg_gc[gtk.STATE_SELECTED],
+ gtk.TRUE,
+ x,
+ y,
+ self.column_widths[i]+1,
+ self.row_height+1)
+ else:
+ gtk.draw_rectangle( pix,
+ rstyles[j].bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE,
+ x,
+ y,
+ self.column_widths[i]+1,
+ self.row_height+1)
+
+ y = y + self.row_height + 1
+
+ if cjust[i-first_column] == 0:
+ cx = x + self.column_widths[i] - cells[j][1]
+ elif cjust[i-first_column] == 1:
+ cx = x
+ else:
+ cx = x + ( (self.column_widths[i] - cells[j][1]) / 2 )
+
+ gtk.draw_text(pix, self.cell_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ cx+self.pad, y-self.pad, cells[j][0])
+
+
+ #
+ # where does the line go
+ #
+ ly = y - 1
+ lx = x + self.column_widths[i] + 1
+
+ #
+ #advance to next column
+ #
+ x = x + self.column_widths[i] + 1
+
+ # Redraw the area to the right of the last column in case there
+ # were any text over-runs:
+ gtk.draw_rectangle( pix,
+ self.style_list[0].bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE,
+ x+1,
+ 0,
+ width-x-1,
+ height)
+
+
+ # Different line drawing options- represent with one
+ # number for shorter if's.
+ # draw all the lines (none for dlcase == 0)
+ dlcase = self.draw_row_lines*3 + self.draw_col_lines
+ if (dlcase == 1) and (self.opts.show_column_titles == 0):
+ dlcase = 0
+ elif (dlcase == 3) and (self.opts.show_row_titles == 0):
+ dlcase = 0
+ elif ((dlcase == 4) and (self.opts.show_row_titles == 0) and
+ (self.opts.show_column_titles == 0)):
+ dlcase = 0
+ elif ((dlcase == 4) and (self.opts.show_row_titles == 1) and
+ (self.opts.show_column_titles == 0)):
+ dlcase = 3
+ elif ((dlcase == 4) and (self.opts.show_row_titles == 0) and
+ (self.opts.show_column_titles == 1)):
+ dlcase = 1
+ elif ((dlcase == 5) and (self.opts.show_row_titles == 0) and
+ (self.opts.show_column_titles == 0)):
+ dlcase = 2
+
+ # calculate total width/height of grid
+ if self.opts.show_row_titles == 0:
+ gwidth = 0
+ else:
+ gwidth = self.row_title_width + 1
+
+ for i in range( first_column, last_column):
+ gwidth = gwidth + self.column_widths[i] + 1
+
+ if self.opts.show_column_titles == 0:
+ gheight = 0
+ else:
+ gheight = self.column_title_height + 1
+
+ for i in range(first_row, last_row+1):
+ gheight = gheight + self.row_height + 1
+
+ if dlcase in [2,4,5,6,7,8]:
+ # lines left, right, top, bottom
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,0,gwidth,0)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,gheight,gwidth,gheight)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,0,0,gheight)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ gwidth,0,gwidth,gheight)
+
+ if dlcase in [1,4,5,7,8] and (self.opts.show_column_titles == 1):
+ # Lines around column titles
+ if self.opts.show_row_titles == 0:
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,0,gwidth,0)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,self.column_title_height+1,
+ gwidth,self.column_title_height+1)
+ roffset = 0
+ else:
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ self.row_title_width+1,0,gwidth,0)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ self.row_title_width+1,
+ self.column_title_height+1,
+ gwidth,self.column_title_height+1)
+ roffset = self.row_title_width + 1
+
+ for i in range( first_column, last_column):
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ roffset,0,
+ roffset,self.column_title_height+1)
+ roffset = roffset + self.column_widths[i] + 1
+
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ roffset,0,
+ roffset,self.column_title_height+1)
+
+ if (dlcase in [3,4,5,7,8]) and (self.opts.show_row_titles == 1):
+ # Lines around row titles
+ if self.opts.show_column_titles == 0:
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,0,0,gheight)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ self.row_title_width+1,0,
+ self.row_title_width+1,gheight)
+ coffset = 0
+ else:
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,self.column_title_height+1,0,gheight)
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ self.row_title_width+1,
+ self.column_title_height+1,
+ self.row_title_width+1,gheight)
+ coffset = self.column_title_height + 1
+
+ for i in range( first_row, last_row+1):
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,coffset,
+ self.row_title_width+1,coffset)
+ coffset = coffset + self.row_height + 1
+
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,coffset,
+ self.row_title_width+1,coffset)
+
+ if dlcase in [2,5,8]:
+ # lines between columns
+ if self.opts.show_row_titles == 0:
+ roffset = 0
+ else:
+ roffset = self.row_title_width + 1
+
+ for i in range( first_column, last_column):
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ roffset,0,
+ roffset,gheight)
+ roffset = roffset + self.column_widths[i] + 1
+
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ roffset,0,
+ roffset,gheight)
+
+ if dlcase in [6,7,8]:
+ # lines between rows
+ if self.opts.show_column_titles == 0:
+ coffset = 0
+ else:
+ coffset = self.column_title_height + 1
+
+ for i in range( first_row, last_row):
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,coffset,
+ gwidth,coffset)
+ coffset = coffset + self.row_height + 1
+ gtk.draw_line(pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0,coffset,
+ gwidth,coffset)
+
+
+ #draw the backing pixmap onto the screen
+ self._area.draw_pixmap(style.white_gc, self._pixmap, 0, 0, 0, 0,
+ width, height )
+
+ if self.editing_cell is not None:
+ # shift editing cell if necessary
+ cell=self.editing_cell
+ if self.src2row[cell[0]] < first_row:
+ self._layout.move(self.editbox,5000,5000)
+ elif cell[1] < first_column:
+ self._layout.move(self.editbox,5000,5000)
+ else:
+ cwidth=self._ColumnDefs[cell[1]].width
+ self.editbox.set_usize(cwidth,self.row_height)
+ self.editbox.set_max_length(
+ self._ColumnDefs[cell[1]].entry_chars)
+ locx=self._ColumnDefs[cell[1]].start_x-\
+ self._ColumnDefs[first_column].start_x+\
+ self.row_title_width+1
+ if self.opts.show_row_titles == 1:
+ locx=locx+1
+ locy=self.column_title_height+2+\
+ ((self.src2row[cell[0]]-self.start_row)*(self.row_height+1))
+ if self.opts.show_column_titles == 1:
+ locy=locy+1
+
+ self._layout.move(self.editbox,locx,locy)
+
+ if bResetAdj or self.bCalcAdjustments:
+ self.calc_adjustments()
+
+ return gtk.FALSE
+
+ def size_allocate(self,*args):
+ """Track changes in table size and pass them on to
+ drawing area.
+ """
+ nsizetuple=self.get_allocation()
+ if self.vscroll_shown == 1:
+ nwidth=nsizetuple[2] - SCROLL_DIM1
+ else:
+ nwidth=nsizetuple[2]
+
+ if self.hscroll_shown == 1:
+ nheight=nsizetuple[3] - SCROLL_DIM1
+ else:
+ nheight=nsizetuple[3]
+
+ self._area.set_usize(nwidth,nheight)
+
+
+ def configure( self, widget, event, *args ):
+ """Track changes in width, height
+ """
+ #only do this if we have been realized
+ if not self.flags() & gtk.REALIZED:
+ return
+
+ # create a memory pixmap to render into
+ a_win = self._area.get_window()
+ self._pixmap = gtk.create_pixmap( a_win, a_win.width, a_win.height )
+
+ style = self.get_style()
+
+ if self.title_font is None:
+ try:
+ self.title_font = gtk.load_font( self.title_font_spec )
+ except:
+ self.title_font = style.font
+
+ self._update_column_title_height()
+ self._update_row_title_width()
+
+ if self.cell_font is None:
+ try:
+ self.cell_font = gtk.load_font( self.cell_font_spec )
+ except:
+ self.cell_font = style.font
+ self.row_height = self.cell_font.ascent + 2*self.pad
+
+ self.bCalcAdjustments=gtk.TRUE
+
+ def calc_adjustments( self ):
+ """Recalculate the adjustment settings
+ """
+ if not (self.flags() & gtk.REALIZED):
+ self.bCalcAdjustments = gtk.TRUE
+ return
+
+ self.updating = gtk.TRUE
+ #horizontal min/max are 0 and max line length - page size
+ hpos = self.hadj.value
+
+ vpos = self.vadj.value
+
+ h_min = 0
+ v_min = 0
+
+ # Compute available grid area without scrollbars (twidth,theight)
+ # and with them (tmswidth, tmsheight)
+ totalsize = self.get_allocation()
+
+ # Extra 1's account for 1-pixel wide lines between cells;
+ twidth = totalsize[2] - 1 - self.row_title_width
+ if self.opts.show_row_titles == 1:
+ twidth = twidth - 1
+
+ theight = totalsize[3] - self.column_title_height - 1
+
+ if self.opts.show_column_titles == 1:
+ theight=theight - 1
+
+ tmswidth = twidth - SCROLL_DIM1
+ tmsheight = theight - SCROLL_DIM1
+
+
+
+ # Number of columns in window will change if columns
+ # have different widths, so calculate how many
+ # clicks it will take to show all of the last column
+ # assuming win_width > width(last_column).
+ # rather than just setting hadj to the number of
+ # columns not visible initially. Note: one click
+ # should move grid over by one column.
+
+ # Compute number of needed clicks in each direction
+ # if scrollbars aren't shown, and number if they are.
+ tneeded_clicks=0
+ tmsneeded_clicks=0
+
+ if len(self.column_widths) > 0:
+ while ((Numeric.sum(Numeric.array(
+ self.column_widths[tneeded_clicks:])+1) > twidth) and
+ (tneeded_clicks < self.g_columns-1)):
+ tneeded_clicks=tneeded_clicks+1
+ while ((Numeric.sum(Numeric.array(
+ self.column_widths[tmsneeded_clicks:])+1) > tmswidth) and
+ (tmsneeded_clicks < self.g_columns-1)):
+ tmsneeded_clicks=tmsneeded_clicks+1
+
+
+ trows = Numeric.floor(float(theight) / (self.row_height+1))
+ tmsrows = Numeric.floor(float(tmsheight) / (self.row_height+1))
+
+ tv_max = max( 0, self.g_rows - trows ) + 1
+ tmsv_max = max( 0, self.g_rows - tmsrows ) + 1
+
+ # decide if horizontal and vertical scrollbars should
+ # be displayed or not
+ show_hscroll = 1
+ show_vscroll = 1
+ if self.hscroll_policy == 1:
+ if ( tneeded_clicks == 0 ) and ( tv_max == 1 ):
+ show_hscroll = 0
+ show_vscroll = 0
+ elif ( tmsneeded_clicks == 0 ):
+ show_hscroll = 0
+ show_vscroll = 1
+ elif ( tmsv_max == 1 ):
+ show_hscroll = 1
+ show_vscroll = 0
+ else:
+ show_hscroll = 1
+ show_vscroll = 1
+ elif self.hscroll_policy == 2:
+ show_hscroll = 0
+ show_vscroll = 0
+
+ if show_hscroll == 0:
+ h_max = tneeded_clicks+1
+ else:
+ h_max = tmsneeded_clicks + 1
+
+ if show_vscroll == 0:
+ v_max = tv_max
+ else:
+ v_max = tmsv_max
+
+ self.hadj.set_all( hpos, h_min, h_max, 1, 1, 1 )
+ self.hadj.changed()
+
+ self.vadj.set_all( vpos, v_min, v_max, 1, 1, 1)
+ self.vadj.changed()
+
+
+ if (show_hscroll == 1) and (self.hscroll_shown != 1):
+ self.hsframe.show()
+ self.hscroll_shown = 1
+ elif (show_hscroll == 0) and (self.hscroll_shown != 0):
+ self.hsframe.hide()
+ self.hscroll_shown = 0
+
+ if (show_vscroll == 1) and (self.vscroll_shown != 1):
+ self.vsframe.show()
+ self.vscroll_shown = 1
+ elif (show_vscroll == 0) and (self.vscroll_shown != 0):
+ self.vsframe.hide()
+ self.vscroll_shown = 0
+
+
+ self.bCalcAdjustments = gtk.FALSE
+ self.updating = gtk.FALSE
+
+ if len(self.row2src) < 1:
+ return
+
+ # This resets the start row/column to the first one
+ # in the case where the whole grid is now shown
+ if ( ( self.vadj.lower == 0 ) and
+ ( self.vadj.upper == 1 ) and
+ ( self.vadj.value > 0 ) ):
+ nrow = self.row2src[0]
+ self.reset_startrow( nrow )
+
+ if ( ( self.hadj.lower == 0 ) and
+ ( self.hadj.upper == 1 ) and
+ ( self.hadj.value > 0 ) ):
+ self.reset_startcolumn( 0 )
+
+
+ def set_scroll_policy(self, hpolicy, vpolicy, expose=1):
+ """ Set the policy for showing horizontal
+ and vertical scrollbars.
+
+ Inputs:
+ hpolicy- integer
+ vpolicy- integer
+ expose- whether or not to immediately
+ redraw the grid (0 to not redraw,
+ 1 to redraw- defaults to 1)
+
+ Policy values: 0- always
+ 1- automatic
+ 2- never
+
+ Policy is 0 (always) by default.
+ """
+ self.hscroll_policy = hpolicy
+ self.vscroll_policy = vpolicy
+ self.bCalcAdjustments = gtk.TRUE
+ if expose == 1:
+ self.expose()
+
+ def clear(self,*args):
+ """ Clear all grid settings, disconnect from
+ source signals.
+ """
+
+ # End cell editing, if it is occurring (save changes)
+ self.end_cell_edit()
+
+ # Disconnect from layer signals (SRC_SHAPESLAYER only)
+ if self.layer_selection_changed_id is not None:
+ self.layer.disconnect(self.layer_selection_changed_id)
+ self.layer_selection_changed_id = None
+ if self.layer_subselection_changed_id is not None:
+ self.layer.disconnect(self.layer_subselection_changed_id)
+ self.layer_subselection_changed_id = None
+ if self.layer_teardown_id is not None:
+ self.layer.disconnect(self.layer_teardown_id)
+ self.layer_teardown_id = None
+
+ # Disconnect from changed signals (SRC_SHAPES, SRC_SHAPESLAYER)
+ if ((self.source_changed_id is not None) and
+ (self.src is not None)):
+ self.src.disconnect(self.source_changed_id)
+ self.source_changed_id=None
+ elif (self.source_changed_id is not None):
+ print 'clear: Warning- encountered undisconnected signal'
+
+ # Clear settings
+ self._initialize_settings()
+
+ def clear_and_expose(self,*args):
+ """ Clear and expose. """
+ self.clear()
+ self.expose()
+
+ def _initialize_settings(self):
+ """ Set up the grid for a new source. """
+
+ #the row/column to put in the top left corner
+ self.start_row = 0
+ self.start_column = 0
+
+ self.last_row = 0
+
+ self.column_widths = []
+
+ #flag to recalculate the adjustments
+ self.bCalcAdjustments = gtk.TRUE
+
+ # Lists of currently selected rows,
+ # columns, cells. Selection state
+ # is stored two ways for easy
+ # access in different situations.
+ # Selected rows always refer to
+ # the source row, not the grid row.
+ # (this makes it easier to deal
+ # with sorting)
+ # Selected column refers to the
+ # grid column because the underlying
+ # source may have no concept of
+ # "column" (eg. shapes have properties,
+ # but there is no intrinsic order to
+ # them).
+ # Cells are referenced by the source
+ # row and grid column (a tuple)
+ self.selected_rows=[]
+ self.selected_columns=[]
+ self.selected_cells=[]
+
+ # Select state indices. Each element
+ # of these is either:
+ # 0- not selected
+ # or
+ # 1- selected.
+ # For rows and columns these are vectors,
+ # for the cells this is a matrix.
+ # The sizes are:
+ # row_selectstate: number of source rows (nR)
+ # column_selectstate: number of grid columns (nC)
+ # cell_selectstate: nR x nC
+ #
+ # row_selectstate refers to the source row
+ # in the original source order (ie. unsorted)
+ # column_selectstate refers to the column index
+ # in the grid display.
+ # cells are indexed by source row (unsorted) and
+ # displayed column index.
+ self.row_selectstate=None
+ self.column_selectstate=None
+ self.cell_selectstate=None
+
+ # Selection tracking
+ self.last_selected_row=None
+ self.last_selected_column=None
+ self.last_selected_cell=None
+ self.last_toggled_row=None
+ self.last_toggled_column=None
+ self.last_toggled_cell=None
+
+ # click event tracking (hack used to get
+ # around the fact that double clicking
+ # doesn't seem to work well on windows for longish callbacks-
+ # disadvantage is that the consecutive clicks
+ # can be arbitrarily far apart...). Hack is used on all
+ # platforms for consistency.
+ self.last_click_cell=(None,None)
+ self.last_click_row=None
+ self.last_click_column=None
+ self.last_click_button=None
+
+ #set to true if changing some value that would end up causing multiple
+ #expose events or an endless loop even.
+ self.updating = gtk.FALSE
+ # Define source parameters; initialize them
+ # to empty values
+ self.src=None
+ self.src_type=SRC_NONE
+
+ # Indices to map from source index to
+ # grid row index, and vice versa.
+ # -2 is in src2row to indicate that
+ # the source data for that row is
+ # None and should not be used. -1
+ # is used to indicate that the
+ # source data for that row is not
+ # part of the current subset and
+ # should not be used.
+ self.src2row=[]
+ self.row2src=[]
+
+ # More parameters
+ self.g_columns=0 # Number of grid columns
+ self.g_rows=0 # Number of grid rows
+ self.s_rows=0 # Number of source rows
+
+ # Sorting parameters
+ self.sort_column=-1 # No sorting to start with
+ self.sort_reverse=0 # ascending (0) or descending (1)
+
+ # source changed: used for SRC_SHAPES
+ # and SRC_SHAPESLAYER
+ self.source_changed_id=None
+
+ # layer and view: only used for
+ # SRC_SHAPESLAYER
+ self.layer=None
+ self.layer_selection_changed_id=None
+ self.layer_subselection_changed_id=None
+ self.layer_teardown_id=None
+ self.view=None
+
+ # Flags used to control callback behaviour in
+ # different contexts (eg. to avoid exposes
+ # in row selection if necessary)
+ self._flags={}
+ self._flags['selecting-rows']=0
+ self._flags['frozen']=0
+
+ self.row_style_index=None
+ self.column_style_index=None
+ # Below: not used yet, but will be later.
+ #self.rowtitle_style_index=None
+ #self.columntitle_style_index=None
+
+ self.row_titles=[]
+
+ self.editing_cell=None
+
+ def layer_subselection_cb(self,layer):
+ # When a selection changes, a the selected list is changed,
+ # then the selection-changed signal is sent out, then
+ # the subselection changes, then the subselection-changed
+ # signal is sent out. To reset the start row, you have to hook
+ # into the subselection-changed callback, since all
+ # selection-changed callbacks are executed before
+ # subselection is updated, so calling get_subselection from the
+ # selection-changed callback will lag the most recent selection
+ # by one.
+ subselection = layer.get_subselected()
+
+ if len(self.src) < self.s_rows:
+ # selection changed signal is sent
+ # out before shapes changed signal
+ # when an invalid area is drawn.
+ # Return if this is the case.
+ return
+
+ if subselection != -1:
+ self.last_selected_row=subselection
+ self.last_toggled_row=subselection
+ self.reset_startrow(subselection)
+
+ # If this selection was triggered by actions
+ # on the view rather than through the grid,
+ # redraw the grid (if this was triggered through
+ # the grid this function is called from select_rows,
+ # which does the expose if necessary).
+ if self._flags['selecting-rows'] == 0:
+ self.expose()
+
+ def layer_selection_cb(self, layer, *args):
+ """ Shapeslayer case- selection has been changed in view. """
+ shps = layer.get_selected()
+
+ if len(self.src) < self.s_rows:
+ # selection changed signal is sent
+ # out before shapes changed signal
+ # when an invalid area is drawn.
+ # Return if this is the case.
+ return
+
+ if len(shps) == 1:
+ self.last_selected_row=shps[0]
+ self.last_toggled_row=shps[0]
+ else:
+ self.last_selected_row=None
+ self.last_toggled_row=None
+
+ self._unselect_all_rows()
+ self._select_rows(shps)
+
+ if self._flags['selecting-rows'] == 0:
+
+ nlist=self._rows_updated()
+
+ if (len(shps) == 0) or (len(nlist) > 0):
+ # If no shapes are selected, layer_subselection_cb
+ # won't be called, so layer_selection_cb should do
+ # the expose (otherwise layer_subselection_cb will)
+ self.expose()
+
+ self.notify('row-selection-changed',tuple(self.selected_rows))
+
+ if len(nlist) > 0:
+ for item in nlist:
+ self.notify(item[0],item[1])
+
+ def freeze(self):
+ """ Freeze and allow internal changes without exposing. """
+ if self.source_changed_id is not None:
+ self.src.signal_handler_block(self.source_changed_id)
+ if self.layer_selection_changed_id is not None:
+ self.src.signal_handler_block(self.layer_selection_changed_id)
+ if self.layer_subselection_changed_id is not None:
+ self.src.signal_handler_block(self.layer_subselection_changed_id)
+ self._flags['frozen']=1
+
+ def thaw(self,expose=1):
+ """ Thaw and expose if desired. """
+ if self.source_changed_id is not None:
+ self.src.signal_handler_unblock(self.source_changed_id)
+ if self.layer_selection_changed_id is not None:
+ self.src.signal_handler_unblock(self.layer_selection_changed_id)
+ if self.layer_subselection_changed_id is not None:
+ self.src.signal_handler_unblock(
+ self.layer_subselection_changed_id)
+ self._flags['frozen']=0
+
+ if expose == 1:
+ self.expose()
+
+ def sort_by_column( self, column=None,reverse=None,expose=1 ):
+ """ Sort the grid rows according to the
+ values in one of the columns.
+ """
+
+ if ((self.src is None) or (len(self.src) < 1)):
+ return
+
+ if column is None:
+ # default to last one if sort property not specified
+ column=self.sort_column
+ else:
+ self.sort_column=column
+
+ if reverse is None:
+ reverse=self.sort_reverse
+ else:
+ self.sort_reverse=reverse
+
+ if column > len(self._ColumnDefs):
+ txt='pgugrid: attempted to sort by nonexistent column '+str(column)
+ raise RuntimeError,txt
+
+ ind_list=[]
+ if self._ColumnDefs[self.sort_column].type == 'complex':
+ # complex numbers can't be sorted with list sorting
+ for s_row in self.row2src:
+ ind_list.append((self._get_datastr(s_row,self.sort_column),
+ s_row))
+ else:
+ for s_row in self.row2src:
+ ind_list.append((self._get_data(s_row,self.sort_column),s_row))
+
+ ind_list.sort()
+ if self.sort_reverse == 1:
+ ind_list.reverse()
+
+ for idx in range(len(ind_list)):
+ self.row2src[idx]=ind_list[idx][1]
+ self.src2row[ind_list[idx][1]]=idx
+
+
+ if expose == 1:
+ if self.last_selected_row is not None:
+ self.reset_startrow(self.last_selected_row)
+
+ self.expose()
+
+
+class pguGridWin(gtk.GtkWindow):
+ def __init__(self,title,selection_mode=1,source=None,config=None):
+ """ selection mode: 0 for no row selection, 1
+ for single selection, 2 for multiple.
+
+ source: source to initialize grid with
+ """
+
+ gtk.GtkWindow.__init__(self)
+ self.set_title(title)
+ if config is None:
+ if selection_mode == 0:
+ config=(2,0,0,0,0,0,0,0)
+ elif selection_mode == 1:
+ config=(2,1,0,0,0,0,0,0)
+ else:
+ config=(2,2,0,0,0,0,0,0)
+
+ self.grid=pguGrid(config)
+ self.add(self.grid)
+
+ self.set_policy(gtk.TRUE,gtk.TRUE,gtk.TRUE)
+ if source is not None:
+ self.set_source(source)
+
+ self.show_all()
+ if source is not None:
+ self.grid.resize_to_default(800,600)
+
+
+ def set_source(self,src,view=None):
+ self.grid.set_source(src,view)
+
+ def set_subset(self,indices):
+ self.grid.set_subset(indices)
+
+
+class pguTestGridWin(gtk.GtkWindow):
+ def __init__(self,title,config=None,source=None):
+ gtk.GtkWindow.__init__(self)
+ self.set_title(title)
+ if config is None:
+ config=(2,1,0,1,0,1,0,0)
+ self.grid=pguGrid(config)
+ self.add(self.grid)
+
+ self.set_policy(gtk.TRUE,gtk.TRUE,gtk.TRUE)
+ if source is not None:
+ self.set_source(source)
+ self.grid.resize_to_default()
+
+ self.show_all()
+
+ def set_source(self,src,view=None):
+ self.grid.set_source(src,view)
+
+ def set_subset(self,indices):
+ self.grid.set_subset(indices)
+
+
+class _test_listobj:
+ def __init__(self,strmem,intmem,floatmem,cplxmem):
+ self.stringval=strmem
+ self.intval=intmem
+ self.floatval=floatmem
+ self.complexval=cplxmem
+ self.array=Numeric.array([1,2,3])
+
+ def dummy_function(self):
+ pass
+
+if __name__ == "__main__":
+
+ import sys
+
+
+ with_def=1 # set to 1 to test with define_columns
+
+ config_list=[]
+ i=1
+ while i < min(len(sys.argv),9):
+ config_list.append(int(sys.argv[i]))
+ i=i+1
+
+ if len(sys.argv) > 9:
+ try:
+ lastarg=int(sys.argv[9])
+ config_list.append(lastarg)
+ shpfile=None
+ except:
+ shpfile=sys.argv[9]
+ config_list.append(None)
+ else:
+ shpfile=None
+ config_list.append(None)
+
+ cfg=tuple(config_list)
+
+ if len(sys.argv) == 11:
+ shpfile=sys.argv[10]
+
+ cfgstr=str(cfg)
+ win = pguTestGridWin('Test grid 1: shps with schema, '+cfgstr,config=cfg)
+ p1=['test1','test2','test3','test4','test5']
+ p2=[11.5,1.5,1.2,1.66,5.4]
+ p3=[1,2,3,4,600]
+ shps=gview.GvShapes()
+ shps.add_field('prop1-string','string',10)
+ shps.add_field('prop2-float','float',10,5)
+ shps.add_field('prop3-int','integer',10)
+ for idx in range(30):
+ shps.append(gview.GvShape())
+ shps[idx].set_node(5,3)
+ shps[idx].set_property('prop1-string',str(p1[idx%5]))
+ shps[idx].set_property('prop2-float',str(p2[idx%5]))
+ shps[idx].set_property('prop3-int',str(p3[idx%5]))
+
+ win.set_source(shps)
+ win.grid.set_row_title_type('user-defined',0,['row 1','row 2','row 3'])
+
+ if with_def == 1:
+ win.grid.define_columns(members=['prop1-string','prop2-float',
+ 'prop3-int'],
+ titles=['STRING title','FLOAT title','INT title'],
+ editables=None,
+ formats=["%-s","%-10.3f","%3d"],
+ types=['string','float','integer'],
+ justify=[0,1,2],title_justify=[0,1,2])
+ print 'Test grid 1 column titles: right, left, center'
+ print 'Test grid 1 columns : right, left, center'
+
+ idx=win.grid.add_style(((65000,0,0),None,(65000,30000,30000),None,None,None))
+ idx2=win.grid.add_style(((0,0,65000),None,(30000,30000,65000),None,None,None))
+ win.grid.set_row_style([1,2,3,4,5],idx)
+ win.grid.set_column_style([0,2],idx2)
+ win.grid.set_default_style(((65000,65000,0),None,(0,65000,65000),None,None,None))
+ win.connect( 'delete-event', gtk.mainquit )
+ win.set_uposition(20,20)
+
+ win2=pguTestGridWin('Test grid 2: Numpy, '+cfgstr,config=cfg)
+ numpy=Numeric.array([[1,2,3,4,5,6,7,8,9,0,1,2],[2,3,4,5,6,6,7,8,9,0,1,2],
+ [6,5,4,3,2,6,7,8,9,0,1,2],[1,3,5,7,9,6,7,8,9,0,1,2]])
+ win2.set_source(numpy)
+ if cfg[0] in [1,3]:
+ win2.grid.set_row_title_type('source',expose=0)
+
+ if with_def == 1:
+ win2.grid.define_columns(members=[0,1,2,3,4,5,6,7,8,9,10,11],
+ titles=['c0','c1','c2','c3','c4','Column Five',
+ 'c6','Seventh Column with Long Title',
+ 'c8','c9',
+ 'c10- yet another very long title',
+ 'c11-really,really,really,really,really,really,really,really long title'],
+ editables=None,
+ types='float',
+ justify=1,title_justify=0,force_width=90)
+ print 'Test grid 2 column titles: all right'
+ print 'Test grid 2 columns : all left'
+
+
+ win2.set_uposition(400,20)
+ idx=win2.grid.add_style(((65000,0,65000),None,(65000,30000,65000),None,None,None))
+ idx2=win2.grid.add_style(((0,65000,0),None,(30000,65000,30000),None,None,None))
+ win2.grid.set_row_style([1,2],idx)
+ win2.grid.set_column_style([0,1,2],idx2)
+ win2.grid.set_default_row_title_style(((0,0,45000),None,None,None,None,None))
+ win2.grid.set_default_col_title_style(((65000,40000,10000),None,None,None,None,None))
+ listlist=[[1,'hello',1.2],[2,'hi',3.4],[3,'bonjour',5.6],
+ [4,'hola',3.2],[5,'guten tag',1.4]]
+
+ win2.grid.set_scroll_policy(1,1)
+
+ win3 = pguTestGridWin('Test grid 3: list of lists '+cfgstr,config=cfg)
+ win3.set_source(listlist)
+ if with_def == 1:
+ win3.grid.define_columns(members=[1,0,2,1],
+ titles=['c11','cl0','c12','c11again'],
+ justify=0,title_justify=2,
+ force_width=50)
+ print 'Test grid 3 column titles: all center'
+ print 'Test grid 3 columns : all right'
+
+ win3.set_uposition(800,20)
+
+ shps2=gview.GvShapes()
+ for idx in range(5):
+ shps2.append(gview.GvShape())
+ shps2[idx].set_node(5,3)
+ shps2[idx].set_property('prop1',str(p1[idx]))
+ shps2[idx].set_property('prop2',str(p2[idx]))
+ win4 = pguTestGridWin('Test grid 1b: shps without schema, '+cfgstr,
+ config=cfg,source=shps2)
+ if with_def == 1:
+ win4.grid.define_columns(members=['prop2'],
+ titles=['FLOAT title'],
+ editables=None,
+ types=['float'],justify=1,title_justify=1)
+ print 'Test grid 1b column titles: all left'
+ print 'Test grid 1b columns : all left'
+
+ win4.set_uposition(20,300)
+ win4.grid.set_default_selection_colour((0,0,65000))
+
+ listobj=[]
+ listobj.append(_test_listobj('obj0',0,0.1,complex(1,-1)))
+ listobj.append(_test_listobj('obj1',2,0.2,complex(2,-1)))
+ listobj.append(_test_listobj('obj2',4,3.7,complex(3,1)))
+ listobj.append(_test_listobj('obj3',1,2.0,complex(0,-5)))
+ listobj.append(_test_listobj('obj4',3,0.1,complex(1,0)))
+ win5 = pguTestGridWin('Test grid 4: list of objects '+cfgstr,config=cfg)
+ if with_def == 1:
+ win5.grid.define_columns(members=['stringval','intval'],justify=[1,2],
+ title_justify=[0,2])
+ print 'Test grid 4 column titles: right, center'
+ print 'Test grid 4 columns : left,center'
+ win5.grid.set_source(listobj,redefine_columns=0)
+ win5.grid.resize_to_default()
+ else:
+ win5.set_source(listobj)
+
+ win5.set_uposition(400,300)
+
+
+ if with_def == 1:
+ win.grid.resize_to_default()
+ win2.grid.resize_to_default()
+ win3.grid.resize_to_default()
+ win4.grid.resize_to_default()
+ win5.grid.resize_to_default()
+
+ # If shapefile specified
+ print 'shpfile: ',shpfile
+ if shpfile is not None:
+ shps6=gview.GvShapes(shapefilename=shpfile)
+ win6 = pguTestGridWin('Test grid 5: shapefile '+cfgstr,config=cfg,
+ source=shps6)
+ #if with_def == 1:
+ # win6.grid.define_columns(formats=[None,None,'%11.2f','%11.2f'])
+
+ win6.set_uposition(800,300)
+ win6.grid.resize_to_default()
+ print 'Test grid 5 column titles: all center'
+ print 'Test grid 5 columns : all right'
+
+ listobj2=[1,2,3,4,5]
+ win7=pguTestGridWin('Test grid 6: list of integers '+cfgstr,config=cfg)
+ win7.set_source(listobj2)
+ win7.set_uposition(20,600)
+
+ listobj2=('one','two','three','four','five','six','seven')
+ win8=pguTestGridWin('Test grid 7: tuple of strings '+cfgstr,config=cfg)
+ win8.set_source(listobj2)
+ win8.set_uposition(400,600)
+
+
+ listobj2=((1,'hello',3,5.2),(8,'hi',7,9.2),(64,'hola',1,3.8))
+ win9=pguTestGridWin('Test grid 8: tuple of tuples '+cfgstr,config=cfg)
+ win9.set_source(listobj2)
+ win9.set_uposition(800,600)
+ win9.grid.set_scroll_policy(1,1)
+
+ emptylist=[]
+ win10=pguTestGridWin('Test grid 9: emptylist '+cfgstr,config=cfg)
+ win10.set_source(emptylist)
+ win10.grid.set_empty_message(None)
+ win10.set_uposition(20,800)
+
+ win11=pguTestGridWin('Test grid 10: titled emptylist '+cfgstr,config=cfg)
+ win11.grid.set_source(emptylist,
+ members=(1,2,3),titles=('one','two','three'))
+ win11.set_uposition(400,800)
+
+ win12=pguTestGridWin('Test grid 10: titled None '+cfgstr,config=cfg)
+ win12.grid.set_source(emptylist,members=('col one','col two','col three'))
+ win12.set_uposition(800,800)
+
+ win.grid.set_line_drawing(2,2)
+
+ if with_def == 1:
+ win7.grid.resize_to_default()
+ win8.grid.resize_to_default()
+ win9.grid.resize_to_default()
+ win10.grid.resize_to_default()
+ win11.grid.resize_to_default()
+ win12.grid.resize_to_default()
+
+
+ gtk.mainloop()
+
Added: packages/openev/branches/upstream/current/pymod/pgumenu.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgumenu.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgumenu.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,275 @@
+###############################################################################
+# $Id: pgumenu.py,v 1.3 2002/08/13 16:09:29 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: Extended Menu handling classes
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgumenu.py,v $
+# Revision 1.3 2002/08/13 16:09:29 pgs
+# added a pguToggleMenuItem and an option in the menu factory for adding
+# a <toggle> menu item.
+#
+# Revision 1.2 2002/07/23 17:29:21 warmerda
+# Recover if menu pixmap not found.
+#
+# Revision 1.1 2001/05/02 03:32:18 pgs
+# new file
+#
+#
+
+import gtk
+from gtk import TRUE, FALSE
+import string
+import os
+import gview
+import pgu
+
+MENU_FACTORY_MENU_BAR = 0
+MENU_FACTORY_MENU = 1
+MENU_FACTORY_OPTION_MENU = 2
+
+# type is MENU_FACTORY_{MENU,MENU_BAR,OPTION_MENU}
+class pguMenuFactory:
+ """
+ Utility class for creating different kinds of menus. Taken verbatim
+ from the pygtk MenuFactory class in GtkExtra.py with an enhancement
+ to add images to the menu and with comments added.
+
+ TODO:
+ right now, all menu items are indented by a spacing factor of 22 pixels
+ if no image is specified (to make everything line up. This means that
+ any images put in the menu should be 22 pixels wide.
+
+ """
+
+ def __init__(self, type=MENU_FACTORY_MENU_BAR):
+ """
+ Initialize the menu factory
+ """
+ self.accelerator = gtk.GtkAccelGroup()
+ if type == MENU_FACTORY_MENU_BAR:
+ self.__w = gtk.GtkMenuBar()
+ self.__ret = self.__w
+ elif type == MENU_FACTORY_MENU:
+ self.__w =gtk. GtkMenu()
+ self.__w.set_accel_group(self.accelerator)
+ self.__ret = self.__w
+ elif type == MENU_FACTORY_OPTION_MENU:
+ self.__w = gtk.GtkMenu()
+ self.__w.set_accel_group(self.accelerator)
+ self.__ret = gtk.GtkOptionMenu()
+ self.__ret.set_menu(self.__w)
+ self.__menus = {}
+ self.__items = {}
+
+ def __getattr__(self, key):
+ """
+ map getattr calls through to the menu instead of this object
+ """
+ return getattr(self.__ret, key)
+
+ def add_entries(self, entries):
+ """
+ add multiple entries at once
+ """
+ for entry in entries:
+ apply(self.create, tuple(entry))
+
+ def create(self, path, accelerator=None, callback=None, *args):
+ """
+ create a single menuitem and add it to one of the menus already
+ created (or create a new one)
+ """
+ last_slash = string.rfind(path, '/')
+ if last_slash < 0:
+ parentmenu = self.__w
+ else:
+ parentmenu = self.get_menu(path[:last_slash])
+ label = path[last_slash+1:]
+ if label == '<separator>':
+ item = gtk.GtkMenuItem()
+ elif label[:7] == '<image:':
+ end = string.find(label, '>')
+ img_name = label[7:end]
+ hbox = gtk.GtkHBox(spacing=2)
+ try:
+ hbox.pack_start(self.create_pixmap(img_name), expand=FALSE)
+ except:
+ print 'Unable to load menu pixmap: ' + img_name
+
+ lbl = gtk.GtkLabel(label[end+1:])
+ lbl.set_justify(gtk.JUSTIFY_LEFT)
+ hbox.pack_start(lbl, expand=FALSE)
+ item = gtk.GtkMenuItem()
+ item.add(hbox)
+ item.show_all()
+ elif label[:8] == '<toggle>':
+ item = pguToggleMenuItem(label[8:])
+
+ elif label[:7] == '<check>':
+ item = gtk.GtkCheckMenuItem(label[7:])
+ else:
+ if parentmenu == self.__w:
+ item = gtk.GtkMenuItem(label)
+ else:
+ hbox = gtk.GtkHBox()
+ spc = gtk.GtkLabel('')
+ spc.set_usize(22,18)
+ hbox.pack_start(spc, expand=FALSE)
+ lbl = gtk.GtkLabel(label)
+ lbl.set_justify(gtk.JUSTIFY_LEFT)
+ hbox.pack_start(lbl, expand=FALSE)
+ item = gtk.GtkMenuItem()
+ item.add(hbox)
+ if label != '<nothing>':
+ item.show()
+ if accelerator:
+ key, mods = self.parse_accelerator(accelerator)
+ item.add_accelerator("activate", self.accelerator,
+ key, mods, 'visible')
+ if callback:
+ apply(item.connect, ("activate", callback) + args)
+ # right justify the help menu automatically
+ if string.lower(label) == 'help' and parentmenu == self.__w:
+ item.right_justify()
+ parentmenu.append(item)
+ self.__items[path] = item
+ return item
+
+ def get_menu(self, path):
+ """
+ get the menu rooted at the given path
+ """
+ if path == '':
+ return self.__w
+ if self.__menus.has_key(path):
+ return self.__menus[path]
+ wid = self.create(path)
+ menu = gtk.GtkMenu()
+ menu.set_accel_group(self.accelerator)
+ wid.set_submenu(menu)
+ self.__menus[path] = menu
+ return menu
+
+ def parse_accelerator(self, accelerator):
+ """
+ parse an accelerator entry
+ """
+ key = 0
+ mods = 0
+ done = FALSE
+ while not done:
+ if accelerator[:7] == '<shift>':
+ mods = mods | gtk.GDK.SHIFT_MASK
+ accelerator = accelerator[7:]
+ elif accelerator[:5] == '<alt>':
+ mods = mods | gtk.GDK.MOD1_MASK
+ accelerator = accelerator[5:]
+ elif accelerator[:6] == '<meta>':
+ mods = mods | gtk.GDK.MOD1_MASK
+ accelerator = accelerator[6:]
+ elif accelerator[:9] == '<control>':
+ mods = mods | gtk.GDK.CONTROL_MASK
+ accelerator = accelerator[9:]
+ else:
+ done = TRUE
+ key = ord(accelerator[0])
+ return key, mods
+
+ def remove_entry(self, path):
+ """
+ remove a single entry by its path
+ """
+ if path not in self.__items.keys():
+ return
+ item = self.__items[path]
+ item.destroy()
+ length = len(path)
+ # clean up internal hashes
+ for i in self.__items.keys():
+ if i[:length] == path:
+ del self.__items[i]
+ for i in self.__menus.keys():
+ if i[:length] == path:
+ del self.__menus[i]
+ def remove_entries(self, paths):
+ """
+ remove menuitems based on the menu path name used to add them
+ """
+ for path in paths:
+ self.remove_entry(path)
+
+ def find(self, path):
+ """
+ find a menuitem instance by the path for the menu item. This
+ is the text used in the add_entries call.
+ """
+ return self.__items[path]
+
+ def create_pixmap(self, filename):
+ """
+ create a pixmap from a filename
+
+ filename - string, the filename to create the pixmap from
+ """
+ full_filename = os.path.join(gview.home_dir, 'pics', filename)
+ if not os.path.isfile(full_filename):
+ print '%s filename not found, using default.xpm' % full_filename
+ full_filename = os.path.join(gview.home_dir, 'pics', 'default.xpm')
+ pix, mask = gtk.create_pixmap_from_xpm(self, None, full_filename)
+ return gtk.GtkPixmap(pix, mask)
+
+class pguToggleMenuItem( gtk.GtkMenuItem ):
+
+ def __init__(self, label=""):
+ import pgutogglebutton
+ gtk.GtkMenuItem.__init__( self )
+
+ hbox = gtk.GtkHBox( spacing = 2 )
+ self.tb = pgutogglebutton.pguToggleButton( )
+ self.tb.connect( 'toggled', self.toggled_cb)
+ hbox.pack_start( self.tb, expand=FALSE )
+
+ evt_box = gtk.GtkEventBox()
+ evt_box.connect( 'button-release-event', self.toggle_it )
+
+ lbl = gtk.GtkLabel( label )
+ evt_box.add( lbl )
+
+ hbox.pack_start( evt_box )
+ self.add( hbox )
+ self.show_all()
+
+ def set_active( self, bState ):
+ self.tb.set_active( bState )
+
+ def get_active( self ):
+ return self.tb.get_active()
+
+ def toggle_it( self, widget, event, *args ):
+ self.set_active( not self.tb.get_active() )
+
+ def toggled_cb( self, widget, *args ):
+ self.activate()
+ self.get_ancestor( gtk.GtkMenuShell.get_type() ).deactivate()
+
\ No newline at end of file
Added: packages/openev/branches/upstream/current/pymod/pguprogress.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pguprogress.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pguprogress.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,103 @@
+###############################################################################
+# $Id: pguprogress.py,v 1.1 2000/06/27 13:22:20 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Simplified progress monitor dialog.
+# Author: Frank Warmerdam, warmerda at home.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pguprogress.py,v $
+# Revision 1.1 2000/06/27 13:22:20 warmerda
+# New
+#
+#
+#
+
+from gtk import *
+
+class PGUProgressDialog(GtkDialog):
+ def __init__(self, title = 'Progress', cancel = FALSE ):
+ GtkDialog.__init__(self)
+ self.set_title( title )
+ self.min = 0.0
+ self.max = 1.0
+ self.message = "complete"
+ self.cancelled = FALSE
+
+ vbox = GtkVBox(spacing=5)
+ vbox.set_border_width(10)
+ self.vbox.pack_start(vbox)
+
+ label = GtkLabel(" 0% "+self.message)
+ label.set_alignment(0, 0.5)
+ vbox.pack_start(label, expand=TRUE)
+ self.label = label
+
+ pbar = GtkProgressBar()
+ pbar.set_usize(200, 20)
+ vbox.pack_start(pbar)
+
+ if cancel:
+ button = GtkButton("cancel")
+ self.cancel = button
+ button.connect( "clicked", self.CancelCB )
+ self.action_area.pack_start(button)
+
+ self.pbar = pbar
+ self.show_all()
+
+ def CancelCB( self, *args ):
+ self.cancelled = TRUE
+
+ def Reset(self):
+ self.cancelled = FALSE
+
+ def SetRange( self, min, max ):
+ self.min = min
+ self.max = max
+
+ def SetDefaultMessage( self, message ):
+ self.message = message
+
+ def ProgressCB( self, complete, message, *args ):
+
+ self.complete = self.min + (self.max-self.min) * complete
+ if message == "":
+ message = self.message
+
+ message = str(int(complete*100)) + "% " + message
+ self.label.set_text(message)
+
+ self.pbar.update( complete )
+ while events_pending():
+ mainiteration(FALSE)
+
+ if self.cancelled:
+ return 0
+ else:
+ return 1
+
+
+if __name__ == '__main__':
+ pdialog = PGUProgressDialog( "Progress Test" )
+
+ mainloop()
+
Added: packages/openev/branches/upstream/current/pymod/pgushapesgrid.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgushapesgrid.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgushapesgrid.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1046 @@
+###############################################################################
+# $Id: pgushapesgrid.py,v 1.10 2003/07/27 04:58:44 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Scrollable text area widget for displaying GvShapes data
+# Author: Paul Spencer, spencer at dmsolutions.ca
+#
+# Developed by DM Solutions Group (www.dmsolutions.ca) for CIETcanada
+#
+###############################################################################
+# Copyright (c) 2000-2002, CIETcanada
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgushapesgrid.py,v $
+# Revision 1.10 2003/07/27 04:58:44 warmerda
+# dos2unix
+#
+# Revision 1.9 2003/04/14 18:49:39 gmwalter
+# Fix typo.
+#
+# Revision 1.8 2003/04/14 18:37:54 gmwalter
+# Updated to include sorting/indexing functions.
+#
+# Revision 1.7 2002/09/14 16:17:13 pgs
+# added support for selecting a cell
+#
+# Revision 1.6 2002/08/27 19:12:29 pgs
+# added notion of 'selected' shapes
+#
+# Revision 1.5 2002/08/19 17:13:13 pgs
+# small fix for NULL values
+#
+# Revision 1.4 2002/08/15 18:17:23 pgs
+# fixed bug in expose when a property is None.
+#
+# Revision 1.3 2002/08/13 17:42:32 pgs
+# added a nice frame ;)
+#
+# Revision 1.2 2002/08/13 16:08:52 pgs
+# several changes to rendering logic to allow for resetting the adjustments
+# if the column widths change, plus easier calculations of cell spacings for
+# consistency
+#
+#
+
+"""
+
+"""
+
+import gtk,GDK
+import gview
+import Numeric
+import gvsignaler
+
+class pguShapesGrid( gtk.GtkTable, gvsignaler.Signaler ):
+
+ def __init__(self,editable=1):
+
+ self._editable=editable
+ if self._editable == 1:
+ gtk.GtkTable.__init__( self, rows=3, cols=2 )
+ else:
+ gtk.GtkTable.__init__( self, rows=2, cols=2 )
+
+ self.hadj = gtk.GtkAdjustment()
+ self.vadj = gtk.GtkAdjustment()
+
+ self._hscroll = gtk.GtkHScrollbar( adj = self.hadj )
+ self._vscroll = gtk.GtkVScrollbar( adj = self.vadj )
+ self._area = gtk.GtkDrawingArea()
+ self._pixmap = None
+ #this mask also seems to enable scrolling???
+ evt_mask = gtk.GDK.BUTTON_PRESS_MASK | gtk.GDK.BUTTON_RELEASE_MASK | \
+ gtk.GDK.KEY_PRESS_MASK | gtk.GDK.KEY_RELEASE_MASK
+ self._area.set_events( evt_mask )
+
+
+ if self._editable == 1:
+ self._entry = gtk.GtkEntry()
+ self._entry.set_sensitive( gtk.FALSE )
+ self._entry.connect( 'changed', self.entry_changed )
+
+ #the data source
+ self.source = None
+ self.source_changed_id = None
+ self.subset = []
+
+ # indices/info for sorting (indices maps source index to nRow; inv_indices
+ # maps nRow to source index, and similar for subindices).
+ self.indices = None
+ self.inv_indices = None
+ self.subindices = None
+ self.inv_subindices = None
+ self.sort_reverse=0
+
+ #string values to use as titles
+ self.titles = [ ]
+
+ #fonts for drawing titles and cells put here
+ self.title_font = None
+ self.cell_font = None
+
+ #the overall size of the data set
+ self.n_rows = 0
+ self.n_cols = 0
+
+ #the height of a single row and title row
+ self.row_height = 0
+ self.title_height = 0
+
+ #the row/col to put in the top left corner
+ self.start_row = 0
+ self.start_col = 0
+
+ #the current row/col selected (when we support clicking :)
+ self.current_row = 0 # current row in display widget coordinates
+ self.current_row_src = -1 # current row in source coordinates (source index)
+ self.current_col = 0
+
+ self.col_widths = []
+
+ #the number of pixels around each cell
+ self.cell_half = 4
+ self.cell_full = (self.cell_half) * 2 + 1
+
+ self.max_width = 0
+ self.max_height = 0
+
+ #flag to recalculate the adjustments
+ self.bCalcAdjustments = gtk.TRUE
+
+ # list of indices of currently selected shapes (NOT the same as the
+ # currently editable cell)
+ self.selected_shapes=None
+
+ #set to true if changing some value that would end up causing multiple
+ #expose events or an endless loop even.
+ self.updating = gtk.FALSE
+
+ frm = gtk.GtkFrame()
+ frm.set_shadow_type(gtk.SHADOW_ETCHED_OUT)
+ frm.add(self._area)
+
+ if self._editable == 1:
+ self.attach( self._entry, 0, 1, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK )
+ self.attach( frm, 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=gtk.FILL )
+ self.attach( self._vscroll, 1, 2, 1, 2, xoptions=gtk.SHRINK)
+ self.attach( self._hscroll, 0, 1, 2, 3, yoptions=gtk.SHRINK )
+ else:
+ self.attach( frm, 0, 1, 0, 1, xoptions=gtk.FILL, yoptions=gtk.FILL )
+ self.attach( self._vscroll, 1, 2, 0, 1, xoptions=gtk.SHRINK)
+ self.attach( self._hscroll, 0, 1, 1, 2, yoptions=gtk.SHRINK )
+
+ self.show_all()
+
+ # signals: Note that the right-click (button 3) event
+ # is a special case used internally to select cells for
+ # editing.
+ self.publish('clicked-selected-row')
+ self.publish('clicked-unselected-row')
+ self.publish('title-clicked')
+
+ self._area.connect( 'expose-event', self.expose )
+ self._area.connect( 'configure-event', self.configure )
+ self._area.connect( 'button-press-event', self.click )
+ self.hadj.connect( 'value-changed', self.changed )
+ self.vadj.connect( 'value-changed', self.changed )
+ self.connect( 'style-set', self.expose )
+
+ def entry_changed( self, widget ):
+ """called when the user has changed the text in an entry
+ """
+ if self.current_row is not None and self.current_col is not None:
+ if self.current_row > 0:
+ self.source[self.current_row_src].set_property( \
+ self.titledict[self.titles[self.current_col]], self._entry.get_text() )
+
+ self.expose()
+
+ def click( self, widget, event ):
+ """the user clicked the widget, select a cell?
+ """
+
+ # If left button clicked, select/delect a row; if right button
+ # clicked, select a column.
+ if len(self.col_widths) < 1:
+ return
+
+ #
+ # determine the column that the user clicked in by first offsetting
+ # for the current start column (accounts for columns scrolled off the
+ # left edge)
+ #
+ current = 0
+ for i in range(self.start_col):
+ current = current + self.col_widths[i] + self.cell_full
+
+ #
+ # now actually look for the right column. If nCol is None at the end
+ # then the user clicked off the right edge.
+ #
+ nCol = None
+ current_temp = 0
+ for i in range(self.start_col, len(self.col_widths)):
+ current_temp = current_temp + self.col_widths[i] + self.cell_full
+ if event.x < current_temp:
+ nCol = i
+ break
+
+ current = current + current_temp
+
+ #
+ # now determine the row. If its 0 then they clicked a 'title'. If it
+ # is None then they clicked off the bottom edge.
+ # Use the same trick as for the columns to account for ones scrolled
+ # off the top, but its trickier because the first row is always the
+ # titles. And its easier because all rows are the same height :)
+ #
+ nRow = None
+ if event.y < (self.row_height + self.cell_full):
+ nRow = 0
+ else:
+ # NOTE: the max(self.start_row-1,0) below is a kludge to
+ # avoid an offset problem after scrolling (first scroll
+ # click doesn't seem to actually cause the window to scroll,
+ # even though vadj updates)
+ row = max(self.start_row-1,0) + int(event.y / (self.row_height + self.cell_full))
+ if row <= self.n_rows:
+ nRow = row
+
+ if nRow == 0 and nCol is not None:
+ cprop=self.titledict[self.titles[nCol]]
+ self.notify('title-clicked',nCol,cprop)
+
+ if (event.button != 3):
+ # Notify that a selected or unselected row was clicked,
+ # and send event.
+ if nRow is not None and nRow > 0:
+ if self.selected_shapes[self.grid2src(nRow)] == 1:
+ self.notify('clicked-selected-row',self.grid2src(nRow),0,event)
+ else:
+ self.notify('clicked-unselected-row',self.grid2src(nRow),0,event)
+ elif (event.state & GDK.SHIFT_MASK):
+ # stop editing
+ self.current_row = 0
+ self.current_row_src = -1
+ self.current_col = 0
+ if self._editable == 1:
+ self._entry.set_sensitive( gtk.FALSE )
+ self.expose()
+
+ else:
+ self.current_row = nRow
+ self.current_row_src = self.grid2src(nRow)
+ self.current_col = nCol
+
+ if self._editable == 1:
+ if nRow is not None and nCol is not None and nRow > 0:
+ self._entry.set_sensitive( gtk.TRUE )
+ val = self.source[self.grid2src(nRow)].get_property(self.titledict[self.titles[nCol]])
+ self._entry.set_text( val )
+ self._entry.grab_focus()
+ else:
+ self._entry.set_text( '' )
+ self._entry.set_sensitive( gtk.FALSE )
+
+ self.expose()
+
+
+ def changed( self, widget ):
+ """Track changes to the scrollbars and record the
+ """
+
+ self.start_row = int(self.vadj.value)
+ self.start_col = int(self.hadj.value)
+ self.expose()
+
+ def set_subset( self, subset = []):
+ """Sets an array of shape indexes that constitute a displayable
+ subset of the shapes
+
+ subset - list of integer values
+
+ If selected is None or an empty list, then all records will be
+ displayed.
+ """
+ if subset is None:
+ subset = []
+
+ self.subset = subset
+
+ self.start_row = 0
+ self.start_col = 0
+ if len(self.subset) > 0:
+ self.n_rows = len(self.subset)
+
+ self.bCalcAdjustments = gtk.TRUE
+ self.source_sort()
+ self.expose()
+
+ def set_source( self, source, titledict=None, hidden=None ):
+ """Set the data source
+
+ shapes - a GvShapes instance
+
+ titledict - dictionary of titles for properties (optional)
+
+ hidden - properties to hide
+
+ reset all the internal parameters
+ """
+ self.clear()
+ #trap setting to None or an invalid shapes object
+ if source == None or source._o == None or len(source) == 0:
+ return
+
+ self.source = source
+ self.source_changed_id = self.source.connect( 'changed', self.source_changed_cb )
+ self.subset = []
+
+ schema = source.get_schema()
+ self.n_cols = len(schema)
+ self.n_rows = len(source)
+
+ # no shapes initially selected.
+ # Shapes are selected by source index.
+ self.selected_shapes=Numeric.zeros([len(source),1])
+ # Sorted position of shape- initially in order of location in source.
+ # Used to map nRow->source index and vice versa.
+ self.indices=Numeric.array(range(len(source)))+1
+ self.inv_indices=Numeric.argsort(self.indices)
+ self.sort_reverse=0
+ self.subindices=None
+ self.inv_subindices=None
+
+ self.sort_property=None
+
+ self.titledict={}
+ if titledict is None:
+ titledict={}
+
+ self._hidden_titles=[]
+ if hidden is not None:
+ for item in hidden:
+ self._hidden_titles.append(item)
+
+ for i in range(len(schema)):
+ title = schema[i][0]
+
+ if title not in self._hidden_titles:
+ if titledict.has_key(title):
+ self.titles.append(titledict[title])
+ self.titledict[titledict[title]]=title
+ else:
+ self.titles.append(title)
+ self.titledict[title]=title
+
+ #update the scrollbars
+ self.bCalcAdjustments = gtk.TRUE
+ self.expose()
+
+ def ssrc2grid( self, ss_index ):
+ # Convert from source index (0...Nsrc-1 or 0...Nsubset-1)
+ # to grid row # (1...Nsrc or 1...Nsubset)
+ if ((self.source is None) or (ss_index > len(self.source)-1) or (ss_index < 0)):
+ return 0
+
+ if len(self.subset) > 0:
+ if ss_index > len(self.subset)-1:
+ return 0
+ grid_row = self.subindices[ss_index]
+ else:
+ grid_row = self.indices[ss_index]
+
+ return grid_row
+
+ def src2grid( self, s_index ):
+ # Convert from source index
+ # to grid row # (1...Nsrc or 1...Nsubset)
+ if ((self.source is None) or (s_index > len(self.source)-1) or (s_index < 0)):
+ return 0
+
+ if len(self.subset) > 0:
+ ss_index=None
+ for ind in range(len(self.subset)):
+ if self.subset[ind] == s_index:
+ ss_index=ind
+ if ss_index is None:
+ return 0
+
+ grid_row = self.subindices[ss_index]
+ else:
+ grid_row = self.indices[s_index]
+
+ return grid_row
+
+ def grid2ssrc( self, grid_row ):
+ # Convert from grid row (0...Nsrc or 0...Nsubset)
+ # to source or subset index # (1...Nsrc-1 or 1...Nsubset-1)
+ if ((self.source is None) or (grid_row > len(self.source)) or (grid_row < 1)):
+ return -1
+
+ if len(self.subset) > 0:
+ if grid_row > len(self.subset):
+ return -1
+ ss_index = self.inv_subindices[grid_row-1]
+ else:
+ ss_index = self.inv_indices[grid_row-1]
+
+ return ss_index
+
+ def grid2src( self, grid_row ):
+ # Convert from grid row (0...Nsrc or 0...Nsubset)
+ # to source index # (1...Nsrc-1)
+ if ((self.source is None) or (grid_row > len(self.source)) or (grid_row < 1)):
+ return -1
+
+ if len(self.subset) > 0:
+ if grid_row > len(self.subset):
+ return -1
+ src_index = self.subset[self.inv_subindices[grid_row-1]]
+ else:
+ src_index = self.inv_indices[grid_row-1]
+
+ return src_index
+
+
+ def source_sort( self, sort_property=None,reverse=None ):
+ # Need to call expose event after sorting to display
+ # inv_indices/inv_subindices map (nRow-1)->source/subset
+ # index; indices/subindices map source/subset index->nRow
+ if ((self.source is None) or (len(self.source) < 1)):
+ return
+
+ # clear editing cell selections
+ self.current_row = 0
+ self.current_row_src = -1
+
+ if sort_property is None:
+ # default to last one if sort property not specified
+ sort_property=self.sort_property
+
+ if reverse is None:
+ reverse=self.sort_reverse
+
+ if (len(self.subset) == 0):
+ self.subindices=None
+ self.inv_subindices=None
+ if sort_property is None:
+ self.sort_property=sort_property
+ self.sort_reverse=reverse
+ if self.sort_reverse == 0:
+ self.inv_indices=Numeric.array(range(len(self.source)))
+ else:
+ self.inv_indices=Numeric.array(range(len(self.source)-1,-1,-1))
+ # Grid rows are from 1...N (titles are 0)
+ self.indices=Numeric.argsort(self.inv_indices)+1
+ return
+ else:
+ # If a subset is defined, the main set shouldn't be
+ # used at all in expose. Don't bother sorting it.
+ self.indices=None
+ self.inv_indices=None
+ if sort_property is None:
+ self.sort_property=sort_property
+ self.sort_reverse=reverse
+ if self.sort_reverse == 0:
+ self.inv_subindices=Numeric.array(range(len(self.subset)))
+ else:
+ self.inv_subindices=Numeric.array(range(len(self.subset)-1,-1,-1))
+ self.subindices=Numeric.argsort(self.inv_subindices)+1
+ return
+
+
+ # Check that requested sort property exists
+ have_prop=0
+ prop_type='string'
+ for cprop in self.source.get_schema():
+ if cprop[0] == sort_property:
+ have_prop=1
+ prop_type=cprop[1]
+
+ if have_prop == 1:
+ self.sort_property=sort_property
+ self.sort_reverse=reverse
+ if (len(self.subset) == 0):
+ ind_list=[]
+ count=0
+ if ((prop_type == 'float') or (prop_type == 'integer')):
+ for cshape in self.source:
+ # convert to float so sorting is numeric
+ ind_list.append((float(cshape.get_property(sort_property)),count))
+ count=count+1
+ else:
+ # sort as a string
+ for cshape in self.source:
+ ind_list.append((cshape.get_property(sort_property),count))
+ count=count+1
+
+ ind_list.sort()
+ if self.sort_reverse == 1:
+ ind_list.reverse()
+ self.inv_indices=Numeric.zeros((count,))
+ for c_ind in range(count):
+ self.inv_indices[c_ind]=ind_list[c_ind][1]
+ self.indices=Numeric.argsort(self.inv_indices)+1
+ else:
+ ind_list=[]
+ if ((prop_type == 'float') or (prop_type == 'integer')):
+ count = 0
+ for cindex in self.subset:
+ ind_list.append((float(self.source[cindex].get_property(sort_property)),count))
+ count=count+1
+ else:
+ count=0
+ for cindex in self.subset:
+ ind_list.append((self.source[cindex].get_property(sort_property),count))
+ count=count+1
+
+ ind_list.sort()
+ if self.sort_reverse == 1:
+ ind_list.reverse()
+ self.inv_subindices=Numeric.zeros((len(self.subset),))
+ for c_ind in range(len(self.subset)):
+ self.inv_subindices[c_ind]=ind_list[c_ind][1]
+ self.subindices=Numeric.argsort(self.inv_subindices)+1
+ else:
+ print 'Invalid sort property.'
+
+ def source_changed_cb( self, *args ):
+ # If shapes have been added/deleted, update relevant info:
+ if len(self.source) > self.n_rows:
+ temp=self.selected_shapes
+ self.selected_shapes=Numeric.zeros([len(self.source),1])
+ self.selected_shapes[:self.n_rows]=temp
+ self.n_rows=len(self.source)
+ elif len(self.source) < self.n_rows:
+ temp=self.selected_shapes
+ self.selected_shapes=Numeric.zeros([len(self.source),1])
+ self.selected_shapes[:len(self.source)]=temp
+ self.n_rows=len(self.source)
+ # Remove deleted shapes from subset:
+ if len(self.subset) > 0:
+ new_subset=[]
+ for item in self.subset:
+ if item < self.n_rows:
+ new_subset.append(item)
+ self.subset=new_subset
+
+ # Update schema, if necessary
+ new_schema=self.source.get_schema()
+ if len(new_schema) != self.n_cols:
+ self.n_cols=len(new_schema)
+ for i in range(len(new_schema)):
+ if new_schema[i][0] not in self._hidden_titles:
+ if not (titledict.has_key(new_schema[i][0])):
+ self.titledict[new_schema[i][0]]=new_schema[i][0]
+ self.titles.append(new_schema[i][0])
+ self.schema=new_schema
+
+ self.source_sort()
+ self.bCalcAdjustments = gtk.TRUE
+ self.expose()
+
+ def calc_adjustments( self ):
+ """Recalculate the adjustment settings
+ """
+ if not (self.flags() & gtk.REALIZED) or len(self.col_widths) == 0:
+ self.bCalcAdjustments = gtk.TRUE
+ return
+
+ self.updating = gtk.TRUE
+ #horizontal min/max are 0 and max line length - page size
+ hpos = self.hadj.value
+ h_min = 0
+ win_width = self._area.get_window().width - self.cell_full
+ for i in range( len(self.col_widths) - 1, -1, -1):
+ win_width = win_width - self.col_widths[i] - self.cell_full
+ if win_width < 0:
+ break;
+
+ if i == 0 and win_width >= 0:
+ h_max = 0
+ elif i == 0:
+ h_max = 1
+ else:
+ h_max = i + 2
+
+ self.hadj.set_all( hpos, h_min, h_max, 1, 1, 1 )
+ self.hadj.changed()
+
+ vpos = self.vadj.value
+ v_min = 0
+ cells_height = self._area.get_window().height - \
+ self.row_height - self.cell_full
+ row_height = self.row_height + self.cell_full
+ rows = cells_height / row_height
+
+ if len(self.subset) == 0:
+ v_max = len(self.source)
+ else:
+ v_max = len(self.subset)
+ #v_max = max( 0, v_max - rows ) + 1
+ v_max = max( 0, v_max - rows ) + 2
+
+ self.vadj.set_all( vpos, v_min, v_max, 1, 1, 1)
+ self.vadj.changed()
+ self.bCalcAdjustments = gtk.FALSE
+ self.updating = gtk.FALSE
+
+ def select_row(self,row,col=0,expose=1):
+ # Row should be in SOURCE INDEX coordinates, NOT
+ # grid or subset coordinates.
+ # Note: col argument is only there to be consistent with
+ # gtk clist- I don't really see why it is needed, since
+ # row number should be enough to select a given row.
+
+ if self.selected_shapes is None:
+ print 'No shapes to select...'
+ return 0
+ elif (len(self.selected_shapes) <= row):
+ print 'Selected shape index out of range...'
+ return 0
+ else:
+ self.selected_shapes[row]=1
+ if expose == 1:
+ self.expose()
+ return 1
+
+ def unselect_row(self,row,col=0,expose=1):
+ # Row should be in SOURCE INDEX coordinates, NOT
+ # grid or subset coordinates.
+ # Note: col argument is only there to be consistent with
+ # gtk clist- I don't really see why it is needed, since
+ # row number should be enough to select a given row.
+
+ if self.selected_shapes is None:
+ print 'No shapes to unselect...'
+ return 0
+ elif (len(self.selected_shapes) <= row):
+ print 'Selected shape index out of range...'
+ return 0
+ else:
+ self.selected_shapes[row]=0
+ if expose == 1:
+ self.expose()
+ return 1
+
+ def select_all(self,expose=1):
+ if self.selected_shapes is not None:
+ self.selected_shapes[:]=1
+ if expose == 1:
+ self.expose()
+ return 1
+ else:
+ print 'No shapes to select...'
+ return 0
+
+ def unselect_all(self,expose=1):
+ if self.selected_shapes is not None:
+ self.selected_shapes[:]=0
+ if expose == 1:
+ self.expose()
+ return 1
+ else:
+ print 'No shapes to unselect...'
+ return 0
+
+ def get_shape_coords(self,row):
+ if ((self.source is not None) and (len(self.source) > row)):
+ return self.source[row].get_node()
+ else:
+ return None
+
+ def expose( self, *args ):
+ """Draw the widget
+ """
+ if not (self.flags() & gtk.REALIZED):
+ return
+
+ if len(self.col_widths) != len(self.titles):
+ self.max_width = self.cell_full
+ self.col_widths=[]
+ for title in self.titles:
+ col_width = self.title_font.width( title )
+
+ self.col_widths.append( col_width )
+
+ self.max_width = self.max_width + col_width + self.cell_full
+
+ self. max_length = self.cell_full + \
+ ( len(self.titles) * ( self.row_height + self.cell_full ) )
+
+
+ #
+ # pre-calculate half a cell spacing because we use it a lot
+ #
+ cell_half = self.cell_half
+ cell_full = self.cell_full
+
+ #
+ # create a memory pixmap to render into
+ #
+ win = self._area.get_window()
+ width = win.width
+ height = win.height
+ pix = self._pixmap
+
+ #
+ # prefetch the style
+ #
+ style = self.get_style()
+
+ #
+ # clear the pixmap
+ #
+ gtk.draw_rectangle( pix, style.white_gc, gtk.TRUE,
+ 0, 0, width, height )
+
+ if self.source == None or self.source._o == None or len(self.source) == 0:
+ msg = "NO DATA TO DISPLAY"
+ msg_width = self.title_font.width( msg )
+ msg_height = self.title_font.height( msg )
+ msg_x = (width / 2) - (msg_width / 2)
+ msg_y = (height / 2) + (msg_height / 2 )
+ gtk.draw_text( pix, self.title_font,
+ style.fg_gc[gtk.STATE_INSENSITIVE],
+ msg_x, msg_y, msg )
+ self._area.draw_pixmap(style.white_gc, self._pixmap,
+ 0, 0, 0, 0,
+ width, height )
+
+ return gtk.FALSE
+
+
+ #
+ # track changes in column width because of wide columns
+ #
+ bResetAdj = gtk.FALSE
+
+ #
+ # calculate the number of rows to draw
+ #
+ base_height = height
+ title_height = self.title_height
+ data_height = base_height - title_height
+ disp_rows = int(data_height / ( self.row_height + 3 ))
+
+ #
+ # starting x for the the first column
+ #
+ x = cell_half
+
+ first_row = self.start_row
+ last_row = first_row + disp_rows
+ first_col = self.start_col
+ last_col = len(self.titles)
+
+ #
+ # loop through a column at a time
+ #
+ for i in range( first_col, last_col ):
+ #
+ # don't bother drawing if we're going to start past the right edge
+ #
+ if x > width:
+ continue
+
+ #
+ # pre-calculate the column width for this draw
+ # and remember the text values to draw
+ #
+ cells = []
+
+ # Info on whether or not shapes are selected (1 if selected)
+ cell_is_selected = []
+
+ for j in range( first_row, last_row ):
+ idx = self.grid2src(j)
+ if idx == -1:
+ continue
+
+ txt = self.source[idx].get_property( self.titledict[self.titles[i]] )
+ if txt is None:
+ txt = ""
+
+ cell_width = self.cell_font.width( txt )
+ cells.append( (txt, cell_width) )
+ cell_is_selected.append(self.selected_shapes[idx])
+ if cell_width > self.col_widths[i]:
+ bResetAdj = gtk.TRUE
+ self.col_widths[i] = cell_width
+
+ #
+ # figure out the size and placement of the title text
+ #
+ y = self.title_height + cell_half
+ title_width = self.title_font.width( self.titles[i] )
+ self.col_widths[i] = max( self.col_widths[i], title_width )
+
+ #
+ # draw the 'button'
+ #
+ bx = x - cell_half + 1
+ by = y - self.title_height - cell_half
+ bw = self.col_widths[i] + cell_full - 1
+ bh = self.title_height + cell_full
+ gtk.draw_rectangle( pix, style.bg_gc[gtk.STATE_NORMAL],
+ gtk.TRUE, bx, by, bw, bh)
+
+ gtk.draw_line( pix, style.bg_gc[gtk.STATE_PRELIGHT],
+ bx, by, bx, by + bh - 1 )
+ gtk.draw_line( pix, style.bg_gc[gtk.STATE_PRELIGHT],
+ bx, by, bx + bw, by )
+ #
+ # draw the title
+ #
+ tx = x + ( ( self.col_widths[i] - title_width ) / 2 )
+ gtk.draw_text( pix, self.title_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ tx, y, self.titles[i] )
+
+ #
+ # draw the horizontal line below the title
+ #
+ ly = y + cell_half + 1
+ lx = x + self.col_widths[i] + cell_half - 1
+ gtk.draw_line( pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0, ly - 1, lx, ly - 1 )
+
+ # Calculate total width of all cells
+ sum_col_widths=0.0
+ for cwidth in self.col_widths:
+ sum_col_widths = sum_col_widths + cwidth + self.cell_full
+
+ #
+ # draw the contents of the cells
+ #
+ for j in range( len(cells) ):
+ if cell_is_selected[j] == 1 and i == first_col:
+ gtk.draw_rectangle( pix, style.bg_gc[gtk.STATE_PRELIGHT],
+ gtk.TRUE,
+ 0,
+ y + cell_half,
+ sum_col_widths,
+ self.row_height + cell_full )
+ elif self.current_row is not None and \
+ self.current_col is not None and \
+ self.current_row != 0 and \
+ self.current_col == i and \
+ j + max(self.start_row-1,0) == self.current_row - 1:
+ gtk.draw_rectangle( pix, style.bg_gc[gtk.STATE_PRELIGHT],
+ gtk.TRUE,
+ x - cell_half,
+ y + cell_half,
+ self.col_widths[i] + cell_full,
+ self.row_height + cell_full )
+ y = y + self.row_height + cell_full
+ cx = x + self.col_widths[i] - cells[j][1]
+ gtk.draw_text(pix, self.cell_font,
+ style.fg_gc[gtk.STATE_NORMAL],
+ cx, y, cells[j][0])
+ #
+ # only draw the line under each row once, when we are drawing
+ # the last column
+ #
+ if x + self.col_widths[i] + cell_full > width or \
+ i == last_col - 1:
+ ly = y + cell_half + 1
+ lx = x + self.col_widths[i] + cell_half - 1
+ gtk.draw_line( pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0, ly - 1, lx, ly - 1)
+
+ #
+ # where does the line go
+ #
+ ly = y + cell_half + 1
+ lx = x + self.col_widths[i] + cell_half
+
+ #
+ # special case for first column, start under the title row
+ #
+ if i == 0:
+ gtk.draw_line( pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ 0, bh , 0, ly - 1 )
+
+ #
+ # draw the vertical lines to the right of each column
+ #
+ gtk.draw_line( pix, style.fg_gc[gtk.STATE_INSENSITIVE],
+ lx, 1, lx , y + cell_half )
+
+ #
+ #advance to next column
+ #
+ x = x + self.col_widths[i] + cell_full
+
+ #draw the backing pixmap onto the screen
+ self._area.draw_pixmap(style.white_gc, self._pixmap, 0, 0, 0, 0,
+ width, height )
+
+ if bResetAdj or self.bCalcAdjustments:
+ self.calc_adjustments()
+
+ return gtk.FALSE
+
+ def configure( self, widget, event, *args ):
+ """Track changes in width, height
+ """
+ #only do this if we have been realized
+ if not self.flags() & gtk.REALIZED:
+ return
+
+ # create a memory pixmap to render into
+ a_win = self._area.get_window()
+ self._pixmap = gtk.create_pixmap( a_win, event.width, event.height )
+
+ style = self.get_style()
+
+ if self.title_font is None:
+ try:
+ self.title_font = gtk.load_font( self.title_font_spec )
+ except:
+ self.title_font = style.font
+ self.title_height = self.title_font.ascent
+
+ if self.cell_font is None:
+ try:
+ self.cell_font = gtk.load_font( self.cell_font_spec )
+ except:
+ self.cell_font = style.font
+ self.row_height = self.cell_font.ascent
+
+ self.bCalcAdjustments=gtk.TRUE
+
+ def clear( self, *args ):
+ if self.source_changed_id is not None and self.source is not None:
+ self.source.disconnect( self.source_changed_id )
+ self.source = None
+ self.source_changed_id = None
+ self.titles = []
+ self.titledict={}
+ self._hidden_titles=[]
+ self.col_widths = []
+ self.n_rows = 0
+ self.n_cols = 0
+ self.start_row = 0
+ self.start_col = 0
+ self.current_row = 0
+ self.current_row_src = -1
+ self.current_col = 0
+
+ # indices/info for sorting (indices maps source index to nRow; inv_indices
+ # maps nRow to source index, and similar for subindices).
+ self.indices = None
+ self.inv_indices = None
+ self.subindices = None
+ self.inv_subindices = None
+ self.sort_reverse=0
+ self.expose()
+
+ def reset_startrow(self, c_row):
+ # Check if c_row is visible. If not,
+ # reset start row to c_row in widget
+ win = self._area.get_window()
+ width = win.width
+ height = win.height
+
+ base_height = height
+ title_height = self.title_height
+ data_height = base_height - title_height
+ # The 3 is there to make sure that we don't scroll
+ # 1 or 2 off the bottom of the widget: it may make
+ # the jump to the top occur sooner than it has to.
+ disp_rows = int(data_height / ( self.row_height + self.cell_full + 3 ))
+ first_row = self.start_row
+ last_row = first_row + disp_rows
+
+ if ((c_row >= self.start_row) and (c_row <= last_row)):
+ return
+
+ # If c_row isn't in current window, scroll
+ # so it is the new start row.
+ vmax = self.vadj.__getattr__('upper')
+ if c_row >= vmax:
+ self.vadj.set_value(vmax)
+ elif c_row < 1:
+ self.vadj.set_value(1)
+ else:
+ self.vadj.set_value(c_row)
+
+ self.vadj.value_changed()
+
+
+class TestGrid( gtk.GtkWindow ):
+
+ def __init__(self):
+ gtk.GtkWindow.__init__( self )
+ self.set_title("Test ShapesGrid")
+
+ vbox = gtk.GtkVBox()
+ self.grid = pguShapesGrid()
+ self.grid.set_usize( 300, 300 )
+ self.entry = gtk.GtkEntry()
+ self.button = gtk.GtkButton( "set shapes file" )
+ self.button.connect( "clicked", self.set_shapes )
+
+ vbox.pack_start( self.grid )
+ vbox.pack_start( self.entry, expand=gtk.FALSE )
+ vbox.pack_start( self.button, expand=gtk.FALSE )
+ self.add(vbox)
+ self.show_all()
+
+ def set_shapes( self, widget=None, src = None ):
+ if src is None:
+ src = self.entry.get_text()
+ else:
+ self.entry.set_text( src )
+
+
+ shapes = gview.GvShapes( shapefilename = src )
+ if shapes is not None and shapes._o is not None:
+ self.grid.set_source( shapes )
+
+
+if __name__ == "__main__":
+ win = TestGrid()
+ win.set_shapes( src = "c:\\projects\\dmsolutions\\ciet\\ciet_data\\wcsite.shp" )
+ win.connect( 'delete-event', gtk.mainquit )
+ gtk.mainloop()
+
Added: packages/openev/branches/upstream/current/pymod/pgutextarea.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgutextarea.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgutextarea.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,304 @@
+###############################################################################
+# $Id: pgutextarea.py,v 1.5 2003/02/14 17:59:14 pgs Exp $
+#
+# Project: OpenEV
+# Purpose: Scrollable text area widget
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgutextarea.py,v $
+# Revision 1.5 2003/02/14 17:59:14 pgs
+# added page_up and page_down
+#
+# Revision 1.4 2002/08/13 17:42:23 pgs
+# added a nice frame ;)
+#
+# Revision 1.3 2002/07/26 19:12:24 pgs
+# added freeze/thaw methods to enhance performance for many updates
+# from a single action.
+#
+# Revision 1.2 2002/07/23 19:17:48 pgs
+# performance fix, draw to pixmap first
+#
+# Revision 1.1 2002/07/23 16:38:52 pgs
+# new file
+#
+#
+
+"""
+This widget is very simple, it just allows you to append text to it. It allows
+you to scroll around in the text in a very limited fashion. PyGTK 0.6.6
+doesn't define the events for GDK_SCROLL so it's commented out here.
+
+
+Also, the width calculations seem to be off so the horizontal page size
+calculations don't give a perfect page width. However, the width always seems
+to be wider than necessary so you can at least see everything.
+
+To use it, simply put it in a container ( the scrollbars are embedded )
+
+Call append_text to append a string to it. Carriage returns are acceptable
+
+text_area.contents is a list containing one entry per line.
+
+use scroll_to to scroll the window to a particular line - it will attempt to
+put the line at the top, taking into account the vertical page size and the
+overall size of the buffer. This means that you will at least see from the
+requested line to the end of the buffer if the requeseted line doesn't end
+up at the top.
+
+All scroll calculations are done in terms of characters, not pixels. I tried
+this and it gave very nice scrolling but the calculations for optimizing the
+expose function were kinda scary, so I dropped. The end result is that it
+looks better if you use a fixed width font.
+
+Freeze/Thaw shouldn't be necessary - I should be checking to see if the added
+text is visible and if not, just updating the scrollbars (but even that can
+take time)
+
+Wish-list:
+remove the scrollbars and use in a GtkScrolledWindow
+make scrolling pixel based
+mouse scrolling support
+accessor functions
+documentation ;)
+"""
+
+import gtk
+
+class pguTextArea( gtk.GtkTable ):
+
+ def __init__(self):
+ gtk.GtkTable.__init__( self, rows=2, cols=2 )
+
+ self.hadj = gtk.GtkAdjustment()
+ self.vadj = gtk.GtkAdjustment()
+
+ self._hscroll = gtk.GtkHScrollbar( adj = self.hadj )
+ self._vscroll = gtk.GtkVScrollbar( adj = self.vadj )
+ self._area = gtk.GtkDrawingArea()
+ #set events for scrolling (not defined in GDK
+ #self._area.set_events(1 << 21)
+ self.contents = []
+ self.max_width = 0
+ self.max_length = 0
+ self.height = 0
+ self.line_height = 0
+ self.start_line = 0
+ self.start_col = 0
+ self.freeze_count = 0
+ self.updating = gtk.FALSE
+
+ frm = gtk.GtkFrame()
+ frm.set_shadow_type( gtk.SHADOW_ETCHED_OUT )
+ frm.add(self._area)
+ self.attach( frm, 0, 1, 0, 1 )
+ self.attach( self._vscroll, 1, 2, 0, 1, xoptions=gtk.SHRINK)
+ self.attach( self._hscroll, 0, 1, 1, 2, yoptions=gtk.SHRINK )
+
+ self.show_all()
+
+ self._area.connect( 'expose-event', self.expose )
+ self.connect( 'configure-event', self.configure )
+ self.hadj.connect( 'value-changed', self.changed )
+ self.vadj.connect( 'value-changed', self.changed )
+ self._area.connect( "scroll-event", self.event )
+ self.connect( 'style-set', self.expose )
+
+ def freeze( self ):
+ """Freeze the widget - no further updates until thawed
+ """
+ self.freeze_count = self.freeze_count + 1
+ return
+
+ def thaw( self ):
+ """Thaw the widget - this may not cause an update unless
+ the freeze count reaches 0
+ """
+ self.freeze_count = max( self.freeze_count - 1, 0 )
+ if self.freeze_count == 0:
+ self.calc_adjustments()
+ self.expose()
+
+ """
+ this would handle scroll events but it seems to get into an endless
+ loop sometimes????
+ def event( self, widget, event ):
+ #event type for scrolling not defined in GDK
+ #and pygtk0.6.6 doesn't include a scroll event
+ try:
+ if event.type == 31:
+ dir = 1
+ if event.direction == 0:
+ dir = -1
+ newval = max( self.vadj.value + dir, self.vadj.lower )
+ self.vadj.value = min( newval, self.vadj.upper - self.vadj.page_size)
+ self.vadj.value_changed()
+ except:
+ pass
+ """
+ def changed( self, widget ):
+ """Track changes to the scrollbars and record the
+ """
+ self.start_line = int(self.vadj.value)
+ self.start_col = int(self.hadj.value)
+ self.expose()
+
+ def append_text( self, text ):
+ """Append a block of text to the widget
+
+ Record new max width/length for scrollbar calculations
+ """
+ if len(text) > 0 and text[-1] == '\n':
+ text = text[:-1]
+ font = self.get_style().font
+ rows = text.split( "\n" )
+ for row in rows:
+ idx = self.contents.append( row )
+ self.max_width = max( font.measure(row), self.max_width )
+ self.max_length = max( len(row), self.max_length )
+ #record line height only once,
+ #use ascent only, height (ascent+descent) includes extra whitespace
+ if self.line_height == 0:
+ self.line_height = int( font.extents(row)[3] )
+
+ if self.freeze_count == 0:
+ self.calc_adjustments()
+
+ def calc_adjustments( self ):
+ """Recalculate the adjustment settings
+ """
+ if self.freeze_count > 0:
+ return
+
+ self.updating = gtk.TRUE
+ geom = self._area.get_allocation()
+ #horizontal min/max are 0 and max line length - page size
+ hpos = self.hadj.value
+ if self.max_length == 0:
+ hpage = 1
+ else:
+ hpage = int(geom[2]/(self.max_width/self.max_length)/2)
+ hstep = int( hpage / 4 )
+ self.hadj.set_all( hpos, 0, self.max_length - hpage, 1, hstep, hpage )
+ self.hadj.changed()
+
+ vpos = self.vadj.value
+ if self.line_height == 0:
+ vpage = 1
+ else:
+ vpage = int(geom[3]/(self.line_height))
+ vstep = int( vpage / 4 )
+ vmax = max( 1, len(self.contents) )
+ self.vadj.set_all( vpos, 0, vmax, 1, vstep, vpage )
+ self.vadj.changed()
+ self.updating = gtk.FALSE
+
+ def expose( self, *args ):
+ """Draw the widget
+ """
+ if self.freeze_count > 0:
+ return
+
+ if not (self.flags() & gtk.REALIZED):
+ return
+ if not (self.flags() & gtk.MAPPED):
+ return
+
+ geom = self._area.get_allocation()
+ pix = gtk.create_pixmap( self._area.get_window(), geom[2], geom[3] )
+ style = self.get_style()
+ gtk.draw_rectangle(pix, style.white_gc, gtk.TRUE, 0, 0,
+ geom[2], geom[3])
+ gtk.draw_rectangle(pix, style.black_gc, gtk.FALSE, 0, 0,
+ geom[2], geom[3])
+ font = self.get_style().font
+
+ v_offset = 0
+ for line in self.contents[self.start_line:]:
+ v_offset = v_offset + self.line_height
+ gtk.draw_string( pix, font, style.black_gc, 3,
+ v_offset, line[self.start_col:] )
+ if v_offset > geom[3]:
+ break
+
+ self._area.draw_pixmap(style.white_gc, pix, 0, 0, 0, 0, geom[2]-1, geom[3]-1 )
+
+ return gtk.FALSE
+
+ def configure( self, widget, event, *args ):
+ """Track changes in width, height
+ """
+ self.resize_children()
+ self.calc_adjustments()
+ self.expose()
+
+ def scroll_to( self, line ):
+ """Scroll the window to the requested line number
+
+ Attempt to put the line at the top. If there are less lines
+ after the requested line than will fit the page, then it will
+ move to a lower line number to display the whole last page
+ """
+ line = min( line, len(self.contents))
+ line = min( line, len(self.contents) - self.vadj.page_size)
+ if line != int(self.vadj.value):
+ self.vadj.set_value( line )
+ if int(self.hadj.value) != 0:
+ self.hadj.set_value( 0 )
+
+ def page_up(self):
+ self.scroll_to( self.vadj.value - self.vadj.page_size )
+
+ def page_down(self):
+ self.scroll_to( self.vadj.value + self.vadj.page_size )
+
+
+class TestText( gtk.GtkWindow ):
+
+ def __init__(self):
+ gtk.GtkWindow.__init__( self )
+ self.set_title("Test TextArea")
+
+ vbox = gtk.GtkVBox()
+ self.text = pguTextArea()
+ self.entry = gtk.GtkEntry()
+ self.button = gtk.GtkButton( "insert" )
+ self.button.connect( "clicked", self.insert_text )
+
+ vbox.pack_start( self.text )
+ vbox.pack_start( self.entry, expand=gtk.FALSE )
+ vbox.pack_start( self.button, expand=gtk.FALSE )
+ self.add(vbox)
+ self.show_all()
+
+ def insert_text( self, *args ):
+ self.text.append_text( self.entry.get_text() )
+ self.entry.set_text( "" )
+
+
+if __name__ == "__main__":
+ win = TestText()
+ for i in range(3):
+ win.text.append_text( "This is a\ntest of some\nlonger inserts and should work really well" )
+ win.connect( 'delete-event', gtk.mainquit )
+ gtk.mainloop()
+
\ No newline at end of file
Added: packages/openev/branches/upstream/current/pymod/pgutogglebutton.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pgutogglebutton.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pgutogglebutton.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: pgutogglebutton.py,v 1.1 2002/08/13 16:07:17 pgs Exp $
+#
+# Project: OpenEV Python GTK Utility classes
+# Purpose: Embeddable, configurable toggle widget
+# Author: Paul Spencer, pgs at magma.ca
+#
+###############################################################################
+# Copyright (c) 2000, DM Solutions Group Inc. (www.dmsolutions.on.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pgutogglebutton.py,v $
+# Revision 1.1 2002/08/13 16:07:17 pgs
+# new file
+#
+
+import gtk
+from gtk import TRUE, FALSE
+import gview
+import os.path
+
+class pguToggleButton(gtk.GtkToggleButton):
+ """
+ a widget for displaying toggled state (on/off).
+ """
+
+ def __init__(self, pix_on = "ck_on_l.xpm", pix_off = "ck_off_l.xpm"):
+ """
+ """
+ gtk.GtkToggleButton.__init__( self )
+
+ filename = os.path.join(gview.home_dir, 'pics', pix_on)
+ pix, mask = gtk.create_pixmap_from_xpm(self, None, filename)
+ self.pix_on = gtk.GtkPixmap( pix, mask )
+ self.pix_on.show()
+
+ filename = os.path.join(gview.home_dir, 'pics', pix_off)
+ pix, mask = gtk.create_pixmap_from_xpm(self, None, filename)
+ self.pix_off = gtk.GtkPixmap( pix, mask )
+ self.pix_off.show()
+
+ self.add( self.pix_off )
+
+ self.active_pix = self.pix_off
+
+ self.set_usize( pix.width, pix.height )
+
+ self.connect( 'toggled', self.expose )
+ self.connect( 'expose-event', self.expose )
+ self.show()
+
+ def expose( self, *args ):
+
+ if not self.flags() & gtk.REALIZED:
+ return
+
+
+ if self.get_active():
+ active_pix = self.pix_on
+ else:
+ active_pix = self.pix_off
+ if active_pix != self.active_pix:
+ self.remove( self.active_pix )
+ self.active_pix = active_pix
+ self.add( self.active_pix )
+
+if __name__ == "__main__":
+ dlg = gtk.GtkDialog()
+ filename = os.path.join(gview.home_dir, 'pics')
+ print 'pixs from ', filename
+ tb = pguToggleButton()
+ dlg.vbox.pack_start( tb )
+
+ btn = gtk.GtkButton( "OK" )
+ btn.connect( 'clicked', gtk.mainquit )
+ dlg.action_area.pack_start( btn )
+ dlg.connect( 'delete-event', gtk.mainquit )
+ dlg.show_all()
+ gtk.mainloop()
+
\ No newline at end of file
Added: packages/openev/branches/upstream/current/pymod/pyshell.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/pyshell.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/pyshell.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2440 @@
+#! /usr/bin/env python
+###############################################################################
+#
+# Project: OpenEV
+# Purpose: GTK interface to Python Shell
+# Author: Steve Rawlinson srawlin at atlsci.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: pyshell.py,v $
+# Revision 1.14 2003/09/09 15:18:46 gmwalter
+# Update openev.py so that if default xml files are not present in xmlconfig
+# directory, old configuration is used. Get rid of deprecation warnings
+# for python 2.3 by updating clist get_selection_info calls and colour
+# allocation (alloc) calls to use integers instead of floats.
+#
+# Revision 1.13 2003/07/28 19:42:34 gmwalter
+# Checked in Diana's xml changes (modified to include tools), added
+# python shell xml configuration.
+#
+# Revision 1.12 2003/02/14 14:26:21 warmerda
+# Fixed cntl-d support on windows.
+# http://bugzilla.remotesensing.org/show_bug.cgi?id=285
+#
+# Revision 1.11 2003/01/02 20:45:17 gmwalter
+# Fixed a GtkAdjustment (vscrollbar) setting to avoid seg-faults on windows.
+#
+# Revision 1.10 2002/12/12 07:43:15 warmerda
+# get command processing working again
+#
+# Revision 1.9 2002/07/18 17:45:13 warmerda
+# various upgrades related to gvcommand support, and scroll fixes
+#
+# Revision 1.8 2002/07/12 12:46:06 warmerda
+# expanded tabs
+#
+# Revision 1.7 2001/11/14 14:05:13 warmerda
+# freeze()/thaw() text widget to avoid overwrites on windows
+#
+# Revision 1.6 2001/11/12 18:43:17 warmerda
+# add locals pseudo-command
+#
+# Revision 1.5 2001/10/02 21:19:43 warmerda
+# specify iso8859 for the font
+#
+# Revision 1.4 2001/05/22 12:42:57 warmerda
+# Patch to make cntl-D only close window if there is no input like
+# the shell version. Provided by Jeffery D. Collins.
+#
+# Revision 1.3 2000/11/08 16:07:07 warmerda
+# fixed gdkcolor values to stay in 16bit signed range
+#
+# Revision 1.2 2000/07/26 14:35:07 srawlin
+# increased font size, fixed Ctrl-D bug, changed key bindings to use GDK defined values
+#
+# Revision 1.1 2000/07/25 21:26:05 srawlin
+# new - Gtk interface to python shell
+#
+#
+#
+
+MAX_COMMAND_PATHS = 15
+MAX_MODULE_PATHS = 15
+
+from gtk import *
+import GtkExtra, GDK
+import code, string, sys, os
+import gvutils
+
+def launch(pyshellfile=None):
+ import gview
+ try:
+ gview.app.shell.get_window()._raise()
+ gview.app.shell.show()
+ except:
+ import gvcorecmds
+
+ shell = Shell(pyshellfile=pyshellfile)
+ gview.app.shell = shell
+
+ # Initialization Commands
+ shell.command('from Numeric import *')
+ shell.command('from gdalnumeric import *')
+ shell.command('from gvshell import *')
+ shell.command('from gvplot import plot')
+ shell.command('gview.shell_base_vars = dir()')
+ shell.interp.clear_history()
+ gvcorecmds.Register( shell )
+
+ shell.show_all()
+
+ return gview.app.shell
+
+def launch_standalone(pyshellfile=None):
+ import gview
+ import gvcorecmds
+
+ shell = Shell(pyshellfile=pyshellfile,standalone=1)
+ gview.app.shell = shell
+
+ # Initialization Commands
+ shell.command('from Numeric import *')
+ shell.command('from gdalnumeric import *')
+ shell.command('from gvshell import *')
+ shell.command('from gvplot import plot')
+ shell.command('gview.shell_base_vars = dir()')
+ gvcorecmds.Register( shell )
+
+ shell.show_all()
+
+
+
+class MyInteractiveConsole(code.InteractiveConsole):
+
+ def __init__(self, text_shell, inherit=None, history_list=None,
+ status_bar=None):
+ self.text_shell = text_shell
+ locals = sys.modules['__main__'].__dict__
+ if inherit:
+ code.InteractiveConsole.__init__(self, locals=locals)
+ else:
+ code.InteractiveConsole.__init__(self)
+
+ self.cmdlist = {}
+
+ style = text_shell.get_style()
+ self.fg = style.fg[STATE_NORMAL]
+ self.bg = style.white
+ self.font = load_font(
+ "-*-courier-medium-r-normal-*-14-140-*-*-*-*-iso8859-*")
+
+ # Avoid using GdkColor to allocate colours
+ self.redtext=self.text_shell.get_colormap().alloc(25000,0,0)
+ self.bluetext=self.text_shell.get_colormap().alloc(0,0,32757)
+ self.greentext=self.text_shell.get_colormap().alloc(0,25000,0)
+
+ self.history_list = history_list
+ self.status_bar = status_bar
+ self.status_msg_id = None
+
+ # Journaling-related variables
+ # If journal_fh is None, journaling is off.
+ self.journal_fh = None # file handle for journaling
+ self.journal_fname = None # file name
+
+ # List of helpfiles to check for command/
+ # function help (full paths).
+ self.helpfiles=[]
+ self.help_cmdtxt={}
+ self.help_functxt={}
+ self.help_builtintxt={}
+
+ # Macro flag:
+ # in_macro- use to avoid macro commands going into history buffer
+ self.in_macro = 0 # Not currently in a macro
+
+ # Error flag: use to exit potentially nested macros without completing
+ # them if an error is encountered.
+ self.last_err = 0 # error status of last push command
+
+ def clearFlags(self):
+ # Function for top level shell to use to clear interpreter
+ # macro and error flags.
+ self.in_macro = 0
+ self.last_err = 0
+
+ def showProgress(self,percent,msg=None):
+ if self.status_bar is None:
+ return
+ self.status_bar.progress_bar.set_percentage(percent/100.0)
+ if msg is not None:
+ if (self.status_msg_id is not None):
+ self.status_bar.remove(self.status_bar.shell_context,self.status_msg_id)
+
+ self.status_msg_id = self.status_bar.push(self.status_bar.shell_context,msg)
+
+ def clear_history(self):
+ if self.history_list is None:
+ return
+ self.history_list.freeze()
+ self.history_list.clear()
+ self.history_list.thaw()
+
+
+ def push(self, line):
+ if ((self.in_macro == 0) and (self.history_list is not None)):
+ self.history_list.freeze()
+ self.history_list.insert(0,([line]))
+ # limit history list to 200 commands
+ # (gtk doesn't like long clists)
+ if self.history_list.rows > 200:
+ for count in range(self.history_list.rows-200):
+ self.history_list.remove(200)
+ self.history_list.thaw()
+
+ # locals replaced by a proper command
+ #if line[:6] == 'locals':
+ # line = 'local_vars_list(locals())'
+
+ s_line=string.lstrip(line)
+ if ((len(s_line) > 8) and (s_line[:6] == 'macro ')):
+ fname=string.strip(s_line[6:])
+
+ if ((len(fname) > 11) and (fname[:11] == 'macro_file=')):
+ # User has specified macro_file keyword
+ fname=fname[11:]
+
+ # Search order for macro:
+ # 1) fname
+ # 2) OPENEV_MACRO_PATH/fname (multiple semi-colon separated
+ # paths may be specified in the OPENEV_MACRO_PATH
+ # environment variable).
+ # 3) OPENEVHOME/fname
+ # 4) OPENEV_HOME/fname
+ #
+ if not (os.path.isfile(fname)):
+ macropaths=os.environ.get('OPENEV_MACRO_PATH')
+ if macropaths is not None:
+ for mpath in string.split(macropaths,";"):
+ mspath=string.strip(mpath)
+ if os.path.isfile(os.path.join(mspath,fname)):
+ fname=os.path.join(mspath,fname)
+ break
+
+ if not (os.path.isfile(fname)):
+ oevpath=os.environ.get('OPENEVHOME')
+ if oevpath is not None:
+ temp=os.path.join(oevpath,'macros')
+ temp=os.path.join(temp,fname)
+ if os.path.isfile(temp):
+ fname=temp
+
+ if not (os.path.isfile(fname)):
+ oevpath=os.environ.get('OPENEV_HOME')
+ if oevpath is not None:
+ temp=os.path.join(oevpath,'macros')
+ temp=os.path.join(temp,fname)
+ if os.path.isfile(temp):
+ fname=temp
+
+
+ if os.path.isfile(fname):
+ # keep track of indentation, in case macros
+ # are called within for loops of other
+ # macros
+ mac_indent_level=len(line)-len(s_line)
+ indent_txt=''
+ for count in range(mac_indent_level):
+ indent_txt=indent_txt+' '
+
+ fh=open(fname)
+ line1=fh.read(20)
+ if (string.find(line1,"openev macro") > 0):
+ fh.seek(0)
+ fh.readline()
+ commandlines=fh.readlines()
+ for cline in commandlines:
+ # Treat each line of a macro as though it was
+ # entered at the command prompt.
+ cline=string.replace(cline,chr(10),"")
+ cline=indent_txt+cline
+ self.my_write(cline+chr(10),'command')
+
+ # Set in_macro flag before each command, in
+ # case there is a macro within a macro, and
+ # in_macro gets set to 0 after exiting the
+ # nested macro
+ self.in_macro=1
+
+ self.push(string.rstrip(cline))
+
+ # If an error has been encountered, return
+ # immediately leaving error flag intact so
+ # that higher-level macros can also detect
+ # it and exit.
+ #
+ # NOTE: later, may want to add an option
+ # to the macro command or a flag on the shell
+ # that tells macros to force their way through
+ # even if an error is encountered...
+ if self.last_err == 1:
+ return 0
+
+ self.history_pos = None
+ if self.history_list is not None:
+ self.history_list.unselect_all()
+
+ fh.close()
+ else:
+ self.showText(fname+' does not exist or is not a file.','error')
+
+ self.in_macro=0
+ return 0
+
+ # If journaling is on, write the line unless the line
+ # is itself a journal command
+ if self.journal_fh is not None:
+ if not ((len(line) >= 7) and (line[:7] == 'journal')):
+ self.journal_fh.writelines(line+'\n')
+ self.journal_fh.flush()
+
+
+ if len(self.cmdlist) > 0:
+ cmd_name, remainder = parse_interpreter_line(line)
+ if self.cmdlist.has_key( cmd_name ):
+ # HISTORICAL NOTE: the change from cc.execute()'ing at
+ # this level to executing inside the shell through
+ # _run_command_line was necessary for commands to work
+ # within a for-loop. For instance:
+ #
+ # for i in range(3):
+ # print i
+ # newview
+ #
+ # Before, this used to immediately launch one view, then
+ # print the integers 1, 2, and 3 on separate lines because
+ # only the for-line and print-line actually got passed
+ # through to the the interpreter.
+ # The actual sequence of events was:
+ # - push the line "for i in range(3):" into interpreter.
+ # Interpreter sees that this is an incomplete loop and
+ # stores it in a buffer, doing nothing.
+ # - push the line " print i" into interpreter.
+ # Since end of loop has not been detected, interpreter
+ # stores line in buffer.
+ # - new view command is detected: run newview's
+ # execution code.
+ # - push the line "" into the interpreter. Interpreter
+ # now has a complete loop that can be executed, executes
+ # it, and flushes the buffer.
+ #
+ # Changing the code so that
+ # it is executed within the interpreter allows the newview
+ # to launch as one would expect because the code is now
+ # all executed in the context of the interpreter:
+ #
+ # for i in range(3):
+ # print i
+ # _run_command_line('newview')
+ #
+ # This does introduce one complication: COMMANDS MUST NOT
+ # CALL THE interp.push OR code.InteractiveConsole.push
+ # FUNCTIONS IN THEIR EXECUTION CODE BECAUSE THE BUFFER
+ # FOR EACH PUSH COMMAND IS NOT CLEARED UNTIL IT COMPLETES,
+ # SO CALLING PUSH WITHIN PUSH RESULTS IN A RECURSIVE LOOP.
+
+ # Old code
+ #cc.execute()
+ #return code.InteractiveConsole.push(self,'')
+ # end of old code
+
+ # Get the indentation level of the line
+ temp_line=string.lstrip(line)
+ indent_level=len(line)-len(temp_line)
+ txt=''
+ for count in range(indent_level):
+ txt=txt+' '
+
+ if string.find(line,'"') == -1:
+ txt=txt+'_run_command_line("'+line+'")'
+ elif string.find(line,"'") == -1:
+ txt=txt+"_run_command_line('"+line+"')"
+ else:
+ line2=string.replace(line,"'",'"')
+ txt=txt+"_run_command_line('"+line2+"')"
+
+ return code.InteractiveConsole.push(self,txt)
+
+
+ return code.InteractiveConsole.push(self,line)
+
+ # This is a CommandInterpreter method as per gvcommand.py
+ def isInteractive( self ):
+ return 1
+
+ # This is a CommandInterpreter method as per gvcommand.py
+ def showText( self, text, text_class ):
+ text = text + chr(10)
+ if text_class == 'error':
+ self.my_write( text, 'stderr' )
+ else:
+ self.my_write( text, 'stdout' )
+
+
+ def showtraceback(self):
+ """Display the exception that just occurred.
+
+ We remove the first stack item because it is our own code.
+
+ The output is written by self.write(), below.
+
+ """
+ try:
+ import traceback
+ if sys.exc_info()[2] is not None:
+ exc_info = traceback.extract_tb(sys.exc_info()[2])
+ txt = 'Unexpected Error:'
+ txt = txt + '\n Type : '+str(sys.exc_type)
+ if sys.exc_info()[1] is None:
+ txt = txt + '\n Description: '+ 'Undefined\n'
+
+ else:
+ txt = txt + '\n Description: '+str(sys.exc_info()[1]) + '\n'
+
+ if len(exc_info) > 2:
+ # Ignore the first 2 tuples- in the context of the interpreter,
+ # these are just the console and the exec statement and are
+ # irrelevant
+ txt = txt + '\n Traceback:\n'
+ for ctuple in exc_info[2:]:
+ txt = txt + '\n file : '+os.path.basename(ctuple[0])
+ txt = txt + '\n line number: '+str(ctuple[1])
+ txt = txt + '\n function : '+str(ctuple[2])
+ txt = txt + '\n line : '+str(ctuple[3])+'\n'
+
+ else:
+ txt = 'Unexpected Error:'
+ txt = txt + '\n No description available.\n'
+ except:
+ txt = 'Unexpected Error:'
+ txt = txt + '\n No description available.\n'
+
+ self.write(txt)
+
+ # Status of last line pushed via toplevel shell's echo function
+ self.last_err = 1
+
+ def write(self, data):
+ # Override base class write
+ # Red - tracebacks
+ # This method is only used when an error has occurred (eg. a
+ # syntax error)- stdout is redirected to my_write.
+ self.text_shell.insert(self.font, self.redtext, self.bg, data)
+
+ self.last_err = 1
+
+ def my_write(self, data, name):
+ self.text_shell.freeze()
+ # Comment line just below this is deprecated- GdkColor isn't used now
+ # Colours need to be in function calls for some reason else segfaults!?!
+
+ # Normal output is reported in GREEN
+ if name == 'stdout':
+ self.text_shell.insert(self.font, self.greentext, self.bg, data)
+ # Anticipated errors are reported in BLUE
+ elif name == 'stderr':
+ self.text_shell.insert(self.font, self.bluetext, self.bg, data)
+ # should still set error flag
+ self.last_err = 1
+ # Titles are bigger and BLUE
+ elif name == 'title':
+ self.text_shell.insert(
+ load_font("-*-courier-bold-o-normal-*-14-140-*-*-*-*-iso8859-*"),
+ self.bluetext,
+ self.bg, data )
+
+ # Everything else is just the normal foreground color (black)
+ else:
+ self.text_shell.insert(self.font, self.fg, self.bg, data)
+
+ self.text_shell.thaw()
+
+ vscrollbar = self.text_shell.get_vadjustment()
+
+ try:
+ # This offset seems to be necessary on windows, which
+ # segfaults if vscrollbar.upper or larger values are
+ # used.
+ hoffset=self.text_shell.get_window().height
+ vscrollbar.set_value( vscrollbar.upper - hoffset )
+ except:
+ pass
+
+ def get_command_help(self, command,quiet=0):
+ # quiet- if quiet is 0, include module,
+ # and group info; otherwise don't.
+
+ if self.cmdlist.has_key(command):
+ # Command is loaded. Determine what module
+ # it is in.
+ if hasattr(self.cmdlist[command],'__module__'):
+ modname=os.path.basename(self.cmdlist[command].__module__)
+ mname,ext=os.path.splitext(modname)
+ else:
+ mname=None
+
+ # check for registered help for command
+ # under module mname.
+ if self.help_cmdtxt.has_key(command):
+ if mname is None:
+ # If module unknown, return all
+ # text help.
+ ctext=''
+ for centry in self.help_cmdtxt[command]:
+ if quiet == 0:
+ ctext=ctext+'Module: '+centry[0]+'\n'
+ ctext=ctext+'Group: '+centry[1]+'\n\n'
+
+ ctext=ctext+centry[3] + '\n'
+ return ctext
+
+ for centry in self.help_cmdtxt[command]:
+ if centry[0] == mname:
+ ctext=''
+ if quiet == 0:
+ ctext='Module: '+centry[0]+'\n'
+ ctext=ctext+'Group: '+centry[1]+'\n\n'
+
+ ctext=ctext+centry[3] + '\n'
+
+ return ctext
+
+
+ # No suitable text help found, but command found so
+ # construct basic help.
+ if quiet == 0:
+ txt='Module: '
+ if mname is None:
+ txt=txt+'Unknown\n'
+ else:
+ txt=txt+mname+'\n'
+
+ if hasattr(self.cmdlist[command],'Group'):
+ txt=txt+'Group: '+self.cmdlist[command].Group + '\n\n'
+ else:
+ txt='Group: None\n\n'
+ else:
+ txt=''
+
+ txt=txt+'Usage: '+self.cmdlist[command].Usage + '\n'
+ if hasattr(self.cmdlist[command],'__doc__'):
+ txt=txt+_format_doc(self.cmdlist[command].__doc__)+'\n'
+
+ return txt
+
+ elif self.help_cmdtxt.has_key(command):
+ # If module unknown, return all
+ # text help.
+ ctext=''
+ for centry in self.help_cmdtxt[command]:
+ if quiet == 0:
+ ctext=ctext+'Module: '+centry[0]+'\n'
+ ctext=ctext+'Group: '+centry[1]+'\n'
+
+ ctext=ctext+centry[3] + '\n\n'
+
+ return ctext
+
+ else:
+ return None
+
+
+ def get_function_help(self, func, module_name=None, quiet=0):
+ """ Search for documentation on function func.
+ If module_name is set to None, search
+ through the local shell variables for func
+ and try to determine func's module from
+ its attributes; otherwise, look for any
+ help on function func.
+ If module_name is not None, check if
+ a func from module module_name is in the shell
+ variables or in the help. If not, try to
+ import it.
+ """
+ import Numeric
+
+ dtxt=None # default text
+ # mname- name of module for shell variable func
+ # if func is present in shell.
+ mname=None
+
+ # Get default python documentation, but don't return
+ # it unless module name is okay.
+ if ((self.locals.has_key(func)) and
+ (type(self.locals[func]) == type(launch)) and
+ (hasattr(self.locals[func],'__doc__'))):
+
+ if quiet == 0:
+ if hasattr(self.locals[func],'func_code'):
+ modname=os.path.basename(self.locals[func].func_code.co_filename)
+ mname,ext=os.path.splitext(modname)
+ dtxt='Module: '+mname+'\n\n'
+ else:
+ dtxt='Module: unknown\n\n'
+ else:
+ dtxt=''
+
+ dtxt=dtxt+_format_doc(self.locals[func].__doc__) + '\n'
+
+ elif ((self.locals.has_key(func)) and
+ (type(self.locals[func]) == type(Numeric.cos)) and
+ (hasattr(self.locals[func],'__doc__'))):
+
+ # Can't determine module from a ufunc's attributes
+ if quiet == 0:
+ dtxt='Universal function (ufunc)\n\n'
+ else:
+ dtxt=''
+
+ dtxt=dtxt+_format_doc(self.locals[func].__doc__) + '\n'
+
+ if self.help_functxt.has_key(func):
+ # If user specified particular module to
+ # search, only return help for that
+ # module.
+ if module_name is not None:
+ for centry in self.help_functxt[func]:
+ if centry[0] == module_name:
+ ctext=''
+ if quiet == 0:
+ ctext='Module: '+centry[0]+'\n\n'
+
+ ctext=ctext+centry[2]
+ return ctext
+
+ # If module name was not specfied, but
+ # func is present in the shell and module
+ # can be determined from func, return
+ # help for that module only.
+ elif mname is not None:
+ for centry in self.help_functxt[func]:
+ if centry[0] == mname:
+ ctext=''
+ if quiet == 0:
+ ctext='Module: '+centry[0]+'\n\n'
+
+ ctext=ctext+centry[2]
+ return ctext
+
+ # If no module specified or found, return
+ # all text file help available on func.
+ else:
+ ctext=''
+ for centry in self.help_functxt[func]:
+ if quiet == 0:
+ ctext=ctext+'Module: '+centry[0]+'\n\n'
+
+ ctext=ctext+centry[2]+'\n\n'
+
+ return ctext
+
+ # At this point, no suitable text file help has been found
+ if ((module_name is not None) and
+ (mname != module_name)):
+ # shell variable doesn't match requested module.
+ # try to import module and create help.
+ try:
+ exec 'import '+module_name
+ exec 'funcinst='+module_name+'.'+func
+ exec 'docstr=funcinst.__doc__'
+ except:
+ # couldn't load module or function, or couldn't
+ # locate documentation string once loaded
+ return None
+
+ if (type(funcinst) == type(launch)):
+ if quiet == 0:
+ dtxt='Module: '+module_name+'\n\n'
+ else:
+ dtxt=''
+ dtxt=dtxt+_format_doc(docstr)+'\n'
+ return dtxt
+
+ elif (type(funcinst) == type(Numeric.cos)):
+ if quiet == 0:
+ dtxt='Module: '+module_name+'\n\n'
+ dtxt=dtxt+'Universal function (ufunc)\n\n'
+ else:
+ dtxt=''
+ dtxt=dtxt+_format_doc(docstr)+'\n'
+ return dtxt
+
+ else:
+ # Not a recognized non-builtin function
+ # (type must be either function or ufunc)
+ return None
+
+ else:
+ return dtxt
+
+
+ def get_builtin_help(self, func, module_name=None,quiet=0):
+ if self.help_builtintxt.has_key(func):
+ if module_name is not None:
+ for centry in self.help_builtintxt[func]:
+ if centry[0] == module_name:
+ ctext=''
+ if quiet == 0:
+ ctext='Module: '+centry[0]+'\n\n'
+
+ ctext=ctext+centry[2]
+ return ctext
+ else:
+ ctext=''
+ for centry in self.help_builtintxt[func]:
+ if quiet == 0:
+ ctext=ctext+'Module: '+centry[0]+'\n\n'
+
+ ctext=ctext+centry[2]+'\n\n'
+
+ return ctext
+
+ # If code gets to here, no suitable help
+ # for func has been found.
+ if module_name is None:
+ if ((self.locals.has_key(func)) and
+ (type(self.locals[func]) == type(hasattr)) and
+ (hasattr(self.locals[func],'__doc__'))):
+ txt=_format_doc(self.locals[func].__doc__) + '\n'
+ return txt
+ else:
+ try:
+ # builtin function
+ txt=_format_doc(self.locals['__builtins__'][func].__doc__)+ '\n'
+ return txt
+ except:
+ return None
+
+ # No help has been found yet, and specific module has been requested
+ try:
+ exec 'import '+module_name
+ exec 'funcinst='+module_name+'.'+func
+ exec 'docstr=funcinst.__doc__'
+ if (type(funcinst) == type(hasattr)):
+ if quiet == 0:
+ txt='Module: '+module_name+'\n\n'
+ else:
+ txt=''
+ txt=txt+_format_doc(docstr) + '\n'
+ return txt
+ else:
+ return None
+ except:
+ # couldn't load module or function, or couldn't
+ # locate documentation string once loaded
+ return None
+
+ def add_helpfile(self, helpfilename):
+ if helpfilename in self.helpfiles:
+ # Already registered.
+ return 1
+
+ if os.path.isfile(helpfilename) == 0:
+ self.showText('Warning: help file '+helpfilename+'\n does not exist','error')
+ return 0
+
+ self.helpfiles.append(helpfilename)
+ fh=open(helpfilename)
+ helplines=fh.readlines()
+ ckey=None
+ ctext=''
+ ctype=None
+
+ # add a dummy line to the end to force the last
+ # command to be assigned (since assignment is
+ # done once a new command is started).
+ helplines.append('COMMAND_NAME=dummyhelpline')
+
+ for cline in helplines:
+ # linetype: 0 if an ordinary line is read, 1 if help for
+ # a new command is being defined, 2 if help for a new
+ # function is being defined, 3 if help for a new
+ # builtin function is being defined.
+ linetype=0
+ if(( len(cline) > 13) and (cline[:13] == 'COMMAND_NAME=')):
+ linetype=1
+
+ if(( len(cline) > 14) and (cline[:14] == 'FUNCTION_NAME=')):
+ linetype=2
+
+ if(( len(cline) > 13) and (cline[:13] == 'BUILTIN_NAME=')):
+ linetype=3
+
+ if (linetype > 0):
+ if (ckey is not None) and (ctype is not None):
+ # Assign last function/command's text, if
+ # present, before going on to next one.
+ if ctype == 'cmd':
+ # split help text into module, group,
+ # html filename, text.
+ parsed_help=_parse_cmdhelp_text(ctext)
+ if parsed_help is None:
+ errtxt='Invalid helpfile '+helpfilename+\
+ ':\nBad entry for command'+ckey+'.'
+ raise errtxt
+
+ mname=parsed_help[0]
+ gname=parsed_help[1]
+ hname=parsed_help[2]
+ ctext=parsed_help[3]
+
+ if self.help_cmdtxt.has_key(ckey):
+ # Some help has already been registered
+ # for a function of this name.
+ # Check if module already has help registered.
+ conflict=0
+ for idx in range(len(self.help_cmdtxt[ckey])):
+ item=self.help_cmdtxt[ckey][idx]
+ if item[0] == mname:
+ txt='Warning: multiple sets of help found for '+\
+ 'command '+ckey+', module '+mname+'.'+\
+ '\nIgnoring all but first.\n'
+ self.showText(txt,'error')
+ conflict=1
+
+ if conflict == 0:
+ self.help_cmdtxt[ckey].append([mname,gname,hname,ctext])
+ else:
+ self.help_cmdtxt[ckey]=[]
+ self.help_cmdtxt[ckey].append([mname,gname,hname,ctext])
+
+ elif ctype == 'blt':
+ parsed_help=_parse_funchelp_text(ctext)
+ if parsed_help is None:
+ errtxt='Invalid helpfile '+helpfilename+\
+ ':\nBad entry for built-in function '+ckey+'.'
+ raise errtxt
+
+ mname=parsed_help[0]
+ hname=parsed_help[1]
+ ctext=parsed_help[2]
+
+ if self.help_builtintxt.has_key(ckey):
+ # Some help has already been registered
+ # for a function of this name
+ # Check if module already has help registered.
+ conflict=0
+ for idx in range(len(self.help_builtintxt[ckey])):
+ item=self.help_builtintxt[ckey][idx]
+ if item[0] == mname:
+ txt='Warning: multiple sets of help found for '+\
+ 'built-in function '+ckey+', module '+mname+'.'+\
+ '\nIgnoring all but first.'
+ self.showText(txt,'error')
+ conflict=1
+
+ if conflict == 0:
+ self.help_builtintxt[ckey].append([mname,hname,ctext])
+ else:
+ self.help_builtintxt[ckey]=[]
+ self.help_builtintxt[ckey].append([mname,hname,ctext])
+ else:
+ parsed_help=_parse_funchelp_text(ctext)
+ if parsed_help is None:
+ errtxt='Invalid helpfile '+helpfilename+\
+ ':\nBad entry for function '+ckey+'.'
+ raise errtxt
+
+ mname=parsed_help[0]
+ hname=parsed_help[1]
+ ctext=parsed_help[2]
+
+ if self.help_functxt.has_key(ckey):
+ # Some help has already been registered
+ # for a function of this name
+ # Check if module already has help registered.
+ conflict=0
+ for idx in range(len(self.help_functxt[ckey])):
+ item=self.help_functxt[ckey][idx]
+ if item[0] == mname:
+ txt='Warning: multiple sets of help found for '+\
+ 'function '+ckey+', module '+mname+'.'+\
+ '\nIgnoring all but first.'
+ self.showText(txt,'error')
+ conflict=1
+
+ if conflict == 0:
+ self.help_functxt[ckey].append([mname,hname,ctext])
+ else:
+ self.help_functxt[ckey]=[]
+ self.help_functxt[ckey].append([mname,hname,ctext])
+
+ if (linetype == 1):
+ junk,ckey = string.split(cline,'=',1)
+ ckey=string.strip(ckey)
+ ctext=''
+ ctype='cmd'
+ elif (linetype == 2):
+ junk,ckey = string.split(cline,'=',1)
+ ckey=string.strip(ckey)
+ ctext=''
+ ctype='fnc'
+ elif (linetype == 3):
+ junk,ckey = string.split(cline,'=',1)
+ ckey=string.strip(ckey)
+ ctext=''
+ ctype='blt'
+ else:
+ ctext=ctext+cline
+
+ return 1
+
+class PseudoFile:
+# To send stdout to our console
+
+ def __init__(self, shell, name):
+ self.shell = shell
+ self.name = name
+
+ def write(self, s):
+ self.shell.my_write(s, self.name)
+ # self.shell.write(s)
+
+ import gdal
+ gdal.Debug( "stderr", s )
+
+ def writelines(self, l):
+ map(self.write, l)
+
+ def flush(self):
+ pass
+
+ def isatty(self):
+ return 1
+
+
+# Creates interactive Python Shell
+#
+# inherit - true if parent's python environment be inherited
+# None if it shouldn't and want a clean environment
+
+class Shell(GtkWindow):
+ def __init__(self, inherit=None, width=550, height = 250, standalone=0,pyshellfile=None):
+
+ # Main Window, buttons
+ GtkWindow.__init__(self)
+ self.set_title('Python Shell')
+ self.set_border_width(3)
+
+ self.pyshellfile=pyshellfile
+
+
+ if pyshellfile is not None:
+ guicmds=self.load_pyshell_file_from_xml(self.pyshellfile)
+ else:
+ # If pyshellfile is None, default to old appearance.
+
+ #menucmds=[]
+ #menucmds.append(self.__get_standard_menu_entries())
+ #guicmds=(menucmds,None,None,None)
+ guicmds=(None,None,None,None)
+
+ # Use a paned window if the history area is present; a normal
+ # vbox if it isn't.
+ # panel for menu, messages, icons, command line
+ if (guicmds[2] is not None):
+ pane1=GtkVPaned()
+ vbox = GtkVBox(homogeneous=FALSE,spacing=2)
+ self.add(pane1)
+ pane1.add1(vbox)
+ else:
+ vbox=GtkVBox(homogeneous=FALSE,spacing=2)
+ self.add(vbox)
+
+ self.standalone = standalone
+
+ # Path Preferences
+ # Currently, the module and script paths
+ # are treated the same way- they are added
+ # to the system path, and python will search
+ # all three for commands, modules.
+ self.preferences={}
+
+ import gview
+ import sys
+
+ mpathstring=""
+ for i in range(1,MAX_MODULE_PATHS+1):
+ mpath = gview.get_preference('pyshell_module_path'+str(i))
+ if mpath is not None:
+ if mpath not in sys.path:
+ sys.path.append(mpath)
+ if len(mpathstring) == 0:
+ mpathstring=mpath
+ else:
+ mpathstring=mpathstring+";"+mpath
+
+ cpathstring=""
+ for i in range(1,MAX_COMMAND_PATHS+1):
+ cpath = gview.get_preference('pyshell_command_path'+str(i))
+ if cpath is not None:
+ if cpath not in sys.path:
+ sys.path.append(cpath)
+ if len(cpathstring) == 0:
+ cpathstring=cpath
+ else:
+ cpathstring=cpathstring+";"+cpath
+
+ self.preferences['MODULE PATHS']=mpathstring
+ self.preferences['COMMAND PATHS']=cpathstring
+
+ self.path_dlg = None
+
+ # Menu
+ if (guicmds[0] is not None):
+ menuf = gvutils.GvMenuFactory()
+ self.menuf = menuf
+ if self.standalone != 0:
+ self.close_cb = self.close
+ else:
+ self.close_cb = self.destroy
+
+ for cmd in guicmds[0]:
+ exec cmd
+
+ self.add_accel_group(menuf.accelerator)
+ vbox.pack_start(menuf,expand=FALSE)
+ else:
+ self.menuf = None
+
+ # Iconbar
+ if (guicmds[1] is not None) and (len(guicmds[1]) > 0):
+ self.iconbar = GtkToolbar(ORIENTATION_HORIZONTAL,
+ TOOLBAR_ICONS)
+ for cmd in guicmds[1]:
+ exec cmd
+
+ vbox.pack_start(self.iconbar,expand=FALSE)
+ else:
+ self.iconbar = None
+
+ top_console = GtkHBox(homogeneous=FALSE, spacing=2)
+ vbox.pack_start(top_console, expand=TRUE)
+
+ text = GtkText()
+ text.set_editable(FALSE)
+ top_console.pack_start(text, expand=TRUE)
+
+ # Scrollbars
+ scroll = GtkVScrollbar(adj=text.get_vadjustment())
+ top_console.pack_start(scroll, expand=FALSE)
+
+ #Horizontal separator bar
+ vbox.pack_start(GtkHSeparator(), expand=FALSE)
+
+ # Prompt Text Area
+ prompt = GtkText()
+ prompt.set_usize(550, 50)
+ prompt.set_editable(TRUE)
+ vbox.pack_start(prompt, expand=FALSE)
+
+ if guicmds[2] is not None:
+ vbox2=GtkVBox()
+ pane1.add2(vbox2)
+ #Horizontal separator bar
+ hlabel = GtkLabel('Command History')
+ hlabel.set_justify(JUSTIFY_LEFT)
+ #vbox2.pack_start(GtkHSeparator(), expand=FALSE)
+ histhbox=GtkHBox()
+ vbox2.pack_start(histhbox,expand=FALSE,fill=FALSE)
+ histhbox.pack_start(hlabel,expand=FALSE,fill=FALSE)
+ # History list
+ histbox = GtkScrolledWindow()
+ vbox2.pack_start(histbox)
+ histlist = GtkCList(cols=1)
+
+ # Changed from add_with_viewport to
+ # add to avoid Gtk warnings about
+ # size allocation for long history
+ # lists (> about 65 lines). Not sure
+ # why this is necessary, but someone
+ # else had fixed the problem that way
+ # according to an email found with google.
+ # histbox.add_with_viewport(histlist)
+ histbox.add(histlist)
+
+ histlist.set_selection_mode(SELECTION_SINGLE)
+ histlist.connect('button-press-event',self.list_clicked)
+ else:
+ histlist = None
+
+ if guicmds[3] is not None:
+ #Horizontal separator bar
+ # vbox2 is only created if the history area is created
+ # (paned window is only necessary in that case currently).
+ if guicmds[2] is not None:
+ vbox2.pack_start(GtkHSeparator(), expand=FALSE)
+ else:
+ vbox.pack_start(GtkHSeparator(), expand=FALSE)
+ self.status_bar = GtkStatusbar()
+ self.status_bar.progress_bar = GtkProgressBar()
+ self.status_bar.shell_context = self.status_bar.get_context_id('shell')
+ self.status_bar.pack_start(self.status_bar.progress_bar, expand=FALSE)
+ if guicmds[2] is not None:
+ vbox2.pack_start(self.status_bar, expand=FALSE)
+ else:
+ vbox.pack_start(self.status_bar, expand=FALSE)
+ else:
+ self.status_bar = None
+
+ # Setup up the size of the dialog
+ totalheight = height
+ if self.menuf is not None:
+ totalheight=totalheight + 50
+ if self.iconbar is not None:
+ totalheight=totalheight + 50
+ if histlist is not None:
+ totalheight=totalheight + 250
+
+ self.set_usize(width, totalheight)
+ self.set_policy(FALSE, TRUE, TRUE)
+
+ # Text properties
+ style = text.get_style()
+ self.fg = style.fg[STATE_NORMAL]
+ self.bg = style.white
+ self.font = load_font(
+ "-*-courier-medium-r-normal-*-14-140-*-*-*-*-iso8859-*")
+
+ vbox.show_all()
+ self.history_list = histlist
+ self.text = text
+ self.prompt = prompt
+
+ # Environment variables
+ self.prompt_state = 0
+ self.history_buffer = []
+ self.history_pos = None
+
+ # watch for key presses such as returns and Ctrl-D
+ self.prompt.connect_after('key-press-event', self.echo)
+
+ # Setup actual python interpreter
+ self.interp = MyInteractiveConsole(text, inherit, self.history_list,
+ self.status_bar)
+
+ # Redefine stdout and stderr so they go to our console
+ sys.stdout = PseudoFile(self.interp, 'stdout')
+
+ # May 2003- commented out the stderr pseudofile- general
+ # openev errors probably shouldn't go to python shell.
+ #sys.stderr = PseudoFile(self.interp, 'stderr')
+
+ self.set_prompt()
+ self.interp.my_write( \
+ ' --== Interactive Python Interpreter ==--\n\n',
+ 'title')
+
+ # Make sure that function to parse command lines is loaded.
+ self.interp.push('from pyshell import _run_command_line')
+
+ # Standalone property: 0 if shell launched
+ # from OpenEV or similar application; 1 if
+ # shell launched alone. Shells that are
+ # standalone will connect to the gtk quit event.
+
+ if self.standalone != 0:
+ self.connect('delete-event',self.close)
+
+ def preferences_cb(self,*args):
+ self.pref_gui_cb()
+
+ def launch_help_cb(self,*args):
+ PyshellHelpDialog()
+
+ def close(self,*args):
+ response = \
+ GtkExtra.message_box( 'Confirmation',
+ 'Are you sure you want to exit OpenEV Command Shell?',
+ ('Yes', 'No') )
+
+
+ if response == 'Yes':
+ import gview
+ gview.save_preferences() # save path preferences
+ gview.app.quit()
+
+ return TRUE
+
+ def show_progress(self,percent,msg=None):
+ if self.status_bar is None:
+ return
+
+ self.interp.showProgress(percent,msg)
+
+ # Make sure that progress bar updates
+ # immediately
+ while events_pending():
+ mainiteration()
+
+ def echo(self, text, event, *args):
+ # Watch for Returns - Main processing loop here!!!!
+ if event.keyval == GDK.Return:
+ input = str(self.prompt.get_chars(0, -1))
+
+ # Remove any internal newlines.
+ input = string.replace(input,chr(10),"")
+
+ # echo command in text dialog
+ self.append_text(input+chr(10))
+
+ # Pick out command, and strip trailing white space (newline)
+ command = string.rstrip(input[4:])
+
+ self.interp.clearFlags()
+ self.prompt_state = self.interp.push(command)
+
+ # Add command to history buffer
+ self.history_buffer.insert(0, command)
+
+ # Reset the prompt if needed, and history position
+ self.set_prompt()
+ self.history_pos = None
+ if self.history_list is not None:
+ self.history_list.unselect_all()
+
+ # Watch for Ctrl-D
+ elif (event.keyval in (ord('d'), ord('D'))) \
+ and (event.state & GDK.CONTROL_MASK):
+ input = str(self.prompt.get_chars(0, -1))
+ if len(input) == 4:
+ if self.standalone != 0:
+ import gview
+ gview.app.quit()
+ else:
+ self.destroy()
+
+ # Up Arrow - back in history list
+ elif event.keyval == GDK.Up:
+ if len(self.history_buffer) > 0:
+ self.set_prompt()
+
+ if self.history_pos is None:
+ self.history_pos = -1
+
+ if self.history_pos < len(self.history_buffer) - 1:
+ self.history_pos = self.history_pos + 1
+
+ self.prompt.insert(self.font, self.fg, self.bg, self.history_buffer[self.history_pos])
+
+ if self.history_list is not None:
+ if self.history_pos < self.history_list.rows:
+ self.history_list.select_row(self.history_pos,0)
+
+
+ # Down Arrow - forward in history list
+ elif event.keyval == GDK.Down:
+ if (self.history_pos is not None) and (self.history_pos > 0):
+ self.set_prompt()
+ self.history_pos = self.history_pos - 1
+ self.prompt.insert(self.font, self.fg, self.bg, self.history_buffer[self.history_pos])
+
+ # select relevant row in history list
+ if self.history_list is not None:
+ if self.history_pos < self.history_list.rows:
+ self.history_list.select_row(self.history_pos,0)
+
+ elif (self.history_pos is not None) and (self.history_pos == 0):
+ self.set_prompt()
+ self.history_pos = None
+ if self.history_list is not None:
+ self.history_list.unselect_all()
+
+ # Make sure we don't delete the prompt
+ elif (event.keyval == GDK.BackSpace) and (self.prompt.get_position() < 4):
+ self.prompt.insert(self.font, self.fg, self.bg, ' ')
+
+ # Watch user doesn't uses arrow keys to move into prompt
+ if self.prompt.get_position() < 5:
+ self.prompt.set_position(4)
+
+ return TRUE
+
+ def list_clicked(self, lst, event):
+ if self.history_list is None:
+ return
+
+ try:
+ row, col = lst.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ if event.button == 1:
+ lst.emit_stop_by_name('button-press-event')
+ self.set_prompt()
+ self.prompt.insert(self.font, self.fg, self.bg, lst.get_text(row,col))
+ self.history_list.select_row(row,col)
+ if len(self.history_buffer) >= row:
+ self.history_pos = row
+
+ def append_text(self, msg):
+ self.interp.my_write( msg, 'command' )
+
+ def set_prompt(self):
+ if self.prompt_state == 0:
+ # Line dealt with in some way - reset prompt
+ self.prompt.delete_text(0, -1)
+ self.prompt.insert(self.font, self.fg, self.bg, '>>> ')
+ elif self.prompt_state == 1:
+ # More input required
+ self.prompt.delete_text(0, -1)
+ self.prompt.insert(self.font, self.fg, self.bg, '... ')
+ else:
+ raise RunTimeError, ' Should not get here - pyshell.py '
+
+ def command(self, line):
+ """ Takes single line commands, doesn't echo line to console, but output will """
+
+ self.prompt_state = self.interp.push(line)
+
+ def add_command(self, command):
+ self.interp.cmdlist[string.lower(command.Name)] = command
+
+ def add_helpfile(self,helpfilename):
+ self.interp.add_helpfile(helpfilename)
+
+ def get_commands(self):
+ return list(self.interp.cmdlist.values())
+
+ def hide_dialog_cb(self,*args):
+ dialog = args[0]
+ dialog.hide()
+ return TRUE
+
+ def pref_gui_cb(self):
+ if self.path_dlg is None:
+ new_dlg = GtkWindow()
+ new_dlg.connect('delete-event',self.hide_dialog_cb)
+ new_dlg.set_title('Paths')
+ new_dlg.set_usize(450,100)
+
+ self.path_dlg = new_dlg
+
+ path_keys = ['MODULE PATHS','COMMAND PATHS']
+ nrows = len(self.preferences.keys())+1
+ wtable = GtkTable(nrows,2,FALSE)
+ wtable.set_row_spacings(5)
+ wtable.set_col_spacings(5)
+ wtable.set_border_width(5)
+ new_dlg.add(wtable)
+
+
+ for idx in range(len(path_keys)):
+ startpath=self.preferences[path_keys[idx]]
+ clabel = GtkLabel(path_keys[idx])
+ wtable.attach(clabel, 0,1, idx,idx+1)
+ centry = GtkEntry(maxlen=350)
+ # replace the path string with
+ # an entry object
+ self.preferences[path_keys[idx]] = centry
+ centry.set_editable(TRUE)
+ centry.set_usize(280, 25)
+ centry.set_text(startpath)
+ wtable.attach(centry, 1,2, idx,idx+1)
+
+ apply_button = GtkButton('Apply')
+ wtable.attach(apply_button, 1,2, nrows-1,nrows)
+ apply_button.connect('clicked',self._update_prefs_cb,'Paths')
+
+ wtable.show()
+ self.path_dlg.show_all()
+
+ else:
+ self.path_dlg.show_all()
+ self.path_dlg.get_window()._raise()
+
+ def _update_prefs_cb(self,*args):
+ pref_type = args[1]
+ if pref_type == 'Paths':
+ modpaths = self.preferences['MODULE PATHS'].get_text()
+ commandpaths = self.preferences['COMMAND PATHS'].get_text()
+
+ import sys
+ import string
+ import gview
+
+ # Clear old settings to ''
+ # Note: old paths are not popped in case a
+ # path is shared (eg. if the user specifies
+ # OPENEVHOME as a path), since each path is
+ # only added once.
+
+ for idx in range(1,MAX_MODULE_PATHS+1):
+ if gview.get_preference('pyshell_module_path'+str(idx)) is not None:
+ gview.set_preference('pyshell_module_path'+str(idx),'')
+
+ for idx in range(1,MAX_COMMAND_PATHS+1):
+ if gview.get_preference('pyshell_command_path'+str(idx)) is not None:
+ gview.set_preference('pyshell_command_path'+str(idx),'')
+
+ # Get new settings: paths are assumed to be separated
+ # by commas.
+ modtokens=string.split(modpaths,";")
+ idx=1
+
+ for modpath in modtokens:
+ if len(modpath) == 0:
+ continue
+
+ if (modpath not in sys.path) and (os.path.isdir(modpath)):
+ sys.path.append(modpath)
+
+ if (os.path.isdir(modpath)):
+ if idx < MAX_MODULE_PATHS+1:
+ gview.set_preference('pyshell_module_path'+str(idx),modpath)
+ else:
+ gvutils.warning('Only the first'+str(MAX_MODULE_PATHS+1)+\
+ 'module paths will be loaded from preferences.')
+ idx=idx+1
+ else:
+ import gvutils
+ gvutils.warning(modpath+' does not exist or is not a directory.')
+
+ cmdtokens=string.split(commandpaths,";")
+ idx=1
+ for cmdpath in cmdtokens:
+ if len(cmdpath) == 0:
+ continue
+
+ if (cmdpath not in sys.path) and (os.path.isdir(cmdpath)):
+ sys.path.append(cmdpath)
+
+ if (os.path.isdir(cmdpath)):
+ if idx < MAX_COMMAND_PATHS+1:
+ gview.set_preference('pyshell_command_path'+str(idx),cmdpath)
+ else:
+ gvutils.warning('Only the first'+ str(MAX_COMMAND_PATHS+1)+\
+ ' command paths will be loaded from preferences.')
+ idx=idx+1
+
+ else:
+ import gvutils
+ gvutils.warning(cmdpath+' does not exist or is not a directory.')
+
+ self.hide_dialog_cb(self.path_dlg)
+
+ def __get_standard_menu_entries(self):
+ # python shell menu entries that are available
+ # without the addition of tools (not exposed
+ # by default).
+ menucmd="self.menuf.add_entries(["+\
+ "('File/Preferences', None, self.preferences_cb ),"+\
+ "('File/Quit', '<control>D', self.close_cb),"+\
+ "('Help/Help',None,self.launch_help_cb)"+\
+ "])"
+ return menucmd
+
+ def load_pyshell_file_from_xml(self,pyshellfile="DefaultPyshellFile.xml"):
+ import gview
+ import gdal
+
+ pyshellfile=os.path.join(gview.home_dir,'xmlconfig',pyshellfile)
+ try:
+ raw_xml = open(pyshellfile).read()
+ except:
+ raise AttributeError,"Unable to load " + pyshellfile
+ return
+
+ tree = gdal.ParseXMLString( raw_xml )
+ if tree is None:
+ raise AttributeError,"Problem occured parsing pyshell file " + pyshellfile
+ return
+
+ if tree[1] != 'GViewAppPyshell':
+ raise AttributeError,"Root of %s is not GViewAppPyshell node " % iconfile
+ return
+
+ # Optional parts of python shell: menu, icon bar, history area, progress bar
+ # If not specified in the xml file, they will not be included. Currently
+ # History area and progress bar are either present or not, with the []
+ # indicating that they should be included. Later, preferences may or may not
+ # be added to customize them. Menu and icon customization is similar to
+ # the main OpenEV shell.
+ menucmds=None
+ iconcmds=None
+ historycmds=None
+ progresscmds=None
+ for node in tree[2:]:
+ if node[1] == 'Menu':
+ menucmds=self.parse_menu_xml_node(node)
+ elif node[1] == 'Iconbar':
+ iconcmds=self.parse_icon_xml_node(node)
+ elif node[1] == 'History':
+ historycmds=[]
+ elif node[1] == 'Progress':
+ progresscmds=[]
+ else:
+ txt="Invalid node %s in pyshell file %s.\n" % node[1],pyshellfile
+ txt=txt+"Valid node types are Menu, Iconbar, History, and Progress."
+ raise AttributeError,txt
+
+ # This tuple may be extended at a later date
+ return (menucmds,iconcmds,historycmds,progresscmds)
+
+ def parse_menu_xml_node(self,menunode):
+ import gview
+
+ tools_to_include='All'
+ tools_accounted_for=[]
+ menu_list=[]
+
+ for node in menunode[2:]:
+ if node[1] == 'entry':
+ node_path = gvutils.XMLFind( node, 'path')
+ if node_path is None:
+ raise AttributeError,"Invalid menu file format - missing path"
+
+ entry_type = gvutils.XMLFindValue( node_path, 'type', '')
+ entry_path = gvutils.XMLFindValue( node, 'path','')
+
+ if (string.find(entry_path,"/") == -1):
+ raise AttributeError,"Invalid menu file format - bad path:%s" % entry_path
+
+ if (entry_type != ''):
+ entry_type = "<" + entry_type + ">"
+ path_split=string.split(entry_path,"/")
+ path_split[-1] = entry_type + path_split[-1]
+ entry_path=string.join(path_split,"/")
+
+ entry_accelerator = gvutils.XMLFindValue( node, 'accelerator', 'None')
+ if (entry_accelerator != 'None'):
+ (key,mod) = string.split(entry_accelerator,'+')
+ entry_accelerator = "'<" + key + ">" + mod + "'"
+
+ entry_callback = gvutils.XMLFindValue( node, 'callback', 'None')
+ entry= "(" \
+ + string.join((entry_path,entry_accelerator, \
+ entry_callback),",")
+
+ arguments = gvutils.XMLFind( node, 'arguments')
+ if arguments is not None:
+ args_list = []
+ args = gvutils.XMLFind( arguments, 'arg','')
+ if args is not None:
+ for arg in args:
+ args_list.append(gvutils.XMLFindValue( arg, '',''))
+ entry = entry + "," + string.join(args_list,",")
+
+ entry = entry + ")"
+
+ menu_list.append(entry)
+
+ elif node[1] == 'tools':
+ tools_to_include=node[2][1]
+
+ elif node[1] == 'simpletoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid menu file format - missing tool name"
+
+ if gview.app.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid menu file format- tool "+toolname+" not loaded."
+
+ ctool=gview.app.Tool_List[gview.app.tool_index[toolname]][1]
+ for cpath in ctool.pymenu_entries.entries.keys():
+ # Ignore default position- overridden by position in file
+ # Also note: tool callbacks don't have arguments
+ entry_accelerator=ctool.pymenu_entries.entries[cpath][2]
+ if entry_accelerator is None:
+ entry_accelerator=str(None)
+ else:
+ entry_accelerator="'"+entry_accelerator+"'"
+
+ entry= "(" \
+ + string.join(("'"+cpath+"'",entry_accelerator, \
+ "gview.app.Tool_List[gview.app.tool_index['"+toolname+\
+ "']][1].pymenu_entries.entries['"+cpath+"'][1]"),",")+")"
+
+ menu_list.append(entry)
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+
+ elif node[1] == 'complextoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid menu file format - missing tool name"
+
+ oldpath = gvutils.XMLFindValue( node, 'oldpath')
+
+ if oldpath is None:
+ txt="Invalid menu file format - complex tool entry\nrequires oldpath item."
+ raise AttributeError,txt
+ oldpath = oldpath[1:-1] # Entries in XML file are surrounded by quotes- get rid of them
+
+ newpath = gvutils.XMLFindValue( node, 'newpath')
+ if newpath is None:
+ txt="Invalid menu file format - complex tool entry\nrequires newpath item."
+ raise AttributeError,txt
+ newpath = newpath[1:-1] # Entries in XML file are surrounded by quotes- get rid of them
+
+ if gview.app.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid menu file format- tool "+toolname+" not loaded."
+
+ ctool=gview.app.Tool_List[gview.app.tool_index[toolname]][1]
+ if ctool.pymenu_entries.entries.has_key(oldpath) == 0:
+ raise AttributeError,'Invalid menu file entry- tool '+toolname+\
+ ' has no\nmenu entry '+oldpath
+
+ entry_accelerator=gvutils.XMLFindValue( node, 'accelerator' )
+ if entry_accelerator is None:
+ entry_accelerator=ctool.pymenu_entries.entries[oldpath][2]
+ else:
+ (key,mod)=string.split(entry_accelerator,'+')
+ entry_accelerator="<"+key+">"+mod
+
+ if entry_accelerator is None:
+ entry_accelerator=str(None)
+ else:
+ entry_accelerator="'"+entry_accelerator+"'"
+
+ entry= "(" \
+ + string.join(("'"+newpath+"'",entry_accelerator, \
+ "gview.app.Tool_List[gview.app.tool_index['"+toolname+\
+ "']][1].pymenu_entries.entries['"+oldpath+"'][1]"),",") + ")"
+
+ menu_list.append(entry)
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+
+ if tools_to_include not in ['All','None','Some']:
+ raise AttributeError,"Invalid menu file format- <tool> entry should be All, None, or Some."
+
+ if ((tools_to_include == 'None') and (len(tools_accounted_for) > 0)):
+ txt = "Invalid menu file format- if <tool> entry is None,\nno "
+ txt = txt+"simpletoolentry or complextoolentry items may be specified."
+ raise AttributeError,txt
+
+ remaining_cmds=[]
+ if tools_to_include == 'All':
+ for citem in gview.app.Tool_List:
+ if citem[0] not in tools_accounted_for:
+ ctool=citem[1]
+ for centry in ctool.pymenu_entries.entries.keys():
+ cpos=ctool.pymenu_entries.entries[centry][0]
+ cpos=max(cpos,0)
+ accel=ctool.pymenu_entries.entries[centry][2]
+ if accel is None:
+ accel=str(None)
+ else:
+ accel="'"+accel+"'"
+
+ entry= "self.menuf.insert_entry(" \
+ + string.join((str(cpos),"'"+centry+"'",accel, \
+ "gview.app.Tool_List[gview.app.tool_index['"+citem[0]+\
+ "']][1].pymenu_entries.entries['"+centry+"'][1]"),",")+")"
+ remaining_cmds.append(entry)
+
+ # create the menu command to populate the entries
+ menu_cmds=[]
+ menu_cmd = "self.menuf.add_entries([" + string.join(menu_list,',') + "])"
+ menu_cmds.append(menu_cmd)
+ if len(remaining_cmds) > 0:
+ menu_cmds.extend(remaining_cmds)
+
+ return menu_cmds
+
+ def parse_icon_xml_node(self,iconnode):
+ import gview
+
+ tools_to_include = 'All'
+ tools_accounted_for=[]
+ tool_entry_list=[]
+ icon_list=[]
+ for node in iconnode[2:]:
+ if node[1] == 'icon':
+ type = None
+ icon_label = gvutils.XMLFindValue( node, 'label','None')
+ icon_hint = gvutils.XMLFindValue( node, 'hint','None')
+ icon_callback = gvutils.XMLFindValue( node, 'callback','None')
+ icon_help = gvutils.XMLFindValue( node, 'help','None')
+ icon_file = gvutils.XMLFindValue( node, 'xpm','None')
+ # xpm files - need to add path and possible help
+ if (icon_file != 'None'):
+ type = 'xpm'
+ icon = "self.add_icon_to_bar(" \
+ + string.join((icon_file,icon_label,icon_hint, \
+ icon_callback,icon_help),",") \
+ + ")"
+
+ # pixmap files - not adding path or help
+ icon_file = gvutils.XMLFindValue( node, 'pixmap','None')
+ if (icon_file!= 'None'):
+ type = 'pixmap'
+ icon = "self.iconbar.append_item(" \
+ + string.join((icon_label,icon_hint,icon_hint, \
+ icon_file,icon_callback),",") \
+ + ")"
+
+ # widget
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ if (icon_file!= 'None'):
+ type = 'widget'
+ icon_file = gvutils.XMLFindValue( node, 'widget','None')
+ icon = "self.iconbar.append_widget(" \
+ + string.join((icon_file,icon_hint,icon_hint),",") \
+ + ")"
+ # none of the above
+ if type is None:
+ raise AttributeError,"Invalid icon file format - unknown type"
+
+ icon_list.append(icon)
+ elif node[1] == 'tools':
+ tools_to_include=node[2][1]
+ elif node[1] == 'simpletoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid pyshell file format - missing tool name"
+
+ if gview.app.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid pyshell file format- tool "+toolname+" not loaded."
+
+ ctool=gview.app.Tool_List[gview.app.tool_index[toolname]][1]
+ idx=0
+ for centry in ctool.pyicon_entries.entries:
+ icon_file=centry[0]
+
+ icon_label=centry[1]
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ icon_hint=centry[2]
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ # Ignore position- it is overridden by this entry's location in the
+ # xml file
+ icon_callback=centry[4]
+ icon_help=centry[5]
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ icon_type=centry[6]
+ if icon_type == 'xpm':
+ icon = "self.add_icon_to_bar(" \
+ + string.join(("'"+icon_file+"'",\
+ icon_label,icon_hint, \
+ "gview.app.Tool_List[gview.app.tool_index['"+\
+ toolname+"']][1].pyicon_entries.entries["+\
+ str(idx)+"][4]",icon_help),",") + ")"
+ icon_list.append(icon)
+ else:
+ raise AttributeError,"Invalid icon type "+icon_type+" in tool "+toolname+"."
+ idx=idx+1
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+ elif node[1] == 'complextoolentry':
+ toolname = gvutils.XMLFindValue( node, 'name')
+ if toolname is None:
+ raise AttributeError,"Invalid icon file format - missing tool name."
+
+ oindex = gvutils.XMLFindValue( node, 'index')
+
+ if oindex is None:
+ txt="Invalid icon file format - complex tool entry\n"+\
+ "requires the index of the icon entry\n"
+ txt=txt+"to replace (0...number of entries-1).\n"
+ raise AttributeError,txt
+ try:
+ oindex=int(oindex)
+ except:
+ raise AttributeError,"Invalid icon file- icon index to replace must be an integer."
+
+ if gview.app.tool_index.has_key(toolname) == 0:
+ raise AttributeError,"Invalid icon file entry- tool "+toolname+" not loaded."
+
+ ctool=gview.app.Tool_List[gview.app.tool_index[toolname]][1]
+ if len(ctool.pyicon_entries.entries) < (oindex+1):
+ txt='Invalid file file entry- for tool '+toolname+'.\n maximum entry index is '
+ txt=txt+str(len(ctool.pyicon_entries.entries)-1)+'.'
+
+ icon_file=gvutils.XMLFindValue( node, 'xpm')
+ icon_hint=gvutils.XMLFindValue( node, 'hint')
+ icon_label=gvutils.XMLFindValue( node, 'label')
+ icon_help=gvutils.XMLFindValue( node, 'help')
+
+ if icon_file is None:
+ icon_file="'"+ctool.icon_entries.entries[oindex][0]+"'"
+ elif os.path.isfile(icon_file):
+ if os.name == 'nt':
+ icon_file="'"+string.replace(icon_file,"\\","\\\\")+"'"
+ else:
+ icon_file="'"+icon_file+"'"
+ elif os.path.isfile(os.path.join(gview.home_dir,'tools',icon_file)):
+ icon_file="'"+os.path.join(gview.home_dir,'tools',icon_file)+"'"
+ if os.name == 'nt':
+ icon_file=string.replace(icon_file,"\\","\\\\")
+ elif os.path.isfile(os.path.join(gview.home_dir,'pics',icon_file)):
+ icon_file="'"+os.path.join(gview.home_dir,'pics',icon_file)+"'"
+ if os.name == 'nt':
+ icon_file=string.replace(icon_file,"\\","\\\\")
+ else:
+ txt = "Cannot find file "+tempf+'. Either the full\n'
+ txt = txt+"path must be specified, or "+tempf+ " must be\n"
+ txt = txt+"placed in the tools or pics directory."
+ raise AttributeError,txt
+
+
+ if icon_label is None:
+ icon_label=ctool.pyicon_entries.entries[oindex][1]
+
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ if icon_hint is None:
+ icon_hint=ctool.pyicon_entries.entries[oindex][2]
+
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ if icon_help is None:
+ icon_help=ctool.pyicon_entries.entries[oindex][5]
+
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ icon_callback=ctool.pyicon_entries.entries[oindex][4]
+ icon_type=ctool.pyicon_entries.entries[oindex][6]
+ if icon_type == 'xpm':
+ icon = "self.add_icon_to_bar(" \
+ + string.join((icon_file,icon_label,icon_hint, \
+ "gview.app.Tool_List[gview.app.tool_index['"+\
+ toolname+"']][1].pyicon_entries.entries["+\
+ str(oindex)+"][4]",icon_help),",") + ")"
+ icon_list.append(icon)
+ else:
+ raise AttributeError,"Invalid icon type "+icon_type+" in tool "+toolname+"."
+
+ if toolname not in tools_accounted_for:
+ tools_accounted_for.append(toolname)
+
+
+ if tools_to_include not in ['All','None','Some']:
+ raise AttributeError,"Invalid pyshell file format- icon <tool>"+\
+ " entry should be All, None, or Some."
+
+ if ((tools_to_include == 'None') and (len(tools_accounted_for) > 0)):
+ txt = "Invalid icon file format- if <tool> entry is None,\nno "
+ txt = txt+"simpletoolentry or complextoolentry items may be specified."
+ raise AttributeError,txt
+
+ if tools_to_include == 'All':
+ for citem in gview.app.Tool_List:
+ if citem[0] not in tools_accounted_for:
+ ctool=citem[1]
+ idx=0
+ for centry in ctool.pyicon_entries.entries:
+ if centry[6] != 'xpm':
+ raise AttributeError,"Error loading tool entry for tool "+\
+ citem[0]+"- icon type "+centry[6]+" invalid."
+
+ icon_file="'"+centry[0]+"'"
+ icon_label=centry[1]
+ if icon_label is not None:
+ icon_label="'"+icon_label+"'"
+ else:
+ icon_label=str(None)
+
+ icon_hint=centry[2]
+ if icon_hint is not None:
+ icon_hint="'"+icon_hint+"'"
+ else:
+ icon_hint=str(None)
+
+ icon_help=centry[5]
+ if icon_help is not None:
+ icon_help="'"+icon_help+"'"
+ else:
+ icon_help=str(None)
+
+ # Default position in icon bar used
+ pos=centry[3]
+ icon = "self.add_icon_to_bar(" +\
+ string.join((icon_file,icon_label,icon_hint, \
+ "gview.app.Tool_List[gview.app.tool_index['"+citem[0]+\
+ "']][1].pyicon_entries.entries["+\
+ str(idx)+"][4]",icon_help),",") + ")"
+
+ pos=max(pos,0)
+ if pos > len(icon_list):
+ icon_list.append(icon)
+ else:
+ icon_list.insert(pos,icon)
+ idx=idx+1
+
+ return icon_list
+
+ def add_icon_to_bar(self, filename, text, hint_text, cb, help_topic=None):
+ # Next line doesn't overwrite filename if it is already a full
+ # path (os.path.join is intelligent).
+ import gview
+ import gvhtml
+ if os.name == 'nt':
+ filename=string.replace(filename,"\\","\\\\")
+
+ full_filename = os.path.join(gview.home_dir,'pics',filename)
+ pix, mask = create_pixmap_from_xpm(self,None,full_filename)
+ item = self.iconbar.append_item(text,hint_text, hint_text,
+ GtkPixmap(pix,mask), cb )
+ if help_topic is not None:
+ gvhtml.set_help_topic(item, help_topic)
+
+def parse_interpreter_line(line):
+ tokens = string.split( line, None, 1 )
+
+ # Null input line is considered valid.
+ if len(tokens) == 0:
+ return ('', '')
+
+ if len(tokens) == 1:
+ return (string.lower(tokens[0]), '')
+ else:
+ return (string.lower(tokens[0]), tokens[1])
+
+
+class PyshellHelpDialog(GtkWindow):
+
+ def __init__(self):
+ GtkWindow.__init__(self)
+ self.set_title('Python Shell Help')
+ self.set_usize(500,500)
+ #gvhtml.set_help_topic( self, "pyshell_help.html" );
+
+ self.set_border_width(3)
+ vbox = GtkVPaned()
+ self.notebook = GtkNotebook()
+ self.add( vbox )
+ vbox.add1(self.notebook)
+
+
+ # Create text window for showing help for selected
+ # command/function
+ pixel_scroll = GtkScrolledWindow()
+ pixel_scroll.set_usize(496,250)
+ vbox.add2(pixel_scroll)
+
+ self.help_text = GtkText()
+ self.help_text.set_line_wrap(FALSE)
+ self.help_text.set_word_wrap(FALSE)
+ self.help_text.set_editable(FALSE)
+ pixel_scroll.add(self.help_text)
+ self.help_text.insert_defaults('')
+
+ # Number of columns to put in command and
+ # function CList's.
+ self.ncols_cmd=2
+ self.ncols_func=2
+ self.ncols_builtin=2
+
+ self.create_commandhelp()
+ self.create_functionhelp()
+ self.create_builtinhelp()
+
+ self.show_all()
+
+
+ def create_commandhelp(self):
+ self.cpane=GtkVBox(spacing=10)
+ self.cpane.set_border_width(10)
+ self.notebook.append_page(self.cpane,GtkLabel('Commands'))
+ self.cpane_scroll=GtkScrolledWindow()
+ self.cpane_scroll.set_usize(496,250)
+ self.cpane.pack_start(self.cpane_scroll)
+
+ self.cpane_list=GtkCList(cols=self.ncols_cmd)
+ for idx in range(self.ncols_cmd):
+ self.cpane_list.set_column_width(idx,200)
+
+ self.cpane_list.set_selection_mode(SELECTION_SINGLE)
+
+ self.cpane_scroll.add(self.cpane_list)
+
+ # Add items to the list based on interpreter
+ import gview
+ self.loaded_cmd_keys=gview.app.shell.interp.cmdlist.keys()
+ self.unloaded_cmd_keys=[]
+ for citem in gview.app.shell.interp.help_cmdtxt.keys():
+ if citem not in self.loaded_cmd_keys:
+ self.unloaded_cmd_keys.append(citem)
+
+ self.total_cmd_keys=[]
+ self.total_cmd_keys.extend(self.loaded_cmd_keys)
+ self.total_cmd_keys.extend(self.unloaded_cmd_keys)
+ self.total_cmd_keys.sort()
+
+ if ((len(self.total_cmd_keys) % self.ncols_cmd) == 0):
+ nrows=len(self.total_cmd_keys)/self.ncols_cmd
+ else:
+ nrows=len(self.total_cmd_keys)/self.ncols_cmd + 1
+
+ for crow in range(nrows):
+ if (crow < nrows-1) or ((len(self.total_cmd_keys) % self.ncols_cmd) == 0):
+ values=[]
+ for idx in range(self.ncols_cmd):
+ values.append(self.total_cmd_keys[crow*self.ncols_cmd+idx])
+
+ self.cpane_list.append(tuple(values))
+ else:
+ values=[]
+ for idx in range(self.ncols_cmd):
+ if ((crow*self.ncols_cmd)+idx < len(self.total_cmd_keys)):
+ values.append(self.total_cmd_keys[crow*self.ncols_cmd+idx])
+ else:
+ values.append('')
+
+ self.cpane_list.append(tuple(values))
+
+ # Connections
+ self.cpane_list.connect('button-press-event',self.cmdlist_clicked_cb)
+
+ def cmdlist_clicked_cb(self, lst, event):
+
+ # Should also clear old text at this point
+ try:
+ row,col=lst.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ if event.button == 1:
+ lst.emit_stop_by_name('button-press-event')
+ ckey=lst.get_text(row,col)
+ import gview
+ txt=gview.app.shell.interp.get_command_help(ckey)
+ if ckey in self.loaded_cmd_keys:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (command)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (command)\n\nNo help available.'
+
+ else:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (command- not loaded)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (command- not loaded)\n\nNo help available.'
+
+ self.update_text(txt)
+
+ def create_functionhelp(self):
+ self.fpane=GtkVBox(spacing=10)
+ self.fpane.set_border_width(10)
+ self.notebook.append_page(self.fpane,GtkLabel('Functions'))
+ self.fpane_scroll=GtkScrolledWindow()
+ self.fpane_scroll.set_usize(396,250)
+ self.fpane.pack_start(self.fpane_scroll)
+
+ self.fpane_list=GtkCList(cols=self.ncols_func)
+ for idx in range(self.ncols_func):
+ self.fpane_list.set_column_width(idx,200)
+
+ self.fpane_list.set_selection_mode(SELECTION_SINGLE)
+
+ self.fpane_scroll.add(self.fpane_list)
+
+ # Add items to the list based on interpreter
+ import gview
+
+ # Need numeric to locate ufunc's
+ import Numeric
+
+ self.loaded_func_keys=[]
+ for ckey in gview.app.shell.interp.locals.keys():
+ if (type(gview.app.shell.interp.locals[ckey]) == type(launch)):
+ self.loaded_func_keys.append(ckey)
+ if (type(gview.app.shell.interp.locals[ckey]) == type(Numeric.logical_and)):
+ self.loaded_func_keys.append(ckey)
+
+ self.unloaded_func_keys=[]
+ for ckey in gview.app.shell.interp.help_functxt.keys():
+ if ckey not in self.loaded_func_keys:
+ self.unloaded_func_keys.append(ckey)
+
+ self.total_func_keys=[]
+ self.total_func_keys.extend(self.loaded_func_keys)
+ self.total_func_keys.extend(self.unloaded_func_keys)
+ self.total_func_keys.sort()
+
+ if ((len(self.total_func_keys) % self.ncols_func) == 0):
+ nrows=len(self.total_func_keys)/self.ncols_func
+ else:
+ nrows=len(self.total_func_keys)/self.ncols_func + 1
+
+ for crow in range(nrows):
+ if (crow < nrows-1) or ((len(self.total_func_keys) % self.ncols_func) == 0):
+ values=[]
+ for idx in range(self.ncols_func):
+ values.append(self.total_func_keys[crow*self.ncols_func+idx])
+
+ self.fpane_list.append(tuple(values))
+ else:
+ values=[]
+ for idx in range(self.ncols_func):
+ if ((crow*self.ncols_func)+idx < len(self.total_func_keys)):
+ values.append(self.total_func_keys[crow*self.ncols_func+idx])
+ else:
+ values.append('')
+
+ self.fpane_list.append(tuple(values))
+
+ # Connections
+ self.fpane_list.connect('button-press-event',self.funclist_clicked_cb)
+
+ def funclist_clicked_cb(self, lst, event):
+
+ # Should also clear old text at this point
+ try:
+ row,col=lst.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ if event.button == 1:
+ lst.emit_stop_by_name('button-press-event')
+ ckey=lst.get_text(row,col)
+ import gview
+ txt=gview.app.shell.interp.get_function_help(ckey)
+ if ckey in self.loaded_func_keys:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (function)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (function)\n\nNo help available.\n'
+ else:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (function- not loaded)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (function- not loaded)\n\nNo help available.\n'
+
+ self.update_text(txt)
+
+ def create_builtinhelp(self):
+ self.bpane=GtkVBox(spacing=10)
+ self.bpane.set_border_width(10)
+ self.notebook.append_page(self.bpane,GtkLabel('Built-in Functions'))
+ self.bpane_scroll=GtkScrolledWindow()
+ self.bpane_scroll.set_usize(396,250)
+ self.bpane.pack_start(self.bpane_scroll)
+
+ self.bpane_list=GtkCList(cols=self.ncols_builtin)
+ for idx in range(self.ncols_builtin):
+ self.bpane_list.set_column_width(idx,200)
+
+ self.bpane_list.set_selection_mode(SELECTION_SINGLE)
+
+ self.bpane_scroll.add(self.bpane_list)
+
+ # Add items to the list based on interpreter
+ import gview
+
+ self.loaded_builtin_keys=[]
+ for ckey in gview.app.shell.interp.locals.keys():
+ if (type(gview.app.shell.interp.locals[ckey]) == type(hasattr)):
+ self.loaded_builtin_keys.append(ckey)
+ for ckey in gview.app.shell.interp.locals['__builtins__'].keys():
+ if (type(gview.app.shell.interp.locals['__builtins__'][ckey]) == type(hasattr)):
+ self.loaded_builtin_keys.append(ckey)
+
+
+ self.unloaded_builtin_keys=[]
+ for ckey in gview.app.shell.interp.help_builtintxt.keys():
+ if ckey not in self.loaded_builtin_keys:
+ self.unloaded_builtin_keys.append(ckey)
+
+ self.total_builtin_keys=[]
+ self.total_builtin_keys.extend(self.loaded_builtin_keys)
+ self.total_builtin_keys.extend(self.unloaded_builtin_keys)
+ self.total_builtin_keys.sort()
+
+ if ((len(self.total_builtin_keys) % self.ncols_builtin) == 0):
+ nrows=len(self.total_builtin_keys)/self.ncols_builtin
+ else:
+ nrows=len(self.total_builtin_keys)/self.ncols_builtin + 1
+
+ for crow in range(nrows):
+ if (crow < nrows-1) or ((len(self.total_builtin_keys) % self.ncols_builtin) == 0):
+ values=[]
+ for idx in range(self.ncols_builtin):
+ values.append(self.total_builtin_keys[crow*self.ncols_builtin+idx])
+
+ self.bpane_list.append(tuple(values))
+ else:
+ values=[]
+ for idx in range(self.ncols_builtin):
+ if ((crow*self.ncols_builtin)+idx < len(self.total_builtin_keys)):
+ values.append(self.total_builtin_keys[crow*self.ncols_builtin+idx])
+ else:
+ values.append('')
+
+ self.bpane_list.append(tuple(values))
+
+ # Connections
+ self.bpane_list.connect('button-press-event',self.builtin_clicked_cb)
+
+ def builtin_clicked_cb(self, lst, event):
+
+ # Should also clear old text at this point
+ try:
+ row,col=lst.get_selection_info(int(event.x), int(event.y))
+ except:
+ return
+
+ if event.button == 1:
+ lst.emit_stop_by_name('button-press-event')
+ ckey=lst.get_text(row,col)
+ import gview
+ txt=gview.app.shell.interp.get_builtin_help(ckey)
+ if ckey in self.loaded_builtin_keys:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (built-in function)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (built-in function)\n\nNo help available.\n'
+ else:
+ if txt is not None:
+ txt='\t\t\t'+ckey+' (built-in function- not loaded)\n\n'+txt
+ else:
+ txt='\t\t\t'+ckey+' (built-in function- not loaded)\n\nNo help available.\n'
+
+ self.update_text(txt)
+
+ def update_text(self,txt):
+ self.help_text.freeze()
+ del_len=self.help_text.get_length()
+ self.help_text.backward_delete(del_len)
+ self.help_text.insert_defaults(txt+'\0')
+ self.help_text.thaw()
+
+
+def _format_doc(doc_string):
+ """Reformat docstring for help display."""
+
+ if doc_string is None:
+ return 'None'
+
+ dsplit=string.split(doc_string,'\n')
+ if len(dsplit) == 1:
+ return doc_string
+
+ # if __doc__ has more than one line,
+ # all except first will be indented.
+ # Get rid of this indent.
+
+ indent=0
+ for cline in dsplit[1:]:
+ temp=string.lstrip(cline)
+ if len(temp) > 0:
+ indent=len(cline)-len(temp)
+ break
+
+ new_doc=dsplit[0]
+ for cline in dsplit[1:]:
+ new_doc=string.join([new_doc,cline[indent:]],'\n')
+
+ return new_doc
+
+
+def _parse_cmdhelp_text(txt):
+ """ Parse command help text into module, group, html, text.
+
+ Returns (Module, Group, Html, help_text) if command
+ help is successfully parsed; None if parsing
+ fails. Module and Group are required. Html is
+ an optional reference to an Html file. help_text
+ is the actual help text.
+
+ Command help entries should be of the form:
+
+ COMMAND_NAME=my_command
+ Module: my_module
+ Group: my_group
+ Html: my_html.html
+
+ documentation...
+
+ The entries must be in that order if all are present,
+ but Html may be omitted. If Html or documentation
+ are not present, None will be returned in their place.
+ """
+
+ mname=None
+ stxt=string.split(txt,'\n')
+
+ if len(stxt) < 2:
+ return None
+
+ # first line should be module
+ mline=stxt[0]
+ if ((len(mline) > 7) and (mline[:7] == 'Module:')):
+ mname=string.strip(mline[7:])
+ else:
+ return None
+
+ # second line should be group
+ gline=stxt[1]
+ if ((len(gline) > 6) and (gline[:6] == 'Group:')):
+ gname=string.strip(gline[6:])
+ else:
+ return None
+
+ if len(stxt) == 2:
+ return (mname,gname,None,None)
+
+ # third line MAY be html
+ hline=stxt[2]
+ if ((len(hline) > 5) and (hline[:5] == 'Html:')):
+ hname=string.strip(hline[5:])
+ if len(stxt) > 3:
+ htext=string.join(stxt[3:],'\n')
+ else:
+ htext=None
+
+ return (mname,gname,hname,htext)
+ else:
+ htext=string.join(stxt[2:],'\n')
+ return (mname,gname,None,htext)
+
+
+def _parse_funchelp_text(txt):
+ """ Parse function help text into module, html, text.
+
+ Returns (Module, Html, help_text) if function
+ help is successfully parsed; None if parsing
+ fails. Module is required. Html is
+ an optional reference to an Html file. help_text
+ is the actual help text.
+
+ Function help entries should be of the form:
+
+ FUNCTION_NAME=my_function
+ Module: my_module
+ Html: my_html.html
+
+ documentation...
+
+ or
+
+ BUILTIN_NAME=my_builtin_function
+ Module: my_module
+ Html: my_html.html
+
+ documentation...
+
+ The entries must be in that order if all are present,
+ but Html may be omitted. If Html or documentation
+ are not present, None will be returned in their place.
+ """
+
+ mname=None
+ stxt=string.split(txt,'\n')
+
+ if len(stxt) < 1:
+ return None
+
+ # first line should be module
+ mline=stxt[0]
+ if ((len(mline) > 7) and (mline[:7] == 'Module:')):
+ mname=string.strip(mline[7:])
+ else:
+ return None
+
+ if len(stxt) == 1:
+ return (mname,None,None)
+
+ # second line MAY be html
+ hline=stxt[1]
+ if ((len(hline) > 5) and (hline[:5] == 'Html:')):
+ hname=string.strip(hline[5:])
+ if len(stxt) > 2:
+ htext=string.join(stxt[2:],'\n')
+ else:
+ htext=None
+
+ return (mname,hname,htext)
+ else:
+ htext=string.join(stxt[1:],'\n')
+ return (mname,None,htext)
+
+
+
+def _run_command_line(line):
+ # This part is very hackish, though consistent with
+ # how openev transfers information between modules
+ # in other cases (eg. main app). In order to allow the
+ # function to change the value of a variable in the
+ # interpreter, use the fact that the shell is
+ # stored globally under the name "gview.app.shell",
+ # and the interpreter is stored as "interp" beneath it.
+ # and update it's "locals" dictionary to fill in the
+ # needed values.
+
+ import gview
+ import gvcommand
+ cc=gvcommand.CommandContext(line,gview.app.shell.interp.cmdlist,gview.app.shell.interp)
+ return_val = cc.execute()
+ # return_val will be 0 or 1 for simple commands; 0
+ # for failure, 1 for success. If the arguments were
+ # modify-in-place, the return value will be a tuple
+ # consisting of (0 or 1, {} [,options]). Here, 0 or 1
+ # indicates success or failure as before, {} is a
+ # dictionary of variables to set in the command shell
+ # (keyword is the variable name, value is the value)-
+ # this dictionary can be empty. the options part is
+ # not implemented yet, but might be later on if
+ # more flexibility is needed. It should always be
+ # optional though.
+
+ if (type(return_val) == type(())) and (len(return_val) > 1):
+
+ for ckey in return_val[1].keys():
+ if ckey is not 'None':
+ gview.app.shell.interp.locals[ckey]=return_val[1][ckey]
+
+
+if __name__ == '__main__':
+ app = Shell()
+ app.show_all()
+
+ GtkExtra.debug_main_quit()
+ mainloop()
+
Property changes on: packages/openev/branches/upstream/current/pymod/pyshell.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/scmexpr.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/scmexpr.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/scmexpr.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+import string
+import types
+# get the fastest implementation of StringIO
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+trans = [' '] * 256
+for i in range(256):
+ if chr(i) in string.letters + string.digits + '_':
+ trans[i] = chr(i)
+ else:
+ trans[i] = '_'
+trans = string.join(trans, '')
+
+def parse(fp):
+ stack = [()]
+ line = fp.readline()
+ while line:
+ while line:
+ line = string.lstrip(line)
+ if not line:
+ break
+ elif line[0] == '(':
+ stack.append(())
+ line = line[1:]
+ elif line[0] == ')':
+ closed = stack[-1]
+ del stack[-1]
+ stack[-1] = stack[-1] + (closed,)
+ line = line[1:]
+ elif line[0] == '"':
+ pos = string.index(line[1:], '"')
+ stack[-1] = stack[-1] + (eval(line[:pos+2]),)
+ line = line[pos+2:]
+ elif line[0] in string.digits:
+ str = ""
+ while line and line[0] in "0123456789+-.":
+ str = str + line[0]
+ line = line[1:]
+ stack[-1] = stack[-1] + (string.atof(str),)
+ elif line[0] == ';':
+ break
+ else:
+ str = ""
+ while line and line[0] not in " \t();\n":
+ str = str + line[0]
+ line = line[1:]
+ stack[-1] = stack[-1] + (str,)
+ line = fp.readline()
+ if len(stack) != 1:
+ raise IOError, "parentheses don't match"
+ return stack[0]
+
+class Parser:
+ def __init__(self, arg):
+ """Argument is either a string, a parse tree, or file object"""
+ if type(arg) == types.StringType:
+ self.filename = arg
+ self.parseTree = parse(open(arg))
+ elif type(arg) == types.TupleType:
+ self.filename = '<none>'
+ self.parseTree = arg
+ elif type(arg) == types.FileType:
+ self.filename = arg.name
+ self.parseTree = parse(arg)
+ else:
+ raise TypeError, \
+ 'second arg must be string, tuple or file'
+ def startParsing(self, tuples=None):
+ if tuples == None: tuples = self.parseTree
+ for tup in tuples:
+ self.handle(tup)
+ def handle(self, tup):
+ cmd = string.translate(tup[0], trans)
+ if hasattr(self, cmd):
+ apply(getattr(self, cmd), tup[1:])
+ else:
+ self.unknown(tup)
+ def unknown(self, tup):
+ pass
+
+_testString = """; a scheme file
+(define-func gdk_font_load ; a comment at end of line
+ GdkFont
+ ((string name)))
+
+(define-boxed GdkEvent
+ gdk_event_copy
+ gdk_event_free
+ "sizeof(GdkEvent)")
+"""
+
+if __name__ == '__main__':
+ import sys
+ if sys.argv[1:]:
+ fp = open(sys.argv[1])
+ else:
+ fp = StringIO(_testString)
+ statements = parse(fp)
+ for s in statements:
+ print `s`
Added: packages/openev/branches/upstream/current/pymod/testmain.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/testmain.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/testmain.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+import gtk, gtkmissing, gview
+import layerdlg
+
+def create_view(name, plines, areas, raster):
+ win = gtk.GtkWindow()
+ win.set_title(name)
+ win.set_policy(gtk.TRUE, gtk.TRUE, gtk.FALSE)
+
+ shell = gtk.GtkVBox()
+ win.add(shell)
+
+ view = gview.GvViewArea()
+ view.size(512,512)
+ shell.pack_start(view, expand=gtk.TRUE)
+
+ if raster:
+ raster_layer = gview.GvRasterLayer(raster)
+ view.add_layer(raster_layer)
+ view.add_layer(gview.GvPqueryLayer())
+ view.add_layer(gview.GvAreaLayer(areas))
+ view.add_layer(gview.GvLineLayer(plines))
+
+ statusbar = gtk.GtkHBox()
+ shell.pack_start(statusbar, expand=gtk.FALSE)
+ label = gtk.GtkLabel()
+ statusbar.pack_start(label, expand=gtk.FALSE, padding=3)
+ tracker = gview.GvTrackTool(label)
+ tracker.activate(view)
+
+ view.connect('key-press-event', testmain_button_press)
+
+ win.show_all()
+ view.grab_focus()
+ win.connect('delete-event', gtk.mainquit)
+ gtk.quit_add_destroy(1, win)
+ return view
+
+def testmain_button_press(view, event, *args):
+ global last_group
+
+ if event.string == 'g':
+ last_group = gview.undo_start_group();
+
+ if event.string == 'e':
+ gview.undo_end_group(last_group);
+
+ if event.string == 'p':
+ view.print_to_file( 425, 550, "out.tif", "GTiff" )
+ view.print_postscript_to_file( 425, 550, 1, "out.ps" )
+
+class Toolbar(gtk.GtkWindow):
+ def __init__(self):
+ gtk.GtkWindow.__init__(self)
+
+ toolbox = gview.GvToolbox()
+ toolbox.add_tool("select", gview.GvSelectionTool())
+ toolbox.add_tool("line", gview.GvLineTool())
+ toolbox.add_tool("area", gview.GvAreaTool())
+ toolbox.add_tool("node", gview.GvNodeTool())
+ toolbox.add_tool("point", gview.GvPointTool())
+ toolbox.add_tool("roi", gview.GvRoiTool())
+
+ toolbar = gtk.GtkToolbar(gtk.ORIENTATION_VERTICAL, gtk.TOOLBAR_TEXT)
+ self.add(toolbar)
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, None,
+ 'Select', 'Selection tool',
+ None, None, self.toggle, "select")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Query Pnt', 'Query point marking tool',
+ None, None, self.toggle, "point")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Line', 'Line drawing tool',
+ None, None, self.toggle, "line")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw Area', 'Area drawing tool',
+ None, None, self.toggle, "area")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Edit Node', 'Node edit tool',
+ None, None, self.toggle, "node")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, but,
+ 'Draw ROI', 'ROI drawing tool',
+ None, None, self.toggle, "roi")
+ but = toolbar.append_element(gtk.TOOLBAR_CHILD_TOGGLEBUTTON, None,
+ 'Link Views', 'Link views together',
+ None, None, self.link)
+
+ self.connect('delete-event', gtk.mainquit)
+ toolbar.show()
+ self.show()
+ self.toolbox = toolbox
+ self.toolbar = toolbar
+ self.link = gview.GvViewLink()
+
+ def toggle(self, but, data):
+ self.toolbox.activate_tool(data)
+
+ def link(self, but):
+ but = gtk.GtkToggleButton(_obj=but)
+ if (but.active):
+ self.link.enable()
+ else:
+ self.link.disable()
+ def add_view(self, view):
+ self.toolbox.activate(view)
+ self.link.register_view(view)
+
+def setup(numwin, fname=None):
+ plines = gview.GvPolylines()
+ plines.set_name("Some lines")
+ gview.undo_register(plines)
+
+ areas = gview.GvAreas()
+ areas.set_name("Some areas")
+ gview.undo_register(areas)
+
+ if fname:
+ raster = gview.GvRaster(fname,sample=gview.SMAverage)
+ raster.set_name(fname)
+ else:
+ raster = None
+
+ toolbar = Toolbar()
+ ldlg = layerdlg.LayerDlg()
+ ldlg.connect('destroy', gtk.mainquit)
+ ldlg.show()
+
+ for i in range(numwin):
+ name = 'View %d' % (i+1)
+ view = create_view(name, plines, areas, raster)
+ toolbar.add_view(view)
+ ldlg.add_view(name, view)
+
+if __name__ == '__main__':
+ try:
+ import sys
+ numwin = eval(sys.argv[1])
+ except:
+ numwin = 1
+ if len(sys.argv) > 2:
+ raster = sys.argv[2]
+ else:
+ raster = None
+ setup(numwin, raster)
+ gtk.mainloop()
Property changes on: packages/openev/branches/upstream/current/pymod/testmain.py
___________________________________________________________________
Name: svn:executable
+
Added: packages/openev/branches/upstream/current/pymod/toolexample.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/toolexample.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/toolexample.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,968 @@
+#
+# Tool designed to be added to gviewapp's self.Tool_List
+# To try: openev -t <full path to toolfile_example.txt>
+# Assumes that gviewapp at least has a toolbar with
+# roi and poi tools, a layer manager, and view manager.
+
+import gviewapp
+import gtk
+import os
+import gdal, gdalnumeric
+import Numeric
+import string
+import gvsignaler
+
+FALSE = gtk.FALSE
+TRUE = gtk.TRUE
+import gview,gvutils
+
+
+class StoredROIPOI:
+ def __init__(self):
+ self.roi = (1,1,1,1)
+ self.poi = (1,1) # pixel/line in raster coords
+
+ # View/layer used to select poi/roi
+ self.roi_layer = None
+ self.roi_view = None
+ self.poi_layer = None
+ self.poi_view = None
+
+ def update_roi(self,roi_info,roilayer,roiview):
+ self.roi = roi_info
+ self.roi_layer = roilayer
+ self.roi_view = roiview
+
+ def update_poi(self,poi_info,poilayer,poiview):
+ self.poi = poi_info
+ self.poi_layer = poilayer
+ self.poi_view = poiview
+
+
+class GeneralPOITool(gviewapp.Tool_GViewApp):
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.RP_Stored = StoredROIPOI()
+
+ # relegate initialization of dialog, menu
+ # and connections to functions so they
+ # can be customized
+ self.init_dialog()
+ self.init_menu()
+ self.init_connections()
+
+ def init_dialog(self):
+ self.RP_ToolDlg = General_POIToolDlg()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/POI Analysis Tool",1,self.roipoitool_cb)
+
+ def init_connections(self):
+ self.app.toolbar.poi_tool.connect('poi-changed',self.update_poi_cb)
+ self.RP_ToolDlg.subscribe('re-activated',self.update_dlgpoi_frame)
+ self.RP_ToolDlg.subscribe('poitool-needs-set',self.set_poitool)
+ self.RP_ToolDlg.subscribe('analyze-pressed',self.analyze_cb)
+
+ def roipoitool_cb(self, *args):
+ self.RP_ToolDlg.show_all()
+ self.RP_ToolDlg.make_active()
+ self.RP_ToolDlg.get_window()._raise()
+
+ def update_poi_cb(self, *args):
+ # always store last chosen poi
+ try:
+ poi_info = self.app.toolbar.get_poi()
+ except:
+ # if poi has been disabled (eg. if current selection
+ # mode is roi), leave it at the latest value
+ return
+
+ # Returns the NAME of the view, and a COPY of the layer
+ [cview, clayer] = self.app.layerdlg.get_selected_layer()
+
+ if (cview is None) or (clayer is None):
+ # poi only makes sense in the context of a view and layer
+ return
+
+ # Get a reference to the active view
+ cur_view = self.app.layerdlg.get_active_view()
+ if (cur_view.get_raw(clayer) == 0):
+ # View is not in row/col coords-- convert
+ [pixel,line] = clayer.view_to_pixel(poi_info[0],poi_info[1])
+ poi_info = (pixel,line)
+
+ self.RP_Stored.update_poi(poi_info,clayer,cview)
+ # if tooldlg is active, update its region display frame
+ if self.RP_ToolDlg.is_active():
+ self.update_dlgpoi_frame()
+
+ def update_dlgpoi_frame(self, *args):
+ if self.RP_ToolDlg.is_active():
+ poi_info = self.RP_Stored.poi
+ self.RP_ToolDlg.update_poiframe(poi_info)
+ if self.RP_ToolDlg.is_auto_updating():
+ # Automatic analysis is on
+ self.RP_ToolDlg.analyze_cb(self)
+
+ else:
+ return
+
+ def set_poitool(self, *args):
+ self.app.toolbar.poi_button.set_active(gtk.TRUE)
+
+ def analyze_cb(self,*args):
+ line = self.RP_ToolDlg.entry_dict['line'].get_text()
+ pix = self.RP_ToolDlg.entry_dict['pixel'].get_text()
+ print 'In poi tool analyze_cb- POI is: ',line,'L ',pix,'P'
+
+
+class GeneralROITool(gviewapp.Tool_GViewApp):
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.RP_Stored = StoredROIPOI()
+
+ # relegate initialization of dialog, menu
+ # and connections to functions so they
+ # can be customized
+ self.init_dialog()
+ self.init_menu()
+ self.init_connections()
+
+ def init_dialog(self):
+ self.RP_ToolDlg = General_ROIToolDlg()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/ROI Analysis Tool",1,self.roipoitool_cb)
+
+ def init_connections(self):
+ self.app.toolbar.roi_tool.connect('roi-changed',self.update_roi_cb)
+ self.RP_ToolDlg.subscribe('re-activated',self.update_dlgroi_frame)
+ self.RP_ToolDlg.subscribe('roitool-needs-set',self.set_roitool)
+ self.RP_ToolDlg.subscribe('analyze-pressed',self.analyze_cb)
+
+ def roipoitool_cb(self, *args):
+ self.RP_ToolDlg.show_all()
+ self.RP_ToolDlg.make_active()
+ self.RP_ToolDlg.get_window()._raise()
+
+ def update_roi_cb(self, *args):
+ # always store last chosen roi
+ try:
+ roi_info = self.app.toolbar.get_roi()
+ except:
+ # if roi has been disabled (eg. if current selection
+ # mode is poi), leave it at the latest value
+ return
+
+ [cview, clayer] = self.app.layerdlg.get_selected_layer()
+
+ if (cview is None) or (clayer is None):
+ # roi only makes sense in the context of a view and layer
+ return
+
+ # Get a reference to the active view
+ cur_view = self.app.layerdlg.get_active_view()
+ if (cur_view.get_raw(clayer) == 0):
+ # View is not in row/col coords-- convert
+ # Note that region will not be exactly the one drawn,
+ # since a rectangle is extracted rather than a
+ # trapezoid.
+
+ [pixel,line] = clayer.view_to_pixel(roi_info[0],roi_info[1])
+ [pixel2,line2] = clayer.view_to_pixel(roi_info[0]+roi_info[2],
+ roi_info[1]+roi_info[3])
+ if pixel > pixel2:
+ temp = pixel
+ pixel = pixel2
+ pixel2 = temp
+
+ if line > line2:
+ temp = line
+ line = line2
+ line2 = temp
+
+ roi_info = (pixel,line,pixel2-pixel,line2-line)
+
+ self.RP_Stored.update_roi(roi_info,clayer,cview)
+ # if tooldlg is active, update its region display frame
+ if self.RP_ToolDlg.is_active():
+ self.update_dlgroi_frame()
+
+ def update_dlgroi_frame(self, *args):
+ if self.RP_ToolDlg.is_active():
+ roi_info = self.RP_Stored.roi
+ self.RP_ToolDlg.update_roiframe(roi_info)
+ if self.RP_ToolDlg.is_auto_updating():
+ # Automatic analysis is on
+ self.RP_ToolDlg.analyze_cb(self)
+
+ else:
+ return
+
+ def set_roitool(self, *args):
+ self.app.toolbar.roi_button.set_active(gtk.TRUE)
+
+ def analyze_cb(self,*args):
+ line = self.RP_ToolDlg.entry_dict['start_line'].get_text()
+ pix = self.RP_ToolDlg.entry_dict['start_pix'].get_text()
+ sl = self.RP_ToolDlg.entry_dict['num_lines'].get_text()
+ sp = self.RP_ToolDlg.entry_dict['num_pix'].get_text()
+ print 'In roi tool analyze_cb- ROI is: ',line,'L ',pix,'P (',sl,'x',sp,')'
+
+
+class General_ROIPOIToolDlg(gtk.GtkWindow,gvsignaler.Signaler):
+ # A base class that has 3 frames: a
+ # top one with a "needs updating" string
+ # and Analyze button; a middle one
+ # that will display either an roi or
+ # a poi; and an ending one with 2 toggles
+ # and a Set Tool button.
+ def __init__(self):
+ gtk.GtkWindow.__init__(self)
+
+ self.button_dict = {} # store references to buttons/frames/text entries--
+ self.frame_dict = {} # we may need to access them.
+ self.entry_dict = {}
+
+ self.show_list = [] # list of widgets to show
+
+ self.init_setup_window()
+ self.init_create_gui_panel() # base widgets/panel
+ self.init_customize_gui_panel()
+
+ # signals
+ self.publish('re-activated')
+ self.publish('roitool-needs-set')
+ self.publish('poitool-needs-set')
+ self.publish('analyze-pressed')
+
+ # Basic connections
+ self.button_dict['Analyze'].connect('clicked',self.analyze_cb)
+ self.button_dict['Activate'].connect('toggled',self.activate_toggled)
+ self.button_dict['Auto Update'].connect('toggled',self.auto_update_toggled)
+ self.button_dict['Set Tool'].connect('clicked',self.set_tool_cb)
+
+ # Set default sensitivities
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.TRUE)
+ self.button_dict['Activate'].set_active(gtk.FALSE)
+
+ self.connect('delete-event',self.close)
+
+
+ for item in self.show_list:
+ item.show()
+
+ def init_setup_window(self):
+ self.set_title('General Tool')
+ self.set_border_width(10)
+ self.set_usize(450,300)
+
+ def init_create_gui_panel(self):
+
+ # Basic Buttons...
+ self.button_dict['Analyze'] = gtk.GtkButton('Analyze')
+ self.show_list.append(self.button_dict['Analyze'])
+
+ self.button_dict['Activate'] = gtk.GtkCheckButton('Activate')
+ self.show_list.append(self.button_dict['Activate'])
+
+ self.button_dict['Auto Update'] = gtk.GtkCheckButton('Auto Update')
+ self.show_list.append(self.button_dict['Auto Update'])
+
+ self.button_dict['Set Tool'] = gtk.GtkButton('Set Tool')
+ self.show_list.append(self.button_dict['Set Tool'])
+
+ # Basic Frames...
+
+ # first frame
+ self.frame_dict['base_frame1'] = gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['base_frame1'])
+
+ hbox1 = gtk.GtkHBox(gtk.TRUE,5)
+ self.show_list.append(hbox1)
+ hbox1.pack_end(self.button_dict['Analyze'],gtk.TRUE,gtk.TRUE,0)
+ self.frame_dict['base_frame1'].add(hbox1)
+
+ # second frame- will contain roi or poi info
+ self.frame_dict['base_frame2'] = gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['base_frame2'])
+
+ # third frame
+ self.frame_dict['base_frame3'] = gtk.GtkFrame();
+ self.show_list.append(self.frame_dict['base_frame3'])
+
+ hbox3 = gtk.GtkHBox(gtk.TRUE,5)
+ self.show_list.append(hbox3)
+ hbox3.pack_start(self.button_dict['Activate'],gtk.TRUE,gtk.TRUE,0)
+ hbox3.pack_start(self.button_dict['Auto Update'],gtk.TRUE,gtk.TRUE,0)
+ hbox3.pack_start(self.button_dict['Set Tool'],gtk.TRUE,gtk.TRUE,0)
+ self.frame_dict['base_frame3'].add(hbox3)
+
+ # Top level panel...
+ self.main_panel = gtk.GtkVBox(gtk.FALSE,5)
+ self.main_panel.pack_start(self.frame_dict['base_frame1'],gtk.FALSE,gtk.FALSE,0)
+ self.main_panel.pack_start(self.frame_dict['base_frame2'],gtk.FALSE,gtk.FALSE,0)
+ self.main_panel.pack_end(self.frame_dict['base_frame3'],gtk.FALSE,gtk.FALSE,0)
+ self.add(self.main_panel)
+ self.show_list.append(self.main_panel)
+
+ def init_customize_gui_panel(self):
+ pass
+
+ def analyze_cb(self,*args):
+ self.notify('analyze-pressed')
+
+ def activate_toggled(self,*args):
+ if self.button_dict['Activate'].get_active():
+ self.set_entry_sensitivities(gtk.TRUE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.TRUE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.TRUE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.TRUE)
+ self.notify('re-activated')
+ else:
+ self.set_entry_sensitivities(gtk.FALSE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.FALSE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.FALSE)
+
+
+ def auto_update_toggled(self,*args):
+ # If auto-update is on, analyze button should not be sensitive
+ if self.button_dict['Auto Update'].get_active():
+ self.button_dict['Analyze'].set_sensitive(gtk.FALSE)
+ else:
+ self.button_dict['Analyze'].set_sensitive(gtk.TRUE)
+
+ def set_tool_cb(self,*args):
+ pass
+
+ def set_entry_sensitivities(self,bool_val):
+ pass
+
+ def is_active(self):
+ if self.button_dict['Activate'].get_active():
+ return gtk.TRUE
+ else:
+ return gtk.FALSE
+
+ def make_active(self):
+ self.set_tool_cb()
+ self.button_dict['Activate'].set_active(gtk.TRUE)
+
+ def is_auto_updating(self):
+ if self.button_dict['Auto Update'].get_active():
+ return gtk.TRUE
+ else:
+ return gtk.FALSE
+
+ def close(self,*args):
+ # If tool is closed, user probably wants to be rid of it...
+ self.button_dict['Activate'].set_active(gtk.FALSE)
+ self.hide()
+ return TRUE
+
+
+class General_ROIToolDlg(General_ROIPOIToolDlg):
+ def __init__(self):
+ General_ROIPOIToolDlg.__init__(self)
+
+ def init_setup_window(self):
+ self.set_title('General ROI Tool')
+ self.set_border_width(10)
+ self.set_usize(450,150)
+
+ def init_customize_gui_panel(self):
+ # By now, main panel, basic frames, buttons have been created
+ # Middle frame (region display) must be filled in.
+
+ patch_table = gtk.GtkTable(2,4,FALSE)
+ self.show_list.append(patch_table)
+ self.frame_dict['base_frame2'].add(patch_table)
+
+ patch_table.set_border_width(5)
+ patch_table.set_col_spacings(5)
+ patch_table.set_col_spacing(1, 20)
+
+ label1 = gtk.GtkLabel('Start Line: ')
+ label1.set_alignment(0, 0.5)
+ patch_table.attach(label1, 0,1, 0, 1)
+
+ self.entry_dict['start_line'] = gtk.GtkEntry()
+ self.entry_dict['start_line'].set_editable(gtk.FALSE)
+ self.entry_dict['start_line'].set_usize(90, 25)
+ self.entry_dict['start_line'].set_text('1')
+ patch_table.attach(self.entry_dict['start_line'], 1,2, 0,1)
+
+ label2 = gtk.GtkLabel('Start Pixel: ')
+ label2.set_alignment(0, 0.5)
+ patch_table.attach(label2, 2,3,0, 1)
+
+ self.entry_dict['start_pix'] = gtk.GtkEntry()
+ self.entry_dict['start_pix'].set_editable(gtk.FALSE)
+ self.entry_dict['start_pix'].set_usize(90, 25)
+ self.entry_dict['start_pix'].set_text('1')
+ patch_table.attach(self.entry_dict['start_pix'], 3,4, 0,1)
+
+ label3 = gtk.GtkLabel('Num. of Lines: ')
+ label3.set_alignment(0, 0.5)
+ patch_table.attach(label3, 0,1, 1, 2)
+
+ self.entry_dict['num_lines'] = gtk.GtkEntry()
+ self.entry_dict['num_lines'].set_editable(gtk.FALSE)
+ self.entry_dict['num_lines'].set_usize(90, 25)
+ self.entry_dict['num_lines'].set_text('1')
+ patch_table.attach(self.entry_dict['num_lines'], 1,2, 1,2)
+
+ label4 = gtk.GtkLabel('Num. of Pixels: ')
+ label4.set_alignment(0, 0.5)
+ patch_table.attach(label4, 2,3,1, 2)
+
+ self.entry_dict['num_pix'] = gtk.GtkEntry()
+ self.entry_dict['num_pix'].set_editable(gtk.FALSE)
+ self.entry_dict['num_pix'].set_usize(90, 25)
+ self.entry_dict['num_pix'].set_text('1')
+ patch_table.attach(self.entry_dict['num_pix'], 3,4, 1,2)
+
+ # Create tooltips
+ self.tooltips = gtk.GtkTooltips()
+ tip_text = "Re-enable region-of-interest selection mode (" \
+ "required for this tool's operation)."
+ self.tooltips.set_tip(self.button_dict['Set Tool'],tip_text)
+ tip_text = 'Automatically update every time the region of ' + \
+ 'interest changes.'
+ self.tooltips.set_tip(self.button_dict['Auto Update'],tip_text)
+ tip_text = 'Enable/Disable this tool.'
+ self.tooltips.set_tip(self.button_dict['Activate'],tip_text)
+ tip_text = 'Perform analysis.'
+ self.tooltips.set_tip(self.button_dict['Analyze'],tip_text)
+
+
+ self.frame_dict['base_frame2'].show_all()
+
+ def set_tool_cb(self,*args):
+ self.notify('roitool-needs-set')
+
+
+ def update_roiframe(self,roi_info):
+ self.entry_dict['start_line'].set_text(str(int(roi_info[1])))
+ self.entry_dict['start_pix'].set_text(str(int(roi_info[0])))
+ self.entry_dict['num_lines'].set_text(str(int(roi_info[3])))
+ self.entry_dict['num_pix'].set_text(str(int(roi_info[2])))
+
+ def set_entry_sensitivities(self,bool_val):
+ self.entry_dict['start_line'].set_sensitive(bool_val)
+ self.entry_dict['start_pix'].set_sensitive(bool_val)
+ self.entry_dict['num_lines'].set_sensitive(bool_val)
+ self.entry_dict['num_pix'].set_sensitive(bool_val)
+
+
+
+class General_POIToolDlg(General_ROIPOIToolDlg):
+ def __init__(self):
+ General_ROIPOIToolDlg.__init__(self)
+
+ def init_setup_window(self):
+ self.set_title('General POI Tool')
+ self.set_border_width(10)
+ self.set_usize(450,120)
+
+ def init_customize_gui_panel(self):
+ # By now, main panel, basic frames, buttons have been created
+ # Middle frame (region display) must be filled in.
+
+ patch_table = gtk.GtkTable(1,4,FALSE)
+ self.show_list.append(patch_table)
+ self.frame_dict['base_frame2'].add(patch_table)
+
+ patch_table.set_border_width(5)
+ patch_table.set_col_spacings(5)
+ patch_table.set_col_spacing(1, 20)
+
+ label1 = gtk.GtkLabel('Line: ')
+ label1.set_alignment(0, 0.5)
+ patch_table.attach(label1, 0,1, 0, 1)
+
+ self.entry_dict['line'] = gtk.GtkEntry()
+ self.entry_dict['line'].set_editable(gtk.FALSE)
+ self.entry_dict['line'].set_usize(90, 25)
+ self.entry_dict['line'].set_text('1')
+ patch_table.attach(self.entry_dict['line'], 1,2, 0,1)
+
+ label2 = gtk.GtkLabel('Pixel: ')
+ label2.set_alignment(0, 0.5)
+ patch_table.attach(label2, 2,3,0, 1)
+
+ self.entry_dict['pixel'] = gtk.GtkEntry()
+ self.entry_dict['pixel'].set_editable(gtk.FALSE)
+ self.entry_dict['pixel'].set_usize(90, 25)
+ self.entry_dict['pixel'].set_text('1')
+ patch_table.attach(self.entry_dict['pixel'], 3,4, 0,1)
+
+ # Create tooltips
+ self.tooltips = gtk.GtkTooltips()
+ tip_text = "Re-enable point-of-interest selection mode (" + \
+ "required for this tool's operation)."
+ self.tooltips.set_tip(self.button_dict['Set Tool'],tip_text)
+ tip_text = 'Automatically update every time the point of ' + \
+ 'interest changes.'
+ self.tooltips.set_tip(self.button_dict['Auto Update'],tip_text)
+ tip_text = 'Enable/Disable this tool.'
+ self.tooltips.set_tip(self.button_dict['Activate'],tip_text)
+ tip_text = 'Perform analysis.'
+ self.tooltips.set_tip(self.button_dict['Analyze'],tip_text)
+
+
+ self.frame_dict['base_frame2'].show_all()
+
+ def set_tool_cb(self,*args):
+ self.notify('poitool-needs-set')
+
+ def update_poiframe(self,poi_info):
+ self.entry_dict['line'].set_text(str(int(poi_info[1])))
+ self.entry_dict['pixel'].set_text(str(int(poi_info[0])))
+
+ def set_entry_sensitivities(self,bool_val):
+ self.entry_dict['line'].set_sensitive(bool_val)
+ self.entry_dict['pixel'].set_sensitive(bool_val)
+
+
+class Pixel_Tool(GeneralPOITool):
+ def __init__(self,app=None):
+ GeneralPOITool.__init__(self,app)
+
+ def init_dialog(self):
+ self.RP_ToolDlg = Pixel_ToolDlg()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Pixel Tool",1,self.roipoitool_cb)
+
+ def analyze_cb(self,*args):
+ # Find the view and layer
+ [cview, clayer] = self.app.layerdlg.get_selected_layer()
+ if (cview is None) or (clayer is None):
+ # analysis only makes sense in the context of a view and layer
+ gvutils.error('No View/Layer selected!')
+ return
+
+ text = self.basic_pixel_analysis(cview,clayer)
+
+ self.RP_ToolDlg.update_pixelinfo_text(text)
+
+ def basic_pixel_analysis(self,cview,clayer):
+ line = self.RP_ToolDlg.entry_dict['line'].get_text()
+ pix = self.RP_ToolDlg.entry_dict['pixel'].get_text()
+ disp_text = 'Pixel Attributes: \n'
+ fname = clayer.get_name() # layer title == file name
+ disp_text = disp_text + ' Filename: ' + fname + '\n'
+ disp_text = disp_text + ' Line: ' + str(line)
+ disp_text = disp_text + ' Pixel: ' + str(pix) + '\n'
+ try:
+ gdal_dataset = clayer.get_data().get_dataset()
+ except:
+ disp_text = disp_text + '\n\n<Not a raster layer>\n'
+ return disp_text
+
+ [long,lat]=clayer.get_data().pixel_to_georef(float(pix),float(line))
+ disp_text = disp_text + ' Latitude: ' + str(lat)
+ disp_text = disp_text + ' Longitude: ' + str(long) + '\n'
+
+ try:
+ value = gdal_dataset.ReadAsArray(int(float(pix)),int(float(line)),1,1)
+ except:
+ disp_text = disp_text + '\n\n<Unable to read data>\n'
+ return disp_text
+
+ disp_text = disp_text +'\n Value: ' + str(value[0,0].astype(value.typecode()))
+ return disp_text
+
+
+
+
+class Pixel_ToolDlg(General_POIToolDlg):
+ def __init__(self):
+ General_POIToolDlg.__init__(self)
+
+ def init_setup_window(self):
+ self.set_title('Pixel Tool')
+ self.set_border_width(10)
+ self.set_usize(450,450)
+
+ def init_customize_gui_panel(self):
+ # Inherit all the usual stuff...
+ General_POIToolDlg.init_customize_gui_panel(self)
+
+ # Add new frame with pixel info, keeping track of
+ # the frame and text object...
+ self.frame_dict['pixel_info_frame'] = gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['pixel_info_frame'])
+
+ pixel_vbox = gtk.GtkVBox()
+ self.show_list.append(pixel_vbox)
+ self.frame_dict['pixel_info_frame'].add(pixel_vbox)
+
+ pixel_scroll = gtk.GtkScrolledWindow()
+ self.show_list.append(pixel_scroll)
+ pixel_vbox.pack_start(pixel_scroll,expand = gtk.TRUE)
+
+ self.entry_dict['pixel_info_text'] = gtk.GtkText()
+ self.show_list.append(self.entry_dict['pixel_info_text'])
+ self.entry_dict['pixel_info_text'].set_line_wrap(gtk.FALSE)
+ self.entry_dict['pixel_info_text'].set_word_wrap(gtk.FALSE)
+ self.entry_dict['pixel_info_text'].set_editable(gtk.FALSE)
+ pixel_scroll.add(self.entry_dict['pixel_info_text'])
+ self.entry_dict['pixel_info_text'].insert_defaults('')
+ self.main_panel.pack_start(self.frame_dict['pixel_info_frame'],gtk.TRUE,gtk.TRUE,0)
+
+ def update_pixelinfo_text(self,text):
+ del_len = self.entry_dict['pixel_info_text'].get_length()
+ self.entry_dict['pixel_info_text'].backward_delete(del_len)
+ self.entry_dict['pixel_info_text'].insert_defaults(text)
+
+
+
+class Stats_Tool(GeneralROITool):
+ def __init__(self,app=None):
+ GeneralROITool.__init__(self,app)
+
+ # Information needed for creating target view window
+ self.target_view_title = 'Stats Tool Target Area'
+ self.target_view_window = None
+ self.target_view_layer = None
+ self.target_view_data = None # Numpy array of data
+ self.target_view_ds = None # gdal dataset for target_view_data
+
+ def init_dialog(self):
+ self.RP_ToolDlg = Stats_ToolDlg()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Stats Tool",3,self.roipoitool_cb)
+
+ def update_dlgroi_frame(self,*args):
+ # Update frame as in general tool
+ if self.RP_ToolDlg.is_active():
+ roi_info = self.RP_Stored.roi
+ self.RP_ToolDlg.update_roiframe(roi_info)
+
+ else:
+ return
+
+ self.update_roi_view()
+
+ if self.RP_ToolDlg.is_auto_updating():
+ # Automatic analysis is on
+ self.RP_ToolDlg.analyze_cb(self)
+
+ def update_roi_view(self,*args):
+ # Shouldn't get here if inactive anyway, but just in case...
+ if (self.RP_ToolDlg.is_active() == gtk.FALSE):
+ return
+
+ # Update view based on new frame values
+ line = int(float(self.RP_ToolDlg.entry_dict['start_line'].get_text()))
+ pix = int(float(self.RP_ToolDlg.entry_dict['start_pix'].get_text()))
+ sl = int(float(self.RP_ToolDlg.entry_dict['num_lines'].get_text()))
+ sp = int(float(self.RP_ToolDlg.entry_dict['num_pix'].get_text()))
+
+ # Find the view and layer
+ cview = self.app.view_manager.get_active_view_window().title
+ clayer = self.app.sel_manager.get_active_layer()
+ if (cview is None) or (clayer is None):
+ # Target can only be extracted if a view/layer is selected
+ return
+ if (sl == 0 or sp == 0):
+ print "Trying to extract region with zero lines or zero pixels!"
+ return
+
+ try:
+ filename = clayer.get_parent().get_dataset().GetDescription()
+ except:
+ gvutils.error('Unable to determine filename!')
+ return
+
+ try:
+ target_data = gdalnumeric.LoadFile(filename,pix,line,sp,sl)
+ target_ds = gdalnumeric.OpenArray(target_data)
+ rl_mode_value = clayer.get_mode()
+ except:
+ gvutils.error('Unable to extract data and/or display mode info!')
+ return
+
+ if self.target_view_window is not None:
+ # Need to delete old layer in target window and put in new one
+ if self.target_view_layer is not None:
+ self.target_view_window.viewarea.remove_layer(self.target_view_layer)
+ # Create new layer
+ self.target_view_data = target_data
+ self.target_view_ds = target_ds
+ self.target_view_layer = \
+ gview.GvRasterLayer(gview.GvRaster(dataset = self.target_view_ds,real=1),
+ rl_mode = rl_mode_value)
+
+ if ((rl_mode_value == gview.RLM_RGBA) and (self.target_view_ds.RasterCount > 2)):
+ green_raster = gview.GvRaster(dataset = self.target_view_ds,real=2)
+ blue_raster = gview.GvRaster(dataset = self.target_view_ds,real=3)
+
+ self.target_view_layer.set_source(1,green_raster)
+ self.target_view_layer.set_source(2,blue_raster)
+
+ if self.target_view_ds.RasterCount > 3:
+ band = self.target_view_ds.GetRasterBand(4)
+ if band.GetRasterColorInterpretation() == gdal.GCI_AlphaBand:
+ self.target_view_layer.blend_mode_set( gview.RL_BLEND_FILTER )
+ alpha_raster = gview.GvRaster(dataset = self.target_view_ds,real=4)
+ self.target_view_layer.set_source(3,alpha_raster)
+
+ self.target_view_layer.set_name(filename)
+ refresh_old_window = 0 # redraw roi first time
+ if self.target_view_window is None:
+ # Need to create a window to display the current target in
+ import gvviewwindow
+ self.target_view_window = gvviewwindow.GvViewWindow(self.app,
+ title=self.target_view_title,show_menu = 0, show_icons=0,
+ show_tracker=1,show_scrollbars=1)
+
+ self.target_view_window.connect('destroy',self.close_target_view_cb)
+ refresh_old_window = 1
+
+ self.target_view_window.viewarea.add_layer(self.target_view_layer)
+ self.target_view_window.show()
+
+ # The roi must be redrawn on the overview if a new window was created
+ # (it will have disappeared)
+ # HACK!!!
+ if refresh_old_window == 1:
+ view_list = self.app.view_manager.get_views()
+ for item in view_list:
+ if (item.title == cview):
+ self.app.view_manager.set_active_view(item)
+ item.viewarea.set_active_layer(clayer)
+ self.app.toolbar.roi_tool.append((pix,line,sp,sl))
+
+ def analyze_cb(self,*args):
+ # Find the view and layer
+ cview = self.app.view_manager.get_active_view_window().title
+ clayer = self.app.sel_manager.get_active_layer()
+ if (cview is None) or (clayer is None):
+ # analysis only makes sense in the context of a view and layer
+ gvutils.error('No View/Layer selected!')
+ return
+
+ text = self.basic_region_analysis(cview,clayer)
+
+ self.RP_ToolDlg.update_regioninfo_text(text)
+ if (self.RP_ToolDlg.button_dict['Log To File'].get_active() == gtk.TRUE):
+ log_filename = self.RP_ToolDlg.entry_dict['log_file'].get_text()
+ if (len(log_filename) < 2):
+ gvutils.error('Log file not set!')
+ else:
+ try:
+ logfile = open(log_filename,'a')
+ logfile.writelines(text + '\n\n')
+ logfile.close()
+ except:
+ err_txt = 'Unable to create or append to ' + log_filename + '.'
+ gvutils.error(err_txt)
+
+ def basic_region_analysis(self,cview,clayer):
+ line = self.RP_ToolDlg.entry_dict['start_line'].get_text()
+ pix = self.RP_ToolDlg.entry_dict['start_pix'].get_text()
+ sl = self.RP_ToolDlg.entry_dict['num_lines'].get_text()
+ sp = self.RP_ToolDlg.entry_dict['num_pix'].get_text()
+
+ number_of_elements = Numeric.multiply.reduce(self.target_view_data.shape)
+ if (self.is_patch_complex() == 1):
+ # Calculate stats for absloute and power
+ max = Numeric.maximum.reduce(Numeric.ravel(abs(self.target_view_data)))
+ mean = Numeric.add.reduce(Numeric.ravel(1.0*(abs(self.target_view_data))))/ \
+ (Numeric.multiply.reduce(self.target_view_data.shape)*1.)
+ mean_power = Numeric.add.reduce(Numeric.ravel(Numeric.power(abs(self.target_view_data),2)))/ \
+ (Numeric.multiply.reduce(self.target_view_data.shape)*1.)
+ min = Numeric.minimum.reduce(Numeric.ravel(abs(self.target_view_data)))
+ if(number_of_elements > 1):
+ var = (Numeric.add.reduce(Numeric.power(Numeric.ravel(abs(self.target_view_data)) \
+ -mean,2))) /(Numeric.multiply.reduce(self.target_view_data.shape)-1.)
+ var_power = (Numeric.add.reduce(Numeric.power(Numeric.ravel(Numeric.power(abs(self.target_view_data),2)) \
+ -mean_power,2))) /(Numeric.multiply.reduce(self.target_view_data.shape)-1.)
+ else:
+ var_power = 0
+ var = 0
+ else:
+ max = Numeric.maximum.reduce(Numeric.ravel(self.target_view_data))
+ mean = Numeric.add.reduce(Numeric.ravel(1.0*self.target_view_data))/ \
+ (Numeric.multiply.reduce(self.target_view_data.shape)*1.)
+ mean_power = Numeric.add.reduce(Numeric.ravel(Numeric.power(self.target_view_data,2)))/ \
+ (Numeric.multiply.reduce(self.target_view_data.shape)*1.)
+ min = Numeric.minimum.reduce(Numeric.ravel(self.target_view_data))
+ if(number_of_elements > 1):
+ var = (Numeric.add.reduce(Numeric.power(Numeric.ravel(self.target_view_data)-mean,2))) / \
+ (Numeric.multiply.reduce(self.target_view_data.shape)-1.)
+ var_power = (Numeric.add.reduce(Numeric.power(Numeric.ravel(Numeric.power(self.target_view_data,2))-mean_power,2))) / \
+ (Numeric.multiply.reduce(self.target_view_data.shape)-1.)
+ else:
+ var_power = 0
+ var = 0
+
+
+ disp_text = 'Region Attributes: \n'
+ fname = clayer.get_parent().get_dataset().GetDescription()
+ disp_text = disp_text + '\tFilename: ' + fname + '\n'
+ disp_text = disp_text + '\tLines: ' + str(int(float(line))) + ' to '
+ disp_text = disp_text + str(int(float(line))+int(float(sl))-1) + '\n'
+ disp_text = disp_text + '\tPixels: ' + str(int(float(pix))) + ' to '
+ disp_text = disp_text + str(int(float(pix))+int(float(sp))-1)+'\n'
+ disp_text = disp_text + '\tRegion Maximum: ' + str(max) + '\n'
+ disp_text = disp_text + '\tRegion Mean: ' + str(mean) + '\n'
+ disp_text = disp_text + '\tRegion Minimum: ' + str(min) + '\n'
+ disp_text = disp_text + '\tRegion Variance: ' + str(var) + '\n'
+ disp_text = disp_text + '\tPower Statistics: ' + '\n'
+ disp_text = disp_text + '\t\tMean Power: ' + str(mean_power) + '\n'
+ disp_text = disp_text + '\t\tPower Variance: ' + str(var_power) + '\n'
+ disp_text = disp_text + '\n'
+ return disp_text
+
+ def close_target_view_cb(self,*args):
+ self.target_view_layer = None
+ self.target_view_window = None
+ self.target_view_ds = None
+
+ def is_patch_complex(self):
+ data_typecode = self.target_view_data.typecode()
+ if (data_typecode == Numeric.Complex):
+ return 1
+ elif (data_typecode == Numeric.Complex0):
+ return 1
+ elif (data_typecode == Numeric.Complex8):
+ return 1
+ elif (data_typecode == Numeric.Complex16):
+ return 1
+ elif (data_typecode == Numeric.Complex32):
+ return 1
+ elif (data_typecode == Numeric.Complex64):
+ return 1
+ else:
+ return 0
+
+
+class Stats_ToolDlg(General_ROIToolDlg):
+ def __init__(self):
+ General_ROIToolDlg.__init__(self)
+
+ def init_setup_window(self):
+ self.set_title('Stats Tool')
+ self.set_border_width(10)
+ self.set_usize(450,650)
+
+ def init_customize_gui_panel(self):
+ # Inherit all the usual stuff...
+ General_ROIToolDlg.init_customize_gui_panel(self)
+
+ # Add new frame with pixel info, keeping track of
+ # the frame and text object...
+ self.frame_dict['region_info_frame'] = gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['region_info_frame'])
+
+ pixel_vbox = gtk.GtkVBox()
+ self.show_list.append(pixel_vbox)
+ self.frame_dict['region_info_frame'].add(pixel_vbox)
+
+ pixel_scroll = gtk.GtkScrolledWindow()
+ self.show_list.append(pixel_scroll)
+ pixel_vbox.pack_start(pixel_scroll,expand = gtk.TRUE)
+
+ self.entry_dict['region_info_text'] = gtk.GtkText()
+ self.show_list.append(self.entry_dict['region_info_text'])
+ self.entry_dict['region_info_text'].set_line_wrap(gtk.FALSE)
+ self.entry_dict['region_info_text'].set_word_wrap(gtk.FALSE)
+ self.entry_dict['region_info_text'].set_editable(gtk.FALSE)
+ pixel_scroll.add(self.entry_dict['region_info_text'])
+ self.entry_dict['region_info_text'].insert_defaults('')
+
+
+ # Add a frame with the log file options
+ self.frame_dict['log_frame']=gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['log_frame'])
+
+ log_table = gtk.GtkTable(2,4,gtk.FALSE)
+ self.show_list.append(log_table)
+ self.frame_dict['log_frame'].add(log_table)
+
+ log_table.set_border_width(5)
+ log_table.set_col_spacings(5)
+ log_table.set_col_spacing(1, 20)
+
+ self.button_dict['Log To File'] = gtk.GtkCheckButton('Log To File')
+ self.show_list.append(self.button_dict['Log To File'])
+ log_table.attach(self.button_dict['Log To File'], 0,1, 0, 1)
+
+ self.button_dict['Select Log'] = gtk.GtkButton('Select Log')
+ self.show_list.append(self.button_dict['Select Log'])
+ log_table.attach(self.button_dict['Select Log'], 3,4, 0, 1)
+
+ log_label = gtk.GtkLabel('Log File (full path): ')
+ log_label.set_alignment(0, 0.5)
+ log_table.attach(log_label, 0,1, 1, 2)
+
+ self.entry_dict['log_file'] = gtk.GtkEntry()
+ self.entry_dict['log_file'].set_editable(gtk.TRUE)
+ self.entry_dict['log_file'].set_usize(400,25)
+ self.entry_dict['log_file'].set_text('')
+ log_table.attach(self.entry_dict['log_file'], 1,4, 1,2)
+
+ self.main_panel.pack_start(self.frame_dict['region_info_frame'],gtk.TRUE,gtk.TRUE,0)
+ self.main_panel.pack_start(self.frame_dict['log_frame'],gtk.FALSE,gtk.FALSE,0)
+
+ # Customized connections
+ self.button_dict['Select Log'].connect('clicked',self.select_log_cb)
+
+ # Set default sensitivities for customized tool
+ self.button_dict['Log To File'].set_active(gtk.FALSE)
+ self.button_dict['Log To File'].set_sensitive(gtk.TRUE)
+ self.button_dict['Select Log'].set_sensitive(gtk.TRUE)
+
+ def update_regioninfo_text(self,text):
+ del_len = self.entry_dict['region_info_text'].get_length()
+ self.entry_dict['region_info_text'].backward_delete(del_len)
+ self.entry_dict['region_info_text'].insert_defaults(text)
+
+ def update_logfile_text(self,filepath,*args):
+ self.entry_dict['log_file'].set_text(filepath)
+
+ def set_entry_sensitivities(self,bool_val):
+ self.entry_dict['start_line'].set_sensitive(bool_val)
+ self.entry_dict['start_pix'].set_sensitive(bool_val)
+ self.entry_dict['num_lines'].set_sensitive(bool_val)
+ self.entry_dict['num_pix'].set_sensitive(bool_val)
+ self.entry_dict['log_file'].set_sensitive(bool_val)
+
+ def select_log_cb(self,*args):
+ import pgufilesel
+ pgufilesel.SimpleFileSelect( self.update_logfile_text,
+ None,
+ 'Select Log File',
+ help_topic = 'files.html' )
+
+ def activate_toggled(self,*args):
+ if self.button_dict['Activate'].get_active():
+ self.set_entry_sensitivities(gtk.TRUE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.TRUE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.TRUE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.TRUE)
+ self.button_dict['Log To File'].set_sensitive(gtk.TRUE)
+ self.button_dict['Log To File'].set_active(gtk.FALSE)
+ self.button_dict['Select Log'].set_sensitive(gtk.TRUE)
+ self.notify('re-activated')
+ else:
+ self.set_entry_sensitivities(gtk.FALSE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.FALSE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.FALSE)
+ self.button_dict['Log To File'].set_sensitive(gtk.FALSE)
+ self.button_dict['Log To File'].set_active(gtk.FALSE)
+ self.button_dict['Select Log'].set_sensitive(gtk.FALSE)
+
+
Added: packages/openev/branches/upstream/current/pymod/toolfile_example.txt
===================================================================
--- packages/openev/branches/upstream/current/pymod/toolfile_example.txt (rev 0)
+++ packages/openev/branches/upstream/current/pymod/toolfile_example.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,7 @@
+# Example tool file for openev extension
+
+MODULE_NAME = toolexample
+TOOL_NAME = Stats_Tool
+TOOL_NAME=GeneralPOITool
+TOOL_NAME=GeneralROITool
+TOOL_NAME = Pixel_Tool
Added: packages/openev/branches/upstream/current/pymod/vecplot.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/vecplot.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/vecplot.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,3721 @@
+#! /usr/bin/env python
+###############################################################################
+# $Id: vecplot.py,v 1.7 2004/06/27 20:18:14 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: GvViewArea-based plotting.
+# Author: Gillian Walter <gillian.walter at atlantis-scientific.com>
+#
+# Developed by Atlantis Scientific Inc. (www.atlantis-scientific.com) for
+# DRDC Ottawa
+#
+###############################################################################
+# Copyright (c) Her majesty the Queen in right of Canada as represented
+# by the Minister of National Defence, 2003.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: vecplot.py,v $
+# Revision 1.7 2004/06/27 20:18:14 gmwalter
+# Fixed xspc/xtics bug in vecplot, added
+# character-based field width option to
+# pgugrid.py.
+#
+# Revision 1.6 2004/03/01 17:29:51 gmwalter
+# Bug fix for interactive plot merging, add see-all
+# function for setting extents properly.
+#
+# Revision 1.5 2004/02/12 22:36:08 gmwalter
+# Add functions for easily creating a line from three
+# lists of nodes (x,y,z), avoiding python-level for
+# loop.
+#
+# Revision 1.4 2004/01/16 21:32:52 gmwalter
+# Added in rough 3d support to see what
+# problems arise.
+#
+# Revision 1.3 2004/01/13 14:55:00 gmwalter
+# Add some functionality for modifying plots.
+#
+# Revision 1.2 2004/01/09 22:28:33 gmwalter
+# A few bug fixes.
+#
+# Revision 1.1 2004/01/07 20:41:48 gmwalter
+# Initial check-in of plotting and
+# annotation layer modules developed
+# for DRDC Ottawa.
+#
+#
+
+# - For 2D or 3D plotting
+#
+# - Layers:
+# - data
+# - xlabel/ylabel/title (each is movable)
+# - legend
+# - Grid/tics/axis (optional grid, display of x/y values, etc.)
+#
+# Problems: 3D legend? Might want to have ability to adjust the 3D plot
+# without legend, "sink" it to a raster (using print), then
+# put the legend layer on top.
+#
+# Eventually: contours, mesh, etc.
+
+#######################################
+# IMMEDIATE TO-DO:
+# 1) Fix up plot object/view area/window relationships and decide
+# on appropriate API
+#
+# 2) Labels/Axis- should be able to reset without discarding when
+# pxmin/pxmax or borders reset. Labels need not
+# be updated when data max/mins are reset, though
+# axis must be (discontinuities, spacing).
+
+
+#
+# NOTE: To avoid roundoff errors in getting data from interactive plots,
+# make sure openev is compiled with GV_USE_DOUBLE_PRECISION_COORD
+# (otherwise rounding could lead to points that are on the
+# plot boundary not being shown)
+#
+# LATER TO-DO:
+#
+# 1) Line symbols at nodes
+#
+
+import gview
+import Numeric
+import gtk
+import GtkExtra
+import os
+import string
+import gvogrfs
+import gvsignaler
+
+#########################################################################
+# Class hierarchy (not completely implemented yet)
+#
+# Classes meant to be used externally:
+#
+# GvPlotWindow: window to store a GvSimplePlot, GvMPlotTable, or GvMPlotLayout
+# GvPlot: a GvViewArea that stores one or more plot class instances, and.
+# provides an interface for using the internal plot classes.
+# Each plot class instance is assigned a set of extents within
+# the GvPlot which it uses in creating its layers.
+# GvSimplePlot is a simple implementation of this class for the
+# 2D cartesian case. The general case needs more thought.
+# GvMPlotTable: A gtk table containing multiple GvPlot instances
+# GvMPlotLayout: A gtk layout containing multiple GvPlot instances
+#
+# The GvMPlotTable/GvMPlotLayout classes should only be required if the
+# user wishes to have 2-D and 3-D plots side-by-side or embedded in
+# each other, or for displaying multiple 3-D plots (so that zooming/panning
+# rotation can be done independently in each 3-D plot). They have not
+# been implemented yet (3-D hasn't been either).
+#
+# Classes/functions meant to be used internally:
+#
+# plot classes:
+#
+# gvplot_2Ddata_cartesian- class for doing 2-D cartesian plots. Axis can
+# be linear or log, and can contain one or more
+# discontinuities. More than one array of data
+# can be plotted.
+#
+# Each plot class is characterized by one or more data arrays, one
+# set of axis (top/left/bottom/right), one set of data and view extents and
+# function for converting from data coordinates to view coordinates, one
+# set of labels, one border layer (2 area shapes: a background for the border
+# and a background for the data frame), and one legend.
+#
+# If data is to be plotted using two separate ranges and two sets of
+# axis are required (eg. velocity over top of acceleration), use two
+# plot classes within the same GvPlot using the same plot extents, and don't
+# add a border layer to the top plot.
+#
+# supporting classes used by plot classes (internal):
+#
+# gvplot_array_cartesian- store arrays after getting rid of inf's and nan's,
+# and store min/max values of the arrays.
+#
+# gvplot_layer_defaults- store layer legend labels (also used in the layer
+# name) and properties.
+#
+# gvplot_axis- store axis extents and display, tic information.
+#
+# functions for creating layers:
+# Create2DBorderLayer
+# CreateArrayDataLayer, CreateGridDataLayer
+# CreateAxisLayer
+# CreateLabelLayer
+# CreateLegendLayer
+#
+# Layers that form a single plot, created by plot classes (from bottom up):
+# Border layer
+# Data layer(s)- one or more
+# Axis layer
+# Label layer
+# Legend layer
+
+GVPLOT_DATA_LAYER='Data' # plotted data
+GVPLOT_LABEL_LAYER='Labels' # x/y/z labels, title, other annotation
+GVPLOT_LEGEND_LAYER='Legend' # Legend
+GVPLOT_AXIS_LAYER='Axis' # Axis lines and Axis tic-marks/values
+GVPLOT_BORDER_LAYER='Border' # Backdrop to plot and border
+
+# Recognized types of axis
+GVPLOT_AXISTYPE_LINEAR='Linear'
+GVPLOT_AXISTYPE_LOG='Log'
+
+# Axis display options
+GVPLOT_AXIS_NOTSHOWN=0 # Not displayed
+GVPLOT_AXIS_NOTICS=1 # Show axis, but no tics
+GVPLOT_AXIS_VTICS=2 # Show only major tics, without labels
+GVPLOT_AXIS_VTICSLABELS=3 # Show only major tics, with labels
+GVPLOT_AXIS_VTICSLABELSTICS=4 # Show major tics with labels and minor tics
+
+DEFAULT_EDGE_PADDING=0.15
+
+
+if os.name == 'nt':
+ DEFAULT_FONT="-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*"
+else:
+ DEFAULT_FONT="-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"
+
+
+
+
+# plot classes
+
+class gvplot_2Ddata_cartesian:
+ """ Store an accumulation of _gvplot_arraydata instances,
+ along with plot-window specific information.
+ """
+ def __init__(self,plot_label,pxmin=0.0,pymin=0.0,pxmax=1.0,pymax=1.0):
+ """ plot_label- text label to prepend to layer names for this plot
+ pxmin/pxmax/pymin/pymax- extents that plot should cover in
+ main view window.
+ """
+ ###############################################################
+ # Properties that will be common to other 2-D plot classes #
+ ###############################################################
+
+ # Data: one or more gvplot_array_cartesian objects to plot.
+ # Each will be plotted as a separate line layer. Each item
+ # in array_layer_defaults stores the label (for legend)
+ # and layer properties of the corresponding array_data
+ # item (eg. '_line_width', '_line_color','_gv_ogrfs_line',
+ # '_gl_antialias')
+ self.array_data=[] # Data to plot
+ self.array_layer_defaults=[] # Data plotting properties
+
+
+ # Axis: zero or more axis/lines to create. These are all put
+ # together in a single layer. Layer-wide properties
+ # are stored in axis_layer_properties- use this to
+ # set the colours/widths of all axis/lines at once.
+ # Individual axis properties (start/end points and
+ # discontinuity locations in plot coordinates, locations
+ # of major and minor tics also in plot coordinates,
+ # labels for major tics, formats for labels, colours
+ # if desired) are stored in axis_data. Individual
+ # properties override layer-wide properties.
+ # By default, 4 keys are created: top, bottom, left,
+ # and right. More can be added.
+ self.axis_data={}
+ self.axis_data['top']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['bottom']=gvplot_axis(GVPLOT_AXIS_VTICSLABELS)
+ self.axis_data['bottom'].vtics_properties['_gv_ogrfs']=\
+ 'LABEL(c:#000000FF,'+\
+ 'f:"'+DEFAULT_FONT+'",t:{label},a:0.0,s:1.0,dx:-10.0,dy:15.0);'+\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:0.0,s:1.0)'
+ self.axis_data['left']=gvplot_axis(GVPLOT_AXIS_VTICSLABELS)
+ self.axis_data['left'].vtics_properties['_gv_ogrfs']=\
+ 'LABEL(c:#000000FF,'+\
+ 'f:"'+DEFAULT_FONT+'",t:{label},a:0.0,s:1.0,dx:-40.0,dy:5.0);'+\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:270.0,s:1.0)'
+ self.axis_data['right']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_layer_properties={}
+
+ # axis defaults
+ self.axis_layer_properties['_gl_antialias']='1'
+ self.axis_layer_properties['_line_color']='0.0 0.0 0.0 1.0'
+
+ # Extents that plot covers in main view area (plot coordinates)
+ self.pxmin=pxmin
+ self.pxmax=pxmax
+ self.pymin=pymin
+ self.pymax=pymax
+ self.plot_label=plot_label
+
+ # left/right/top/bottom border padding
+ self.lborder=DEFAULT_EDGE_PADDING
+ self.rborder=DEFAULT_EDGE_PADDING
+ self.tborder=DEFAULT_EDGE_PADDING
+ self.bborder=DEFAULT_EDGE_PADDING
+
+ # border backgrounds (inner- behind plotted data;
+ # outer- around edge of data). Border layer is only
+ # created if show_inner_border or show_outer_border
+ # is set to 1.
+ self.show_inner_border=0
+ self.show_outer_border=0
+ self.inner_border_props={}
+ self.outer_border_props={}
+ self.outer_border_props['_area_edge_color']='1.0 1.0 1.0 1.0'
+ self.outer_border_props['_area_edge_width']='1.0'
+ self.outer_border_props['_area_fill_color']='1.0 1.0 1.0 1.0'
+ self.inner_border_props['_area_edge_color']='1.0 1.0 1.0 1.0'
+ self.inner_border_props['_area_edge_width']='1.0'
+ self.inner_border_props['_area_fill_color']='1.0 1.0 1.0 1.0'
+
+
+ # Label parameters:
+ # label_data- a dictionary containing several lists, each
+ # with an (x,y) tuple of plot coordinates, and
+ # a text string or None.
+ # properties- properties to set on the layer (usually just
+ # contains a key/value pair for _gv_ogrfs,
+ # which contains display info). Text for labels
+ # is taken from the 'label' property set for
+ # the shape.
+ self.label_data={}
+ self.label_layer_properties={}
+
+ # defaults
+ self.label_layer_properties['_gv_ogrfs_point']=\
+ 'LABEL(c:#000000FF,f:"'+DEFAULT_FONT+'",t:{label})'
+
+ x0=self.pxmin+(self.lborder/5.0)*(self.pxmax-self.pxmin)
+ xm=(self.pxmax+self.pxmin)/2.0+self.lborder-self.rborder
+ xf=self.pxmax-(self.rborder/5.0)*(self.pxmax-self.pxmin)
+ y0=self.pymin+(self.bborder/4.0)*(self.pymax-self.pymin)
+ ym=(self.pymax+self.pymin)/2.0+self.bborder-self.tborder
+ yf=self.pymax-(self.tborder/2.0)*(self.pymax-self.pymin)
+
+ self.label_data['xlabel']=[(xm,y0,0),'xlabel']
+ self.label_data['ylabel']=[(x0,ym,0),None]
+ self.label_data['title']=[(xm,yf,0),None]
+
+ # Legend parameters:
+ # show_legend- 1 if legend should be created; 0 otherwise
+ # location- an x,y tuple that specifies where the top left
+ # corner of the legend should fall as a fraction
+ # of pxmax-pxmin, pymax-pymin (plot extents):
+ # each value should be in the range 0-1.
+
+ self.show_legend=0
+ self.legend_location=None
+
+
+ ########################
+ # Specific properties. #
+ ########################
+
+ # Each min/max pair corresponds to
+ # a continous range in the plot axis
+ # NOTE: In the log axis case, these still
+ # correspond to the non-logged min/max's;
+ # logarithms are taken as the data layer
+ # created- ie. for a log plot that ranges
+ # from 10^0 to 10^2, the values here would
+ # be 1 and 100.
+ self.xmins=[]
+ self.xmaxs=[]
+ self.xloc=None # Major xtic locations (data coordinates)
+ self.xfmt="%g" # Formatting string for tic labels
+
+ self.ymins=[]
+ self.ymaxs=[]
+ self.yloc=None # Major ytic locations (data coordinates)
+ self.yfmt="%g"
+
+ self.xaxistype=GVPLOT_AXISTYPE_LINEAR
+ self.yaxistype=GVPLOT_AXISTYPE_LINEAR
+
+ #################################################
+ # Layers
+ #################################################
+ self.BorderLayer=None
+ self.DataLayers=[]
+ self.AxisLayer=None
+ self.LabelLayer=None
+ self.LegendLayer=None
+
+ def create_layers(self):
+ """ Create layers """
+ self.BorderLayer=Create2DBorderLayer(self)
+ if self.BorderLayer is not None:
+ ll=[self.BorderLayer]
+ else:
+ ll=[]
+
+ self.DataLayers=[]
+ for idx in range(len(self.array_data)):
+ self.DataLayers.append(CreateArrayDataLayer(self,idx))
+ ll.extend(self.DataLayers)
+
+ self.AxisLayer=CreateAxisLayer(self)
+ if ll is not None:
+ ll.append(self.AxisLayer)
+
+ self.LabelLayer=CreateLabelLayer(self)
+ if self.LabelLayer is not None:
+ ll.append(self.LabelLayer)
+
+ self.LegendLayer=Create2DLegendLayer(self)
+ if self.LegendLayer is not None:
+ ll.append(self.LegendLayer)
+
+ return ll
+
+ def get_layer(self,ltype=GVPLOT_DATA_LAYER,idx=0):
+ """ Get the layer of type ltype. If ltype is 'Data',
+ index idx is also specified to indicate which
+ data layer to return. If layer is not present,
+ return None.
+ """
+ if ltype is GVPLOT_DATA_LAYER:
+ if len(self.DataLayers) > idx:
+ return self.DataLayers[idx]
+ else:
+ return None
+ elif ltype is GVPLOT_AXIS_LAYER:
+ return self.AxisLayer
+ elif ltype is GVPLOT_BORDER_LAYER:
+ return self.BorderLayer
+ elif ltype is GVPLOT_LABEL_LAYER:
+ return self.LabelLayer
+ elif ltype is GVPLOT_LEGEND_LAYER:
+ return self.LegendLayer
+ else:
+ raise RuntimeError,'get_layer: Invalid layer type'
+
+ def create_layer(self,ltype=GVPLOT_DATA_LAYER,idx=0):
+ """ Create or update the layer of type ltype. If ltype is 'Data',
+ index idx is also specified to indicate which
+ data layer to return. If layer is not present,
+ return None.
+ """
+ if ltype is GVPLOT_DATA_LAYER:
+ if len(self.DataLayers) > idx:
+ self.DataLayers[idx]=CreateArrayDataLayer(self,idx)
+ elif len(self.DataLayers) == idx:
+ self.DataLayers.append(CreateArrayDataLayer(self,idx))
+ else:
+ raise RuntimeError,'create_layer: invalid data layer index'
+ elif ltype is GVPLOT_AXIS_LAYER:
+ self.AxisLayer=CreateAxisLayer(self)
+ return self.AxisLayer
+ elif ltype is GVPLOT_BORDER_LAYER:
+ self.BorderLayer=Create2DBorderLayer(self)
+ return self.BorderLayer
+ elif ltype is GVPLOT_LABEL_LAYER:
+ self.LabelLayer=CreateLabelLayer(self)
+ return self.LabelLayer
+ elif ltype is GVPLOT_LEGEND_LAYER:
+ self.LegendLayer=Create2DLegendLayer(self)
+ return self.LegendLayer
+ else:
+ raise RuntimeError,'create_layer: Invalid layer type'
+
+
+
+ def get_layers(self):
+ """ Return all layers that have been created, but don't
+ create new ones.
+ """
+ if self.BorderLayer is not None:
+ ll=[self.BorderLayer]
+ else:
+ ll=[]
+
+ ll.extend(self.DataLayers)
+ if self.AxisLayer is not None:
+ ll.append(self.AxisLayer)
+
+ if self.LabelLayer is not None:
+ ll.append(self.LabelLayer)
+
+ if self.LegendLayer is not None:
+ ll.append(self.LegendLayer)
+
+ return ll
+
+ def update_data_from_plot(self,index):
+ """ Update the underlying array data based on the
+ modifications to the current plot. This will
+ discard any data outside of the viewing
+ ranges.
+ """
+ newx,newy=self.get_data_from_plot(index)
+ self.array_data[index]=gvplot_array_cartesian(newx,newy)
+
+ def merge_data_from_plot(self,index):
+ """ Update the underlying array data based on the
+ modifications to the current plot. This will
+ try to merge the plot with the underlying data
+ (data from the original array that lies outside
+ the current viewing range is included).
+ """
+ newx,newy=self.get_data_from_plot(index)
+ # find data that was out of range and not plotted
+ xold=self.array_data[index].xarr
+ yold=self.array_data[index].yarr
+ outx,outy,outz=GetOutlierData(xold,self.xmins,self.xmaxs,
+ yold,self.ymins,self.ymaxs)
+ newx.extend(outx)
+ newy.extend(outy)
+ newx2,newy2=MakeContiguousXY(newx,newy)
+ self.array_data[index]=gvplot_array_cartesian(newx2,newy2)
+
+
+
+ def get_data_from_plot(self,index):
+ """ Get (potentially modified) data from the the data layer
+ corresponding to array_data[index].
+ """
+ if index > len(self.DataLayers)-1:
+ return None
+
+ l=self.DataLayers[index]
+ shps=l.get_parent()
+ xlists=[]
+ ylists=[]
+ arrxlists=[]
+ arrylists=[]
+ idx=0
+ for shp in shps:
+ xlists.append([])
+ ylists.append([])
+ for cnodeidx in range(shp.get_nodes()):
+ cnode=shp.get_node(cnodeidx)
+ xlists[idx].append(cnode[0])
+ ylists[idx].append(cnode[1])
+ xdata,ydata,ok=self.get_xyposition(Numeric.array(xlists[idx]),
+ Numeric.array(ylists[idx]))
+ arrxlists.append(xdata)
+ arrylists.append(ydata)
+ idx=idx+1
+
+ return (arrxlists,arrylists)
+
+ def set_extents(self,xmin=None,xmax=None,xspc=None,nxtics=0,
+ ymin=None,ymax=None,yspc=None,nytics=0,nice=1):
+ """ Set data extents for plot. In each case below, entering
+ a value of None indicates that the plot should decide on
+ sensible min/max's. If xmin is an array, xmax must be
+ an array of the same length, and vice versa (same for
+ ymin/ymax). Each xmin/xmax pair represents one continuous
+ range of values to plot.
+
+ xmin- minimum in x direction (None, single value, or array)
+ ymin- minimum in y direction (None, single value, or array)
+ xmax- maximum in x direction (None, single value, or array)
+ ymax- maximum in y direction (None, single value, or array)
+ xspc- approximate tic spacing in x direction (None or single value)
+ yspc- approximate tic spacing in y direction (None or single value)
+ nxtics- number of minor x tics per major x tic (defaults to 0)
+ nytics- number of minor y tics per major y tic (defaults to 0)
+ nice- 1 if plot is allowed to alter entered values slightly
+ to make them look 'nice'- eg. 0.015999 can be rounded
+ to 0.16, etc.; 0 if plot must not alter the values.
+ Defaults to 1.
+ """
+
+ if len(self.array_data) > 0:
+ if xmin is None:
+ xmin=self.array_data[0].xmin
+ for item in self.array_data[1:]:
+ xmin=min([xmin,item.xmin])
+
+ if xmax is None:
+ xmax=self.array_data[0].xmax
+ for item in self.array_data[1:]:
+ xmax=max([xmax,item.xmax])
+
+ if ymin is None:
+ ymin=self.array_data[0].ymin
+ for item in self.array_data[1:]:
+ ymin=min([ymin,item.ymin])
+
+ if ymax is None:
+ ymax=self.array_data[0].ymax
+ for item in self.array_data[1:]:
+ ymax=max([ymax,item.ymax])
+
+ if nice == 1:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ self.xmins=dxmin
+ self.xmaxs=dxmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dylocs,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=dymin
+ self.ymaxs=dymax
+ self.ylocs=dylocs
+ self.yfmt=fmt
+ else:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ if type(xmin) not in [type([]),type((1,))]:
+ self.xmins=[xmin]
+ else:
+ self.xmins=xmin
+ if type(xmax) not in [type([]),type((1,))]:
+ self.xmaxs=[xmax]
+ else:
+ self.xmaxs=xmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dyspc,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ if type(ymin) not in [type([]),type((1,))]:
+ self.ymins=[ymin]
+ else:
+ self.ymins=ymin
+
+ if type(ymax) not in [type([]),type((1,))]:
+ self.ymaxs=[ymax]
+ else:
+ self.ymaxs=ymax
+
+ self.ylocs=dylocs
+ self.yfmt=fmt
+ else:
+ if ((xmin is None) or (xmax is None) or (ymin is None) or
+ (ymax is None)):
+ raise RuntimeError,'set_extents: if no data has been set,'+\
+ 'then\nxmin/xmax/ymin/ymax must all be specified.'
+
+ if nice == 1:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ self.xmins=dxmin
+ self.xmaxs=dxmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dylocs,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=dymin
+ self.ymaxs=dymax
+ self.ylocs=dylocs
+ self.yfmt=fmt
+ else:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ # TO DO: ADD A CHECK HERE AND MAKE SURE THEY ARE LISTS!
+ self.xmins=xmin
+ self.xmaxs=xmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dyspc,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=list(dymin)
+ self.ymaxs=list(dymax)
+ self.ylocs=list(dylocs)
+ self.yfmt=fmt
+
+ self.set_axis()
+
+ def set_axis(self):
+ """ Set the default axis """
+
+ new_axis_data={}
+ xbreaks=GetAxisBreaks(self.xmins,self.xmaxs,self.xaxistype)
+ ybreaks=GetAxisBreaks(self.ymins,self.ymaxs,self.yaxistype)
+ ext=self.get_plot_extents(include_border=0)
+ pxlocs,xok=DataToPlot1D(ext[0],ext[3],self.xmins,self.xmaxs,
+ self.xlocs,self.xaxistype)
+ pylocs,yok=DataToPlot1D(ext[1],ext[4],self.ymins,self.ymaxs,
+ self.ylocs,self.yaxistype)
+
+ toplocs=[]
+ bottomlocs=[]
+ leftlocs=[]
+ rightlocs=[]
+ ext=self.get_plot_extents(include_border=0)
+
+ for item in pxlocs:
+ toplocs.append((item,ext[4]))
+ bottomlocs.append((item,ext[1]))
+ for item in pylocs:
+ leftlocs.append((ext[0],item))
+ rightlocs.append((ext[3],item))
+
+ # TO DO: add minor tics
+ new_axis_data['top']=self.axis_data['top']
+ new_axis_data['top'].set_data(toplocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[0],ext[4],0),
+ (ext[3],ext[4],0),
+ xbreaks)
+ new_axis_data['bottom']=self.axis_data['bottom']
+ new_axis_data['bottom'].set_data(bottomlocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[0],ext[1],0),
+ (ext[3],ext[1],0),
+ xbreaks)
+ new_axis_data['left']=self.axis_data['left']
+ new_axis_data['left'].set_data(leftlocs,list(self.ylocs),self.yfmt,
+ None,
+ (ext[0],ext[1],0),
+ (ext[0],ext[4],0),
+ ybreaks)
+ new_axis_data['right']=self.axis_data['right']
+ new_axis_data['right'].set_data(rightlocs,list(self.ylocs),self.yfmt,
+ None,
+ (ext[3],ext[1],0),
+ (ext[3],ext[4],0),
+ ybreaks)
+
+ self.axis_data=new_axis_data
+
+ #########################################################################
+ # Versions of the following functions will be required of most or #
+ # all plot classes. #
+ #########################################################################
+
+ def add_data(self,xarr,yarr,label='',properties=None, interactive=0):
+ """ Add an array to the data to plot """
+ self.array_data.append(gvplot_array_cartesian(xarr,yarr))
+ self.array_layer_defaults.append(
+ gvplot_layer_defaults(label,properties,interactive))
+ return len(self.array_data)-1
+
+ def set_labels(self,xlabel=None,ylabel=None,title=None):
+ """ Set labels. """
+ self.label_data['xlabel'][1]=xlabel
+ self.label_data['ylabel'][1]=ylabel
+ self.label_data['title'][1]=title
+
+ def set_plot_extents(self,pxmin,pxmax,pymin,pymax):
+ """ Set/Reset the extents covered by this plot in the view.
+ Update labels, axis, data info.
+ """
+
+ oldpxmin=self.pxmin
+ oldpxmax=self.pxmax
+ oldpymin=self.pymin
+ oldpymax=self.pymax
+
+ self.pxmin=pxmin
+ self.pxmax=pxmax
+ self.pymin=pymin
+ self.pymax=pymax
+
+ # Update label positions
+ for ckey in self.label_data.keys():
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.label_data[ckey][0][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.label_data[ckey][0][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.label_data[ckey][0]=(xnew,ynew,0)
+
+ # Update axis information
+ for ckey in self.axis_data.keys():
+ for idx in range(len(self.axis_data[key].vtics)):
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].vtics[idx][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].vtics[idx][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].vtics[idx]=(xnew,ynew,0)
+
+ for idx in range(len(self.axis_data[key].tics)):
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].tics[idx][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].tics[idx][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].tics[idx]=(xnew,ynew,0)
+
+ if self.axis_data[ckey].start is not None:
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].start[0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].start[1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].start=(xnew,ynew,0)
+
+ if self.axis_data[ckey].end is not None:
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].end[0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].end[1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].end=(xnew,ynew,0)
+
+ if self.axis_data[ckey].breaks is not None:
+ for idx in range(len(breaks)):
+ xnew1=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].breaks[idx][0][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew1=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].breaks[idx][0][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ xnew2=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].breaks[idx][1][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew2=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].breaks[idx][1][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].breaks[idx]=((xnew1,ynew1,0),
+ (xnew2,ynew2,0))
+
+ if len(self.xmins) == 0:
+ return
+
+ self.reset_axis()
+
+ def get_extents(self):
+ """ Get data extents: (xmins, xmaxs, ymins, ymaxs, zmins, zmaxs). """
+ return (self.xmins,self.xmaxs,self.ymins,
+ self.ymaxs,[0],[0])
+
+ def get_plot_extents(self,include_border=1):
+ """ Get plot extents with (include_border=1) or
+ without (include_border=0) borders.
+ (xmin,ymin,zmin,xmax,ymax,zmax). For
+ this class, zmin=zmax=0 always. The third
+ dimension is included because the CreateAxisLayer
+ function will be shared with the 3d case.
+ """
+ if include_border == 1:
+ return (self.pxmin,self.pymin,0,self.pxmax,self.pymax,0)
+
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.bborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.tborder
+
+ return (dxmin,dymin,0,dxmax,dymax,0)
+
+
+ def get_xyposition(self,x,y):
+ """ Get the data position corresponding to GvViewPlot position x,y.
+ x and y may be single values or same-length 1-D arrays.
+ """
+
+ # Get plot extents minus borders.
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.bborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.tborder
+
+ if type(x) == type(Numeric.array([])):
+ x=Numeric.ravel(x)
+
+ if type(y) == type(Numeric.array([])):
+ y=Numeric.ravel(y)
+
+ x,xok=PlotToData1D(dxmin,dxmax,self.xmins,self.xmaxs,x,self.xaxistype)
+ y,yok=PlotToData1D(dymin,dymax,self.ymins,self.ymaxs,y,self.yaxistype)
+
+ okarr=Numeric.where(xok==0,0,yok)
+
+ return (x,y,okarr)
+
+ def get_plotposition(self,x,y):
+ """ Get the GvViewPlot position corresponding to data position x,y.
+ x and y may be single values or same-length 1-D arrays.
+ """
+
+ # Get plot extents minus borders.
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.bborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.tborder
+
+ if type(x) == type(Numeric.array([])):
+ x=Numeric.ravel(x)
+
+ if type(y) == type(Numeric.array([])):
+ y=Numeric.ravel(y)
+
+ x,xok=DataToPlot1D(dxmin,dxmax,self.xmins,self.xmaxs,x,self.xaxistype)
+ y,yok=DataToPlot1D(dymin,dymax,self.ymins,self.ymaxs,y,self.yaxistype)
+
+ okarr=Numeric.where(xok==0,0,yok)
+
+ return (x,y,okarr)
+
+ def set_arraylayer_properties(self,idx,props):
+ """ Set the display properties for the idxth data layer.
+ idx- index of data
+ props- a dictionary of properties to set (keys) and their
+ values.
+
+ An error will be raised if there is no idx'th data array
+ to plot.
+
+ Example properties:
+ _line_color='1.0 0.0 0.0 1.0'
+ _line_width='1.0'
+ _gl_antialias='1' (turn on display antialiasing)
+ """
+ self.array_layer_defaults[idx]=props
+
+ def set_axislayer_properties(self,props):
+ """ Set the display properties of the axis layer
+
+ Example properties:
+ _line_color='1.0 0.0 0.0 1.0'
+ _line_width='1.0'
+ _gl_antialias='1' (turn on display antialiasing)
+
+ """
+ self.axis_layer_properties=props
+
+ def set_label_color(self,color):
+ """ Set label layer color to color. """
+
+ import gvogrfs
+ cstr2=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr2) < 9:
+ cstr2=cstr2+'FF'
+ if self.label_layer_properties.has_key('_gv_ogrfs_point'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ self.label_layer_properties['_gv_ogrfs_point'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ self.label_layer_properties['_gv_ogrfs_point']=ogrfs.unparse()
+
+ def set_axis_color(self,color):
+ """ Set all axis and axis label colours to color.
+ color is a tuple of 4 values, each between
+ 0 and 1, representing red/green/blue/alpha
+ components.
+ """
+ cstr1=str(color[0])+' '+str(color[1])+' '+str(color[2])+\
+ ' '+str(color[3])
+ self.axis_layer_properties['_line_color']=cstr1
+
+ import gvogrfs
+ cstr2=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr2) < 9:
+ cstr2=cstr2+'FF'
+ for caxis in self.axis_data.values():
+ caxis.line_properties['_line_color']=cstr1
+ if caxis.vtics_properties.has_key('_gv_ogrfs'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ caxis.vtics_properties['_gv_ogrfs'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ caxis.vtics_properties['_gv_ogrfs']=ogrfs.unparse()
+
+ if caxis.tics_properties.has_key('_gv_ogrfs'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ caxis.tics_properties['_gv_ogrfs'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ caxis.tics_properties['_gv_ogrfs']=ogrfs.unparse()
+
+
+ def set_axis_properties(self,key,lprops,vprops,tprops):
+ """ Set the properties of the shapes forming the axis
+ referenced by 'key'. Default keys are 'top, 'bottom',
+ 'left','right'. An error will be raised if the axis
+ dictionary doesn't contain key.
+
+ Parameters:
+ key- key to index axis
+ lprops- line properties (if different from layer default)
+ vprops- vtic properties
+ tprops- tic properties
+
+ Example properties: (defaults for left axis shown here)
+ _gv_ogrfs='LABEL(c:#000000FF,'+\
+ 'f:"-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*",
+ t:{label},a:0.0,s:1.0,dx:-35.0,dy:5.0);'+\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:270.0,s:1.0)'
+
+ Note: the label property is always used to get text
+ in CreateAxisLayer, so the t:{label} portion
+ of this should be left alone.
+ """
+
+ self.axis_data[key].line_properties=lprops
+ self.axis_data[key].vtics_properties=vprops
+ self.axis_data[key].tics_properties=tprops
+
+
+ def set_border_padding(self,top,bottom,left,right):
+ """ Set border padding as a fraction of the plot
+ extents (0-1).
+ top- top padding
+ bottom- bottom
+ left- left
+ right- right
+ """
+ self.tborder=top
+ self.bborder=bottom
+ self.lborder=left
+ self.rborder=right
+
+ def set_borderlayer_properties(self,show_outer,show_inner,
+ outer_props,inner_props):
+ """ Set border layer properties:
+ show_outer- 1 to create outer border, 0 to not create it
+ show_inner- 1 to create inner border, 0 to not create it
+ outer_props- dictionary of outer border properties
+ (None to leave at defaults)
+ inner_props- dictionary of inner border properties
+ (None to leave at defaults)
+
+ Example properties:
+
+ outer_props['_area_edge_color']='1.0 1.0 1.0 1.0'
+ outer_props['_area_edge_width']='1.0'
+ outer_props['_area_fill_color']='1.0 1.0 1.0 1.0'
+
+ """
+ self.show_outer_border=show_outer
+ if outer_props is not None:
+ self.outer_border_props=outer_props
+
+ self.show_inner_border=show_inner
+ if inner_props is not None:
+ self.inner_border_props=inner_props
+
+ def set_labellayer_properties(self,label_props):
+ """ Set label layer properties:
+ Example:
+ _gv_ogrfs_point='LABEL(c:#000000FF,
+ f:"-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*",t:{label})'
+
+ Note: the label property is always used to get text
+ in CreateLabelLayer, so the t:{label} portion
+ of this should be left alone.
+ """
+ self.label_layer_properties=label_props
+
+ def set_legend(self,show=1,location=None):
+ """ Set legend status:
+ show- 1 (show) or 0 (hide)
+ location- offset as a fraction of
+ current plot extents
+ (xoffset,yoffset); if None,
+ default will be used.
+ """
+ self.show_legend=show
+ if location is not None:
+ self.legend_location=location
+ else:
+ self.legend_location=(self.lborder+0.05,
+ 1.0-self.tborder-0.1)
+
+ def add_axis(self,key,properties,start_tuple,end_tuple,breaks=None,
+ type=GVPLOT_AXIS_NOTICS):
+ """ Add an axis (line):
+ key- key to reference the axis
+ properties- axis properties
+ start_tuple- an (x,y) tuple in data coordinates representing
+ the start point of the line.
+ end_tuple- an (x,y) tuple in data coordinates representing
+ the start point of the line.
+ breaks- breaks in the axis/line (defaults to None, must be
+ a list of start/end tuples if present). Also in
+ data coordinates.
+ type- type of axis (0-4: not shown, shown but no tics, shown
+ with major tics but no labels, shown with major tics
+ and labels, shown with major tics and labels and minor
+ tics).
+
+ """
+ pass
+
+
+class gvplot_3Ddata_cartesiangrid:
+ """ Store an accumulation of _gvplot_arraydata instances,
+ along with plot-window specific information.
+ """
+ def __init__(self,plot_label,pxmin=0.0,pymin=0.0,pzmin=0.0,pxmax=1.0,
+ pymax=1.0,pzmax=1.0):
+ """ plot_label- text label to prepend to layer names for this plot
+ pxmin/pxmax/pymin/pymax/pzmin/pzmax- extents that plot should
+ cover in main view window.
+ """
+ self.array_data=[] # Data to plot
+ self.array_layer_defaults=[] # Data plotting properties
+
+
+ # Axis: zero or more axis/lines to create. These are all put
+ # together in a single layer. Layer-wide properties
+ # are stored in axis_layer_properties- use this to
+ # set the colours/widths of all axis/lines at once.
+ # Individual axis properties (start/end points and
+ # discontinuity locations in plot coordinates, locations
+ # of major and minor tics also in plot coordinates,
+ # labels for major tics, formats for labels, colours
+ # if desired) are stored in axis_data. Individual
+ # properties override layer-wide properties.
+ # By default, 4 keys are created: top, bottom, left,
+ # and right. More can be added.
+ self.axis_data={}
+ self.axis_data['topleft']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['topright']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['topfront']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['topback']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['bottomleft']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['bottomright']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['bottomfront']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['bottomback']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['leftfront']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['leftback']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['rightfront']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+ self.axis_data['rightback']=gvplot_axis(GVPLOT_AXIS_NOTICS)
+
+ # axis defaults
+ self.axis_layer_properties={}
+ self.axis_layer_properties['_gl_antialias']='1'
+ self.axis_layer_properties['_line_color']='0.0 0.0 0.0 1.0'
+
+ # Extents that plot covers in main view area (plot coordinates)
+ self.pxmin=pxmin
+ self.pxmax=pxmax
+ self.pymin=pymin
+ self.pymax=pymax
+ self.pzmin=pzmin
+ self.pzmax=pzmax
+ self.plot_label=plot_label
+
+ # left/right/top/bottom border padding
+ self.lborder=DEFAULT_EDGE_PADDING
+ self.rborder=DEFAULT_EDGE_PADDING
+ self.tborder=DEFAULT_EDGE_PADDING
+ self.bborder=DEFAULT_EDGE_PADDING
+ self.fborder=DEFAULT_EDGE_PADDING
+ self.bkborder=DEFAULT_EDGE_PADDING # back
+
+
+ # Label parameters:
+ # label_data- a dictionary containing several lists, each
+ # with an (x,y,z) tuple of plot coordinates, and
+ # a text string or None.
+ # properties- properties to set on the layer (usually just
+ # contains a key/value pair for _gv_ogrfs,
+ # which contains display info). Text for labels
+ # is taken from the 'label' property set for
+ # the shape.
+ self.label_data={}
+ self.label_layer_properties={}
+
+ # defaults
+ self.label_layer_properties['_gv_ogrfs_point']=\
+ 'LABEL(c:#000000FF,f:"'+DEFAULT_FONT+'",t:{label})'
+
+ x0=self.pxmin+(self.lborder/5.0)*(self.pxmax-self.pxmin)
+ xm=(self.pxmax+self.pxmin)/2.0+self.lborder-self.rborder
+ xf=self.pxmax-(self.rborder/5.0)*(self.pxmax-self.pxmin)
+ y0=self.pymin+(self.fborder/4.0)*(self.pymax-self.pymin)
+ ym=(self.pymax+self.pymin)/2.0+self.fborder-self.bkborder
+ yf=self.pymax-(self.bkborder/2.0)*(self.pymax-self.pymin)
+ z0=self.pzmin+(self.bborder/4.0)*(self.pzmax-self.pzmin)
+ zm=(self.pzmax+self.pzmin)/2.0+self.bborder-self.tborder
+ zf=self.pzmax-(self.tborder/2.0)*(self.pzmax-self.pzmin)
+
+ self.label_data['xlabel']=[(xm,y0,z0),None]
+ self.label_data['ylabel']=[(x0,ym,z0),None]
+ self.label_data['zlabel']=[(x0,y0,zm),None]
+ self.label_data['title']=[(xm,ym,zf),None]
+
+
+ ########################
+ # Specific properties. #
+ ########################
+
+ # Each min/max pair corresponds to
+ # a continous range in the plot axis
+ # NOTE: In the log axis case, these still
+ # correspond to the non-logged min/max's;
+ # logarithms are taken as the data layer
+ # created- ie. for a log plot that ranges
+ # from 10^0 to 10^2, the values here would
+ # be 1 and 100.
+ self.xmins=[]
+ self.xmaxs=[]
+ self.xloc=None # Major xtic locations (data coordinates)
+ self.xfmt="%g" # Formatting string for tic labels
+
+ self.ymins=[]
+ self.ymaxs=[]
+ self.yloc=None # Major ytic locations (data coordinates)
+ self.yfmt="%g"
+
+ self.zmins=[]
+ self.zmaxs=[]
+ self.zloc=None # Major ztic locations (data coordinates)
+ self.zfmt="%g"
+
+ self.xaxistype=GVPLOT_AXISTYPE_LINEAR
+ self.yaxistype=GVPLOT_AXISTYPE_LINEAR
+ self.zaxistype=GVPLOT_AXISTYPE_LINEAR
+
+ #################################################
+ # Layers
+ #################################################
+ self.DataLayers=[]
+ self.AxisLayer=None
+ self.LabelLayer=None
+
+ def create_layers(self):
+ """ Create layers """
+
+ ll=[]
+ self.DataLayers=[]
+ for idx in range(len(self.array_data)):
+ self.DataLayers.append(CreateGridArrayDataLayer(self,idx))
+ ll.extend(self.DataLayers)
+
+ self.AxisLayer=CreateAxisLayer(self)
+ if ll is not None:
+ ll.append(self.AxisLayer)
+
+ self.LabelLayer=CreateLabelLayer(self)
+ if self.LabelLayer is not None:
+ ll.append(self.LabelLayer)
+
+ return ll
+
+ def get_layer(self,ltype=GVPLOT_DATA_LAYER,idx=0):
+ """ Get the layer of type ltype. If ltype is 'Data',
+ index idx is also specified to indicate which
+ data layer to return. If layer is not present,
+ return None.
+ """
+ if ltype is GVPLOT_DATA_LAYER:
+ if len(self.DataLayers) > idx:
+ return self.DataLayers[idx]
+ else:
+ return None
+ elif ltype is GVPLOT_AXIS_LAYER:
+ return self.AxisLayer
+ elif ltype is GVPLOT_LABEL_LAYER:
+ return self.LabelLayer
+ else:
+ raise RuntimeError,'get_layer: Invalid layer type'
+
+ def create_layer(self,ltype=GVPLOT_DATA_LAYER,idx=0):
+ """ Create or update the layer of type ltype. If ltype is 'Data',
+ index idx is also specified to indicate which
+ data layer to return. If layer is not present,
+ return None.
+ """
+ if ltype is GVPLOT_DATA_LAYER:
+ if len(self.DataLayers) > idx:
+ self.DataLayers[idx]=CreateGridArrayDataLayer(self,idx)
+ elif len(self.DataLayers) == idx:
+ self.DataLayers.append(CreateGridArrayDataLayer(self,idx))
+ else:
+ raise RuntimeError,'create_layer: invalid data layer index'
+ elif ltype is GVPLOT_AXIS_LAYER:
+ self.AxisLayer=CreateAxisLayer(self)
+ return self.AxisLayer
+ elif ltype is GVPLOT_LABEL_LAYER:
+ self.LabelLayer=CreateLabelLayer(self)
+ return self.LabelLayer
+ else:
+ raise RuntimeError,'create_layer: Invalid layer type'
+
+
+
+ def get_layers(self):
+ """ Return all layers that have been created, but don't
+ create new ones.
+ """
+
+ ll.extend(self.DataLayers)
+ if self.AxisLayer is not None:
+ ll.append(self.AxisLayer)
+
+ if self.LabelLayer is not None:
+ ll.append(self.LabelLayer)
+
+ return ll
+
+ def set_extents(self,xmin=None,xmax=None,xspc=None,nxtics=0,
+ ymin=None,ymax=None,yspc=None,nytics=0,
+ zmin=None,zmax=None,zspc=None,nztics=0,nice=1):
+ """ Set data extents for plot. In each case below, entering
+ a value of None indicates that the plot should decide on
+ sensible min/max's. If xmin is an array, xmax must be
+ an array of the same length, and vice versa (same for
+ ymin/ymax). Each xmin/xmax pair represents one continuous
+ range of values to plot.
+
+ xmin- minimum in x direction (None, single value, or array)
+ ymin- minimum in y direction (None, single value, or array)
+ zmin- minimum in z direction (None, single value, or array)
+ xmax- maximum in x direction (None, single value, or array)
+ ymax- maximum in y direction (None, single value, or array)
+ zmax- maximum in z direction (None, single value, or array)
+ xspc- approximate tic spacing in x direction (None or single value)
+ yspc- approximate tic spacing in y direction (None or single value)
+ zspc- approximate tic spacing in y direction (None or single value)
+ nxtics- number of minor x tics per major x tic (defaults to 0)
+ nytics- number of minor y tics per major y tic (defaults to 0)
+ nztics- number of minor y tics per major y tic (defaults to 0)
+ nice- 1 if plot is allowed to alter entered values slightly
+ to make them look 'nice'- eg. 0.015999 can be rounded
+ to 0.16, etc.; 0 if plot must not alter the values.
+ Defaults to 1.
+ """
+
+ if len(self.array_data) > 0:
+ if xmin is None:
+ xmin=self.array_data[0].xmin
+ for item in self.array_data[1:]:
+ xmin=min([xmin,item.xmin])
+
+ if xmax is None:
+ xmax=self.array_data[0].xmax
+ for item in self.array_data[1:]:
+ xmax=max([xmax,item.xmax])
+
+ if ymin is None:
+ ymin=self.array_data[0].ymin
+ for item in self.array_data[1:]:
+ ymin=min([ymin,item.ymin])
+
+ if ymax is None:
+ ymax=self.array_data[0].ymax
+ for item in self.array_data[1:]:
+ ymax=max([ymax,item.ymax])
+
+ if zmin is None:
+ zmin=self.array_data[0].zmin
+ for item in self.array_data[1:]:
+ zmin=min([zmin,item.zmin])
+
+ if zmax is None:
+ zmax=self.array_data[0].zmax
+ for item in self.array_data[1:]:
+ zmax=max([zmax,item.zmax])
+
+ if nice == 1:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ self.xmins=dxmin
+ self.xmaxs=dxmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dylocs,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=dymin
+ self.ymaxs=dymax
+ self.ylocs=dylocs
+ self.yfmt=fmt
+
+ dzmin,dzmax,dzlocs,fmt=GetNiceMinMax(zmin,zmax,zspc,
+ self.zaxistype)
+ self.zmins=dzmin
+ self.zmaxs=dzmax
+ self.zlocs=dzlocs
+ self.zfmt=fmt
+ else:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ if type(xmin) not in [type([]),type((1,))]:
+ self.xmins=[xmin]
+ else:
+ self.xmins=xmin
+ if type(xmax) not in [type([]),type((1,))]:
+ self.xmaxs=[xmax]
+ else:
+ self.xmaxs=xmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dyspc,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ if type(ymin) not in [type([]),type((1,))]:
+ self.ymins=[ymin]
+ else:
+ self.ymins=ymin
+
+ if type(ymax) not in [type([]),type((1,))]:
+ self.ymaxs=[ymax]
+ else:
+ self.ymaxs=ymax
+
+ self.ylocs=dylocs
+ self.yfmt=fmt
+
+ dzmin,dzmax,dzspc,fmt=GetNiceMinMax(zmin,zmax,zspc,
+ self.zaxistype)
+ if type(zmin) not in [type([]),type((1,))]:
+ self.zmins=[zmin]
+ else:
+ self.zmins=zmin
+
+ if type(zmax) not in [type([]),type((1,))]:
+ self.zmaxs=[zmax]
+ else:
+ self.zmaxs=zmax
+
+ self.zlocs=dzlocs
+ self.zfmt=fmt
+ else:
+ if ((xmin is None) or (xmax is None) or (ymin is None) or
+ (ymax is None) or (zmin is None) or (zmax is None)):
+ raise RuntimeError,'set_extents: if no data has been set,'+\
+ 'then\nxmin/xmax/ymin/ymax/zmin/zmax must all be specified.'
+
+ if nice == 1:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ self.xmins=dxmin
+ self.xmaxs=dxmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dylocs,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=dymin
+ self.ymaxs=dymax
+ self.ylocs=dylocs
+ self.yfmt=fmt
+
+ dzmin,dzmax,dzlocs,fmt=GetNiceMinMax(zmin,zmax,zspc,
+ self.zaxistype)
+ self.zmins=dzmin
+ self.zmaxs=dzmax
+ self.zlocs=dzlocs
+ self.zfmt=fmt
+ else:
+ dxmin,dxmax,dxlocs,fmt=GetNiceMinMax(xmin,xmax,xspc,
+ self.xaxistype)
+ # TO DO: ADD A CHECK HERE AND MAKE SURE THEY ARE LISTS!
+ self.xmins=xmin
+ self.xmaxs=xmax
+ self.xlocs=dxlocs
+ self.xfmt=fmt
+
+ dymin,dymax,dyspc,fmt=GetNiceMinMax(ymin,ymax,yspc,
+ self.yaxistype)
+ self.ymins=list(dymin)
+ self.ymaxs=list(dymax)
+ self.ylocs=list(dylocs)
+ self.yfmt=fmt
+
+ dzmin,dzmax,dzspc,fmt=GetNiceMinMax(zmin,zmax,zspc,
+ self.zaxistype)
+ self.zmins=list(dzmin)
+ self.zmaxs=list(dzmax)
+ self.zlocs=list(dzlocs)
+ self.zfmt=fmt
+
+ self.set_axis()
+
+ def set_axis(self):
+ """ Set the default axis """
+
+ new_axis_data={}
+ xbreaks=GetAxisBreaks(self.xmins,self.xmaxs,self.xaxistype)
+ ybreaks=GetAxisBreaks(self.ymins,self.ymaxs,self.yaxistype)
+ zbreaks=GetAxisBreaks(self.zmins,self.zmaxs,self.zaxistype)
+ ext=self.get_plot_extents(include_border=0)
+ pxlocs,xok=DataToPlot1D(ext[0],ext[3],self.xmins,self.xmaxs,
+ self.xlocs,self.xaxistype)
+ pylocs,yok=DataToPlot1D(ext[1],ext[4],self.ymins,self.ymaxs,
+ self.ylocs,self.yaxistype)
+ pzlocs,zok=DataToPlot1D(ext[2],ext[5],self.zmins,self.zmaxs,
+ self.zlocs,self.zaxistype)
+
+ bottomlocs=[]
+ toplocs=[]
+ leftlocs=[]
+ rightlocs=[]
+ frontlocs=[]
+ backlocs=[]
+ ext=self.get_plot_extents(include_border=0)
+
+ for item in pxlocs:
+ backlocs.append((item,ext[4]))
+ frontlocs.append((item,ext[1]))
+ for item in pylocs:
+ leftlocs.append((ext[0],item))
+ rightlocs.append((ext[3],item))
+ for item in pzlocs:
+ bottomlocs.append((ext[2],item))
+ toplocs.append((ext[5],item))
+
+ # TO DO: add minor tics
+ new_axis_data['topleft']=self.axis_data['topleft']
+ new_axis_data['topleft'].set_data(toplocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[0],ext[1],ext[5]),
+ (ext[0],ext[4],ext[5]),
+ xbreaks)
+ new_axis_data['topright']=self.axis_data['topright']
+ new_axis_data['topright'].set_data(toplocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[3],ext[1],ext[5]),
+ (ext[3],ext[4],ext[5]),
+ xbreaks)
+ new_axis_data['topfront']=self.axis_data['topfront']
+ new_axis_data['topfront'].set_data(toplocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[0],ext[1],ext[5]),
+ (ext[3],ext[1],ext[5]),
+ ybreaks)
+ new_axis_data['topback']=self.axis_data['topback']
+ new_axis_data['topback'].set_data(toplocs,list(self.xlocs),self.xfmt,
+ None,
+ (ext[0],ext[4],ext[5]),
+ (ext[3],ext[4],ext[5]),
+ ybreaks)
+ new_axis_data['bottomleft']=self.axis_data['bottomleft']
+ new_axis_data['bottomleft'].set_data(bottomlocs,list(self.xlocs),
+ self.xfmt,
+ None,
+ (ext[0],ext[1],ext[2]),
+ (ext[0],ext[4],ext[2]),
+ xbreaks)
+ new_axis_data['bottomright']=self.axis_data['bottomright']
+ new_axis_data['bottomright'].set_data(bottomlocs,list(self.xlocs),
+ self.xfmt,
+ None,
+ (ext[3],ext[1],ext[2]),
+ (ext[3],ext[4],ext[2]),
+ xbreaks)
+ new_axis_data['bottomfront']=self.axis_data['bottomfront']
+ new_axis_data['bottomfront'].set_data(bottomlocs,list(self.xlocs),
+ self.xfmt,
+ None,
+ (ext[0],ext[1],ext[2]),
+ (ext[3],ext[1],ext[2]),
+ xbreaks)
+ new_axis_data['bottomback']=self.axis_data['bottomback']
+ new_axis_data['bottomback'].set_data(bottomlocs,list(self.xlocs),
+ self.xfmt,
+ None,
+ (ext[0],ext[4],ext[2]),
+ (ext[3],ext[4],ext[2]),
+ xbreaks)
+ new_axis_data['leftfront']=self.axis_data['leftfront']
+ new_axis_data['leftfront'].set_data(leftlocs,list(self.ylocs),
+ self.yfmt,
+ None,
+ (ext[0],ext[1],ext[2]),
+ (ext[0],ext[1],ext[5]),
+ ybreaks)
+ new_axis_data['leftback']=self.axis_data['leftback']
+ new_axis_data['leftback'].set_data(leftlocs,list(self.ylocs),self.yfmt,
+ None,
+ (ext[0],ext[4],ext[2]),
+ (ext[0],ext[4],ext[5]),
+ ybreaks)
+ new_axis_data['rightfront']=self.axis_data['rightfront']
+ new_axis_data['rightfront'].set_data(rightlocs,list(self.ylocs),
+ self.yfmt,
+ None,
+ (ext[3],ext[1],ext[2]),
+ (ext[3],ext[1],ext[5]),
+ ybreaks)
+ new_axis_data['rightback']=self.axis_data['rightback']
+ new_axis_data['rightback'].set_data(rightlocs,list(self.ylocs),
+ self.yfmt,
+ None,
+ (ext[3],ext[4],ext[2]),
+ (ext[3],ext[4],ext[5]),
+ ybreaks)
+
+ self.axis_data=new_axis_data
+
+ #########################################################################
+ # Versions of the following functions will be required of most or #
+ # all plot classes. #
+ #########################################################################
+
+ def add_data(self,xarr,yarr,zarr,label='',properties=None):
+ """ Add an array to the data to plot """
+ self.array_data.append(gvplot_grid_cartesian(xarr,yarr,zarr))
+ self.array_layer_defaults.append(
+ gvplot_layer_defaults(label,properties,interactive=0))
+ return len(self.array_data)-1
+
+ def set_labels(self,xlabel=None,ylabel=None,zlabel=None,title=None):
+ """ Set labels. """
+ self.label_data['xlabel'][1]=xlabel
+ self.label_data['ylabel'][1]=ylabel
+ self.label_data['zlabel'][1]=zlabel
+ self.label_data['title'][1]=title
+
+ def set_plot_extents(self,pxmin,pxmax,pymin,pymax,pzmin,pzmax):
+ """ Set/Reset the extents covered by this plot in the view.
+ Update labels, axis, data info.
+ """
+
+ oldpxmin=self.pxmin
+ oldpxmax=self.pxmax
+ oldpymin=self.pymin
+ oldpymax=self.pymax
+ oldpzmin=self.pzmin
+ oldpzmax=self.pzmax
+
+ self.pxmin=pxmin
+ self.pxmax=pxmax
+ self.pymin=pymin
+ self.pymax=pymax
+ self.pzmin=pzmin
+ self.pzmax=pzmax
+
+ # Update label positions
+ for ckey in self.label_data.keys():
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.label_data[ckey][0][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.label_data[ckey][0][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.label_data[ckey][0][2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.label_data[ckey][0]=(xnew,ynew,znew)
+
+ # Update axis information
+ for ckey in self.axis_data.keys():
+ for idx in range(len(self.axis_data[key].vtics)):
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].vtics[idx][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].vtics[idx][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].vtics[idx][2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].vtics[idx]=(xnew,ynew,znew)
+
+ for idx in range(len(self.axis_data[key].tics)):
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].tics[idx][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].tics[idx][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].tics[idx][2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].tics[idx]=(xnew,ynew,znew)
+
+ if self.axis_data[ckey].start is not None:
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].start[0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].start[1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].start[2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].start=(xnew,ynew,znew)
+
+ if self.axis_data[ckey].end is not None:
+ xnew=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].end[0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].end[1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].end[2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].end=(xnew,ynew,znew)
+
+ if self.axis_data[ckey].breaks is not None:
+ for idx in range(len(breaks)):
+ xnew1=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].breaks[idx][0][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew1=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].breaks[idx][0][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew1=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].breaks[idx][0][2],
+ GVPLOT_AXISTYPE_LINEAR)
+ xnew2=DataToPlot1D(pxmin,pxmax,oldpxmin,oldpxmax,
+ self.axis_data[ckey].breaks[idx][1][0],
+ GVPLOT_AXISTYPE_LINEAR)
+ ynew2=DataToPlot1D(pymin,pymax,oldpymin,oldpymax,
+ self.axis_data[ckey].breaks[idx][1][1],
+ GVPLOT_AXISTYPE_LINEAR)
+ znew2=DataToPlot1D(pzmin,pzmax,oldpzmin,oldpzmax,
+ self.axis_data[ckey].breaks[idx][1][2],
+ GVPLOT_AXISTYPE_LINEAR)
+ self.axis_data[ckey].breaks[idx]=((xnew1,ynew1,znew1),
+ (xnew2,ynew2,znew2))
+
+ if len(self.xmins) == 0:
+ return
+
+ self.reset_axis()
+
+ def get_extents(self):
+ """ Get data extents: (xmins, xmaxs, ymins, ymaxs, zmins, zmaxs). """
+ return (self.xmins,self.xmaxs,self.ymins,
+ self.ymaxs,self.zmins,self.zmaxs)
+
+ def get_plot_extents(self,include_border=1):
+ """ Get plot extents with (include_border=1) or
+ without (include_border=0) borders.
+ (xmin,ymin,zmin,xmax,ymax,zmax).
+ """
+ if include_border == 1:
+ return (self.pxmin,self.pymin,self.pzmin,self.pxmax,self.pymax,
+ self.pzmax)
+
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.fborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.bkborder
+ dzmin=self.pzmin+(self.pzmax-self.pzmin)*self.bborder
+ dzmax=self.pzmax-(self.pzmax-self.pzmin)*self.tborder
+
+ return (dxmin,dymin,dzmin,dxmax,dymax,dzmax)
+
+
+ def get_xyposition(self,x,y,z):
+ """ Get the data position corresponding to GvViewPlot position x,y,z.
+ x, y and z may be single values or same-size arrays.
+ """
+
+ # Get plot extents minus borders.
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.fborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.bkborder
+ dzmin=self.pzmin+(self.pzmax-self.pzmin)*self.bborder
+ dzmax=self.pzmax-(self.pzmax-self.pzmin)*self.tborder
+
+ arrshp=None
+ if type(x) == type(Numeric.array([])):
+ arrshp=x.shape
+ x=Numeric.ravel(x)
+
+ if type(y) == type(Numeric.array([])):
+ y=Numeric.ravel(y)
+
+ if type(y) == type(Numeric.array([])):
+ z=Numeric.ravel(z)
+
+ x,xok=PlotToData1D(dxmin,dxmax,self.xmins,self.xmaxs,x,self.xaxistype)
+ y,yok=PlotToData1D(dymin,dymax,self.ymins,self.ymaxs,y,self.yaxistype)
+ z,zok=PlotToData1D(dzmin,dzmax,self.zmins,self.zmaxs,z,self.zaxistype)
+
+ okarr=Numeric.where(xok==0,0,yok)
+ okarr=Numeric.where(zok==0,0,okarr)
+
+ if arrshp is not None:
+ x=Numeric.reshape(x,arrshp)
+ y=Numeric.reshape(y,arrshp)
+ z=Numeric.reshape(z,arrshp)
+ okarr=Numeric.reshape(okarr,arrshp)
+
+ return (x,y,z,okarr)
+
+ def get_plotposition(self,x,y,z):
+ """ Get the GvViewPlot position corresponding to data position x,y.
+ x and y may be single values or same-length 1-D arrays.
+ """
+
+ # Get plot extents minus borders.
+
+ dxmin=self.pxmin+(self.pxmax-self.pxmin)*self.lborder
+ dxmax=self.pxmax-(self.pxmax-self.pxmin)*self.rborder
+ dymin=self.pymin+(self.pymax-self.pymin)*self.fborder
+ dymax=self.pymax-(self.pymax-self.pymin)*self.bkborder
+ dzmin=self.pzmin+(self.pzmax-self.pzmin)*self.bborder
+ dzmax=self.pzmax-(self.pzmax-self.pzmin)*self.tborder
+
+ arrshp=None
+ if type(x) == type(Numeric.array([])):
+ arrshp=x.shape
+ x=Numeric.ravel(x)
+
+ if type(y) == type(Numeric.array([])):
+ y=Numeric.ravel(y)
+
+ if type(y) == type(Numeric.array([])):
+ z=Numeric.ravel(z)
+
+ x,xok=DataToPlot1D(dxmin,dxmax,self.xmins,self.xmaxs,x,self.xaxistype)
+ y,yok=DataToPlot1D(dymin,dymax,self.ymins,self.ymaxs,y,self.yaxistype)
+ z,zok=DataToPlot1D(dzmin,dzmax,self.zmins,self.zmaxs,z,self.zaxistype)
+
+ okarr=Numeric.where(xok==0,0,yok)
+ okarr=Numeric.where(zok==0,0,okarr)
+
+ if arrshp is not None:
+ x=Numeric.reshape(x,arrshp)
+ y=Numeric.reshape(y,arrshp)
+ z=Numeric.reshape(z,arrshp)
+ okarr=Numeric.reshape(okarr,arrshp)
+
+
+ return (x,y,z,okarr)
+
+ def set_arraylayer_properties(self,idx,props):
+ """ Set the display properties for the idxth data layer.
+ idx- index of data
+ props- a dictionary of properties to set (keys) and their
+ values.
+
+ An error will be raised if there is no idx'th data array
+ to plot.
+
+ Example properties:
+ _area_fill_color='1.0 0.0 0.0 1.0'
+ _area_edge_color='1.0'
+ _gl_antialias='1' (turn on display antialiasing)
+ """
+ self.array_layer_defaults[idx]=props
+
+ def set_axislayer_properties(self,props):
+ """ Set the display properties of the axis layer
+
+ Example properties:
+ _line_color='1.0 0.0 0.0 1.0'
+ _line_width='1.0'
+ _gl_antialias='1' (turn on display antialiasing)
+
+ """
+ self.axis_layer_properties=props
+
+ def set_label_color(self,color):
+ """ Set label layer color to color. """
+
+ import gvogrfs
+ cstr2=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr2) < 9:
+ cstr2=cstr2+'FF'
+ if self.label_layer_properties.has_key('_gv_ogrfs_point'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ self.label_layer_properties['_gv_ogrfs_point'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ self.label_layer_properties['_gv_ogrfs_point']=ogrfs.unparse()
+
+ def set_axis_color(self,color):
+ """ Set all axis and axis label colours to color.
+ color is a tuple of 4 values, each between
+ 0 and 1, representing red/green/blue/alpha
+ components.
+ """
+ cstr1=str(color[0])+' '+str(color[1])+' '+str(color[2])+\
+ ' '+str(color[3])
+ self.axis_layer_properties['_line_color']=cstr1
+
+ import gvogrfs
+ cstr2=gvogrfs.gv_to_ogr_color(color)
+ if len(cstr2) < 9:
+ cstr2=cstr2+'FF'
+ for caxis in self.axis_data.values():
+ caxis.line_properties['_line_color']=cstr1
+ if caxis.vtics_properties.has_key('_gv_ogrfs'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ caxis.vtics_properties['_gv_ogrfs'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ caxis.vtics_properties['_gv_ogrfs']=ogrfs.unparse()
+
+ if caxis.tics_properties.has_key('_gv_ogrfs'):
+ ogrfs=gvogrfs.OGRFeatureStyle(
+ caxis.tics_properties['_gv_ogrfs'])
+ if ogrfs.has_part('LABEL'):
+ part=ogrfs.get_part('LABEL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('LABEL')
+ ogrfs.add_part(part)
+ if ogrfs.has_part('SYMBOL'):
+ part=ogrfs.get_part('SYMBOL')
+ part.set_parm(gvogrfs.OGRFeatureStyleParam('c:'+cstr2))
+ ogrfs.remove_part('SYMBOL')
+ ogrfs.add_part(part)
+ caxis.tics_properties['_gv_ogrfs']=ogrfs.unparse()
+
+
+ def set_axis_properties(self,key,lprops,vprops,tprops):
+ """ Set the properties of the shapes forming the axis
+ referenced by 'key'. Default keys are 'top, 'bottom',
+ 'left','right'. An error will be raised if the axis
+ dictionary doesn't contain key.
+
+ Parameters:
+ key- key to index axis
+ lprops- line properties (if different from layer default)
+ vprops- vtic properties
+ tprops- tic properties
+
+ Example properties: (defaults for left axis shown here)
+ _gv_ogrfs='LABEL(c:#000000FF,'+\
+ 'f:"-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*",
+ t:{label},a:0.0,s:1.0,dx:-35.0,dy:5.0);'+\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:270.0,s:1.0)'
+
+ Note: the label property is always used to get text
+ in CreateAxisLayer, so the t:{label} portion
+ of this should be left alone.
+ """
+
+ self.axis_data[key].line_properties=lprops
+ self.axis_data[key].vtics_properties=vprops
+ self.axis_data[key].tics_properties=tprops
+
+
+ def set_border_padding(self,top,bottom,left,right,front,back):
+ """ Set border padding as a fraction of the plot
+ extents (0-1).
+ top- top padding
+ bottom- bottom
+ left- left
+ right- right
+ front- front
+ back- back
+ """
+ self.tborder=top
+ self.bborder=bottom
+ self.lborder=left
+ self.rborder=right
+ self.fborder=front
+ self.bkborder=back
+
+ def set_labellayer_properties(self,label_props):
+ """ Set label layer properties:
+ Example:
+ _gv_ogrfs_point='LABEL(c:#000000FF,
+ f:"-adobe-helvetica-medium-r-*-*-15-*-*-*-*-*-*-*",t:{label})'
+
+ Note: the label property is always used to get text
+ in CreateLabelLayer, so the t:{label} portion
+ of this should be left alone.
+ """
+ self.label_layer_properties=label_props
+
+ def add_axis(self,key,properties,start_tuple,end_tuple,breaks=None,
+ type=GVPLOT_AXIS_NOTICS):
+ """ Add an axis (line):
+ key- key to reference the axis
+ properties- axis properties
+ start_tuple- an (x,y) tuple in data coordinates representing
+ the start point of the line.
+ end_tuple- an (x,y) tuple in data coordinates representing
+ the start point of the line.
+ breaks- breaks in the axis/line (defaults to None, must be
+ a list of start/end tuples if present). Also in
+ data coordinates.
+ type- type of axis (0-4: not shown, shown but no tics, shown
+ with major tics but no labels, shown with major tics
+ and labels, shown with major tics and labels and minor
+ tics).
+
+ """
+ pass
+
+
+class gvplot_layer_defaults:
+ def __init__(self,label="",properties=None,interactive=0):
+ """ Store display information for a layer. """
+
+ # default display properties for point/line layers
+ if properties is not None:
+ self.properties=properties
+ else:
+ self.properties={}
+ self.properties['_gl_antialias']='1'
+ self.properties['_line_width']='1'
+ self.properties['_line_color']='1.0 0.0 0.0 1.0'
+ self.properties['_gl_antialias']='1'
+
+ self.label=label
+
+ # interactive: 1 if user should be able to edit
+ # the layer; 0 otherwise.
+ self.interactive=interactive
+
+
+# supporting classes for storing plot class components
+
+class gvplot_array_cartesian:
+ """ Store arrays and related information.
+ Discard nan's and inf's and calculate max/mins
+ for plotting convenience.
+ xarr- array or list of arrays
+ yarr- array or list of arrays
+ zarr- array or list of arrays
+
+ xarr, yarr, zarr must be same size.
+ """
+ def __init__(self,xarr,yarr,zarr=None):
+
+
+ if type(xarr) == type(Numeric.array([1,2])):
+ # Below:
+ # Data points must have x, y, and z (if present)
+ # not equal to nan or inf to be included.
+ # This isn't implemented properly yet though
+ # because of problems on some platforms with nan/inf
+ okarr=Numeric.ones(xarr.shape)
+
+ # nt and irix both don't seem to have a notion
+ # of nan and inf, so leave out the checks for
+ # them...
+ #if os.name != 'nt':
+ # okarr=Numeric.where(xarr == float('inf'),0,okarr)
+ # okarr=Numeric.where(xarr == float('nan'),0,okarr)
+ # okarr=Numeric.where(yarr == float('inf'),0,okarr)
+ # okarr=Numeric.where(yarr == float('nan'),0,okarr)
+
+ # if zarr is not None:
+ # okarr=Numeric.where(zarr == float('inf'),0,okarr)
+ # okarr=Numeric.where(zarr == float('nan'),0,okarr)
+
+ self.xarr=Numeric.compress(okarr==1,xarr)
+ self.yarr=Numeric.compress(okarr==1,yarr)
+
+ if zarr is not None:
+ self.zarr=Numeric.compress(okarr==1,zarr)
+
+ self.xmin=min(self.xarr)
+ self.xmax=max(self.xarr)
+ self.ymin=min(self.yarr)
+ self.ymax=max(self.yarr)
+
+ if zarr is not None:
+ self.zmin=min(self.zarr)
+ self.zmax=max(self.zarr)
+ else:
+ self.zarr=None
+ self.zmin=None
+ self.zmax=None
+ elif type(xarr) == type([1,2]):
+ self.xarr=xarr
+ self.yarr=yarr
+ self.zarr=zarr
+ # If nan/inf problems get sorted out, add checking
+ # code below...
+ self.xmin=min(self.xarr[0])
+ self.xmax=max(self.xarr[0])
+ self.ymin=min(self.yarr[0])
+ self.ymin=max(self.yarr[0])
+ if zarr is not None:
+ self.zmin=min(self.zarr[0])
+ self.zmax=max(self.zarr[0])
+
+ for idx in range(1,len(xarr)):
+ self.xmin=min(min(self.xarr[idx]),self.xmin)
+ self.xmax=max(max(self.xarr[idx]),self.xmax)
+ self.ymin=min(min(self.yarr[idx]),self.ymin)
+ self.ymax=max(max(self.yarr[idx]),self.ymax)
+ if zarr is not None:
+ self.zmin=min(min(self.zarr[idx]),self.zmin)
+ self.zmax=max(max(self.zarr[idx]),self.zmax)
+
+
+
+class gvplot_grid_cartesian:
+ """ Store arrays and related information.
+ Discard nan's and inf's and calculate max/mins
+ for plotting convenience.
+ xarr- 2D array or list of arrays
+ yarr- 2D array or list of arrays
+ zarr- 2D array or list of arrays
+
+ xarr, yarr, zarr must be same size.
+ """
+ def __init__(self,xarr,yarr,zarr=None):
+
+ if type(xarr) == type(Numeric.array([1,2])):
+ self.xarr=xarr
+ self.yarr=yarr
+ self.zarr=zarr
+
+ self.xmin=min(Numeric.ravel(self.xarr))
+ self.xmax=max(Numeric.ravel(self.xarr))
+ self.ymin=min(Numeric.ravel(self.yarr))
+ self.ymax=max(Numeric.ravel(self.yarr))
+
+ if zarr is not None:
+ self.zmin=min(Numeric.ravel(self.zarr))
+ self.zmax=max(Numeric.ravel(self.zarr))
+ else:
+ self.zarr=None
+ self.zmin=None
+ self.zmax=None
+
+ elif type(xarr) == type([1,2]):
+ self.xarr=xarr
+ self.yarr=yarr
+ self.zarr=zarr
+
+ self.xmin=min(Numeric.ravel(self.xarr[0]))
+ self.xmax=max(Numeric.ravel(self.xarr[0]))
+ self.ymin=min(Numeric.ravel(self.yarr[0]))
+ self.ymin=max(Numeric.ravel(self.yarr[0]))
+ if zarr is not None:
+ self.zmin=min(Numeric.ravel(self.zarr[0]))
+ self.zmax=max(Numeric.ravel(self.zarr[0]))
+
+ for idx in range(1,len(xarr)):
+ self.xmin=min(min(Numeric.ravel(self.xarr[idx])),self.xmin)
+ self.xmax=max(max(Numeric.ravel(self.xarr[idx])),self.xmax)
+ self.ymin=min(min(Numeric.ravel(self.yarr[idx])),self.ymin)
+ self.ymax=max(max(Numeric.ravel(self.yarr[idx])),self.ymax)
+ if zarr is not None:
+ self.zmin=min(Numeric.ravel(min(self.zarr[idx])),self.zmin)
+ self.zmax=max(Numeric.ravel(max(self.zarr[idx])),self.zmax)
+
+
+
+class gvplot_axis:
+ """ Axis/line properties. """
+ def __init__(self,displaytype=GVPLOT_AXIS_VTICSLABELS,tics_per_vtic=4):
+ # Display defaults, set before plotting. Can
+ # be overridden through function calls. These
+ # are not erased when data max/mins are reset.
+
+ self.display_type=displaytype # whether or not to show axis, tics, etc.
+ self.tics_per_vtic=tics_per_vtic
+
+ self.vtics_properties={}
+ self.tics_properties={}
+
+ # Tic label/format defaults, except for label text
+ # (determined by plotting functions).
+ self.vtics_properties['_gv_ogrfs']='LABEL(c:#000000FF,'+\
+ 'f:"'+DEFAULT_FONT+'",t:{label},a:0.0,s:1.0,dx:0.0,dy:0.0);'+\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:0.0,s:1.0)'
+ self.tics_properties['_gv_ogrfs']=\
+ 'SYMBOL(c:#000000FF,id:ogr-sym-10,a:0.0,s:0.5)'
+
+ # Axis line properties (color, etc) if different from overall
+ # axis layer default
+ self.line_properties={}
+
+ # Properties calculated by plotting object
+
+ # major tics (bigger, may have values)
+ self.vtics=[] # xyz locations in view coords.
+ self.vtics_labels=[] # text for labels
+ self.vtics_fmt=None # format for labels eg. "%6f"
+
+ # minor tics
+ self.tics=[]
+
+ # start and end points of line in
+ # view area coordinates
+ self.start=None
+ self.end=None
+
+ # discontinuities: each a tuple of 2 values
+ # (start,end) where (0 <start < end < 1),and
+ # breaks[idx][1] < breaks[idx+1][0]. Start
+ # and end correspond to fractions of the distance
+ # along the axis.
+ self.breaks=None
+
+ def set_data(self,vtics,vtics_labels,vtics_fmt,tics,start,end,breaks):
+ """ Set the tic data. """
+ self.vtics=vtics
+ self.vtics_labels=vtics_labels
+ self.vtics_fmt=vtics_fmt
+ self.tics=tics
+ self.start=start
+ self.end=end
+ self.breaks=breaks
+
+
+#######################################################################
+# Layer creation functions #
+#######################################################################
+
+def CreateAxisLayer(plot_data,name=None):
+ """ Create Axis and lines (including tics and axis numbering) """
+
+ if name is None:
+ name=plot_data.plot_label+' '+GVPLOT_AXIS_LAYER
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+ for caxis in plot_data.axis_data.values():
+ if caxis.display_type == GVPLOT_AXIS_NOTSHOWN:
+ continue
+ x0,y0,z0=caxis.start
+ xf,yf,zf=caxis.end
+ if caxis.breaks is None:
+ shp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ shp.set_node(x0,y0,z0,0)
+ shp.set_node(xf,yf,zf,1)
+
+ shapes.append(shp)
+ else:
+ last_x=x0
+ last_y=y0
+ last_z=z0
+ for btuple in caxis.breaks:
+ shp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ shp.set_node(last_x,last_y,last_z,0)
+ shp.set_node(x0 +(btuple[0]*(xf-x0)),
+ yf +(btuple[0]*(yf-y0)),
+ zf +(btuple[0]*(zf-z0)),1)
+ last_x = x0 + btuple[1]*(xf-x0)
+ last_y = y0 + btuple[1]*(yf-y0)
+ last_z = z0 + btuple[1]*(zf-z0)
+ shapes.append(shp)
+
+ if caxis.display_type == GVPLOT_AXIS_NOTICS:
+ continue
+
+ for idx in range(len(caxis.vtics)):
+ shp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ shp.set_node(caxis.vtics[idx][0],caxis.vtics[idx][1])
+ if caxis.display_type != GVPLOT_AXIS_VTICS:
+ shp.set_property('label',
+ caxis.vtics_fmt % caxis.vtics_labels[idx])
+ for ckey in caxis.vtics_properties.keys():
+ shp.set_property(ckey,
+ caxis.vtics_properties[ckey])
+ shapes.append(shp)
+
+ if caxis.display_type != GVPLOT_AXIS_VTICSLABELSTICS:
+ continue
+
+ for idx in range(len(caxis.tics)):
+ shp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ shp.set_node(caxis.tics[idx][0],caxis.tics[idx][1])
+ for ckey in caxis.tics_properties.keys():
+ shp.set_property(ckey,
+ caxis.tics_properties[ckey])
+ shapes.append(shp)
+
+ if len(shapes) == 0:
+ return None
+
+ for ckey in plot_data.axis_layer_properties.keys():
+ layer.set_property(ckey,plot_data.axis_layer_properties[ckey])
+
+ return layer
+
+
+def Create2DBorderLayer(plot_data,name=None):
+ """ Create the plot background. """
+
+ if ((plot_data.show_inner_border == 0) and
+ (plot_data.show_outer_border == 0)):
+ return None
+
+ if name is None:
+ name=plot_data.plot_label+' '+GVPLOT_BORDER_LAYER
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+ inner=plot_data.get_plot_extents(include_border=0)
+ outer=plot_data.get_plot_extents(include_border=1)
+
+ # shapes: outer rings clockwise; inner rings
+ # counterclockwise.
+ if plot_data.show_outer_border == 1:
+ nshp=gview.GvShape(type=gview.GVSHAPE_AREA)
+ nshp.set_node(outer[0],outer[3],0.0,0,0)
+ nshp.set_node(outer[2],outer[3],0.0,1,0)
+ nshp.set_node(outer[2],outer[1],0.0,2,0)
+ nshp.set_node(outer[0],outer[1],0.0,3,0)
+ nshp.set_node(outer[0],outer[3],0.0,4,0)
+ nshp.set_node(inner[0],inner[3],0.0,0,1)
+ nshp.set_node(inner[0],inner[1],0.0,1,1)
+ nshp.set_node(inner[2],inner[1],0.0,2,1)
+ nshp.set_node(inner[2],inner[3],0.0,3,1)
+ nshp.set_node(inner[0],inner[3],0.0,4,1)
+ for cprop in plot_data.outer_border_props.keys():
+ nshp.set_property(cprop,
+ plot_data.outer_border_props[cprop])
+ shapes.append(nshp)
+
+ if plot_data.show_inner_border == 1:
+ nshp=gview.GvShape(type=gview.GVSHAPE_AREA)
+ nshp.set_node(inner[0],inner[3],0.0,0,0)
+ nshp.set_node(inner[2],inner[3],0.0,1,0)
+ nshp.set_node(inner[2],inner[1],0.0,2,0)
+ nshp.set_node(inner[0],inner[1],0.0,3,0)
+ nshp.set_node(inner[0],inner[3],0.0,4,0)
+ for cprop in plot_data.inner_border_props.keys():
+ nshp.set_property(cprop,
+ plot_data.inner_border_props[cprop])
+ shapes.append(nshp)
+
+ return layer
+
+def CreateLabelLayer(plot_data,name=None):
+ """ Create annotation (label) layer. """
+
+ if name is None:
+ name=plot_data.plot_label+' '+GVPLOT_LABEL_LAYER
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+ for item in plot_data.label_data.values():
+ if item[1] is None:
+ continue
+
+ shp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ shp.set_node(item[0][0],item[0][1],item[0][2])
+ shp.set_property('label',item[1])
+ shapes.append(shp)
+
+ if len(shapes) == 0:
+ return None
+
+ for prop in plot_data.label_layer_properties.keys():
+ layer.set_property(prop,
+ plot_data.label_layer_properties[prop])
+
+ return layer
+
+
+def Create2DLegendLayer(plot_data,name=None):
+ """ Create a legend layer. """
+
+ if plot_data.show_legend == 0:
+ return None
+
+ if name is None:
+ name=plot_data.plot_label+' '+GVPLOT_LEGEND_LAYER
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+ ext=plot_data.get_plot_extents(include_border=1)
+
+ xrng=ext[3]-ext[0]
+ yrng=ext[4]-ext[1]
+ x0 = plot_data.legend_location[0]*xrng+ext[0]
+ y0 = plot_data.legend_location[1]*yrng+ext[1]
+
+ idx=0
+ for item in plot_data.array_layer_defaults:
+ try:
+ color=item.properties['_line_color']
+ except:
+ continue
+
+ tmp=string.split(color)
+ rgba=[]
+ for tmp2 in tmp:
+ rgba.append(float(tmp2))
+
+ cstr=gvogrfs.gv_to_ogr_color(rgba)
+
+ if (item.label is not None) and (len(item.label) > 0):
+ dshp=gview.GvShape(type=gview.GVSHAPE_POINT)
+ dshp.set_node(x0,y0)
+ dshp.set_property('_gv_ogrfs','LABEL(c:'+cstr+\
+ ',t:"'+item.label+'",f:"'+DEFAULT_FONT+'")')
+ shapes.append(dshp)
+
+
+ y0=y0-0.1*yrng
+ idx=idx+1
+
+ return layer
+
+def CreateGridArrayDataLayer(plot_data,index,name=None):
+ """ Create a 3D grid data layer.
+ plot_data- plot object (eg. gvplot_grid_cartesian)
+ index- index to array to plot
+ name- layer name (if set to None, the layer name
+ will be 'Data: '+plot_data.array_layer_defaults.label)
+ """
+
+ if index > len(plot_data.array_data)-1:
+ raise RuntimeError,'Create Data Layer: invalid data index!'
+
+ if name is None:
+ if plot_data.array_layer_defaults[index].label is not None:
+ name=plot_data.plot_label+GVPLOT_DATA_LAYER+' '+\
+ plot_data.array_layer_defaults[index].label
+ else:
+ name=plot_data.plot_label+GVPLOT_DATA_LAYER+' '+str(index)
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+
+ if type(plot_data.array_data[index].xarr) == type([]):
+ xinlist=plot_data.array_data[index].xarr
+ yinlist=plot_data.array_data[index].yarr
+ zinlist=plot_data.array_data[index].zarr
+ else:
+ xinlist=[plot_data.array_data[index].xarr]
+ yinlist=[plot_data.array_data[index].yarr]
+ zinlist=[plot_data.array_data[index].zarr]
+
+ ext=plot_data.get_plot_extents(include_border=0)
+ okinlist=[]
+
+ for idx in range(len(xinlist)):
+ xarr,xok=DataToPlot1D(ext[0],ext[3],
+ plot_data.xmins,plot_data.xmaxs,
+ xinlist[idx],
+ plot_data.xaxistype)
+
+ yarr,yok=DataToPlot1D(ext[1],ext[4],
+ plot_data.ymins,plot_data.ymaxs,
+ yinlist[idx],
+ plot_data.yaxistype)
+
+ okarr=Numeric.where(yok == 0,0,xok)
+
+ zarr,zok=DataToPlot1D(ext[2],ext[5],
+ plot_data.zmins,plot_data.zmaxs,
+ zinlist[idx],
+ plot_data.zaxistype)
+ okarr=Numeric.where(zok == 0,0,okarr)
+
+ for idx in range(xarr.shape[0]-1):
+ for idx2 in range(xarr.shape[1]-1):
+ if (okarr[idx,idx2]+okarr[idx,idx2+1]+okarr[idx+1,idx2]+
+ okarr[idx+1,idx2+1] == 4):
+ ashp=gview.GvShape(type=gview.GVSHAPE_AREA)
+ ashp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ zarr[idx,idx2])
+ ashp.add_node(xarr[idx+1,idx2],yarr[idx+1,idx2],
+ zarr[idx+1,idx2])
+ ashp.add_node(xarr[idx+1,idx2+1],yarr[idx+1,idx2+1],
+ zarr[idx+1,idx2+1])
+ ashp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ zarr[idx,idx2])
+ shapes.append(ashp)
+ ashp=gview.GvShape(type=gview.GVSHAPE_AREA)
+ ashp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ zarr[idx,idx2])
+ ashp.add_node(xarr[idx,idx2+1],yarr[idx,idx2+1],
+ zarr[idx,idx2+1])
+ ashp.add_node(xarr[idx+1,idx2+1],yarr[idx+1,idx2+1],
+ zarr[idx+1,idx2+1])
+ ashp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ zarr[idx,idx2])
+ shapes.append(ashp)
+ #lshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ #lshp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ # zarr[idx,idx2])
+ #lshp.add_node(xarr[idx+1,idx2],yarr[idx+1,idx2],
+ # zarr[idx+1,idx2])
+ #lshp.add_node(xarr[idx+1,idx2+1],yarr[idx+1,idx2+1],
+ # zarr[idx+1,idx2+1])
+ #lshp.add_node(xarr[idx,idx2+1],yarr[idx,idx2+1],
+ # zarr[idx,idx2+1])
+ #lshp.add_node(xarr[idx,idx2],yarr[idx,idx2],
+ # zarr[idx,idx2])
+ #shapes.append(lshp)
+
+ for ckey in plot_data.array_layer_defaults[index].properties.keys():
+ layer.set_property(ckey,
+ plot_data.array_layer_defaults[index].properties[ckey])
+
+ return layer
+
+
+def CreateArrayDataLayer(plot_data,index,name=None):
+ """ Create a data layer.
+ plot_data- plot object (eg. gvplot_2Ddata_cartesian)
+ index- index to array to plot
+ name- layer name (if set to None, the layer name
+ will be 'Data: '+plot_data.array_layer_defaults.label)
+ """
+
+ if index > len(plot_data.array_data)-1:
+ raise RuntimeError,'Create Data Layer: invalid data index!'
+
+ if name is None:
+ if plot_data.array_layer_defaults[index].label is not None:
+ name=plot_data.plot_label+GVPLOT_DATA_LAYER+' '+\
+ plot_data.array_layer_defaults[index].label
+ else:
+ name=plot_data.plot_label+GVPLOT_DATA_LAYER+' '+str(index)
+
+ shapes=gview.GvShapes(name=name)
+ layer=gview.GvShapesLayer(shapes=shapes)
+
+ ext=plot_data.get_plot_extents(include_border=0)
+ okinlist=[]
+
+ if type(plot_data.array_data[index].xarr) == type([]):
+ xinlist=plot_data.array_data[index].xarr
+ yinlist=plot_data.array_data[index].yarr
+ if plot_data.array_data[index].zarr is not None:
+ zinlist=plot_data.array_data[index].zarr
+ else:
+ xinlist=[plot_data.array_data[index].xarr]
+ yinlist=[plot_data.array_data[index].yarr]
+ if plot_data.array_data[index].zarr is not None:
+ zinlist=[plot_data.array_data[index].zarr]
+
+ for idx in range(len(xinlist)):
+ xarr,xok=DataToPlot1D(ext[0],ext[3],
+ plot_data.xmins,plot_data.xmaxs,
+ xinlist[idx],
+ plot_data.xaxistype)
+
+ yarr,yok=DataToPlot1D(ext[1],ext[4],
+ plot_data.ymins,plot_data.ymaxs,
+ yinlist[idx],
+ plot_data.yaxistype)
+
+ okarr=Numeric.where(yok == 0,0,xok)
+
+ if plot_data.array_data[index].zarr is not None:
+ zarr,zok=DataToPlot1D(ext[2],ext[5],
+ plot_data.zmins,plot_data.zmaxs,
+ zinlist[idx],
+ plot_data.zaxistype)
+ okarr=Numeric.where(zok == 0,0,okarr)
+ else:
+ zarr=Numeric.zeros(Numeric.shape(xarr),Numeric.Float64)
+
+ # NOTE: taking the for-loop down to the c-level didn't
+ # speed up the plot time. The render time seems
+ # to be the limiting factor.
+ newshps=gview.gv_shapes_lines_for_vecplot(xarr,yarr,zarr,okarr)
+ for idx in range(len(newshps)):
+ shapes.append(newshps[idx].copy())
+
+ #lshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ #last_valid=0
+ #for idx2 in range(len(xarr)):
+ # if okarr[idx2] == 1:
+ # lshp.add_node(xarr[idx2],yarr[idx2],zarr[idx2],0)
+ # last_valid=1
+ # else:
+ # if last_valid == 1:
+ # shapes.append(lshp)
+ # lshp=gview.GvShape(type=gview.GVSHAPE_LINE)
+ # last_valid=0
+
+ #if last_valid == 1:
+ # shapes.append(lshp)
+
+ for ckey in plot_data.array_layer_defaults[index].properties.keys():
+ layer.set_property(ckey,
+ plot_data.array_layer_defaults[index].properties[ckey])
+
+ return layer
+
+
+# PLOT class (GvPlot)- stores one or more plots
+class GvSimplePlot(gview.GvViewArea):
+ """ View area wrapper designed for plotting.
+ NOTE: window containing GvSimplePlot view area must
+ have its show_all function called for the first time
+ ATER the GvSimplePlot widget is inserted, but
+ BEFORE plot is called. If these two conditions
+ don't hold, then the configure event that
+ sets up the plot area's internal c-level
+ size parameters sets them to invalid values,
+ and the plot extents will be set incorrectly
+ (plot will be a teeny blob in the center).
+ Calling show_all before and after the widget
+ is inserted also will not work (the second
+ call doesn't seem to do anything).
+ """
+ def __init__(self, _obj=None, bgcolor=(1.0,1.0,1.0,1.0)):
+ gview.GvViewArea.__init__(self,_obj)
+ self.set_background_color(bgcolor)
+ self.set_border_padding()
+ self.bgcolor=bgcolor
+ self.mode='2D'
+
+ # plot information
+ self.plots=[]
+
+
+ def set_border_padding(self,top=DEFAULT_EDGE_PADDING,
+ bottom=DEFAULT_EDGE_PADDING,
+ left=DEFAULT_EDGE_PADDING,
+ right=DEFAULT_EDGE_PADDING):
+ """ Set border padding for plot as a fraction of view
+ area (top,bottom,left, right).
+ """
+ self.tborder=top
+ self.bborder=bottom
+ self.lborder=left
+ self.rborder=right
+
+ def oplot(self, yarr=None, xarr=None, xmin=None,xmax=None,xspc=None,
+ ymin=None, ymax=None, yspc=None,datalabel=None,
+ color=(0.0,0.0,1.0,1.0),drawstyle='_', reset_extents=1,
+ with_legend=0,interactive=0):
+ """ Plot overtop of an existing simple 2-D plot """
+
+ if yarr is None:
+ print 'Usage: oplot(yarr,[,xarr][,xmin=n][,xmax=n][,xspc=n]'
+ print ' [,ymin=n][,ymax=n][yspc=n][,datalabel=text]'
+ print ' [,color=4-tuple][,drawstyle=text]'
+ print ' [,reset_extents=0 or 1][,with_legend=0 or 1])'
+ print ''
+ print ' yarr -- 1-D array of y values to plot'
+ print ' xarr -- x values (optional): if present, must be same'
+ print ' length as yarr.'
+ print ' xmin -- minimum x (may be rounded for nice labels)'
+ print ' xmax -- maximum x (may be rounded for nice labels)'
+ print ' xspc -- # x tics (may be rounded for nice labels)'
+ print ' ymin -- minimum y (may be rounded for nice labels)'
+ print ' ymax -- maximum y (may be rounded for nice labels)'
+ print ' yspc -- # ytics (may be rounded for nice labels)'
+ print ' datalabel -- data label: add a legend (label datalabel) '
+ print ' color -- a tuple of rgba values, each ranging from '
+ print ' 0.0-1.0 (color to draw data line).'
+ print " drawstyle -- linestyle. Currently only '_' is supported. "
+ print ' reset_extents -- reset extents (1) or leave extents as '
+ print ' they are (0). xmin/xmax/ymin/ymax will'
+ print ' be ignored if this is 0.'
+ print ' with_legend -- 1 to add a legend, 0 otherwise. Do not '
+ print ' add until all datasets have been put on.'
+ print ' interactive -- 0 if data in plot is not user-editable;'
+ print ' 1 if it is. Defaults to 0.'
+ print ''
+ return
+
+ if len(self.plots) == 0:
+ raise RuntimeError,'No plot to plot over.'
+
+ try:
+ dshape = Numeric.shape( yarr )
+ except:
+ raise ValueError,"data argument to plot() does not appear to be "+\
+ "a NumPy array"
+
+ dim = len(dshape)
+
+ if dim == 2 and (dshape[0] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[1],))
+ elif dim == 2 and (dshape[1] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[0],))
+ elif dim != 1:
+ raise ValueError,\
+ "data argument dimension or shape is not supported."
+
+ if xarr is None:
+ xarr=Numeric.array(range(len(yarr)))
+
+ cstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+\
+ ' '+str(color[3])
+ props={}
+ props['_line_color']=cstr
+ props['_gl_antialias']='1'
+ idx=self.plots[0].add_data(xarr,yarr,datalabel,props,interactive)
+ if with_legend == 1:
+ self.plots[0].set_legend()
+ if reset_extents == 1:
+ self.plots[0].set_extents(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax,
+ xspc=xspc,yspc=yspc)
+ self.clear_layers()
+ ll=self.plots[0].create_layers()
+ for item in ll:
+ self.add_layer(item)
+ else:
+ self.plots[0].create_layer(ltype=GVPLOT_DATA_LAYER,idx=idx)
+ # Clear the layers from the view then re-add them so that
+ # they are in the right order.
+ self.clear_layers()
+ ll=self.plots[0].get_layers()
+ for item in ll:
+ self.add_layer(item)
+
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.fit_extents(0.0,0.0,1.0,ysize/xsize)
+
+ def plot(self,yarr=None,xarr=None, xlabel=None, ylabel=None, xmin=None,
+ xmax=None,xspc=None,ymin=None, ymax=None, yspc=None,
+ title=None,datalabel=None,
+ color=(1.0,0.0,0.0,1.0),drawstyle='_',interactive=0):
+ """ Simple 2-D plot """
+
+ if yarr is None:
+ print 'Usage: plot(yarr,[,xarr][, xlabel=text] [,ylabel=text]'
+ print ' [,xmin=n][, xmax=n][, xspc=n][, ymin=n]'
+ print ' [, ymax=n][, yspc=n]'
+ print ' [title=text] [datalabel=text]'
+ print ''
+ print ' yarr -- 1-D array of values to plot'
+ print ' xarr -- x values (optional): if present, must be same'
+ print ' length as yarr.'
+ print ' xlabel -- text for x label '
+ print ' xmin -- minimum x (may be rounded for nice labels)'
+ print ' xmax -- maximum x (may be rounded for nice labels)'
+ print ' xspc -- x spacing (if not present, default will be used)'
+ print ' ylabel -- text for y label '
+ print ' ymin -- minimum y (may be rounded for nice labels)'
+ print ' ymax -- maximum y (may be rounded for nice labels)'
+ print ' yspc -- y spacing (if not present, default will be used)'
+ print ' title -- title text'
+ print ' datalabel -- data label: add a legend (label datalabel) '
+ print ' color -- a tuple of rgba values, each ranging from '
+ print ' 0.0-1.0 (color to draw data line).'
+ print " drawstyle -- linestyle. Currently only '_' is supported. "
+ print ' interactive -- 0 if data in plot is not user-editable;'
+ print ' 1 if it is. Defaults to 0.'
+ print ''
+ return
+
+ try:
+ dshape = Numeric.shape( yarr )
+ except:
+ raise ValueError,"data argument to plot() does not appear to be "+\
+ "a NumPy array"
+
+ dim = len(dshape)
+
+ if dim == 2 and (dshape[0] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[1],))
+ elif dim == 2 and (dshape[1] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[0],))
+ elif dim != 1:
+ raise ValueError,\
+ "data argument dimension or shape is not supported."
+
+ if xarr is None:
+ xarr=Numeric.array(range(len(yarr)))
+
+ self.clear()
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.plots.append(gvplot_2Ddata_cartesian('1: ',0.0,0.0,1.0,
+ ysize/xsize))
+ self.plots[0].set_border_padding(self.tborder,self.bborder,
+ self.lborder,self.rborder)
+ cstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+\
+ ' '+str(color[3])
+ props={}
+ props['_line_color']=cstr
+ props['_gl_antialias']='1'
+ self.plots[0].add_data(xarr,yarr,datalabel,props,interactive)
+ self.plots[0].set_extents(xmin=xmin,xmax=xmax,ymin=ymin,
+ ymax=ymax,xspc=xspc,yspc=yspc)
+
+ self.plots[0].set_labels(xlabel,ylabel,title)
+
+ if self.bgcolor == (0.0,0.0,0.0,1.0):
+ self.plots[0].set_axis_color((1.0,1.0,1.0,1.0))
+ self.plots[0].set_label_color((1.0,1.0,1.0,1.0))
+
+ ll=self.plots[0].create_layers()
+ for item in ll:
+ self.add_layer(item)
+
+ self.fit_extents(0.0,0.0,1.0,ysize/xsize)
+
+ def seeall(self):
+ """ Set extents so that whole plot is shown in view. """
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.fit_extents(0.0,0.0,1.0,ysize/xsize)
+
+ def plot3D(self,xarr,yarr,zarr):
+ """ Simple 3-D plot """
+ self.set_mode(gview.MODE_3D)
+
+ props={}
+ props['_area_edge_color']='0.0 0.0 0.0 1.0'
+ props['_area_fill_color']='0.0 0.0 1.0 1.0'
+ #props['_line_color']='0.0 0.0 0.0 1.0'
+ props['_gl_antialias']='1'
+
+ self.clear()
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.plots.append(gvplot_3Ddata_cartesiangrid('1: ',0.0,0.0,0.0,
+ 1.0,1.0,ysize/xsize))
+ self.plots[0].add_data(xarr,yarr,zarr,'',props)
+ self.plots[0].set_extents()
+ #self.plots[0].set_labels(xlabel,ylabel,title)
+
+ self.plots[0].set_axis_color((0.0,0.0,0.0,1.0))
+ self.plots[0].set_label_color((0.0,0.0,0.0,1.0))
+
+ ll=self.plots[0].create_layers()
+ for item in ll:
+ self.add_layer(item)
+
+ self.set_3d_view_look_at((1.2,-0.3,0.5),(-10.0,20.0))
+
+ def set_plot(self,plot):
+ """ Function to allow user to set plot class directly """
+ self.clear()
+ self.plots=[]
+ self.plots.append(plot)
+
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.plot.set_plot_extents(0.0,0.0,1.0,ysize/xsize)
+
+ ll=self.plots[0].create_layers()
+ for item in ll:
+ self.add_layer(item)
+
+
+ def begin_plot(self,xlabel=None,ylabel=None,title=None):
+ """ Begin constructing a plot (use to construct a plot
+ without displaying at each iteration).
+ """
+
+ self.clear()
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.plots.append(gvplot_2Ddata_cartesian('1: ',0.0,0.0,1.0,
+ ysize/xsize))
+ self.plots[0].set_border_padding(self.tborder,self.bborder,
+ self.lborder,self.rborder)
+
+ self.plots[0].set_labels(xlabel,ylabel,title)
+
+ if self.bgcolor == (0.0,0.0,0.0,1.0):
+ self.plots[0].set_axis_color((1.0,1.0,1.0,1.0))
+ self.plots[0].set_label_color((1.0,1.0,1.0,1.0))
+
+ def shift_label(self,label_key,xytuple,plot_idx=0):
+ """ Shift label referenced by label_key by the
+ amounts in xytuple for the plot_idxth plot.
+ label_key- eg. 'xlabel','ylabel','title'
+ xytuple- (x,y), where x and y are fractions
+ of the plot extents
+ plot_idx- plot index of plot whose labels are
+ to be adjusted.
+ """
+ ext=self.plots[plot_idx].get_plot_extents(include_border=1)
+ xrng=ext[3]-ext[0]
+ yrng=ext[4]-ext[1]
+ xold=self.plots[plot_idx].label_data[label_key][0][0]
+ yold=self.plots[plot_idx].label_data[label_key][0][1]
+
+ self.plots[plot_idx].label_data[label_key][0]=(xold+xytuple[0]*xrng,
+ yold+xytuple[1]*yrng,
+ 0)
+
+ def add_data(self, xarr=None, yarr=None,datalabel=None,
+ color=(0.0,0.0,1.0,1.0),drawstyle='_', interactive=0):
+
+ try:
+ dshape = Numeric.shape( xarr )
+ dshape = Numeric.shape( yarr )
+ except:
+ raise ValueError,"data argument to plot() does not appear to be "+\
+ "a NumPy array"
+
+ dim = len(dshape)
+
+ if dim == 2 and (dshape[0] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[1],))
+ elif dim == 2 and (dshape[1] == 1):
+ yarr=Numeric.reshape(yarr,(dshape[0],))
+ elif dim != 1:
+ raise ValueError,\
+ "data argument dimension or shape is not supported."
+
+ if xarr is None:
+ xarr=Numeric.array(range(len(yarr)))
+
+ cstr=str(color[0])+' '+str(color[1])+' '+str(color[2])+\
+ ' '+str(color[3])
+ props={}
+ props['_line_color']=cstr
+ props['_gl_antialias']='1'
+ self.plots[0].add_data(xarr,yarr,datalabel,props,interactive)
+
+
+ def end_plot(self,xmin=None,xmax=None,ymin=None,ymax=None,
+ xtics=None,ytics=None,with_legend=0):
+
+ self.plots[0].set_extents(xmin=xmin,xmax=xmax,ymin=ymin,
+ ymax=ymax)
+ xspc=None
+ yspc=None
+ if xtics is not None:
+ # Currently this will only work for continuous
+ # plots.
+ xmin=self.plots[0].xmins[0]
+ xmax=self.plots[0].xmaxs[len(self.plots[0].xmaxs)-1]
+ xspc=(xmax-xmin)/(xtics-1)
+ rord=Numeric.log10(abs(xspc))
+ nrord=rord % 1
+ spc=pow(10,Numeric.floor(rord))
+ min_diff=abs(xspc-spc)
+ for i in [1,2,5]:
+ nspc=i*pow(10,Numeric.floor(rord))
+ if abs(nspc-spc) < min_diff:
+ min_diff=abs(xspc-nspc)
+ spc=nspc
+ xspc=spc
+
+ if ytics is not None:
+ # Currently this will only work for continuous
+ # plots.
+ ymin=self.plots[0].ymins[0]
+ ymax=self.plots[0].ymaxs[len(self.plots[0].ymaxs)-1]
+ yspc=(ymax-ymin)/(ytics-1)
+ rord=Numeric.log10(abs(yspc))
+ nrord=rord % 1
+ spc=pow(10,Numeric.floor(rord))
+ min_diff=abs(yspc-spc)
+ for i in [1,2,5]:
+ nspc=i*pow(10,Numeric.floor(rord))
+ if abs(nspc-spc) < min_diff:
+ min_diff=abs(yspc-nspc)
+ spc=nspc
+ yspc=spc
+
+ self.plots[0].set_extents(xmin=xmin,xmax=xmax,ymin=ymin,
+ ymax=ymax,xspc=xspc,yspc=yspc)
+
+ if with_legend == 1:
+ self.plots[0].set_legend()
+
+ ll=self.plots[0].create_layers()
+ for item in ll:
+ self.add_layer(item)
+
+ xsize=float(self.get_width())
+ ysize=float(self.get_height())
+ self.fit_extents(0.0,0.0,1.0,ysize/xsize)
+
+ def get_xy_position(self,x,y,plotidx=0):
+ """ Get the data position corresponding to GvViewPlot position x,y
+ for the plot with index plotidx.
+ Input:
+ x- x value(s)
+ y- y value(s)
+ plotidx- index of plot to use in conversion, if more than
+ one plot is present in the view area.
+
+ x and y may be single values or same-length 1-D arrays.
+
+ Output:
+ x- data x position
+ y- data y position
+ okarr- array indicating where the conversion is valid
+ (ie. within plot bounds)
+ """
+ x,y,okarr=self.plots[plotidx].get_xyposition(x,y)
+
+ return (x,y,okarr)
+
+ def get_plotposition(self,x,y,plotidx=0):
+ """ Get the GvViewPlot position corresponding to data position x,y
+ for plot plotidx.
+
+ Input:
+ x- x value(s)
+ y- y value(s)
+ plotidx- index of plot to use in conversion, if more than
+ one plot is present in the view area.
+
+ x and y may be single values or same-length 1-D arrays.
+
+ Output:
+ x- plot x position
+ y- plot y position
+ okarr- array indicating where the conversion is valid
+ (ie. within plot bounds)
+ """
+ x,y,okarr=self.plots[plotidx].get_plotposition(x,y)
+
+ return (x,y,okarr)
+
+ def clear_layers(self):
+ """ Remove all layers. """
+
+ for clayer in self.list_layers():
+ self.remove_layer(clayer)
+
+ def clear(self):
+ """ Clear all layers AND plot information. """
+
+ for clayer in self.list_layers():
+ self.remove_layer(clayer)
+
+ self.plots=[]
+
+
+class GvSimplePlotWindow(gtk.GtkWindow):
+
+ def __init__(self,bgcolor=(1.0,1.0,1.0,1.0)):
+ gtk.GtkWindow.__init__(self)
+ self.plotarea=GvSimplePlot(bgcolor=bgcolor)
+ #self.plotarea.fit_extents(0.0,0.0,1.0,0.84)
+ self.set_policy(gtk.TRUE,gtk.TRUE,gtk.TRUE)
+ shell = gtk.GtkVBox(spacing=0)
+ self.add(shell)
+ self.set_usize(650,545)
+
+ # Print menu
+ menuf = GtkExtra.MenuFactory()
+ self.menuf = menuf
+ menuf.add_entries([
+ ('File/Print', None, self.print_cb)])
+
+ shell.pack_start(menuf, expand=gtk.FALSE)
+
+ shell.pack_start( self.plotarea )
+
+ self.show_all()
+
+ #self.viewarea.fit_extents(0, self.ysize, self.xsize, -self.ysize )
+
+ def print_cb(self, *args):
+ import gvprint
+ pd = gvprint.GvPrintDialog( self.plotarea )
+
+ def plot(self,yarr=None,xarr=None, xlabel=None, ylabel=None, xmin=None,
+ xmax=None,ymin=None, ymax=None, xspc=None,yspc=None,
+ title=None,datalabel=None,
+ color=(1.0,0.0,0.0,1.0),drawstyle='_'):
+ self.plotarea.plot(yarr,xarr,xlabel,ylabel,xmin,xmax,xspc,
+ ymin,ymax,yspc,title,
+ datalabel,color,drawstyle)
+
+ def oplot(self,yarr=None,xarr=None, xmin=None,
+ xmax=None, xspc=None,ymin=None, ymax=None,
+ yspc=None, datalabel=None,
+ color=(1.0,0.0,0.0,1.0),drawstyle='_',reset_extents=1,
+ with_legend=0):
+ self.plotarea.oplot(yarr,xarr,xmin,xmax,xspc,ymin,ymax,yspc,
+ datalabel,color,drawstyle,reset_extents,with_legend)
+
+def DataToPlot1D(pmin,pmax,dmins,dmaxs,dpos,axistype=GVPLOT_AXISTYPE_LINEAR):
+ """ Transform from data to plot coordinates.
+ Input:
+ pmin- plot minimum position not including borders (single value)
+ pmax- plot maximum position not including borders (single value)
+ dmins- data range minima (a list or tuple of at least length 1)
+ dmaxs- data range maxima (a list or tuple of length(dmins))
+ dpos- data positions to transform
+ (single value or 1-D array)
+ axistype- type of axis (eg. linear or log).
+
+ The dmin-dmax ranges must not be overlapping.
+
+ Output:
+ ppos- plot position (float or array)
+ okarr- integer or array of integers indicating where data
+ is within the plot bounds (1's) or invalid (0's)
+ """
+ if axistype not in [GVPLOT_AXISTYPE_LINEAR,GVPLOT_AXISTYPE_LOG]:
+ raise RuntimeError,'DataToPlot1D: unknown axis type!'
+
+ ptype=type(dpos)
+ if ptype != type(Numeric.array([])):
+ dpos=Numeric.array(dpos,Numeric.Float64)
+
+ # First check for length 1 case and do quick
+ # transform and return if it is; otherwise, continue.
+
+ if len(dmins) == 1:
+ # Only one continuous range
+ if axistype == GVPLOT_AXISTYPE_LINEAR:
+ ppos=((float(pmax)-float(pmin))/
+ (float(dmaxs[0])-float(dmins[0])))*\
+ (dpos-float(dmins[0]))+float(pmin)
+
+ okarr=Numeric.where(ppos >= pmin,1,0)
+ okarr=Numeric.where(ppos <= pmax,okarr,0)
+
+ elif axistype == GVPLOT_AXISTYPE_LOG:
+ # Make sure logs don't choke
+ okarr=Numeric.where(dpos > 0,1,0)
+ dpos=Numeric.where(okarr == 0,1,dpos)
+
+ ppos=(((float(pmax)-float(pmin))/float(Numeric.log10(dmaxs[0])-
+ Numeric.log10(dmins[0])))*\
+ (Numeric.log10(dpos)-Numeric.log10(dmins[0])))+pmin
+ okarr=Numeric.where(ppos >= pmin,okarr,0)
+ okarr=Numeric.where(ppos <= pmax,okarr,0)
+
+ if ptype not in [type(Numeric.array([])),type((1,)),type([])]:
+ okarr=okarr[0]
+
+ return (ppos,okarr)
+
+ dmaxs=Numeric.array(dmaxs,Numeric.Float64)
+ dmins=Numeric.array(dmins,Numeric.Float64)
+
+ if axistype == GVPLOT_AXISTYPE_LINEAR:
+ dwidtharr=Numeric.ravel(dmaxs-dmins)
+ dwidth=Numeric.sum(dwidtharr)
+ dcsum=Numeric.cumsum(dwidtharr)
+ drng=Numeric.array(list(dcsum/dwidth).insert(0,0.0))
+ prng=pmin+(drng*(pmax-pmin)) # plot range endpoints
+
+ ppos=Numeric.zeros((len(dpos),),Numeric.Float64)
+ okarr=Numeric.zeros((len(dpos),),Numeric.Float64)
+
+ for idx in range(len(dmins)):
+ sc=Numeric.where(dpos >= dmins[idx],1,0)
+ sc=Numeric.where(dpos <= dmaxs[idx],1,sc)
+ okarr=Numeric.where(sc == 1,1,okarr)
+ sc=sc.astype(Numeric.Float64)
+
+ ppos=ppos+(sc*(prng[idx]+((prng[idx+1]-prng[idx])*
+ (dpos-dmins[idx])/(dmaxs[idx+1]-dmins[idx]))))
+
+ elif axistype == GVPLOT_AXISTYPE_LOG:
+ dmaxs=Numeric.log10(dmaxs)
+ dmins=Numeric.log10(dmins)
+
+ # Make sure logs don't choke
+ okarrmask=Numeric.where(dpos > 0,1,0)
+ dpos=Numeric.where(okarrmask == 0,1,dpos)
+
+ dpos=Numeric.log10(dpos)
+
+ dwidtharr=Numeric.ravel(dmaxs-dmins)
+ dwidth=Numeric.sum(dwidtharr)
+ dcsum=Numeric.cumsum(dwidtharr)
+ drng=Numeric.array(list(dcsum/dwidth).insert(0,0.0))
+ prng=pmin+(drng*(pmax-pmin)) # plot range endpoints
+
+ ppos=Numeric.zeros((len(dpos),),Numeric.Float64)
+ okarr=Numeric.zeros((len(dpos),),Numeric.Float64)
+
+ for idx in range(len(dmins)):
+ sc=Numeric.where(dpos >= dmins[idx],1,0)
+ sc=Numeric.where(dpos <= dmaxs[idx],1,sc)
+ okarr=Numeric.where(sc == 1,1,okarr)
+ sc=sc.astype(Numeric.Float64)
+
+ ppos=ppos+(sc*(prng[idx]+((prng[idx+1]-prng[idx])*
+ (dpos-dmins[idx])/(dmaxs[idx+1]-dmins[idx]))))
+
+ okarr=okarr*okarrmask
+
+ if ptype not in [type(Numeric.array([])),type((1,)),type([])]:
+ okarr=okarr[0]
+
+ return (ppos,okarr)
+
+def PlotToData1D(pmin,pmax,dmins,dmaxs,ppos,axistype=GVPLOT_AXISTYPE_LINEAR):
+ """ Transform from plot to data coordinates.
+ Input:
+ pmin- plot minimum position not including borders (single value)
+ pmax- plot maximum position not including borders (single value)
+ dmins- data range minima (a list or tuple of at least length 1)
+ dmaxs- data range maxima (a list or tuple of length(dmins))
+ ppos- plot positions to transform
+ (single value or 1-D array)
+ axistype- type of axis (eg. linear or log).
+
+ The dmin-dmax ranges must not be overlapping.
+
+ Output:
+ dpos- data position (float or array)
+ okarr- integer or array of integers indicating where plot
+ position is within bounds (1's) or invalid (0's).
+ """
+ if axistype not in [GVPLOT_AXISTYPE_LINEAR,GVPLOT_AXISTYPE_LOG]:
+ raise RuntimeError,'PlotToData1D: unknown axis type!'
+
+ dtype=type(ppos)
+ if dtype != type(Numeric.array([])):
+ ppos=Numeric.array(ppos,Numeric.Float64)
+
+ okarr=Numeric.where(ppos >= pmin,1,0)
+ okarr=Numeric.where(ppos <= pmax,okarr,0)
+
+ # First check for length 1 case and do quick
+ # transform and return if it is; otherwise, continue.
+ if len(dmins) == 1:
+ # Only one continuous range
+ if axistype == GVPLOT_AXISTYPE_LINEAR:
+ dpos=((float(dmaxs[0]-dmins[0])/float(pmax-pmin))*\
+ (ppos-pmin))+dmins[0]
+
+ elif axistype == GVPLOT_AXISTYPE_LOG:
+ dpos=Numeric.power(10,((((Numeric.log10(float(dmaxs[0]))-
+ Numeric.log10(float(dmins[0])))/
+ float(pmax-pmin))*(ppos-pmin))+
+ Numeric.log10(float(dmins[0]))))
+
+ if dtype not in [type(Numeric.array([])),type((1,)),type([])]:
+ okarr=okarr[0]
+
+ return (dpos,okarr)
+
+
+ dmaxs=Numeric.array(dmaxs,Numeric.Float64)
+ dmins=Numeric.array(dmins,Numeric.Float64)
+
+ if axistype == GVPLOT_AXISTYPE_LINEAR:
+ dwidtharr=Numeric.ravel(dmaxs-dmins)
+ dwidth=Numeric.sum(dwidtharr)
+ dcsum=Numeric.cumsum(dwidtharr)
+ drng=Numeric.array(list(dcsum/dwidth).insert(0,0.0))
+ prng=pmin+(drng*(pmax-pmin)) # plot range endpoints
+ pfrac=(float(ppos)-float(pmin))/(float(pmax)-float(pmin))
+ dpos=Numeric.zeros((len(ppos),),Numeric.Float64)
+ for idx in range(len(dmins)):
+ # If ppos is between dmins[idx] and dmaxs[idx],
+ # sc will be 1; otherwise it will be 0
+ sc=(Numeric.sign(pfrac-drng[idx])+
+ Numeric.sign(drng[idx+1]-pfrac))
+ # exact boundary of 2 ranges- use lower.
+ sc=Numeric.where(sc == -1,1,sc)
+ sc=Numeric.where(sc == 1,0,sc)
+ sc=sc.astype(Numeric.Float64)/2.0
+ dpos=dpos+(sc*(dmins[idx]+((dmaxs[idx+1]-dmins[idx])*
+ (ppos-prng[idx])/(prng[idx+1]-prng[idx]))))
+
+ elif axistype == GVPLOT_AXISTYPE_LOG:
+ dmaxs=Numeric.log10(dmaxs)
+ dmins=Numeric.log10(dmins)
+ dwidtharr=Numeric.ravel(dmaxs-dmins)
+ dwidth=Numeric.sum(dwidtharr)
+ dcsum=Numeric.cumsum(dwidtharr)
+ drng=Numeric.array(list(dcsum/dwidth).insert(0,0.0))
+ prng=pmin+(drng*(pmax-pmin)) # plot range endpoints
+ pfrac=(float(ppos)-float(pmin))/(float(pmax)-float(pmin))
+ dpos=Numeric.zeros((len(ppos),),Numeric.Float64)
+ for idx in range(len(dmins)):
+ # If ppos is between dmins[idx] and dmaxs[idx],
+ # sc will be 1; otherwise it will be 0
+ sc=(Numeric.sign(pfrac-drng[idx])+
+ Numeric.sign(drng[idx+1]-pfrac))
+ # exact boundary of 2 ranges- use lower.
+ sc=Numeric.where(sc == -1,1,sc)
+ sc=Numeric.where(sc == 1,0,sc)
+ sc=sc.astype(Numeric.Float64)/2.0
+ dpos=dpos+(sc*(dmins[idx]+((dmaxs[idx+1]-dmins[idx])*
+ (ppos-prng[idx])/(prng[idx+1]-prng[idx]))))
+
+ dpos=Numeric.power(10,dpos)
+
+
+ if dtype not in [type(Numeric.array([])),type((1,)),type([])]:
+ okarr=okarr[0]
+
+ return (dpos,okarr)
+
+def MakeContiguousXY(xarr,yarr):
+ """ Arrange array data by ascending x. """
+ longxlist=[]
+ longylist=[]
+ for idx in range(len(xarr)):
+ longxlist.extend(xarr[idx])
+ longylist.extend(yarr[idx])
+ lxarr=Numeric.array(longxlist)
+ lyarr=Numeric.array(longylist)
+ ind=Numeric.argsort(lxarr)
+ nxarr=Numeric.take(lxarr,ind)
+ nyarr=Numeric.take(lyarr,ind)
+
+ return(nxarr,nyarr)
+
+def GetOutlierData(xarr,xmins,xmaxs,yarr,ymins,ymaxs,
+ zarr=None,zmins=None,zmaxs=None):
+ """ Get data that lies outside of the current plot boundaries.
+ xarr, yarr, (optional zarr)- array, or list of arrays
+
+ xmins/xmaxs- x boundaries (single value or list of values)
+ ymins/ymaxs- y boundaries
+ zmins/zmaxs (optional)- z boundaries
+
+ Note: boundaries and data arrays are in data coordinates,
+ not plot coordinates (xmins/xmaxs etc. are the plot
+ boundaries converted to data coordinates).
+ """
+ if type(xarr) == type(Numeric.array([1,2])):
+ xarr=[xarr]
+ yarr=[yarr]
+ if zarr is not None:
+ zarr=[zarr]
+
+ if type(xmins) not in [type([]),type((1,))]:
+ xmins=[xmins]
+ xmaxs=[xmaxs]
+
+ if type(ymins) not in [type([]),type((1,))]:
+ ymins=[ymins]
+ ymaxs=[ymaxs]
+
+ if zarr is not None:
+ if type(zmins) not in [type([]),type((1,))]:
+ zmins=[zmins]
+ zmaxs=[zmaxs]
+
+ nxarr=[]
+ nyarr=[]
+ nzarr=None
+ if zarr is not None:
+ nzarr=[]
+ else:
+ nzarr=None
+
+ for idx in range(len(xarr)):
+ tx=xarr[idx]
+ ty=yarr[idx]
+ if zarr is not None:
+ tz=zarr[idx]
+ xok=Numeric.zeros(Numeric.shape(tx))
+ for xidx in range(len(xmins)):
+ xok=Numeric.where((tx >= xmins[xidx]) & (tx <= xmaxs[xidx]),1,xok)
+ yok=Numeric.zeros(Numeric.shape(ty))
+ for yidx in range(len(ymins)):
+ yok=Numeric.where((ty >= ymins[yidx]) & (ty <= ymaxs[yidx]),1,yok)
+ if zarr is not None:
+ for zidx in range(len(zmins)):
+ zok=Numeric.where((tz >= zmins[zidx]) & (tz <= zmaxs[zidx]),
+ 1,zok)
+ outlier=Numeric.where(xok == 0,1,0)
+ outlier=Numeric.where(yok == 0,1,outlier)
+ if zarr is not None:
+ outlier=Numeric.where(zok == 0,1,outlier)
+
+ nxarr.append(Numeric.compress(outlier == 1,tx))
+ nyarr.append(Numeric.compress(outlier == 1,ty))
+ if zarr is not None:
+ nzarr.append(Numeric.compress(outlier == 1,tz))
+
+ return (nxarr,nyarr,nzarr)
+
+def GetAxisBreaks(mins,maxs,axis_type=GVPLOT_AXISTYPE_LINEAR,bwidth=0.1):
+ """ Get the axis discontinuity info.
+ mins- axis range minima.
+ maxs- axis range maxima.
+ axis_type- type of axis (linear or log)
+ bwidth- break width as a percentage of axis length.
+ """
+ if len(mins) == 1:
+ return None
+
+ maxs=Numeric.array(maxs)
+ mins=Numeric.array(mins)
+
+ if axis_type == GVPLOT_AXISTYPE_LOG:
+ maxs=Numeric.log10(maxs)
+ mins=Numeric.log10(mins)
+
+ dwidtharr=Numeric.ravel(maxs-mins)
+ dwidth=Numeric.sum(dwidtharr)
+ dcsum=Numeric.cumsum(dwidtharr)
+ drng=Numeric.array(list(dcsum/dwidth))
+ drng=drng[:len(drng)-1]
+ bstarts=drng-(bwidth/2.0)
+ bends=drng+(bwidth/2.0)
+ bstarts=Numeric.where(bstarts < 0.0,0.0,bstarts)
+ bends=Numeric.where(bends > 1.0,1.0,bends)
+ diff=bstarts[1:]-bends[:-1]
+ bstarts[1:]=Numeric.where(diff < 0,bstarts[1:]+diff/2.0,bstarts[1:])
+ bends[:-1]=Numeric.where(diff < 0,bends[:-1]-diff/2.0,bends[:-1])
+
+ breaks=[]
+ for idx in range(len(bstarts)):
+ breaks.append((bstarts[idx],bends[idx]))
+
+ return breaks
+
+
+def GetNiceMinMax(mins,maxs,pref_spacing,axis_type=GVPLOT_AXISTYPE_LINEAR):
+ """ Get 'nice' min/max values that enclose the given range,
+ and return the nice min/max along with a list of data
+ offsets for major tics, and a formatting string for the
+ labels.
+ """
+ if type(mins) not in [type([]),type((1,))]:
+ mins=[mins]
+ if type(maxs) not in [type([]),type((1,))]:
+ maxs=[maxs]
+
+ if axis_type == GVPLOT_AXISTYPE_LINEAR:
+ dmins=[]
+ dmaxs=[]
+ labels=[]
+ for idx in range(len(mins)):
+ tmin,tmax,offsets,fmt=GetNiceLinearMinMax(mins[idx],
+ maxs[idx],pref_spacing)
+ dmins.append(tmin)
+ dmaxs.append(tmax)
+ labels.extend(offsets)
+
+ return (dmins,dmaxs,labels,fmt)
+
+def GetNiceLinearMinMax(minval,maxval,pref_spacing=None):
+ """ Linear axis case:
+ Get 'nice' max/min values that enclose the given range,
+ and return the nice min/max along with a list of data
+ offsets for major tics, and a formatting string for the
+ labels.
+ """
+ if abs(maxval-minval) > 0:
+ rord=Numeric.log10(abs(maxval-minval))
+ else:
+ maxval=maxval*1.1
+ minval=minval*0.9
+ if maxval == 0:
+ maxval=1.0
+ minval=-1.0
+ rord=Numeric.log10(abs(maxval-minval))
+
+ nrord=rord % 1
+
+ # format
+ if rord > 1:
+ fmt="%d"
+ else:
+ prec=int(abs(rord))+2
+ fmt="%."+str(prec)+"f"
+
+ if pref_spacing is None:
+ if nrord < Numeric.log10(2):
+ spc=0.2*pow(10,Numeric.floor(rord))
+ elif nrord < Numeric.log10(5):
+ spc=0.5*pow(10,Numeric.floor(rord))
+ else:
+ spc=pow(10,Numeric.floor(rord))
+ else:
+ spc=pref_spacing
+
+ tmp1=(abs(minval) % spc)/spc
+ new_min=minval - (minval % spc)
+
+ new_max=Numeric.floor((maxval-new_min)/spc)*spc+new_min
+
+ if maxval-new_max > (float(spc)/10000.0):
+ new_max=new_max+spc
+
+ label_offsets=[]
+ for label_val in Numeric.arange(new_min,new_max+spc/100.0,spc):
+ label_offsets.append(label_val)
+
+ return (new_min,new_max,label_offsets,fmt)
+
+
+class GvSimpleSettingsVBox(gtk.GtkVBox,gvsignaler.Signaler):
+ """ Class to hold a number of plot-related settings.
+ Inputs:
+ plotarea- GvSimplePlot to act on
+ plot_num- index to plot within plotarea to apply changes to
+ include_list- tuple of which tables to include:
+ 0- rescale table
+ 1- Apply button
+
+ withx,xminlabel,xmaxlabel,
+ withy,yminlabel,ymaxlabel,
+ withz,zminlabel,zmaxlabel- rescale table settings.
+
+ applylabel- apply button label
+
+ Sends out a 'plot-updated' signal when plot has been
+ changed.
+ """
+ def __init__(self,plotarea=None,plot_num=0,include_list=(0,1),
+ withx=1,xminlabel='X Min',xmaxlabel='X Max',
+ withy=1,yminlabel='Y Min',ymaxlabel='Y Max',
+ withz=0,zminlabel='Z Min',zmaxlabel='Z Max',
+ applylabel='Apply'
+ ):
+ gtk.GtkVBox.__init__(self)
+ self.set_border_width(5)
+ self.set_spacing(5)
+ self.plotarea=plotarea
+ self.plot_num=plot_num
+ self.rescale_table=None
+ self.apply_button=None
+ for item in include_list:
+ if item == 0:
+ self.rescale_table=GvSimpleRescaleTable(
+ withx=withx,xminlabel=xminlabel,xmaxlabel=xmaxlabel,
+ withy=withy,yminlabel=yminlabel,ymaxlabel=ymaxlabel,
+ withz=withz,zminlabel=zminlabel,zmaxlabel=zmaxlabel)
+ self.pack_start(self.rescale_table)
+ elif item == 1:
+ self.apply_button=gtk.GtkButton(applylabel)
+ self.pack_start(self.apply_button,expand=gtk.FALSE)
+
+ if self.apply_button is not None:
+ self.apply_button.connect("clicked",self.apply_cb)
+
+ self.publish('plot-updated')
+
+ def apply_cb(self,*args):
+ """ Update plot. """
+ # If plot was interactive, draw changes back in.
+ for idx in range(len(self.plotarea.plots)):
+ cplot=self.plotarea.plots[idx]
+ for idx2 in range(len(cplot.array_data)):
+ if cplot.array_layer_defaults[idx2].interactive == 1:
+ cplot.merge_data_from_plot(idx2)
+
+ if self.rescale_table is not None:
+ ext=self.rescale_table.get_settings()
+ self.plotarea.plots[self.plot_num].set_extents(xmin=ext[0],
+ xmax=ext[1],ymin=ext[2],ymax=ext[3])
+ ll=self.plotarea.plots[self.plot_num].create_layers()
+ self.plotarea.clear_layers()
+ for item in ll:
+ self.plotarea.add_layer(item)
+ xsize=float(self.plotarea.get_width())
+ ysize=float(self.plotarea.get_height())
+ self.plotarea.fit_extents(0.0,0.0,1.0,ysize/xsize)
+ self.notify('plot-updated')
+
+
+class GvSimpleRescaleTable(gtk.GtkTable):
+ """ Class to provide a table for rescaling a GvSimplePlot.
+ Inputs:
+ withx- 1 to include x in table, 0 to not include
+ xmin- minimum x (None to start from defaults)
+ xmax- maximum x
+ withy- 1 to include y in table, 0 to not include
+ ymin- minimum y
+ ymax- maximum y
+ withz- 1 to include y in table, 0 to not include
+ zmin- minimum y
+ zmax- maximum y
+ """
+ def __init__(self,withx=1,xmin=None,xmax=None,
+ withy=1,ymin=None,ymax=None,
+ withz=1,zmin=None,zmax=None,xminlabel='X Min',
+ xmaxlabel='X Max',yminlabel='Y Min', ymaxlabel='Y Max',
+ zminlabel='Z Min',zmaxlabel='Z Max'):
+ numrows=withx+withy+withz
+ gtk.GtkTable.__init__(self,numrows,5)
+ self.set_row_spacings(5)
+ self.set_col_spacings(5)
+ self.xminentry=None
+ self.xmaxentry=None
+ self.yminentry=None
+ self.ymaxentry=None
+ self.zminentry=None
+ self.zmaxentry=None
+ c_row=0
+ if withx == 1:
+ self.attach(gtk.GtkLabel(xminlabel),0,1,0,1)
+ self.xminentry=gtk.GtkEntry()
+ self.xminentry.set_editable(gtk.TRUE)
+ if xmin is not None:
+ self.xminentry.set_text(str(xmin))
+ else:
+ self.xminentry.set_text('')
+ self.attach(self.xminentry,1,2,0,1)
+ self.attach(gtk.GtkLabel(xmaxlabel),2,3,0,1)
+ self.xmaxentry=gtk.GtkEntry()
+ self.xmaxentry.set_editable(gtk.TRUE)
+ if xmax is not None:
+ self.xmaxentry.set_text(str(xmax))
+ else:
+ self.xmaxentry.set_text('')
+ self.attach(self.xmaxentry,3,4,0,1)
+ c_row=c_row+1
+
+ if withy == 1:
+ self.attach(gtk.GtkLabel(yminlabel),0,1,c_row,c_row+1)
+ self.yminentry=gtk.GtkEntry()
+ self.yminentry.set_editable(gtk.TRUE)
+ if ymin is not None:
+ self.yminentry.set_text(str(ymin))
+ else:
+ self.yminentry.set_text('')
+ self.attach(self.yminentry,1,2,c_row,c_row+1)
+ self.attach(gtk.GtkLabel(ymaxlabel),2,3,c_row,c_row+1)
+ self.ymaxentry=gtk.GtkEntry()
+ self.ymaxentry.set_editable(gtk.TRUE)
+ if ymax is not None:
+ self.ymaxentry.set_text(str(ymax))
+ else:
+ self.ymaxentry.set_text('')
+ self.attach(self.ymaxentry,3,4,c_row,c_row+1)
+ c_row=c_row+1
+
+ if withz == 1:
+ self.attach(gtk.GtkLabel(zminlabel),0,1,c_row,c_row+1)
+ self.zminentry=gtk.GtkEntry()
+ self.zminentry.set_editable(gtk.TRUE)
+ if zmin is not None:
+ self.zminentry.set_text(str(zmin))
+ else:
+ self.zminentry.set_text('')
+ self.attach(self.zminentry,1,2,c_row,c_row+1)
+ self.attach(gtk.GtkLabel(zmaxlabel),2,3,c_row,c_row+1)
+ self.zmaxentry=gtk.GtkEntry()
+ self.zmaxentry.set_editable(gtk.TRUE)
+ if zmax is not None:
+ self.zmaxentry.set_text(str(zmax))
+ else:
+ self.zmaxentry.set_text('')
+ self.attach(self.zmaxentry,3,4,c_row,c_row+1)
+ c_row=c_row+1
+
+ def get_settings(self):
+ """ Return the current settings as a
+ (xmin,xmax,ymin,ymax,zmin,zmax) tuple.
+ If any aren't present or aren't entered,
+ set them to None.
+ """
+ try:
+ xmin=float(self.xminentry.get_text())
+ except:
+ xmin=None
+ try:
+ xmax=float(self.xmaxentry.get_text())
+ except:
+ xmax=None
+ try:
+ ymin=float(self.yminentry.get_text())
+ except:
+ ymin=None
+ try:
+ ymax=float(self.ymaxentry.get_text())
+ except:
+ ymax=None
+ try:
+ zmin=float(self.zminentry.get_text())
+ except:
+ zmin=None
+ try:
+ zmax=float(self.zmaxentry.get_text())
+ except:
+ zmax=None
+
+ return (xmin,xmax,ymin,ymax,zmin,zmax)
+
+
+ def set_settings(self, xmin = None, xmax = None, ymin = None, ymax = None, zmin = None, zmax = None ):
+ """ Sets the value xmin,xmax,ymin,ymax,zmin,zmax
+ in the table entries.
+ A value that is None, has its entry left blank.
+ """
+
+ if xmin is not None and self.xminentry is not None:
+ self.xminentry.set_text(str(xmin))
+
+ if xmax is not None and self.xmaxentry is not None:
+ self.xmaxentry.set_text(str(xmax))
+
+ if ymin is not None and self.yminentry is not None:
+ self.yminentry.set_text(str(ymin))
+
+ if ymax is not None and self.ymaxentry is not None:
+ self.ymaxentry.set_text(str(ymax))
+
+ if zmin is not None and self.zminentry is not None:
+ self.zminentry.set_text(str(zmin))
+
+ if zmax is not None and self.zmaxentry is not None:
+ self.zmaxentry.set_text(str(zmax))
+
+ return
+
+
+
+if __name__ == '__main__':
+ yarr=Numeric.arange(20000,typecode='f')/1000.0
+ yarr2=Numeric.arange(20000,typecode='f')/2000.0
+ yarr3=Numeric.arange(20000,typecode='f')/1500.0
+ yarr=Numeric.sin(yarr)
+ yarr2=2*Numeric.sin(yarr2)
+ yarr3=1.5*Numeric.sin(yarr3)
+ win=GvSimplePlotWindow()
+ win.connect('delete-event',gtk.mainquit)
+ win.show()
+ win.plot(yarr,xlabel='x',ylabel='y',title='y=sin(x)')
+ win_settings=gtk.GtkWindow()
+ win_settings.add(GvSimpleSettingsVBox(win.plotarea))
+ win_settings.show_all()
+ win2=GvSimplePlotWindow(bgcolor=(0.0,0.0,0.0,1.0))
+ win2.show()
+ win2.plot(yarr,xlabel='x',ylabel='y',title='y=sin(x)')
+
+ win3=GvSimplePlotWindow()
+ win3.show()
+ win3.plot(yarr,xmax=5000)
+ win3.oplot(yarr2,color=(0.0,0.0,1.0,1.0),reset_extents=0)
+ win3.oplot(yarr3,color=(0.0,1.0,0.0,1.0),reset_extents=0)
+
+ win4=GvSimplePlotWindow()
+ win4.show()
+ win4.plot(yarr,xmin=17010,xmax=19031)
+ win4.oplot(yarr2,color=(0.0,0.0,1.0,1.0),datalabel='hi',reset_extents=0)
+ win4.oplot(yarr3,color=(0.0,1.0,0.0,1.0),xmin=17010,xmax=19031,
+ with_legend=1)
+
+ xg=Numeric.zeros((20,20),Numeric.Float16)
+ yg=Numeric.zeros((20,20),Numeric.Float16)
+ zg=Numeric.zeros((20,20),Numeric.Float16)
+ for idx1 in range(20):
+ for idx2 in range(20):
+ xg[idx1,idx2]=idx1
+ yg[idx1,idx2]=idx2
+ zg=Numeric.sin(xg*Numeric.pi/10)*Numeric.sin(yg*Numeric.pi/10)
+ win5=GvSimplePlotWindow()
+ win5.show()
+ win5.plotarea.plot3D(xg,yg,zg)
+
+ gtk.mainloop()
+
+
+
Added: packages/openev/branches/upstream/current/pymod/vrtutils.py
===================================================================
--- packages/openev/branches/upstream/current/pymod/vrtutils.py (rev 0)
+++ packages/openev/branches/upstream/current/pymod/vrtutils.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1225 @@
+###############################################################################
+# $Id: vrtutils.py,v 1.17 2005/07/07 21:36:06 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Utilities for creating vrt files.
+# Author: Gillian Walter, gwalter at atlsci.com
+#
+###############################################################################
+# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: vrtutils.py,v $
+# Revision 1.17 2005/07/07 21:36:06 gmwalter
+# Use string to join lines- faster.
+#
+# Revision 1.16 2005/01/12 20:00:13 gmwalter
+# Add option to serialize default geotransform.
+#
+# Revision 1.15 2005/01/04 17:17:20 gmwalter
+# Add option to adjust geocoding for SrcRect != DstRect
+# added to serializeGCPs, serializeGeoTransform.
+#
+# Revision 1.14 2004/11/25 20:53:18 gmwalter
+# Avoid core dump when default geotransform set.
+#
+# Revision 1.13 2004/10/28 18:32:33 gmwalter
+# Add band descriptions, minor fixes.
+#
+# Revision 1.12 2004/10/15 20:45:23 gmwalter
+# Fix typo.
+#
+# Revision 1.11 2004/10/15 17:12:28 gmwalter
+# Added a function.
+#
+# Revision 1.10 2004/08/20 15:57:17 gmwalter
+# Various fixes to export tool, added
+# raw band creation to vrt utilities.
+#
+# Revision 1.9 2004/07/07 23:13:21 gmwalter
+# Update default geotransform->gcp grid to have
+# 16 control points instead of 4.
+#
+# Revision 1.8 2003/09/15 19:11:09 gmwalter
+# Bug fix.
+#
+# Revision 1.7 2003/09/15 18:53:19 gmwalter
+# Added some functionality for combining bands from different files,
+# reprojecting geocoding information.
+#
+# Revision 1.6 2003/04/09 14:46:13 gmwalter
+# Fixed typo in datatype setting.
+#
+# Revision 1.5 2003/02/26 22:53:15 gmwalter
+# Add geocoding information preference.
+#
+# Revision 1.4 2003/01/28 14:31:39 warmerda
+# added log
+#
+#
+import gdal
+import Numeric
+import osr
+import os
+import string
+
+class VRTCreationOptions:
+ def __init__(self,num_dstbands):
+ # num_dstbands: number of bands in destination vrt
+ self.band_opts={}
+ self.geocode_preference=None
+ self.reproj=None
+
+ for cband in range(1,num_dstbands+1):
+ self.band_opts[str(cband)]={}
+ self.band_opts[str(cband)]['band']=str(cband)
+ self.band_opts[str(cband)]['SourceBand']=str(cband)
+
+ def set_geopref(self,geocode_pref=None):
+ # Set the geocode preference
+ # (None or 'geotransform' or 'gcps')
+ if geocode_pref is None:
+ self.geocode_preference=None
+ elif geocode_pref == 'geotransform':
+ self.geocode_preference='geotransform'
+ elif geocode_pref == 'gcps':
+ self.geocode_preference = 'gcps'
+ else:
+ txt="Invalid geocoding preference- options are None,"
+ txt=txt+"'geotransform',or 'gcp'. Resetting to None."
+ print txt
+ self.geocode_preference = None
+
+ def get_geopref(self):
+ return self.geocode_preference
+
+ def set_reproj(self,proj):
+ """ Reproject gcps or geotransform to projection proj (a WKT string)
+ during serialization.
+ """
+ self.reproj=proj
+
+ def set_src_window(self,src_tuple,band_list=None):
+ if band_list is None:
+ # Window all bands
+ for ckey in self.band_opts.keys():
+ self.band_opts[ckey]['SrcRect']=src_tuple
+ else:
+ for cband in band_list:
+ self.band_opts[str(cband)]['SrcRect']=src_tuple
+
+ def set_dst_window(self,dst_tuple,band_list=None):
+ if band_list is None:
+ # Window all bands
+ for ckey in self.band_opts.keys():
+ self.band_opts[ckey]['DstRect']=dst_tuple
+ else:
+ for cband in band_list:
+ self.band_opts[str(cband)]['DstRect']=dst_tuple
+
+ def set_datatype(self,data_type,band_list=None):
+ if band_list is None:
+ # Set datatype in all bands
+ for ckey in self.band_opts.keys():
+ self.band_opts[ckey]['DataType']=gdal.GetDataTypeName(data_type)
+ else:
+ for cband in band_list:
+ self.band_opts[str(cband)]['DataType']=gdal.GetDataTypeName(data_type)
+
+ def set_color_interp(self,color_interp,band_list=None):
+ if band_list is None:
+ # Window all bands
+ for ckey in self.band_opts.keys():
+ self.band_opts[ckey]['ColorInterp']=color_interp
+ else:
+ for cband in band_list:
+ self.band_opts[str(cband)]['ColorInterp']=color_interp
+
+
+ def set_scaling(self,scale_tuple,band_list=None):
+ srcmin=scale_tuple[0]
+ srcmax=scale_tuple[1]
+ dstmin=scale_tuple[2]
+ dstmax=scale_tuple[3]
+ srcdiff=float(srcmax-srcmin)
+ dstdiff=float(dstmax-dstmin)
+ if abs(srcdiff) > 0.0:
+ ratio=dstdiff/srcdiff
+ else:
+ print 'Warning- no dynamic range for source. Ratio defaulting to 1.'
+ ratio=1.0
+
+ offset=dstmin-(srcmin*ratio)
+ if band_list is None:
+ # Window all bands
+ for ckey in self.band_opts.keys():
+ self.band_opts[ckey]['ScaleRatio']=ratio
+ self.band_opts[ckey]['ScaleOffset']=offset
+ else:
+ for cband in band_list:
+ self.band_opts[str(cband)]['ScaleRatio']=ratio
+ self.band_opts[str(cband)]['ScaleOffset']=offset
+
+
+ def get_opts(self):
+ return self.band_opts
+
+def serializeMetadata(indataset=None, dict=None):
+ """ Serialize metadata.
+
+ Inputs:
+
+ indataset- gdal dataset to extract metadata from
+ (None if not using)
+
+ dict- dictionary to use for metadata (None
+ if not using)
+
+ Values in dict will override values in indataset.
+ """
+
+ if indataset is not None:
+ metadict=indataset.GetMetadata()
+ if dict is not None:
+ for item in dict.keys():
+ metadict[item] = dict[item]
+ else:
+ metadict=dict
+
+ if len (metadict) > 0:
+ metabase=[gdal.CXT_Element,'Metadata']
+ for ckey in metadict.keys():
+ mdibase=[gdal.CXT_Element,'MDI']
+ mdibase.append([gdal.CXT_Attribute,'key',[gdal.CXT_Text,ckey]])
+ mdibase.append([gdal.CXT_Text,metadict[ckey]])
+ metabase.append(mdibase)
+ else:
+ metabase=None
+
+ return metabase
+
+
+def serializeGCPs(indataset=None, vrt_options=None,with_Z=0,gcplist=None,
+ projection_attr_txt=None,reproj=None,srcrect=None,
+ dstrect=None):
+ """ This function can be used to serialize gcps with or
+ without an associated gdal dataset.
+
+ Inputs:
+ indataset- a gdal dataset
+ vrt_options- a VRTCreationOptions object
+ with_Z- flag to indicate whether Z values should be included
+ gcplist- a gcplist or None. If it is None, indataset
+ will be searched.
+ projection_attr_text- projection of the gcps. If it is
+ None, indataset will be searched.
+ reproj- projection of output gcps. Only used if vrt_options
+ is None (otherwise it looks in vrt_options for reproj).
+ srcrect, dstrect- source and destination rectangles to use to
+ adjust gcps (optional- default to None).
+ Only used if vrt_options is None (otherwise
+ function looks at the vrt options for the first
+ band and checks that for SrcRect, DstRect).
+ GCPs are updated so that the new pixel and
+ line values of each gcp correspond to the
+ destination rectangle as opposed to the source
+ rectangle.
+
+ Examples:
+ serializeGCPs(dataset,vrtopts)
+ serializeGCPs(gcplist=gcps,projection_attr_txt='GEOGCS...',
+ reproj='PROJCS...')
+ """
+
+ if gcplist is None:
+ gcplist=indataset.GetGCPs()
+
+ if projection_attr_txt is None:
+ projection_attr_txt=indataset.GetGCPProjection()
+
+ srtrans=None
+ if vrt_options is not None:
+ reproj=vrt_options.reproj
+ if reproj == projection_attr_txt:
+ reproj=None
+
+ if (reproj is not None):
+ sr1=osr.SpatialReference()
+ sr2=osr.SpatialReference()
+ try:
+ sr1.ImportFromWkt(reproj)
+ try:
+ sr2.ImportFromWkt(projection_attr_txt)
+ srtrans=osr.CoordinateTransformation(sr2,sr1)
+ except:
+ srtrans=None
+ print 'Warning: unable to reproject gcps- invalid source projection string'
+ except:
+ srtrans=None
+ print 'Warning: unable to reproject gcps- invalid destination projection string'
+
+ if len(gcplist) > 0:
+ gcpbase=[gdal.CXT_Element,'GCPList']
+ if (srtrans is not None):
+ gcpbase.append([gdal.CXT_Attribute,'Projection',
+ [gdal.CXT_Text,reproj]])
+ else:
+ gcpbase.append([gdal.CXT_Attribute,'Projection',
+ [gdal.CXT_Text,projection_attr_txt]])
+ if (vrt_options is None) and ((srcrect is None) or (dstrect is None)):
+ for gcp in gcplist:
+ if srtrans is not None:
+ ngcp=srtrans.TransformPoint(gcp.GCPX,gcp.GCPY,gcp.GCPZ)
+ gcp.GCPX=ngcp[0]
+ gcp.GCPY=ngcp[1]
+ gcp.GCPZ=ngcp[2]
+ gcpbase.append(gcp.serialize(with_Z))
+ else:
+ if vrt_options is not None:
+ bopts=vrt_options.get_opts()[vrt_options.get_opts().keys()[0]]
+ if((bopts.has_key('SrcRect')) and
+ (bopts.has_key('DstRect'))):
+ srcrect = bopts['SrcRect']
+ dstrect = bopts['DstRect']
+ else:
+ srcrect = None
+ dstrect = None
+
+ if (srcrect is None) or (dstrect is None):
+ for gcp in gcplist:
+ if srtrans is not None:
+ ngcp=srtrans.TransformPoint(gcp.GCPX,gcp.GCPY,gcp.GCPZ)
+ gcp.GCPX=ngcp[0]
+ gcp.GCPY=ngcp[1]
+ gcp.GCPZ=ngcp[2]
+ gcpbase.append(gcp.serialize(with_Z))
+ else:
+ (spix,sline,xsize,ysize)=srcrect
+ (dpix,dline,dxsize,dysize)=dstrect
+ for gcp in gcplist:
+ gcpbase2=[gdal.CXT_Element,'GCP']
+ if srtrans is not None:
+ ngcp=srtrans.TransformPoint(gcp.GCPX,gcp.GCPY,gcp.GCPZ)
+ gx=ngcp[0]
+ gy=ngcp[1]
+ gz=ngcp[2]
+ else:
+ gx=gcp.GCPX
+ gy=gcp.GCPY
+ gz=gcp.GCPZ
+ gp=(gcp.GCPPixel+dpix-spix)*dxsize/xsize
+ gl=(gcp.GCPLine+dline-sline)*dysize/ysize
+ gcpbase2.append([gdal.CXT_Attribute,'Id',
+ [gdal.CXT_Text,gcp.Id]])
+ pixval = '%0.15E' % gp
+ lineval = '%0.15E' % gl
+ xval = '%0.15E' % gx
+ yval = '%0.15E' % gy
+ zval = '%0.15E' % gz
+ gcpbase2.append([gdal.CXT_Attribute,'Pixel',
+ [gdal.CXT_Text,pixval]])
+ gcpbase2.append([gdal.CXT_Attribute,'Line',
+ [gdal.CXT_Text,lineval]])
+ gcpbase2.append([gdal.CXT_Attribute,'X',
+ [gdal.CXT_Text,xval]])
+ gcpbase2.append([gdal.CXT_Attribute,'Y',
+ [gdal.CXT_Text,yval]])
+ if with_Z:
+ gcpbase2.append([gdal.CXT_Attribute,'Z',
+ [gdal.CXT_Text,yval]])
+ gcpbase.append(gcpbase2)
+ else:
+ gcpbase=None
+
+ return gcpbase
+
+
+def GeoTransformToGCPs(gt,num_pixels,num_lines,grid=2):
+ """ Form a gcp list from a geotransform. If grid=0, just use 4
+ corners. If grid=1, split each dimension once. If grid=2,
+ split twice, etc:
+
+ grid=0 grid=1 grid=2
+
+ * * * * * * * * *
+
+ * * * *
+ * * *
+ * * * *
+
+ * * * * * * * * *
+
+ This function is meant to be used to convert a geotransform
+ to gcp's so that the geocoded information can be reprojected.
+
+ Inputs: gt- geotransform to convert to gcps
+ num_pixels- number of pixels in the dataset
+ num_lines- number of lines in the dataset
+ grid- see above. Defaults to 2.
+
+ """
+
+ gcp_list=[]
+
+ parr=Numeric.arange(0.0,num_pixels+1.0,num_pixels/(grid+1.0))
+ larr=Numeric.arange(0.0,num_lines+1.0,num_lines/(grid+1.0))
+
+ for idx in range(len(parr)*len(larr)):
+ cgcp=gdal.GCP()
+ pix=parr[idx % len(parr)]
+ line=larr[idx/len(larr)]
+ cgcp.Id=str(idx)
+ cgcp.GCPX=gt[0]+(pix*gt[1])+(line*gt[2])
+ cgcp.GCPY=gt[3]+(pix*gt[4])+(line*gt[5])
+ cgcp.GCPZ=0.0
+ cgcp.GCPPixel=pix
+ cgcp.GCPLine=line
+
+ gcp_list.append(cgcp)
+
+ return gcp_list
+
+def serializeGeoTransform(indataset=None,vrt_options=None,geotransform=None,
+ srcrect=None,dstrect=None,force_geo=0):
+ """
+ Returns a serialized geotransform, or None if the input
+ geotransform is the default (0.0,1.0,0.0,0.0,0.0,1.0).
+
+ Inputs:
+
+ indataset- an input GDAL dataset to get the geotranform
+ from if the geotransform input isn't specified.
+
+ vrtoptions- options for indataset, specifying source and
+ destination rectangles (optional)
+
+ geotransform- a geotransform (6-valued tuple). Overrides
+ the geotransform in indataset, if present.
+
+ srcrect, dstrect- arguments used to shift
+ and scale the transform in case of cropping or resolution
+ changes. The srcrect and dstrect arguments must both be
+ tuples of the form (xstart,ystart,xsize,ysize). If only
+ one is specified, it will be ignored. srcrect and dstrect
+ are IGNORED if vrt_options is not None.
+
+ force_geo- Set to 1 to force the geotransform to be serialized
+ even if the input geotransform is just the
+ default. Is 0 (off) by default.
+ """
+ if geotransform is None:
+ gt=indataset.GetGeoTransform()
+ else:
+ gt=geotransform
+
+ default_geo=(0.0,1.0,0.0,0.0,0.0,1.0)
+ # Don't add anything if the transform
+ # is the default values, unless force_geo
+ # is set to 1.
+ usegeo=force_geo
+ gbase=None
+
+ for i in range(6):
+ if gt[i] != default_geo[i]:
+ usegeo=1
+
+ if usegeo==1:
+ if (vrt_options is None) and ((srcrect is None) or (dstrect is None)):
+ geo_text=' %0.22E, %0.22E, %0.22E, %0.22E, %0.22E, %0.22E' % (gt[0], gt[1], gt[2], gt[3], gt[4], gt[5])
+ else:
+ if vrt_options is not None:
+ bopts=vrt_options.get_opts()[vrt_options.get_opts().keys()[0]]
+ if ((bopts.has_key('SrcRect')) and
+ (bopts.has_key('DstRect'))):
+ srcrect = bopts['SrcRect']
+ dstrect = bopts['DstRect']
+ else:
+ srcrect=None
+ dstrect=None
+ if (srcrect is None) or (dstrect is None):
+ geo_text=' %0.22E, %0.22E, %0.22E, %0.22E, %0.22E, %0.22E' % (gt[0], gt[1], gt[2], gt[3], gt[4], gt[5])
+ else:
+ # Geotransform should be updated to reflect the window
+ # All the bands should have the same windowing/overview options,
+ # so just look at first one
+
+ (spix,sline,xsize,ysize)=srcrect
+ (dpix,dline,dxsize,dysize)=dstrect
+ gt0=gt[0]+gt[1]*(spix-dpix)+gt[2]*(sline-dline)
+ gt3=gt[3]+gt[4]*(spix-dpix)+gt[5]*(sline-dline)
+ # floor- if xsize/ysize/dxsize/dysize are non-integer,
+ # gdal will truncate, so account for that here.
+ gt1=float(gt[1])*Numeric.floor(xsize)/Numeric.floor(dxsize)
+ gt2=float(gt[2])*Numeric.floor(ysize)/Numeric.floor(dysize)
+ gt4=float(gt[4])*Numeric.floor(xsize)/Numeric.floor(dxsize)
+ gt5=float(gt[5])*Numeric.floor(ysize)/Numeric.floor(dysize)
+ geo_text=' %0.22E, %0.22E, %0.22E, %0.22E, %0.22E, %0.22E' % (gt0, gt1, gt2, gt3, gt4, gt5)
+
+ gbase=[gdal.CXT_Element,'GeoTransform',[gdal.CXT_Text,geo_text]]
+ else:
+ gbase=None
+
+ return gbase
+
+def serializeCombinedDatasets(indatasetlist,vrt_options_list=None,
+ band_lists=None):
+ """ Combines bands from several datasets into one. Uses
+ metadata and georeferencing from the FIRST one,
+ and determines raster size from first one.
+ indatasetlist- a list of gdal datasets
+ vrt_options_list- a single vrt_options instance applicable
+ to all the datasets, or else a list
+ of vrt_options (same length as
+ indatasetlist).
+ band_lists- list of lists of bands, or None (use all bands).
+ """
+
+ if vrt_options_list is None:
+ band_opts=[]
+ for ds in indatasetlist:
+ band_opts.append({})
+ else:
+ band_opts=[]
+ if type(vrt_options_list) == type(list):
+ if len(vrt_options_list) != len(indatasetlist):
+ raise 'VRT option list length does not match dataset list '+\
+ 'length!'
+ for opts in vrt_options_list:
+ band_opts.append(opts.get_opts())
+ else:
+ for ds in indatasetlist:
+ band_opts.append(vrt_options_list.get_opts())
+
+ # band opts: A dictionary of band option dictionaries,
+ # indexed by the str(band number)
+ base=[gdal.CXT_Element,'VRTDataset']
+ if vrt_options_list is None:
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(indatasetlist[0].RasterXSize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(indatasetlist[0].RasterYSize)]])
+ else:
+ bopts=band_opts[0]
+ if bopts.has_key('DstRect'):
+ # For now, get dataset size form first band
+ (dpix,dline,dxsize,dysize)=bopts['DstRect']
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(dxsize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(dysize)]])
+ else:
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(indatasetlist[0].RasterXSize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(indatasetlist[0].RasterYSize)]])
+
+ mbase=serializeMetadata(indatasetlist[0])
+ if mbase is not None:
+ base.append(mbase)
+
+ if vrt_options_list is None:
+ geopref=None
+ vrt_options=None
+ elif type(vrt_options_list) == type([]):
+ geopref=vrt_options_list[0].get_geopref()
+ vrt_options=vrt_options_list[0]
+ else:
+ geopref=vrt_options_list.get_geopref()
+ vrt_options=vrt_options_list
+
+ if ((geopref == 'gcps') or (geopref is None)):
+ # If preference is gcps or none, copy any available gcp information
+ gcpbase=serializeGCPs(indatasetlist[0],vrt_options)
+ if gcpbase is not None:
+ base.append(gcpbase)
+
+ if ((gcpbase is None) and (geopref == 'gcps')):
+ print 'Warning- No gcp information to transfer.'
+
+ if ((geopref == 'geotransform') or (geopref is None)):
+ # If preference is geotransform or none, copy any available
+ # geotransform information. If geopref is None and
+ # vrt indicates that the user wishes to reproject georeferencing,
+ # convert to gcps and serialize them.
+
+ srs_text=indatasetlist[0].GetProjection()
+ if vrt_options is not None:
+ reproj=vrt_options.reproj
+ if reproj == srs_text:
+ reproj=None
+ else:
+ reproj=None
+
+ if ((reproj is not None) and (srs_text is not None) and
+ (len(srs_text) > 0) and (gcpbase is None)):
+
+ if geopref is None:
+ gcps=GeoTransformToGCPs(indatasetlist[0].GetGeoTransform(),
+ indatasetlist[0].RasterXSize,
+ indatasetlist[0].RasterYSize)
+ gcpbase=serializeGCPs(indatasetlist[0],vrt_options,
+ gcplist=gcps,projection_attr_txt=srs_text)
+
+ if gcpbase is not None:
+ base.append(gcpbase)
+ else:
+ print 'Warning- reprojection of a geotransform to a '+\
+ '\n new geotransform not supported.'
+ elif (reproj is None):
+ if ((srs_text is not None) and (len(srs_text) > 0)):
+ prjbase=[gdal.CXT_Element,'SRS',[gdal.CXT_Text,srs_text]]
+ base.append(prjbase)
+
+ gbase=serializeGeoTransform(indatasetlist[0],vrt_options)
+ if gbase is not None:
+ base.append(gbase)
+
+ if ((gbase is None) and (geopref == 'geotransform')):
+ print 'Warning- No geotransform information to transfer.'
+ elif gcpbase is None:
+ print 'Warning- No reprojectable geotransform information found.'
+
+ for idx in range(len(indatasetlist)):
+ indataset=indatasetlist[idx]
+ if band_lists is None:
+ band_list=None
+ else:
+ band_list=band_lists[idx]
+
+ if band_list is None:
+ for cband in range(1,indataset.RasterCount+1):
+ if band_opts[idx].has_key(str(cband)):
+ bbase=serializeBand(indataset,
+ opt_dict=band_opts[idx][str(cband)])
+ base.append(bbase)
+ else:
+ opt_dict={}
+ opt_dict['band']=str(cband)
+ opt_dict['SourceBand']=str(cband)
+ bbase=serializeBand(indataset,opt_dict=opt_dict)
+ base.append(bbase)
+ else:
+ for cband in band_list:
+ if band_opts.has_key(str(cband)):
+ bbase=serializeBand(indataset,
+ opt_dict=band_opts[idx][str(cband)])
+ base.append(bbase)
+ else:
+ opt_dict={}
+ opt_dict['band']=str(cband)
+ opt_dict['SourceBand']=str(cband)
+ bbase=serializeBand(indataset,opt_dict=opt_dict)
+ base.append(bbase)
+
+ return base
+
+
+def serializeDataset(indataset,vrt_options=None,band_list=None):
+ if vrt_options is None:
+ band_opts={}
+ else:
+ band_opts=vrt_options.get_opts()
+
+ # band opts: A dictionary of band option dictionaries,
+ # indexed by the str(band number)
+ base=[gdal.CXT_Element,'VRTDataset']
+ if vrt_options is None:
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(indataset.RasterXSize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(indataset.RasterYSize)]])
+ else:
+ bopts=band_opts[band_opts.keys()[0]]
+ if bopts.has_key('DstRect'):
+ # For now, get dataset size form first band
+ (dpix,dline,dxsize,dysize)=bopts['DstRect']
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(dxsize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(dysize)]])
+ else:
+ base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(indataset.RasterXSize)]])
+ base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(indataset.RasterYSize)]])
+
+ mbase=serializeMetadata(indataset)
+ if mbase is not None:
+ base.append(mbase)
+
+ geopref=None
+ if vrt_options is not None:
+ geopref=vrt_options.get_geopref()
+
+ gcpbase=None
+ if ((geopref == 'gcps') or (geopref is None)):
+ # If preference is gcps or none, copy any available gcp information
+ gcpbase=serializeGCPs(indataset,vrt_options)
+ if gcpbase is not None:
+ base.append(gcpbase)
+
+ if ((gcpbase is None) and (geopref == 'gcps')):
+ print 'Warning- No gcp information to transfer.'
+
+ if ((geopref == 'geotransform') or (geopref is None)):
+ # If preference is geotransform or none, copy any available
+ # geotransform information. If geopref is None and
+ # vrt indicates that the user wishes to reproject georeferencing,
+ # convert to gcps and serialize them.
+
+ srs_text=indataset.GetProjection()
+ if vrt_options is not None:
+ reproj=vrt_options.reproj
+ if reproj == srs_text:
+ reproj=None
+ else:
+ reproj=None
+
+ if ((reproj is not None) and (srs_text is not None) and
+ (len(srs_text) > 0) and (gcpbase is None)):
+
+ if geopref is None:
+ gcps=GeoTransformToGCPs(indataset.GetGeoTransform(),
+ indataset.RasterXSize,
+ indataset.RasterYSize)
+ gcpbase=serializeGCPs(indataset,vrt_options,gcplist=gcps,
+ projection_attr_txt=srs_text)
+
+ if gcpbase is not None:
+ base.append(gcpbase)
+ else:
+ print 'Warning- reprojection of a geotransform to a '+\
+ '\n new geotransform not supported.'
+ elif (reproj is None):
+ if ((srs_text is not None) and (len(srs_text) > 0)):
+ prjbase=[gdal.CXT_Element,'SRS',[gdal.CXT_Text,srs_text]]
+ base.append(prjbase)
+
+ gbase=serializeGeoTransform(indataset,vrt_options)
+ if gbase is not None:
+ base.append(gbase)
+
+ if ((gbase is None) and (geopref == 'geotransform')):
+ print 'Warning- No geotransform information to transfer.'
+ elif gcpbase is None:
+ print 'Warning- No reprojectable geotransform information found.'
+
+
+ if band_list is None:
+ for cband in range(1,indataset.RasterCount+1):
+ if band_opts.has_key(str(cband)):
+ bbase=serializeBand(indataset,opt_dict=band_opts[str(cband)])
+ base.append(bbase)
+ else:
+ opt_dict={}
+ opt_dict['band']=str(cband)
+ opt_dict['SourceBand']=str(cband)
+ bbase=serializeBand(indataset,opt_dict=opt_dict)
+ base.append(bbase)
+ else:
+ for cband in band_list:
+ if band_opts.has_key(str(cband)):
+ bbase=serializeBand(indataset,opt_dict=band_opts[str(cband)])
+ base.append(bbase)
+ else:
+ opt_dict={}
+ opt_dict['band']=str(cband)
+ opt_dict['SourceBand']=str(cband)
+ bbase=serializeBand(indataset,opt_dict=opt_dict)
+ base.append(bbase)
+
+ return base
+
+def serializeRawBand(SourceFilename, band, DataType, ByteOrder,
+ ImageOffset, PixelOffset, LineOffset,Description=None):
+ """ Serialize a raw (flat binary) raster band.
+ Inputs:
+
+ SourceFilename- filename of a gdal dataset (a string)
+
+ band- band number that the serialized band will correspond
+ to in the output dataset (an integer).
+
+ DataType- data type (a string). May be 'Byte', 'UInt16',
+ 'Int16', 'UInt32', 'Int32', 'Float32', 'Float64',
+ 'CInt16', 'CInt32', 'CFloat32', 'CFloat64'.
+
+ ByteOrder- MSB or LSB (string)
+
+ ImageOffset- offset to first pixel of band (int)
+
+ PixelOffset- offset between successive pixels in the input (int)
+
+ LineOffset- offset between successive lines in the input (int)
+
+ Description- OPTIONAL description for the band (a string)
+ """
+ base=[gdal.CXT_Element,'VRTRasterBand']
+
+ base.append([gdal.CXT_Attribute,'dataType',
+ [gdal.CXT_Text,DataType]])
+
+ base.append([gdal.CXT_Attribute,'band',[gdal.CXT_Text,str(band)]])
+
+ base.append([gdal.CXT_Attribute,'subClass',
+ [gdal.CXT_Text,"VRTRawRasterBand"]])
+
+ if Description is not None:
+ base.append([gdal.CXT_Element,'Description',
+ [gdal.CXT_Text,Description]])
+
+ base.append([gdal.CXT_Element,'SourceFilename',
+ [gdal.CXT_Text,SourceFilename]])
+ base[len(base)-1].append([gdal.CXT_Attribute,'relativeToVRT',
+ [gdal.CXT_Text,GetRelativeToVRT(SourceFilename)]])
+
+ base.append([gdal.CXT_Element,'ByteOrder',
+ [gdal.CXT_Text,ByteOrder]])
+
+ base.append([gdal.CXT_Element,'ImageOffset',
+ [gdal.CXT_Text,str(ImageOffset)]])
+
+ base.append([gdal.CXT_Element,'PixelOffset',
+ [gdal.CXT_Text,str(PixelOffset)]])
+
+ base.append([gdal.CXT_Element,'LineOffset',
+ [gdal.CXT_Text,str(LineOffset)]])
+
+ return base
+
+def serializeBand(indataset=None,opt_dict={}):
+ """ Serialize a raster band.
+ Inputs:
+ indataset- dataset to take default values from for
+ items that are not specified in opt_dict.
+ Set to None if not needed.
+
+ opt_dict- dictionary to take values from.
+
+ opt_dict will be searched for the following keys:
+
+ SourceFilename- filename of a gdal dataset (a string)
+
+ SourceBand- an integer indicating the band from SourceFilename
+ to use. 1 if not specified.
+
+ band- band number that the serialized band will correspond
+ to in the output dataset (an integer). 1 if not specified.
+
+ DataType- data type (a string). May be 'Byte', 'UInt16',
+ 'Int16', 'UInt32', 'Int32', 'Float32', 'Float64',
+ 'CInt16', 'CInt32', 'CFloat32', 'CFloat64'
+
+ Description- OPTIONAL description to associate with the band (string).
+
+ ColorInterp- OPTIONAL colour interpretation (a string). One of
+ 'Gray', 'Red', 'Green', 'Blue', 'Alpha', 'Undefined', or
+ 'Palette'. If palette is specified, then opt_dict
+ must also have a key 'Palette' with a value that
+ is a gdal ColorTable object.
+
+ NoDataValue- OPTIONAL no data value. Floating point or integer.
+
+ ScaleOffset, ScaleRatio- OPTIONAL scaling offset and ratio for
+ rescaling the input bands (floating point numbers):
+ outband = ScaleOffset + (ScaleRatio*inband)
+
+ SrcRect- a tuple of four integers specifying the extents of the
+ source to use (xoffset, yoffset, xsize, ysize)
+
+ DstRect- a tuple of four integers specifying the extents that
+ SrcRect will correspond to in the output file.
+
+ """
+ base=[gdal.CXT_Element,'VRTRasterBand']
+
+ if opt_dict.has_key('SourceBand'):
+ inband=int(opt_dict['SourceBand'])
+ else:
+ inband=1
+
+ if opt_dict.has_key('band'):
+ outband=int(opt_dict['band'])
+ else:
+ outband=1
+
+ if opt_dict.has_key('DataType'):
+ base.append([gdal.CXT_Attribute,'dataType',
+ [gdal.CXT_Text,opt_dict['DataType']]])
+ elif indataset is not None:
+ base.append([gdal.CXT_Attribute,'dataType',
+ [gdal.CXT_Text,
+ gdal.GetDataTypeName(
+ indataset.GetRasterBand(inband).DataType)]])
+ else:
+ base.append([gdal.CXT_Attribute,'dataType',[gdal.CXT_Text,'Byte']])
+
+
+ base.append([gdal.CXT_Attribute,'band',[gdal.CXT_Text,str(outband)]])
+
+ if opt_dict.has_key('Description'):
+ base.append([gdal.CXT_Element,'Description',
+ [gdal.CXT_Text,opt_dict['Description']]])
+ elif indataset is not None:
+ desc = indataset.GetRasterBand(inband).GetDescription()
+ if len(desc) > 0:
+ base.append([gdal.CXT_Element,'Description',
+ [gdal.CXT_Text,desc]])
+
+ if opt_dict.has_key('ColorInterp'):
+ if opt_dict['ColorInterp'] != 'Undefined':
+ base.append([gdal.CXT_Element,'ColorInterp',
+ [gdal.CXT_Text,opt_dict['ColorInterp']]])
+ if opt_dict['ColorInterp'] == 'Palette':
+ base.append(opt_dict['Palette'].serialize())
+
+ elif indataset is not None:
+ cinterp=indataset.GetRasterBand(inband).GetRasterColorInterpretation()
+ if cinterp != gdal.GCI_Undefined:
+ cinterpname=gdal.GetColorInterpretationName(cinterp)
+ base.append([gdal.CXT_Element,'ColorInterp',
+ [gdal.CXT_Text,cinterpname]])
+ if cinterpname=='Palette':
+ ct = indataset.GetRasterBand(inband).GetRasterColorTable()
+ base.append(ct.serialize())
+
+ if opt_dict.has_key('NoDataValue'):
+ base.append([gdal.CXT_Element,'NoDataValue',
+ [gdal.CXT_Text,str(opt_dict['NoDataValue'])]])
+ elif indataset is not None:
+ nodata_val=indataset.GetRasterBand(inband).GetNoDataValue()
+ if ((nodata_val is not None) and (nodata_val != '')):
+ base.append([gdal.CXT_Element,'NoDataValue',
+ [gdal.CXT_Text,str(nodata_val)]])
+
+ if opt_dict.has_key('ScaleOffset') or opt_dict.has_key('ScaleRatio'):
+ ssbase=[gdal.CXT_Element,'ComplexSource']
+ else:
+ ssbase=[gdal.CXT_Element,'SimpleSource']
+
+ if opt_dict.has_key('SourceFilename'):
+ ssbase.append([gdal.CXT_Element,'SourceFilename',
+ [gdal.CXT_Text,opt_dict['SourceFilename']]])
+ ssbase[len(ssbase)-1].append([gdal.CXT_Attribute,'relativeToVRT',
+ [gdal.CXT_Text,GetRelativeToVRT(opt_dict['SourceFilename'])]])
+ elif indataset is not None:
+ ssbase.append([gdal.CXT_Element,'SourceFilename',
+ [gdal.CXT_Text,indataset.GetDescription()]])
+ ssbase[len(ssbase)-1].append([gdal.CXT_Attribute,'relativeToVRT',
+ [gdal.CXT_Text,GetRelativeToVRT(indataset.GetDescription())]])
+ else:
+ ssbase.append([gdal.CXT_Element,'SourceFilename',
+ [gdal.CXT_Text,'']])
+ ssbase[len(ssbase)-1].append([gdal.CXT_Attribute,
+ 'relativeToVRT',[gdal.CXT_Text,'0']])
+
+ ssbase.append([gdal.CXT_Element,'SourceBand',[gdal.CXT_Text,str(inband)]])
+
+ srcwinbase=[gdal.CXT_Element,'SrcRect']
+
+ if opt_dict.has_key('SrcRect'):
+ xoff=str(opt_dict['SrcRect'][0])
+ yoff=str(opt_dict['SrcRect'][1])
+ xsize=str(opt_dict['SrcRect'][2])
+ ysize=str(opt_dict['SrcRect'][3])
+ elif indataset is not None:
+ xoff='0'
+ yoff='0'
+ xsize=str(indataset.GetRasterBand(inband).XSize)
+ ysize=str(indataset.GetRasterBand(inband).YSize)
+ else:
+ xoff='0'
+ yoff='0'
+ xsize='0'
+ ysize='0'
+
+ srcwinbase.append([gdal.CXT_Attribute,'xOff',[gdal.CXT_Text,xoff]])
+ srcwinbase.append([gdal.CXT_Attribute,'yOff',[gdal.CXT_Text,yoff]])
+ srcwinbase.append([gdal.CXT_Attribute,'xSize',[gdal.CXT_Text,xsize]])
+ srcwinbase.append([gdal.CXT_Attribute,'ySize',[gdal.CXT_Text,ysize]])
+ ssbase.append(srcwinbase)
+
+ dstwinbase=[gdal.CXT_Element,'DstRect']
+ if opt_dict.has_key('DstRect'):
+ x2off=str(opt_dict['DstRect'][0])
+ y2off=str(opt_dict['DstRect'][1])
+ x2size=str(opt_dict['DstRect'][2])
+ y2size=str(opt_dict['DstRect'][3])
+ elif indataset is not None:
+ x2off='0'
+ y2off='0'
+ x2size=str(indataset.GetRasterBand(inband).XSize)
+ y2size=str(indataset.GetRasterBand(inband).YSize)
+ else:
+ x2off='0'
+ y2off='0'
+ x2size='0'
+ y2size='0'
+
+ dstwinbase.append([gdal.CXT_Attribute,'xOff',[gdal.CXT_Text,x2off]])
+ dstwinbase.append([gdal.CXT_Attribute,'yOff',[gdal.CXT_Text,y2off]])
+ dstwinbase.append([gdal.CXT_Attribute,'xSize',[gdal.CXT_Text,x2size]])
+ dstwinbase.append([gdal.CXT_Attribute,'ySize',[gdal.CXT_Text,y2size]])
+ ssbase.append(dstwinbase)
+
+ if opt_dict.has_key('ScaleOffset'):
+ ssbase.append([gdal.CXT_Element,'ScaleOffset',[gdal.CXT_Text,str(opt_dict['ScaleOffset'])]])
+
+ if opt_dict.has_key('ScaleRatio'):
+ ssbase.append([gdal.CXT_Element,'ScaleRatio',[gdal.CXT_Text,str(opt_dict['ScaleRatio'])]])
+
+ base.append(ssbase)
+
+ return base
+
+
+def GetSimilarFiles(filename):
+ """ Looks in the directory of filename for files with the same size
+ and extension, and returns a list containing their full paths.
+ """
+
+ import os
+ import glob
+
+ fdir=os.path.dirname(filename)
+ froot,fext=os.path.splitext(filename)
+ flist=glob.glob(os.path.join(fdir,'*'+fext))
+
+ fsize=os.path.getsize(filename)
+ slist=[]
+ for item in flist:
+ if os.path.getsize(item) == fsize:
+ slist.append(item)
+
+ return slist
+
+
+def GetRelativeToVRT(path):
+ """ Returns '0' if path is absolute, '1' if it is
+ relative to vrt.
+ """
+ if path[0] == '<':
+ # input path is an in-memory vrt file
+ return "0"
+
+ if os.path.isabs(path):
+ return "0"
+ else:
+ return "1"
+
+class VRTDatasetConstructor:
+ """ Class to use for creating vrt datasets from scratch at
+ the python level.
+
+ Initial inputs:
+ pixels- number of pixels in dataset
+ lines- number of lines in dataset
+ """
+ def __init__(self,pixels,lines):
+ self.base=[gdal.CXT_Element,'VRTDataset']
+ self.base.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(pixels)]])
+ self.base.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(lines)]])
+ self.band_idx=1
+ self.xsize=pixels
+ self.ysize=lines
+
+ def AddSimpleBand(self, SourceFilename, SourceBand, DataType,
+ SrcRect=None, DstRect=None, ColorInterp='Undefined',
+ colortable=None, NoDataValue=None,
+ ScaleOffset=None,ScaleRatio=None,
+ Description=None):
+ """ Add a simple raster band
+
+ SourceFilename- filename of a gdal dataset (a string)
+
+ SourceBand- an integer indicating the band from SourceFilename
+ to use.
+
+ DataType- data type (a string). May be 'Byte', 'UInt16',
+ 'Int16', 'UInt32', 'Int32', 'Float32', 'Float64',
+ 'CInt16', 'CInt32', 'CFloat32', 'CFloat64'
+
+ SrcRect- a tuple of four integers specifying the extents of the
+ source to use (xoffset, yoffset, xsize, ysize).
+ Defaults to (0, 0, xsize, ysize) for the dataset.
+
+ DstRect- a tuple of four integers specifying the extents that
+ SrcRect will correspond to in the output file.
+ Defaults to (0, 0, xsize, ysize) for the dataset.
+
+ ColorInterp- OPTIONAL colour interpretation (a string). One of
+ 'Gray', 'Red', 'Green', 'Blue', 'Alpha', 'Undefined', or
+ 'Palette'. If 'Palette' is specified, then colortable
+ must also be specified.
+
+ colortable- GDAL colortable object (only used if ColorInterp
+ is set to 'Palette').
+
+ NoDataValue- OPTIONAL no data value. Floating point or integer.
+
+ ScaleOffset, ScaleRatio- OPTIONAL scaling offset and ratio for
+ rescaling the input bands (floating point numbers):
+ outband = ScaleOffset + (ScaleRatio*inband)
+
+ Description- OPTIONAL description for the band (a string).
+
+ """
+ opt_dict={'SourceFilename':SourceFilename,'SourceBand':SourceBand,
+ 'DataType':DataType,'ColorInterp':ColorInterp}
+
+ if ColorInterp == 'Palette':
+ if colortable is None:
+ raise 'Colour table not specified!'
+ opt_dict['Palette']=colortable
+
+ if SrcRect is not None:
+ opt_dict['SrcRect']=SrcRect
+ else:
+ opt_dict['SrcRect']=(0,0,self.xsize,self.ysize)
+
+ if DstRect is not None:
+ opt_dict['DstRect']=DstRect
+ else:
+ opt_dict['DstRect']=(0,0,self.xsize,self.ysize)
+
+ if ScaleOffset is not None:
+ opt_dict['ScaleOffset']=ScaleOffset
+
+ if ScaleRatio is not None:
+ opt_dict['ScaleRatio']=ScaleRatio
+
+ if NoDataValue is not None:
+ opt_dict['NoDataValue']=NoDataValue
+
+ if Description is not None:
+ opt_dict['Description']=Description
+
+ opt_dict['band']=self.band_idx
+
+ bbase=serializeBand(None,opt_dict)
+
+ self.base.append(bbase)
+ self.band_idx=self.band_idx+1
+
+ def AddRawBand(self, SourceFilename, DataType, ByteOrder,
+ ImageOffset, PixelOffset, LineOffset,
+ Description=None):
+ """ Add a flat binary source raster band.
+ Inputs:
+ SourceFilename- path to source file name (string)
+
+ DataType- datatype (string). One of:
+ Byte Float64
+ UInt16 CInt16
+ Int16 CInt32
+ UInt32 CFloat32
+ Int32 CFloat64
+ Float32
+
+ ByteOrder- MSB or LSB (string)
+
+ ImageOffset- offset to first pixel of band (int)
+
+ PixelOffset- offset between successive pixels in the input (int)
+
+ LineOffset- offset between successive lines in the input (int)
+
+ Description- OPTIONAL description for the band (a string).
+ """
+ bbase=serializeRawBand(SourceFilename,self.band_idx, DataType,
+ ByteOrder,ImageOffset,PixelOffset,
+ LineOffset,Description)
+ self.base.append(bbase)
+ self.band_idx=self.band_idx+1
+
+ def AddMetadata(self, metadict):
+ """ Add metadata from a dictionary """
+ if len(metadict.keys()) < 1:
+ return
+
+ mbase=serializeMetadata(dict=metadict)
+ self.base.append(mbase)
+
+ def SetSRS(self, projection):
+ """ Set projection information for geotransform (a WKT string)"""
+ prjbase=[gdal.CXT_Element,'SRS',[gdal.CXT_Text,projection]]
+ self.base.append(prjbase)
+
+ def SetGeoTransform(self, gt, srcrect=None, dstrect=None, force_geo=0):
+ """ Add a geotransform (input is a tuple of 6 numbers)
+
+ Optional srcrect and dstrect arguments are used to shift
+ and scale the transform in case of cropping or resolution
+ changes. The srcrect and dstrect arguments must both be
+ tuples of the form (xstart,ystart,xsize,ysize). If only
+ one is specified, it will be ignored.
+
+ force_geo- Set to 1 to force the geotransform to be serialized
+ even if the input geotransform is just the
+ default. Is 0 (off) by default.
+ """
+ gbase=serializeGeoTransform(geotransform=gt, srcrect=srcrect,
+ dstrect=dstrect, force_geo=force_geo)
+ if gbase is not None:
+ self.base.append(gbase)
+
+ def SetGCPs(self, gcps, projection='', reprojection=None, srcrect=None,
+ dstrect=None):
+ """ Add gcps from a list of GDAL GCP objects.
+ Optional projection argument should be a WKT string.
+ Optional reprojection argument should also be a WKT
+ string, and should only be specified if the projection
+ argument is also specified.
+
+ Optional srcrect and dstrect arguments are used to shift
+ and scale the gcps in case of cropping or resolution
+ changes. The srcrect and dstrect arguments must both be
+ tuples of the form (xstart,ystart,xsize,ysize). If only
+ one is specified, it will be ignored.
+ """
+ gcpbase=serializeGCPs(gcplist=gcps,projection_attr_txt=projection,
+ reproj=reprojection, srcrect=srcrect,
+ dstrect=dstrect)
+ self.base.append(gcpbase)
+
+ def GetVRTLines(self):
+ """ Return lines suitable for writing to a vrt file. """
+ return gdal.SerializeXMLTree(self.base)
+
+ def GetVRTString(self):
+ """ Return a vrt string that can be opened as a gdal dataset. """
+ lines = self.GetVRTLines()
+ vrtstr = string.join(lines,'')
+ return vrtstr
+
+
+if __name__ == '__main__':
+ import string
+
+ ds=VRTDatasetConstructor(2000,2000)
+ ds.AddSimpleBand('reltest.tif',2,'Float32')
+ ds.AddSimpleBand('/data/abstest.tif',1,'Byte',
+ SrcRect=(1000,2000,4000,4000),
+ ScaleOffset=2,ScaleRatio=3)
+ ds.AddRawBand('rawtest.x00','CFloat32','MSB',0,8,16000)
+ for item in string.split(ds.GetVRTLines(),'\n'):
+ print item
+
+
Added: packages/openev/branches/upstream/current/ramps/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/ramps/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/ramps/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,23 @@
+/blue_green_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/blue_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/blue_white_red_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/brown_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/cyan_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/discrete_1.txt/1.1/Tue Nov 5 14:58:38 2002//
+/discrete_2.txt/1.1/Tue Nov 5 14:58:38 2002//
+/gray_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/green_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/green_yellow_red_ramp.txt/1.3/Mon Nov 4 20:47:23 2002//
+/lavender_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/orange_brown_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/orange_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/pink_red_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/purple_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/real_blue_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/real_red_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/red_blue_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/red_green_ramp.txt/1.2/Mon Nov 4 20:12:02 2002//
+/red_ramp.txt/1.2/Mon Nov 4 20:12:03 2002//
+/rose_red_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+/yellow_ramp.txt/1.1/Wed Aug 13 14:03:55 2003//
+D
Added: packages/openev/branches/upstream/current/ramps/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/ramps/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/ramps/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/ramps
Added: packages/openev/branches/upstream/current/ramps/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/ramps/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/ramps/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/ramps/blue_green_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/blue_green_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/blue_green_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Green-Blue Ramp
+0
+0.0 (0.0, 1.0, 0.0, 1.0)
+1.0 (0.0, 0.0, 1.0, 1.0)
\ No newline at end of file
Added: packages/openev/branches/upstream/current/ramps/blue_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/blue_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/blue_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Blue Ramp
+0
+0.0 (0.0, 0.0, 0.2, 1.0)
+1.0 (0.0, 0.0, 0.9, 1.0)
Added: packages/openev/branches/upstream/current/ramps/blue_white_red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/blue_white_red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/blue_white_red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Blue-White-Red Ramp
+0
+0.0 (0.0, 0.0, 1.0, 1.0)
+0.5 (1.0, 1.0, 1.0, 1.0)
+1.0 (1.0, 0.0, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/brown_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/brown_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/brown_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Brown Ramp
+0
+0.0 (1.0, 0.9, 0.85, 1.0)
+1.0 (0.5, 0.2, 0.1, 1.0)
Added: packages/openev/branches/upstream/current/ramps/cyan_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/cyan_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/cyan_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Cyan Ramp
+0
+0.0 (0.8, 1.0, 1.0, 1.0)
+0.5 (0.0, 1.0, 1.0, 1.0)
+1.0 (0.0, 0.55, 0.55, 1.0)
Added: packages/openev/branches/upstream/current/ramps/discrete_1.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/discrete_1.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/discrete_1.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,14 @@
+Discrete Color Sample 1
+1
+(1.0, 0.0, 0.0, 1.0)
+(1.0, 0.5, 0.0, 1.0)
+(1.0, 1.0, 0.0, 1.0)
+(0.5, 1.0, 0.0, 1.0)
+(0.0, 1.0, 0.0, 1.0)
+(0.0, 1.0, 0.5, 1.0)
+(0.0, 1.0, 1.0, 1.0)
+(0.0, 0.5, 1.0, 1.0)
+(0.0, 0.0, 1.0, 1.0)
+(0.5, 0.0, 1.0, 1.0)
+(1.0, 0.0, 1.0, 1.0)
+(1.0, 0.0, 0.5, 1.0)
\ No newline at end of file
Added: packages/openev/branches/upstream/current/ramps/discrete_2.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/discrete_2.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/discrete_2.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,14 @@
+Discrete Color Sample 2
+1
+(0.5, 0.0, 0.0, 1.0)
+(0.5, 0.25, 0.0, 1.0)
+(0.5, 0.5, 0.0, 1.0)
+(0.25, 0.5, 0.0, 1.0)
+(0.0, 0.5, 0.0, 1.0)
+(0.0, 0.5, 0.25, 1.0)
+(0.0, 0.5, 0.5, 1.0)
+(0.0, 0.25, 0.5, 1.0)
+(0.0, 0.0, 0.5, 1.0)
+(0.25, 0.0, 0.5, 1.0)
+(0.5, 0.0, 0.5, 1.0)
+(0.5, 0.0, 0.25, 1.0)
\ No newline at end of file
Added: packages/openev/branches/upstream/current/ramps/gray_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/gray_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/gray_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Gray Ramp
+0
+0.0 (0.9, 0.9, 0.9, 1.0)
+1.0 (0.2, 0.2, 0.2, 1.0)
Added: packages/openev/branches/upstream/current/ramps/green_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/green_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/green_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Green Ramp
+0
+0.0 (0.0, 0.2, 0.0, 1.0)
+1.0 (0.0, 0.9, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/green_yellow_red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/green_yellow_red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/green_yellow_red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Green-Yellow-Red
+0
+0.0 (0.0, 1.0, 0.0, 1.0)
+0.5 (1.0, 1.0, 0.0, 1.0)
+1.0 (1.0, 0.0, 0.0, 1.0)
\ No newline at end of file
Added: packages/openev/branches/upstream/current/ramps/lavender_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/lavender_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/lavender_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Lavender Ramp
+0
+0.0 (1.0, 0.9, 1.0, 1.0)
+1.0 (0.5, 0.0, 0.5, 1.0)
Added: packages/openev/branches/upstream/current/ramps/orange_brown_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/orange_brown_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/orange_brown_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Orange-Brown Ramp
+0
+0.0 (1.0, 0.93, 0.87, 1.0)
+0.5 (0.94, 0.53, 0.13, 1.0)
+1.0 (0.5, 0.22, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/orange_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/orange_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/orange_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Orange Ramp
+0
+0.0 (1.0, 0.9, 0.85, 1.0)
+1.0 (1.0, 0.25, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/pink_red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/pink_red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/pink_red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Pink Red Ramp
+0
+0.0 (1.0, 0.9, 0.9, 1.0)
+1.0 (0.6, 0.0, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/purple_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/purple_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/purple_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Purple Ramp
+0
+0.0 (1.0, 0.9, 1.0, 1.0)
+1.0 (0.3, 0.0, 0.3, 1.0)
Added: packages/openev/branches/upstream/current/ramps/real_blue_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/real_blue_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/real_blue_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Real Blue Ramp
+0
+0.0 (0.9, 0.9, 1.0, 1.0)
+0.5 (0.0, 0.0, 1.0, 1.0)
+1.0 (0.0, 0.0, 0.4, 1.0)
Added: packages/openev/branches/upstream/current/ramps/real_red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/real_red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/real_red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,5 @@
+Real Red Ramp
+0
+0.0 (1.0, 0.9, 0.9, 1.0)
+0.5 (1.0, 0.0, 0.0, 1.0)
+1.0 (0.4, 0.0, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/red_blue_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/red_blue_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/red_blue_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Red-Blue Ramp
+0
+0.0 (0.9, 0.0, 0.0, 1.0)
+1.0 (0.0, 0.0, 0.9, 1.0)
Added: packages/openev/branches/upstream/current/ramps/red_green_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/red_green_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/red_green_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Red-Green Ramp
+0
+0.0 (0.9, 0.0, 0.0, 1.0)
+1.0 (0.0, 0.9, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Red Ramp
+0
+0.0 (0.9, 0.0, 0.0, 1.0)
+1.0 (0.2, 0.0, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/rose_red_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/rose_red_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/rose_red_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Rose Red Ramp
+0
+0.0 (1.0, 0.6, 0.6, 1.0)
+1.0 (0.4, 0.0, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/ramps/yellow_ramp.txt
===================================================================
--- packages/openev/branches/upstream/current/ramps/yellow_ramp.txt (rev 0)
+++ packages/openev/branches/upstream/current/ramps/yellow_ramp.txt 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+Yellow Ramp
+0
+0.0 (1.0, 1.0, 0.9, 1.0)
+1.0 (0.8, 0.8, 0.0, 1.0)
Added: packages/openev/branches/upstream/current/shapefil.h
===================================================================
--- packages/openev/branches/upstream/current/shapefil.h (rev 0)
+++ packages/openev/branches/upstream/current/shapefil.h 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,475 @@
+#ifndef _SHAPEFILE_H_INCLUDED
+#define _SHAPEFILE_H_INCLUDED
+
+/******************************************************************************
+ * $Id: shapefil.h,v 1.25 2002/05/07 13:46:30 warmerda Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Primary include file for Shapelib.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shapefil.h,v $
+ * Revision 1.25 2002/05/07 13:46:30 warmerda
+ * added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.24 2002/04/10 16:59:54 warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.23 2002/01/15 14:36:07 warmerda
+ * updated email address
+ *
+ * Revision 1.22 2002/01/15 14:32:00 warmerda
+ * try to improve SHPAPI_CALL docs
+ *
+ * Revision 1.21 2001/11/01 16:29:55 warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.20 2001/07/20 13:06:02 warmerda
+ * fixed SHPAPI attribute for SHPTreeFindLikelyShapes
+ *
+ * Revision 1.19 2001/05/31 19:20:13 warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.18 2001/05/31 18:15:40 warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.17 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.16 2000/09/25 14:15:59 warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.15 2000/02/16 16:03:51 warmerda
+ * added null shape support
+ *
+ * Revision 1.14 1999/11/05 14:12:05 warmerda
+ * updated license terms
+ *
+ * Revision 1.13 1999/06/02 18:24:21 warmerda
+ * added trimming code
+ *
+ * Revision 1.12 1999/06/02 17:56:12 warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.11 1999/05/18 19:11:11 warmerda
+ * Added example searching capability
+ *
+ * Revision 1.10 1999/05/18 17:49:38 warmerda
+ * added initial quadtree support
+ *
+ * Revision 1.9 1999/05/11 03:19:28 warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.8 1999/03/23 17:22:27 warmerda
+ * Added extern "C" protection for C++ users of shapefil.h.
+ *
+ * Revision 1.7 1998/12/31 15:31:07 warmerda
+ * Added the TRIM_DBF_WHITESPACE and DISABLE_MULTIPATCH_MEASURE options.
+ *
+ * Revision 1.6 1998/12/03 15:48:15 warmerda
+ * Added SHPCalculateExtents().
+ *
+ * Revision 1.5 1998/11/09 20:57:16 warmerda
+ * Altered SHPGetInfo() call.
+ *
+ * Revision 1.4 1998/11/09 20:19:33 warmerda
+ * Added 3D support, and use of SHPObject.
+ *
+ * Revision 1.3 1995/08/23 02:24:05 warmerda
+ * Added support for reading bounds.
+ *
+ * Revision 1.2 1995/08/04 03:17:39 warmerda
+ * Added header.
+ *
+ */
+
+#include <stdio.h>
+
+#ifdef USE_DBMALLOC
+#include <dbmalloc.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************************************************/
+/* Configuration options. */
+/************************************************************************/
+
+/* -------------------------------------------------------------------- */
+/* Should the DBFReadStringAttribute() strip leading and */
+/* trailing white space? */
+/* -------------------------------------------------------------------- */
+#define TRIM_DBF_WHITESPACE
+
+/* -------------------------------------------------------------------- */
+/* Should we write measure values to the Multipatch object? */
+/* Reportedly ArcView crashes if we do write it, so for now it */
+/* is disabled. */
+/* -------------------------------------------------------------------- */
+#define DISABLE_MULTIPATCH_MEASURE
+
+/* -------------------------------------------------------------------- */
+/* SHPAPI_CALL */
+/* */
+/* The following two macros are present to allow forcing */
+/* various calling conventions on the Shapelib API. */
+/* */
+/* To force __stdcall conventions (needed to call Shapelib */
+/* from Visual Basic and/or Dephi I believe) the makefile could */
+/* be modified to define: */
+/* */
+/* /DSHPAPI_CALL=__stdcall */
+/* */
+/* If it is desired to force export of the Shapelib API without */
+/* using the shapelib.def file, use the following definition. */
+/* */
+/* /DSHAPELIB_DLLEXPORT */
+/* */
+/* To get both at once it will be necessary to hack this */
+/* include file to define: */
+/* */
+/* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
+/* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
+/* */
+/* The complexity of the situtation is partly caused by the */
+/* peculiar requirement of Visual C++ that __stdcall appear */
+/* after any "*"'s in the return value of a function while the */
+/* __declspec(dllexport) must appear before them. */
+/* -------------------------------------------------------------------- */
+
+#ifdef SHAPELIB_DLLEXPORT
+# define SHPAPI_CALL __declspec(dllexport)
+# define SHPAPI_CALL1(x) __declspec(dllexport) x
+#endif
+
+#ifndef SHPAPI_CALL
+# define SHPAPI_CALL
+#endif
+
+#ifndef SHPAPI_CALL1
+# define SHPAPI_CALL1(x) x SHPAPI_CALL
+#endif
+
+/************************************************************************/
+/* SHP Support. */
+/************************************************************************/
+typedef struct
+{
+ FILE *fpSHP;
+ FILE *fpSHX;
+
+ int nShapeType; /* SHPT_* */
+
+ int nFileSize; /* SHP file */
+
+ int nRecords;
+ int nMaxRecords;
+ int *panRecOffset;
+ int *panRecSize;
+
+ double adBoundsMin[4];
+ double adBoundsMax[4];
+
+ int bUpdated;
+
+ unsigned char *pabyRec;
+ int nBufSize;
+} SHPInfo;
+
+typedef SHPInfo * SHPHandle;
+
+/* -------------------------------------------------------------------- */
+/* Shape types (nSHPType) */
+/* -------------------------------------------------------------------- */
+#define SHPT_NULL 0
+#define SHPT_POINT 1
+#define SHPT_ARC 3
+#define SHPT_POLYGON 5
+#define SHPT_MULTIPOINT 8
+#define SHPT_POINTZ 11
+#define SHPT_ARCZ 13
+#define SHPT_POLYGONZ 15
+#define SHPT_MULTIPOINTZ 18
+#define SHPT_POINTM 21
+#define SHPT_ARCM 23
+#define SHPT_POLYGONM 25
+#define SHPT_MULTIPOINTM 28
+#define SHPT_MULTIPATCH 31
+
+
+/* -------------------------------------------------------------------- */
+/* Part types - everything but SHPT_MULTIPATCH just uses */
+/* SHPP_RING. */
+/* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP 0
+#define SHPP_TRIFAN 1
+#define SHPP_OUTERRING 2
+#define SHPP_INNERRING 3
+#define SHPP_FIRSTRING 4
+#define SHPP_RING 5
+
+/* -------------------------------------------------------------------- */
+/* SHPObject - represents on shape (without attributes) read */
+/* from the .shp file. */
+/* -------------------------------------------------------------------- */
+typedef struct
+{
+ int nSHPType;
+
+ int nShapeId; /* -1 is unknown/unassigned */
+
+ int nParts;
+ int *panPartStart;
+ int *panPartType;
+
+ int nVertices;
+ double *padfX;
+ double *padfY;
+ double *padfZ;
+ double *padfM;
+
+ double dfXMin;
+ double dfYMin;
+ double dfZMin;
+ double dfMMin;
+
+ double dfXMax;
+ double dfYMax;
+ double dfZMax;
+ double dfMMax;
+} SHPObject;
+
+/* -------------------------------------------------------------------- */
+/* SHP API Prototypes */
+/* -------------------------------------------------------------------- */
+SHPHandle SHPAPI_CALL
+ SHPOpen( const char * pszShapeFile, const char * pszAccess );
+SHPHandle SHPAPI_CALL
+ SHPCreate( const char * pszShapeFile, int nShapeType );
+void SHPAPI_CALL
+ SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+ double * padfMinBound, double * padfMaxBound );
+
+SHPObject SHPAPI_CALL1(*)
+ SHPReadObject( SHPHandle hSHP, int iShape );
+int SHPAPI_CALL
+ SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
+
+void SHPAPI_CALL
+ SHPDestroyObject( SHPObject * psObject );
+void SHPAPI_CALL
+ SHPComputeExtents( SHPObject * psObject );
+SHPObject SHPAPI_CALL1(*)
+ SHPCreateObject( int nSHPType, int nShapeId,
+ int nParts, int * panPartStart, int * panPartType,
+ int nVertices, double * padfX, double * padfY,
+ double * padfZ, double * padfM );
+SHPObject SHPAPI_CALL1(*)
+ SHPCreateSimpleObject( int nSHPType, int nVertices,
+ double * padfX, double * padfY, double * padfZ );
+
+int SHPAPI_CALL
+ SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
+
+void SHPAPI_CALL
+ SHPClose( SHPHandle hSHP );
+
+const char SHPAPI_CALL1(*)
+ SHPTypeName( int nSHPType );
+const char SHPAPI_CALL1(*)
+ SHPPartTypeName( int nPartType );
+
+/* -------------------------------------------------------------------- */
+/* Shape quadtree indexing API. */
+/* -------------------------------------------------------------------- */
+
+/* this can be two or four for binary or quad tree */
+#define MAX_SUBNODE 4
+
+typedef struct shape_tree_node
+{
+ /* region covered by this node */
+ double adfBoundsMin[4];
+ double adfBoundsMax[4];
+
+ /* list of shapes stored at this node. The papsShapeObj pointers
+ or the whole list can be NULL */
+ int nShapeCount;
+ int *panShapeIds;
+ SHPObject **papsShapeObj;
+
+ int nSubNodes;
+ struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+
+} SHPTreeNode;
+
+typedef struct
+{
+ SHPHandle hSHP;
+
+ int nMaxDepth;
+ int nDimension;
+
+ SHPTreeNode *psRoot;
+} SHPTree;
+
+SHPTree SHPAPI_CALL1(*)
+ SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+ double *padfBoundsMin, double *padfBoundsMax );
+void SHPAPI_CALL
+ SHPDestroyTree( SHPTree * hTree );
+
+int SHPAPI_CALL
+ SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+SHPTree SHPAPI_CALL
+ SHPReadTree( const char * pszFilename );
+
+int SHPAPI_CALL
+ SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
+int SHPAPI_CALL
+ SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
+int SHPAPI_CALL
+ SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+
+void SHPAPI_CALL
+ SHPTreeTrimExtraNodes( SHPTree * hTree );
+
+int SHPAPI_CALL1(*)
+ SHPTreeFindLikelyShapes( SHPTree * hTree,
+ double * padfBoundsMin,
+ double * padfBoundsMax,
+ int * );
+int SHPAPI_CALL
+ SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+
+/************************************************************************/
+/* DBF Support. */
+/************************************************************************/
+typedef struct
+{
+ FILE *fp;
+
+ int nRecords;
+
+ int nRecordLength;
+ int nHeaderLength;
+ int nFields;
+ int *panFieldOffset;
+ int *panFieldSize;
+ int *panFieldDecimals;
+ char *pachFieldType;
+
+ char *pszHeader;
+
+ int nCurrentRecord;
+ int bCurrentRecordModified;
+ char *pszCurrentRecord;
+
+ int bNoHeader;
+ int bUpdated;
+} DBFInfo;
+
+typedef DBFInfo * DBFHandle;
+
+typedef enum {
+ FTString,
+ FTInteger,
+ FTDouble,
+ FTInvalid
+} DBFFieldType;
+
+#define XBASE_FLDHDR_SZ 32
+
+DBFHandle SHPAPI_CALL
+ DBFOpen( const char * pszDBFFile, const char * pszAccess );
+DBFHandle SHPAPI_CALL
+ DBFCreate( const char * pszDBFFile );
+
+int SHPAPI_CALL
+ DBFGetFieldCount( DBFHandle psDBF );
+int SHPAPI_CALL
+ DBFGetRecordCount( DBFHandle psDBF );
+int SHPAPI_CALL
+ DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals );
+
+DBFFieldType SHPAPI_CALL
+ DBFGetFieldInfo( DBFHandle psDBF, int iField,
+ char * pszFieldName, int * pnWidth, int * pnDecimals );
+
+int SHPAPI_CALL
+ DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+int SHPAPI_CALL
+ DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+double SHPAPI_CALL
+ DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+ DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+int SHPAPI_CALL
+ DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+ DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
+ int nFieldValue );
+int SHPAPI_CALL
+ DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+ double dFieldValue );
+int SHPAPI_CALL
+ DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+ const char * pszFieldValue );
+int SHPAPI_CALL
+ DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+ DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+ void * pValue );
+const char SHPAPI_CALL1(*)
+ DBFReadTuple(DBFHandle psDBF, int hEntity );
+int SHPAPI_CALL
+ DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+
+DBFHandle SHPAPI_CALL
+ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
+
+void SHPAPI_CALL
+ DBFClose( DBFHandle hDBF );
+char SHPAPI_CALL
+ DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef _SHAPEFILE_H_INCLUDED */
Added: packages/openev/branches/upstream/current/shpopen.c
===================================================================
--- packages/openev/branches/upstream/current/shpopen.c (rev 0)
+++ packages/openev/branches/upstream/current/shpopen.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1866 @@
+/******************************************************************************
+ * $Id: shpopen.c,v 1.39 2002/08/26 06:46:56 warmerda Exp $
+ *
+ * Project: Shapelib
+ * Purpose: Implementation of core Shapefile read/write functions.
+ * Author: Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, 2001, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL). This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log: shpopen.c,v $
+ * Revision 1.39 2002/08/26 06:46:56 warmerda
+ * avoid c++ comments
+ *
+ * Revision 1.38 2002/05/07 16:43:39 warmerda
+ * Removed debugging printf.
+ *
+ * Revision 1.37 2002/04/10 17:35:22 warmerda
+ * fixed bug in ring reversal code
+ *
+ * Revision 1.36 2002/04/10 16:59:54 warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.35 2001/12/07 15:10:44 warmerda
+ * fix if .shx fails to open
+ *
+ * Revision 1.34 2001/11/01 16:29:55 warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.33 2001/07/03 12:18:15 warmerda
+ * Improved cleanup if SHX not found, provied by Riccardo Cohen.
+ *
+ * Revision 1.32 2001/06/22 01:58:07 warmerda
+ * be more careful about establishing initial bounds in face of NULL shapes
+ *
+ * Revision 1.31 2001/05/31 19:35:29 warmerda
+ * added support for writing null shapes
+ *
+ * Revision 1.30 2001/05/28 12:46:29 warmerda
+ * Add some checking on reasonableness of record count when opening.
+ *
+ * Revision 1.29 2001/05/23 13:36:52 warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.28 2001/02/06 22:25:06 warmerda
+ * fixed memory leaks when SHPOpen() fails
+ *
+ * Revision 1.27 2000/07/18 15:21:33 warmerda
+ * added better enforcement of -1 for append in SHPWriteObject
+ *
+ * Revision 1.26 2000/02/16 16:03:51 warmerda
+ * added null shape support
+ *
+ * Revision 1.25 1999/12/15 13:47:07 warmerda
+ * Fixed record size settings in .shp file (was 4 words too long)
+ * Added stdlib.h.
+ *
+ * Revision 1.24 1999/11/05 14:12:04 warmerda
+ * updated license terms
+ *
+ * Revision 1.23 1999/07/27 00:53:46 warmerda
+ * added support for rewriting shapes
+ *
+ * Revision 1.22 1999/06/11 19:19:11 warmerda
+ * Cleanup pabyRec static buffer on SHPClose().
+ *
+ * Revision 1.21 1999/06/02 14:57:56 kshih
+ * Remove unused variables
+ *
+ * Revision 1.20 1999/04/19 21:04:17 warmerda
+ * Fixed syntax error.
+ *
+ * Revision 1.19 1999/04/19 21:01:57 warmerda
+ * Force access string to binary in SHPOpen().
+ *
+ * Revision 1.18 1999/04/01 18:48:07 warmerda
+ * Try upper case extensions if lower case doesn't work.
+ *
+ * Revision 1.17 1998/12/31 15:29:39 warmerda
+ * Disable writing measure values to multipatch objects if
+ * DISABLE_MULTIPATCH_MEASURE is defined.
+ *
+ * Revision 1.16 1998/12/16 05:14:33 warmerda
+ * Added support to write MULTIPATCH. Fixed reading Z coordinate of
+ * MULTIPATCH. Fixed record size written for all feature types.
+ *
+ * Revision 1.15 1998/12/03 16:35:29 warmerda
+ * r+b is proper binary access string, not rb+.
+ *
+ * Revision 1.14 1998/12/03 15:47:56 warmerda
+ * Fixed setting of nVertices in SHPCreateObject().
+ *
+ * Revision 1.13 1998/12/03 15:33:54 warmerda
+ * Made SHPCalculateExtents() separately callable.
+ *
+ * Revision 1.12 1998/11/11 20:01:50 warmerda
+ * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
+ *
+ * Revision 1.11 1998/11/09 20:56:44 warmerda
+ * Fixed up handling of file wide bounds.
+ *
+ * Revision 1.10 1998/11/09 20:18:51 warmerda
+ * Converted to support 3D shapefiles, and use of SHPObject.
+ *
+ * Revision 1.9 1998/02/24 15:09:05 warmerda
+ * Fixed memory leak.
+ *
+ * Revision 1.8 1997/12/04 15:40:29 warmerda
+ * Fixed byte swapping of record number, and record length fields in the
+ * .shp file.
+ *
+ * Revision 1.7 1995/10/21 03:15:58 warmerda
+ * Added support for binary file access, the magic cookie 9997
+ * and tried to improve the int32 selection logic for 16bit systems.
+ *
+ * Revision 1.6 1995/09/04 04:19:41 warmerda
+ * Added fix for file bounds.
+ *
+ * Revision 1.5 1995/08/25 15:16:44 warmerda
+ * Fixed a couple of problems with big endian systems ... one with bounds
+ * and the other with multipart polygons.
+ *
+ * Revision 1.4 1995/08/24 18:10:17 warmerda
+ * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
+ * functions (such as on the Sun).
+ *
+ * Revision 1.3 1995/08/23 02:23:15 warmerda
+ * Added support for reading bounds, and fixed up problems in setting the
+ * file wide bounds.
+ *
+ * Revision 1.2 1995/08/04 03:16:57 warmerda
+ * Added header.
+ *
+ */
+
+static char rcsid[] =
+ "$Id: shpopen.c,v 1.39 2002/08/26 06:46:56 warmerda Exp $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+#if UINT_MAX == 65535
+typedef long int32;
+#else
+typedef int int32;
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+#define ByteCopy( a, b, c ) memcpy( b, a, c )
+#ifndef MAX
+# define MIN(a,b) ((a<b) ? a : b)
+# define MAX(a,b) ((a>b) ? a : b)
+#endif
+
+static int bBigEndian;
+
+
+/************************************************************************/
+/* SwapWord() */
+/* */
+/* Swap a 2, 4 or 8 byte word. */
+/************************************************************************/
+
+static void SwapWord( int length, void * wordP )
+
+{
+ int i;
+ uchar temp;
+
+ for( i=0; i < length/2; i++ )
+ {
+ temp = ((uchar *) wordP)[i];
+ ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
+ ((uchar *) wordP)[length-i-1] = temp;
+ }
+}
+
+/************************************************************************/
+/* SfRealloc() */
+/* */
+/* A realloc cover function that will access a NULL pointer as */
+/* a valid input. */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+ if( pMem == NULL )
+ return( (void *) malloc(nNewSize) );
+ else
+ return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/* SHPWriteHeader() */
+/* */
+/* Write out a header for the .shp and .shx files as well as the */
+/* contents of the index (.shx) file. */
+/************************************************************************/
+
+static void SHPWriteHeader( SHPHandle psSHP )
+
+{
+ uchar abyHeader[100];
+ int i;
+ int32 i32;
+ double dValue;
+ int32 *panSHX;
+
+/* -------------------------------------------------------------------- */
+/* Prepare header block for .shp file. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < 100; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[2] = 0x27; /* magic cookie */
+ abyHeader[3] = 0x0a;
+
+ i32 = psSHP->nFileSize/2; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ i32 = 1000; /* version */
+ ByteCopy( &i32, abyHeader+28, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+
+ i32 = psSHP->nShapeType; /* shape type */
+ ByteCopy( &i32, abyHeader+32, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+ dValue = psSHP->adBoundsMin[0]; /* set bounds */
+ ByteCopy( &dValue, abyHeader+36, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+36 );
+
+ dValue = psSHP->adBoundsMin[1];
+ ByteCopy( &dValue, abyHeader+44, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+44 );
+
+ dValue = psSHP->adBoundsMax[0];
+ ByteCopy( &dValue, abyHeader+52, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+52 );
+
+ dValue = psSHP->adBoundsMax[1];
+ ByteCopy( &dValue, abyHeader+60, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+60 );
+
+ dValue = psSHP->adBoundsMin[2]; /* z */
+ ByteCopy( &dValue, abyHeader+68, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+68 );
+
+ dValue = psSHP->adBoundsMax[2];
+ ByteCopy( &dValue, abyHeader+76, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+76 );
+
+ dValue = psSHP->adBoundsMin[3]; /* m */
+ ByteCopy( &dValue, abyHeader+84, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+84 );
+
+ dValue = psSHP->adBoundsMax[3];
+ ByteCopy( &dValue, abyHeader+92, 8 );
+ if( bBigEndian ) SwapWord( 8, abyHeader+92 );
+
+/* -------------------------------------------------------------------- */
+/* Write .shp file header. */
+/* -------------------------------------------------------------------- */
+ fseek( psSHP->fpSHP, 0, 0 );
+ fwrite( abyHeader, 100, 1, psSHP->fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Prepare, and write .shx file header. */
+/* -------------------------------------------------------------------- */
+ i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ fseek( psSHP->fpSHX, 0, 0 );
+ fwrite( abyHeader, 100, 1, psSHP->fpSHX );
+
+/* -------------------------------------------------------------------- */
+/* Write out the .shx contents. */
+/* -------------------------------------------------------------------- */
+ panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
+
+ for( i = 0; i < psSHP->nRecords; i++ )
+ {
+ panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
+ panSHX[i*2+1] = psSHP->panRecSize[i]/2;
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
+ if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+ }
+
+ fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX );
+
+ free( panSHX );
+}
+
+/************************************************************************/
+/* SHPOpen() */
+/* */
+/* Open the .shp and .shx files based on the basename of the */
+/* files or either file name. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
+
+{
+ char *pszFullname, *pszBasename;
+ SHPHandle psSHP;
+
+ uchar *pabyBuf;
+ int i;
+ double dValue;
+
+/* -------------------------------------------------------------------- */
+/* Ensure the access string is one of the legal ones. We */
+/* ensure the result string indicates binary to avoid common */
+/* problems on Windows. */
+/* -------------------------------------------------------------------- */
+ if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
+ || strcmp(pszAccess,"r+") == 0 )
+ pszAccess = "r+b";
+ else
+ pszAccess = "rb";
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this machine. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((uchar *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Initialize the info structure. */
+/* -------------------------------------------------------------------- */
+ psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
+
+ psSHP->bUpdated = FALSE;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszLayer)+5);
+ strcpy( pszBasename, pszLayer );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/* Open the .shp and .shx files. Note that files pulled from */
+/* a PC to Unix with upper case filenames won't work! */
+/* -------------------------------------------------------------------- */
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.shp", pszBasename );
+ psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ if( psSHP->fpSHP == NULL )
+ {
+ sprintf( pszFullname, "%s.SHP", pszBasename );
+ psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ }
+
+ if( psSHP->fpSHP == NULL )
+ {
+ free( psSHP );
+ free( pszBasename );
+ free( pszFullname );
+ return( NULL );
+ }
+
+ sprintf( pszFullname, "%s.shx", pszBasename );
+ psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ if( psSHP->fpSHX == NULL )
+ {
+ sprintf( pszFullname, "%s.SHX", pszBasename );
+ psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ }
+
+ if( psSHP->fpSHX == NULL )
+ {
+ fclose( psSHP->fpSHP );
+ free( psSHP );
+ free( pszBasename );
+ free( pszFullname );
+ return( NULL );
+ }
+
+ free( pszFullname );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Read the file size from the SHP file. */
+/* -------------------------------------------------------------------- */
+ pabyBuf = (uchar *) malloc(100);
+ fread( pabyBuf, 100, 1, psSHP->fpSHP );
+
+ psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
+ + pabyBuf[25] * 256 * 256
+ + pabyBuf[26] * 256
+ + pabyBuf[27]) * 2;
+
+/* -------------------------------------------------------------------- */
+/* Read SHX file Header info */
+/* -------------------------------------------------------------------- */
+ fread( pabyBuf, 100, 1, psSHP->fpSHX );
+
+ if( pabyBuf[0] != 0
+ || pabyBuf[1] != 0
+ || pabyBuf[2] != 0x27
+ || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
+ {
+ fclose( psSHP->fpSHP );
+ fclose( psSHP->fpSHX );
+ free( psSHP );
+
+ return( NULL );
+ }
+
+ psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
+ + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
+ psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
+
+ psSHP->nShapeType = pabyBuf[32];
+
+ if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+ {
+ /* this header appears to be corrupt. Give up. */
+ fclose( psSHP->fpSHP );
+ fclose( psSHP->fpSHX );
+ free( psSHP );
+
+ return( NULL );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Read the bounds. */
+/* -------------------------------------------------------------------- */
+ if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
+ memcpy( &dValue, pabyBuf+36, 8 );
+ psSHP->adBoundsMin[0] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
+ memcpy( &dValue, pabyBuf+44, 8 );
+ psSHP->adBoundsMin[1] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
+ memcpy( &dValue, pabyBuf+52, 8 );
+ psSHP->adBoundsMax[0] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
+ memcpy( &dValue, pabyBuf+60, 8 );
+ psSHP->adBoundsMax[1] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
+ memcpy( &dValue, pabyBuf+68, 8 );
+ psSHP->adBoundsMin[2] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
+ memcpy( &dValue, pabyBuf+76, 8 );
+ psSHP->adBoundsMax[2] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
+ memcpy( &dValue, pabyBuf+84, 8 );
+ psSHP->adBoundsMin[3] = dValue;
+
+ if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
+ memcpy( &dValue, pabyBuf+92, 8 );
+ psSHP->adBoundsMax[3] = dValue;
+
+ free( pabyBuf );
+
+/* -------------------------------------------------------------------- */
+/* Read the .shx file to get the offsets to each record in */
+/* the .shp file. */
+/* -------------------------------------------------------------------- */
+ psSHP->nMaxRecords = psSHP->nRecords;
+
+ psSHP->panRecOffset =
+ (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+ psSHP->panRecSize =
+ (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+
+ pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
+ fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
+
+ for( i = 0; i < psSHP->nRecords; i++ )
+ {
+ int32 nOffset, nLength;
+
+ memcpy( &nOffset, pabyBuf + i * 8, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nOffset );
+
+ memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
+ if( !bBigEndian ) SwapWord( 4, &nLength );
+
+ psSHP->panRecOffset[i] = nOffset*2;
+ psSHP->panRecSize[i] = nLength*2;
+ }
+ free( pabyBuf );
+
+ return( psSHP );
+}
+
+/************************************************************************/
+/* SHPClose() */
+/* */
+/* Close the .shp and .shx files. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPClose(SHPHandle psSHP )
+
+{
+/* -------------------------------------------------------------------- */
+/* Update the header if we have modified anything. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->bUpdated )
+ {
+ SHPWriteHeader( psSHP );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Free all resources, and close files. */
+/* -------------------------------------------------------------------- */
+ free( psSHP->panRecOffset );
+ free( psSHP->panRecSize );
+
+ fclose( psSHP->fpSHX );
+ fclose( psSHP->fpSHP );
+
+ if( psSHP->pabyRec != NULL )
+ {
+ free( psSHP->pabyRec );
+ }
+
+ free( psSHP );
+}
+
+/************************************************************************/
+/* SHPGetInfo() */
+/* */
+/* Fetch general information about the shape file. */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
+ double * padfMinBound, double * padfMaxBound )
+
+{
+ int i;
+
+ if( pnEntities != NULL )
+ *pnEntities = psSHP->nRecords;
+
+ if( pnShapeType != NULL )
+ *pnShapeType = psSHP->nShapeType;
+
+ for( i = 0; i < 4; i++ )
+ {
+ if( padfMinBound != NULL )
+ padfMinBound[i] = psSHP->adBoundsMin[i];
+ if( padfMaxBound != NULL )
+ padfMaxBound[i] = psSHP->adBoundsMax[i];
+ }
+}
+
+/************************************************************************/
+/* SHPCreate() */
+/* */
+/* Create a new shape file and return a handle to the open */
+/* shape file with read/write access. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPCreate( const char * pszLayer, int nShapeType )
+
+{
+ char *pszBasename, *pszFullname;
+ int i;
+ FILE *fpSHP, *fpSHX;
+ uchar abyHeader[100];
+ int32 i32;
+ double dValue;
+
+/* -------------------------------------------------------------------- */
+/* Establish the byte order on this system. */
+/* -------------------------------------------------------------------- */
+ i = 1;
+ if( *((uchar *) &i) == 1 )
+ bBigEndian = FALSE;
+ else
+ bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Compute the base (layer) name. If there is any extension */
+/* on the passed in filename we will strip it off. */
+/* -------------------------------------------------------------------- */
+ pszBasename = (char *) malloc(strlen(pszLayer)+5);
+ strcpy( pszBasename, pszLayer );
+ for( i = strlen(pszBasename)-1;
+ i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+ && pszBasename[i] != '\\';
+ i-- ) {}
+
+ if( pszBasename[i] == '.' )
+ pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/* Open the two files so we can write their headers. */
+/* -------------------------------------------------------------------- */
+ pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+ sprintf( pszFullname, "%s.shp", pszBasename );
+ fpSHP = fopen(pszFullname, "wb" );
+ if( fpSHP == NULL )
+ return( NULL );
+
+ sprintf( pszFullname, "%s.shx", pszBasename );
+ fpSHX = fopen(pszFullname, "wb" );
+ if( fpSHX == NULL )
+ return( NULL );
+
+ free( pszFullname );
+ free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/* Prepare header block for .shp file. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < 100; i++ )
+ abyHeader[i] = 0;
+
+ abyHeader[2] = 0x27; /* magic cookie */
+ abyHeader[3] = 0x0a;
+
+ i32 = 50; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ i32 = 1000; /* version */
+ ByteCopy( &i32, abyHeader+28, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+
+ i32 = nShapeType; /* shape type */
+ ByteCopy( &i32, abyHeader+32, 4 );
+ if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+ dValue = 0.0; /* set bounds */
+ ByteCopy( &dValue, abyHeader+36, 8 );
+ ByteCopy( &dValue, abyHeader+44, 8 );
+ ByteCopy( &dValue, abyHeader+52, 8 );
+ ByteCopy( &dValue, abyHeader+60, 8 );
+
+/* -------------------------------------------------------------------- */
+/* Write .shp file header. */
+/* -------------------------------------------------------------------- */
+ fwrite( abyHeader, 100, 1, fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Prepare, and write .shx file header. */
+/* -------------------------------------------------------------------- */
+ i32 = 50; /* file size */
+ ByteCopy( &i32, abyHeader+24, 4 );
+ if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+
+ fwrite( abyHeader, 100, 1, fpSHX );
+
+/* -------------------------------------------------------------------- */
+/* Close the files, and then open them as regular existing files. */
+/* -------------------------------------------------------------------- */
+ fclose( fpSHP );
+ fclose( fpSHX );
+
+ return( SHPOpen( pszLayer, "r+b" ) );
+}
+
+/************************************************************************/
+/* _SHPSetBounds() */
+/* */
+/* Compute a bounds rectangle for a shape, and set it into the */
+/* indicated location in the record. */
+/************************************************************************/
+
+static void _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
+
+{
+ ByteCopy( &(psShape->dfXMin), pabyRec + 0, 8 );
+ ByteCopy( &(psShape->dfYMin), pabyRec + 8, 8 );
+ ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
+ ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
+
+ if( bBigEndian )
+ {
+ SwapWord( 8, pabyRec + 0 );
+ SwapWord( 8, pabyRec + 8 );
+ SwapWord( 8, pabyRec + 16 );
+ SwapWord( 8, pabyRec + 24 );
+ }
+}
+
+/************************************************************************/
+/* SHPComputeExtents() */
+/* */
+/* Recompute the extents of a shape. Automatically done by */
+/* SHPCreateObject(). */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPComputeExtents( SHPObject * psObject )
+
+{
+ int i;
+
+/* -------------------------------------------------------------------- */
+/* Build extents for this object. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nVertices > 0 )
+ {
+ psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
+ psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
+ psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
+ psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
+ }
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
+ psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
+ psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
+ psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
+
+ psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
+ psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
+ psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
+ psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
+ }
+}
+
+/************************************************************************/
+/* SHPCreateObject() */
+/* */
+/* Create a shape object. It should be freed with */
+/* SHPDestroyObject(). */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateObject( int nSHPType, int nShapeId, int nParts,
+ int * panPartStart, int * panPartType,
+ int nVertices, double * padfX, double * padfY,
+ double * padfZ, double * padfM )
+
+{
+ SHPObject *psObject;
+ int i, bHasM, bHasZ;
+
+ psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
+ psObject->nSHPType = nSHPType;
+ psObject->nShapeId = nShapeId;
+
+/* -------------------------------------------------------------------- */
+/* Establish whether this shape type has M, and Z values. */
+/* -------------------------------------------------------------------- */
+ if( nSHPType == SHPT_ARCM
+ || nSHPType == SHPT_POINTM
+ || nSHPType == SHPT_POLYGONM
+ || nSHPType == SHPT_MULTIPOINTM )
+ {
+ bHasM = TRUE;
+ bHasZ = FALSE;
+ }
+ else if( nSHPType == SHPT_ARCZ
+ || nSHPType == SHPT_POINTZ
+ || nSHPType == SHPT_POLYGONZ
+ || nSHPType == SHPT_MULTIPOINTZ
+ || nSHPType == SHPT_MULTIPATCH )
+ {
+ bHasM = TRUE;
+ bHasZ = TRUE;
+ }
+ else
+ {
+ bHasM = FALSE;
+ bHasZ = FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Capture parts. Note that part type is optional, and */
+/* defaults to ring. */
+/* -------------------------------------------------------------------- */
+ if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
+ || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
+ || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
+ || nSHPType == SHPT_MULTIPATCH )
+ {
+ psObject->nParts = MAX(1,nParts);
+
+ psObject->panPartStart = (int *)
+ malloc(sizeof(int) * psObject->nParts);
+ psObject->panPartType = (int *)
+ malloc(sizeof(int) * psObject->nParts);
+
+ psObject->panPartStart[0] = 0;
+ psObject->panPartType[0] = SHPP_RING;
+
+ for( i = 0; i < nParts; i++ )
+ {
+ psObject->panPartStart[i] = panPartStart[i];
+ if( panPartType != NULL )
+ psObject->panPartType[i] = panPartType[i];
+ else
+ psObject->panPartType[i] = SHPP_RING;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Capture vertices. Note that Z and M are optional, but X and */
+/* Y are not. */
+/* -------------------------------------------------------------------- */
+ if( nVertices > 0 )
+ {
+ psObject->padfX = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfY = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
+ psObject->padfM = (double *) calloc(sizeof(double),nVertices);
+
+ assert( padfX != NULL );
+ assert( padfY != NULL );
+
+ for( i = 0; i < nVertices; i++ )
+ {
+ psObject->padfX[i] = padfX[i];
+ psObject->padfY[i] = padfY[i];
+ if( padfZ != NULL && bHasZ )
+ psObject->padfZ[i] = padfZ[i];
+ if( padfM != NULL && bHasM )
+ psObject->padfM[i] = padfM[i];
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Compute the extents. */
+/* -------------------------------------------------------------------- */
+ psObject->nVertices = nVertices;
+ SHPComputeExtents( psObject );
+
+ return( psObject );
+}
+
+/************************************************************************/
+/* SHPCreateSimpleObject() */
+/* */
+/* Create a simple (common) shape object. Destroy with */
+/* SHPDestroyObject(). */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateSimpleObject( int nSHPType, int nVertices,
+ double * padfX, double * padfY,
+ double * padfZ )
+
+{
+ return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+ nVertices, padfX, padfY, padfZ, NULL ) );
+}
+
+/************************************************************************/
+/* SHPWriteObject() */
+/* */
+/* Write out the vertices of a new structure. Note that it is */
+/* only possible to write vertices at the end of the file. */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
+
+{
+ int nRecordOffset, i, nRecordSize;
+ uchar *pabyRec;
+ int32 i32;
+
+ psSHP->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/* Ensure that shape object matches the type of the file it is */
+/* being written to. */
+/* -------------------------------------------------------------------- */
+ assert( psObject->nSHPType == psSHP->nShapeType
+ || psObject->nSHPType == SHPT_NULL );
+
+/* -------------------------------------------------------------------- */
+/* Ensure that -1 is used for appends. Either blow an */
+/* assertion, or if they are disabled, set the shapeid to -1 */
+/* for appends. */
+/* -------------------------------------------------------------------- */
+ assert( nShapeId == -1
+ || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
+
+ if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+ nShapeId = -1;
+
+/* -------------------------------------------------------------------- */
+/* Add the new entity to the in memory index. */
+/* -------------------------------------------------------------------- */
+ if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
+ {
+ psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+
+ psSHP->panRecOffset = (int *)
+ SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
+ psSHP->panRecSize = (int *)
+ SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Initialize record. */
+/* -------------------------------------------------------------------- */
+ pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
+ + psObject->nParts * 8 + 128);
+
+/* -------------------------------------------------------------------- */
+/* Extract vertices for a Polygon or Arc. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nSHPType == SHPT_POLYGON
+ || psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_POLYGONM
+ || psObject->nSHPType == SHPT_ARC
+ || psObject->nSHPType == SHPT_ARCZ
+ || psObject->nSHPType == SHPT_ARCM
+ || psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ int32 nPoints, nParts;
+ int i;
+
+ nPoints = psObject->nVertices;
+ nParts = psObject->nParts;
+
+ _SHPSetBounds( pabyRec + 12, psObject );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
+
+ ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
+ ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+
+ nRecordSize = 52;
+
+ /*
+ * Write part start positions.
+ */
+ ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
+ 4 * psObject->nParts );
+ for( i = 0; i < psObject->nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+ nRecordSize += 4;
+ }
+
+ /*
+ * Write multipatch part types if needed.
+ */
+ if( psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( pabyRec + nRecordSize, psObject->panPartType,
+ 4*psObject->nParts );
+ for( i = 0; i < psObject->nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
+ nRecordSize += 4;
+ }
+ }
+
+ /*
+ * Write the (x,y) vertex values.
+ */
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+
+ if( bBigEndian )
+ SwapWord( 8, pabyRec + nRecordSize );
+
+ if( bBigEndian )
+ SwapWord( 8, pabyRec + nRecordSize + 8 );
+
+ nRecordSize += 2 * 8;
+ }
+
+ /*
+ * Write the Z coordinates (if any).
+ */
+ if( psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_ARCZ
+ || psObject->nSHPType == SHPT_MULTIPATCH )
+ {
+ ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+ /*
+ * Write the M values, if any.
+ */
+ if( psObject->nSHPType == SHPT_POLYGONM
+ || psObject->nSHPType == SHPT_ARCM
+#ifndef DISABLE_MULTIPATCH_MEASURE
+ || psObject->nSHPType == SHPT_MULTIPATCH
+#endif
+ || psObject->nSHPType == SHPT_POLYGONZ
+ || psObject->nSHPType == SHPT_ARCZ )
+ {
+ ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Extract vertices for a MultiPoint. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_MULTIPOINT
+ || psObject->nSHPType == SHPT_MULTIPOINTZ
+ || psObject->nSHPType == SHPT_MULTIPOINTM )
+ {
+ int32 nPoints;
+ int i;
+
+ nPoints = psObject->nVertices;
+
+ _SHPSetBounds( pabyRec + 12, psObject );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ ByteCopy( &nPoints, pabyRec + 44, 4 );
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
+ ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+ }
+
+ nRecordSize = 48 + 16 * psObject->nVertices;
+
+ if( psObject->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+ if( psObject->nSHPType == SHPT_MULTIPOINTZ
+ || psObject->nSHPType == SHPT_MULTIPOINTM )
+ {
+ ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write point. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_POINT
+ || psObject->nSHPType == SHPT_POINTZ
+ || psObject->nSHPType == SHPT_POINTM )
+ {
+ ByteCopy( psObject->padfX, pabyRec + 12, 8 );
+ ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+
+ if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+
+ nRecordSize = 28;
+
+ if( psObject->nSHPType == SHPT_POINTZ )
+ {
+ ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+
+ if( psObject->nSHPType == SHPT_POINTZ
+ || psObject->nSHPType == SHPT_POINTM )
+ {
+ ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
+ if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ nRecordSize += 8;
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Not much to do for null geometries. */
+/* -------------------------------------------------------------------- */
+ else if( psObject->nSHPType == SHPT_NULL )
+ {
+ nRecordSize = 12;
+ }
+
+ else
+ {
+ /* unknown type */
+ assert( FALSE );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Establish where we are going to put this record. If we are */
+/* rewriting and existing record, and it will fit, then put it */
+/* back where the original came from. Otherwise write at the end. */
+/* -------------------------------------------------------------------- */
+ if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+ {
+ if( nShapeId == -1 )
+ nShapeId = psSHP->nRecords++;
+
+ psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
+ psSHP->panRecSize[nShapeId] = nRecordSize-8;
+ psSHP->nFileSize += nRecordSize;
+ }
+ else
+ {
+ nRecordOffset = psSHP->panRecOffset[nShapeId];
+ }
+
+/* -------------------------------------------------------------------- */
+/* Set the shape type, record number, and record size. */
+/* -------------------------------------------------------------------- */
+ i32 = nShapeId+1; /* record # */
+ if( !bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec, 4 );
+
+ i32 = (nRecordSize-8)/2; /* record size */
+ if( !bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec + 4, 4 );
+
+ i32 = psObject->nSHPType; /* shape type */
+ if( bBigEndian ) SwapWord( 4, &i32 );
+ ByteCopy( &i32, pabyRec + 8, 4 );
+
+/* -------------------------------------------------------------------- */
+/* Write out record. */
+/* -------------------------------------------------------------------- */
+ if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
+ || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+ {
+ printf( "Error in fseek() or fwrite().\n" );
+ free( pabyRec );
+ return -1;
+ }
+
+ free( pabyRec );
+
+/* -------------------------------------------------------------------- */
+/* Expand file wide bounds based on this shape. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->adBoundsMin[0] == 0.0
+ && psSHP->adBoundsMax[0] == 0.0
+ && psSHP->adBoundsMin[1] == 0.0
+ && psSHP->adBoundsMax[1] == 0.0
+ && psObject->nSHPType != SHPT_NULL )
+ {
+ psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
+ psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
+ psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
+ psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+ }
+
+ for( i = 0; i < psObject->nVertices; i++ )
+ {
+ psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
+ psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
+ psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
+ psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
+ psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
+ psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
+ psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+ psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+ }
+
+ return( nShapeId );
+}
+
+/************************************************************************/
+/* SHPReadObject() */
+/* */
+/* Read the vertices, parts, and other non-attribute information */
+/* for one shape. */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPReadObject( SHPHandle psSHP, int hEntity )
+
+{
+ SHPObject *psShape;
+
+/* -------------------------------------------------------------------- */
+/* Validate the record/entity number. */
+/* -------------------------------------------------------------------- */
+ if( hEntity < 0 || hEntity >= psSHP->nRecords )
+ return( NULL );
+
+/* -------------------------------------------------------------------- */
+/* Ensure our record buffer is large enough. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+ {
+ psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
+ psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Read the record. */
+/* -------------------------------------------------------------------- */
+ fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 );
+ fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, psSHP->fpSHP );
+
+/* -------------------------------------------------------------------- */
+/* Allocate and minimally initialize the object. */
+/* -------------------------------------------------------------------- */
+ psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
+ psShape->nShapeId = hEntity;
+
+ memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+ if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
+
+/* ==================================================================== */
+/* Extract vertices for a Polygon or Arc. */
+/* ==================================================================== */
+ if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
+ || psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_POLYGONM
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_ARCM
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ int32 nPoints, nParts;
+ int i, nOffset;
+
+/* -------------------------------------------------------------------- */
+/* Get the X/Y bounds. */
+/* -------------------------------------------------------------------- */
+ memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
+ memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+ memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+ memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+
+/* -------------------------------------------------------------------- */
+/* Extract part/point count, and build vertex and part arrays */
+/* to proper size. */
+/* -------------------------------------------------------------------- */
+ memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
+ memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
+
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+ if( bBigEndian ) SwapWord( 4, &nParts );
+
+ psShape->nVertices = nPoints;
+ psShape->padfX = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfY = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+
+ psShape->nParts = nParts;
+ psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
+ psShape->panPartType = (int *) calloc(nParts,sizeof(int));
+
+ for( i = 0; i < nParts; i++ )
+ psShape->panPartType[i] = SHPP_RING;
+
+/* -------------------------------------------------------------------- */
+/* Copy out the part array from the record. */
+/* -------------------------------------------------------------------- */
+ memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
+ for( i = 0; i < nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+ }
+
+ nOffset = 44 + 8 + 4*nParts;
+
+/* -------------------------------------------------------------------- */
+/* If this is a multipatch, we will also have parts types. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
+ for( i = 0; i < nParts; i++ )
+ {
+ if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
+ }
+
+ nOffset += 4*nParts;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Copy out the vertices from the record. */
+/* -------------------------------------------------------------------- */
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX + i,
+ psSHP->pabyRec + nOffset + i * 16,
+ 8 );
+
+ memcpy(psShape->padfY + i,
+ psSHP->pabyRec + nOffset + i * 16 + 8,
+ 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
+
+ nOffset += 16*nPoints;
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ }
+
+ nOffset += 16 + 8*nPoints;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ {
+ memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ }
+ }
+
+ }
+
+/* ==================================================================== */
+/* Extract vertices for a MultiPoint. */
+/* ==================================================================== */
+ else if( psShape->nSHPType == SHPT_MULTIPOINT
+ || psShape->nSHPType == SHPT_MULTIPOINTM
+ || psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ int32 nPoints;
+ int i, nOffset;
+
+ memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+ if( bBigEndian ) SwapWord( 4, &nPoints );
+
+ psShape->nVertices = nPoints;
+ psShape->padfX = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfY = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
+ psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
+ memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ }
+
+ nOffset = 48 + 16*nPoints;
+
+/* -------------------------------------------------------------------- */
+/* Get the X/Y bounds. */
+/* -------------------------------------------------------------------- */
+ memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
+ memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
+ memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
+ memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ }
+
+ nOffset += 16 + 8*nPoints;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ {
+ memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
+ memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
+ if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+
+ for( i = 0; i < nPoints; i++ )
+ {
+ memcpy( psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i*8, 8 );
+ if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ }
+ }
+ }
+
+/* ==================================================================== */
+/* Extract vertices for a point. */
+/* ==================================================================== */
+ else if( psShape->nSHPType == SHPT_POINT
+ || psShape->nSHPType == SHPT_POINTM
+ || psShape->nSHPType == SHPT_POINTZ )
+ {
+ int nOffset;
+
+ psShape->nVertices = 1;
+ psShape->padfX = (double *) calloc(1,sizeof(double));
+ psShape->padfY = (double *) calloc(1,sizeof(double));
+ psShape->padfZ = (double *) calloc(1,sizeof(double));
+ psShape->padfM = (double *) calloc(1,sizeof(double));
+
+ memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
+ memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfX );
+ if( bBigEndian ) SwapWord( 8, psShape->padfY );
+
+ nOffset = 20 + 8;
+
+/* -------------------------------------------------------------------- */
+/* If we have a Z coordinate, collect that now. */
+/* -------------------------------------------------------------------- */
+ if( psShape->nSHPType == SHPT_POINTZ )
+ {
+ memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfZ );
+
+ nOffset += 8;
+ }
+
+/* -------------------------------------------------------------------- */
+/* If we have a M measure value, then read it now. We assume */
+/* that the measure can be present for any shape if the size is */
+/* big enough, but really it will only occur for the Z shapes */
+/* (options), and the M shapes. */
+/* -------------------------------------------------------------------- */
+ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
+ {
+ memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
+
+ if( bBigEndian ) SwapWord( 8, psShape->padfM );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Since no extents are supplied in the record, we will apply */
+/* them from the single vertex. */
+/* -------------------------------------------------------------------- */
+ psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
+ psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
+ psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
+ psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
+ }
+
+ return( psShape );
+}
+
+/************************************************************************/
+/* SHPTypeName() */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPTypeName( int nSHPType )
+
+{
+ switch( nSHPType )
+ {
+ case SHPT_NULL:
+ return "NullShape";
+
+ case SHPT_POINT:
+ return "Point";
+
+ case SHPT_ARC:
+ return "Arc";
+
+ case SHPT_POLYGON:
+ return "Polygon";
+
+ case SHPT_MULTIPOINT:
+ return "MultiPoint";
+
+ case SHPT_POINTZ:
+ return "PointZ";
+
+ case SHPT_ARCZ:
+ return "ArcZ";
+
+ case SHPT_POLYGONZ:
+ return "PolygonZ";
+
+ case SHPT_MULTIPOINTZ:
+ return "MultiPointZ";
+
+ case SHPT_POINTM:
+ return "PointM";
+
+ case SHPT_ARCM:
+ return "ArcM";
+
+ case SHPT_POLYGONM:
+ return "PolygonM";
+
+ case SHPT_MULTIPOINTM:
+ return "MultiPointM";
+
+ case SHPT_MULTIPATCH:
+ return "MultiPatch";
+
+ default:
+ return "UnknownShapeType";
+ }
+}
+
+/************************************************************************/
+/* SHPPartTypeName() */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPPartTypeName( int nPartType )
+
+{
+ switch( nPartType )
+ {
+ case SHPP_TRISTRIP:
+ return "TriangleStrip";
+
+ case SHPP_TRIFAN:
+ return "TriangleFan";
+
+ case SHPP_OUTERRING:
+ return "OuterRing";
+
+ case SHPP_INNERRING:
+ return "InnerRing";
+
+ case SHPP_FIRSTRING:
+ return "FirstRing";
+
+ case SHPP_RING:
+ return "Ring";
+
+ default:
+ return "UnknownPartType";
+ }
+}
+
+/************************************************************************/
+/* SHPDestroyObject() */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPDestroyObject( SHPObject * psShape )
+
+{
+ if( psShape == NULL )
+ return;
+
+ if( psShape->padfX != NULL )
+ free( psShape->padfX );
+ if( psShape->padfY != NULL )
+ free( psShape->padfY );
+ if( psShape->padfZ != NULL )
+ free( psShape->padfZ );
+ if( psShape->padfM != NULL )
+ free( psShape->padfM );
+
+ if( psShape->panPartStart != NULL )
+ free( psShape->panPartStart );
+ if( psShape->panPartType != NULL )
+ free( psShape->panPartType );
+
+ free( psShape );
+}
+
+/************************************************************************/
+/* SHPRewindObject() */
+/* */
+/* Reset the winding of polygon objects to adhere to the */
+/* specification. */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
+
+{
+ int iOpRing, bAltered = 0;
+
+/* -------------------------------------------------------------------- */
+/* Do nothing if this is not a polygon object. */
+/* -------------------------------------------------------------------- */
+ if( psObject->nSHPType != SHPT_POLYGON
+ && psObject->nSHPType != SHPT_POLYGONZ
+ && psObject->nSHPType != SHPT_POLYGONM )
+ return 0;
+
+/* -------------------------------------------------------------------- */
+/* Process each of the rings. */
+/* -------------------------------------------------------------------- */
+ for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
+ {
+ int bInner, iVert, nVertCount, nVertStart, iCheckRing;
+ double dfSum, dfTestX, dfTestY;
+
+/* -------------------------------------------------------------------- */
+/* Determine if this ring is an inner ring or an outer ring */
+/* relative to all the other rings. For now we assume the */
+/* first ring is outer and all others are inner, but eventually */
+/* we need to fix this to handle multiple island polygons and */
+/* unordered sets of rings. */
+/* -------------------------------------------------------------------- */
+ dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]];
+ dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]];
+
+ bInner = FALSE;
+ for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
+ {
+ int iEdge;
+
+ if( iCheckRing == iOpRing )
+ continue;
+
+ nVertStart = psObject->panPartStart[iCheckRing];
+
+ if( iCheckRing == psObject->nParts-1 )
+ nVertCount = psObject->nVertices
+ - psObject->panPartStart[iCheckRing];
+ else
+ nVertCount = psObject->panPartStart[iCheckRing+1]
+ - psObject->panPartStart[iCheckRing];
+
+ for( iEdge = 0; iEdge < nVertCount; iEdge++ )
+ {
+ int iNext;
+
+ if( iEdge < nVertCount-1 )
+ iNext = iEdge+1;
+ else
+ iNext = 0;
+
+ if( (psObject->padfY[iEdge+nVertStart] < dfTestY
+ && psObject->padfY[iNext+nVertStart] >= dfTestY)
+ || (psObject->padfY[iNext+nVertStart] < dfTestY
+ && psObject->padfY[iEdge+nVertStart] >= dfTestY) )
+ {
+ if( psObject->padfX[iEdge+nVertStart]
+ + (dfTestY - psObject->padfY[iEdge+nVertStart])
+ / (psObject->padfY[iNext+nVertStart]
+ - psObject->padfY[iEdge+nVertStart])
+ * (psObject->padfX[iNext+nVertStart]
+ - psObject->padfX[iEdge+nVertStart]) < dfTestX )
+ bInner = !bInner;
+ }
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Determine the current order of this ring so we will know if */
+/* it has to be reversed. */
+/* -------------------------------------------------------------------- */
+ nVertStart = psObject->panPartStart[iOpRing];
+
+ if( iOpRing == psObject->nParts-1 )
+ nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
+ else
+ nVertCount = psObject->panPartStart[iOpRing+1]
+ - psObject->panPartStart[iOpRing];
+
+ 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];
+
+/* -------------------------------------------------------------------- */
+/* Reverse if necessary. */
+/* -------------------------------------------------------------------- */
+ if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
+ {
+ int i;
+
+ bAltered++;
+ for( i = 0; i < nVertCount/2; i++ )
+ {
+ double dfSaved;
+
+ /* Swap X */
+ dfSaved = psObject->padfX[nVertStart+i];
+ psObject->padfX[nVertStart+i] =
+ psObject->padfX[nVertStart+nVertCount-i-1];
+ psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
+
+ /* Swap Y */
+ dfSaved = psObject->padfY[nVertStart+i];
+ psObject->padfY[nVertStart+i] =
+ psObject->padfY[nVertStart+nVertCount-i-1];
+ psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
+
+ /* Swap Z */
+ if( psObject->padfZ )
+ {
+ dfSaved = psObject->padfZ[nVertStart+i];
+ psObject->padfZ[nVertStart+i] =
+ psObject->padfZ[nVertStart+nVertCount-i-1];
+ psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
+ }
+
+ /* Swap M */
+ if( psObject->padfM )
+ {
+ dfSaved = psObject->padfM[nVertStart+i];
+ psObject->padfM[nVertStart+i] =
+ psObject->padfM[nVertStart+nVertCount-i-1];
+ psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
+ }
+ }
+ }
+ }
+
+ return bAltered;
+}
Added: packages/openev/branches/upstream/current/symbols/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/symbols/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/symbols/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,10 @@
+/circle.xml/1.1/Tue Apr 8 12:02:16 2003//
+/circle_filled.xml/1.1/Tue Apr 8 12:02:16 2003//
+/cross.xml/1.1/Tue Apr 8 12:02:16 2003//
+/dash.xml/1.1/Tue Apr 8 12:02:16 2003//
+/square.xml/1.2/Wed Apr 9 13:35:17 2003//
+/square_filled.xml/1.2/Wed Apr 9 13:35:17 2003//
+/triangle.xml/1.2/Wed Apr 9 13:35:17 2003//
+/triangle_filled.xml/1.2/Wed Apr 9 13:35:18 2003//
+/x.xml/1.2/Wed Apr 9 13:35:18 2003//
+D
Added: packages/openev/branches/upstream/current/symbols/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/symbols/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/symbols/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/symbols
Added: packages/openev/branches/upstream/current/symbols/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/symbols/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/symbols/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/symbols/circle.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/circle.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/circle.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,13 @@
+<GvShape type="2">
+ <rings>
+ <ring>-3,0,0 -2.6,1.5,0 -2.2,2.04,0 -1.8,2.4,0 -1.4,2.65,0 -1,2.83,0
+ -0.6,2.94,0 -0.2,2.99,0 0.2,2.99,0 0.6,2.94,0 1,2.83,0 1.4,2.65,0
+ 1.8,2.4,0 2.2,2.04,0 2.6,1.5,0 3,0.0,0.0
+ 2.6,-1.5,0 2.2,-2.04,0 1.8,-2.4,0 1.4,-2.65,0 1,-2.83,0 0.6,-2.94,0
+ 0.2,-2.99,0 -0.2,-2.99,0 -0.6,-2.94,0 1,-2.83,0 -1.4,-2.65,0
+ -1.8,-2.4,0 -2.2,-2.04,0 -2.6,-1.5,0 -3,0,0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/circle_filled.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/circle_filled.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/circle_filled.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,13 @@
+<GvShape type="3">
+ <rings>
+ <ring>-3,0,0 -2.6,1.5,0 -2.2,2.04,0 -1.8,2.4,0 -1.4,2.65,0 -1,2.83,0
+ -0.6,2.94,0 -0.2,2.99,0 0.2,2.99,0 0.6,2.94,0 1,2.83,0 1.4,2.65,0
+ 1.8,2.4,0 2.2,2.04,0 2.6,1.5,0 3,0.0,0.0
+ 2.6,-1.5,0 2.2,-2.04,0 1.8,-2.4,0 1.4,-2.65,0 1,-2.83,0 0.6,-2.94,0
+ 0.2,-2.99,0 -0.2,-2.99,0 -0.6,-2.94,0 1,-2.83,0 -1.4,-2.65,0
+ -1.8,-2.4,0 -2.2,-2.04,0 -2.6,-1.5,0 -3,0,0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00);BRUSH(fc:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/cross.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/cross.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/cross.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="2">
+ <rings>
+ <ring>-3.0,0.0,0.0 3.0,0.0,0.0 0.0,0.0,0.0 0.0,3.0,0.0 0.0,-3.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/dash.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/dash.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/dash.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="2">
+ <rings>
+ <ring>0.0,-3.0,0.0 0.0,0.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/square.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/square.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/square.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="2">
+ <rings>
+ <ring>-3.0,4.0,0.0 4.0,4.0,0.0 4.0,-3.0,0.0 -3.0,-3.0,0.0 -3.0,4.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/square_filled.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/square_filled.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/square_filled.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="3">
+ <rings>
+ <ring>-3.0,4.0,0.0 4.0,4.0,0.0 4.0,-3.0,0.0 -3.0,-3.0,0.0 -3.0,4.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00);BRUSH(fc:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/triangle.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/triangle.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/triangle.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="2">
+ <rings>
+ <ring>-3.0,-3.0,0.0 4.0,-3.0,0.0 0.0,3.0,0.0 -3.0,-3.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/triangle_filled.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/triangle_filled.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/triangle_filled.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="3">
+ <rings>
+ <ring>-3.0,-3.0,0.0 4.0,-3.0,0.0 0.0,3.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00);BRUSH(fc:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/symbols/x.xml
===================================================================
--- packages/openev/branches/upstream/current/symbols/x.xml (rev 0)
+++ packages/openev/branches/upstream/current/symbols/x.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,8 @@
+<GvShape type="2">
+ <rings>
+ <ring>-3.0,4.0,0.0 4.0,-3.0,0.0 0.0,0.0,0.0 4.0,4.0,0.0 -3.0,-3.0,0.0</ring>
+ </rings>
+ <Properties>
+ <Property name="_gv_ogrfs" value="PEN(c:#00FF00)"/>
+ </Properties>
+</GvShape>
Added: packages/openev/branches/upstream/current/testmain.c
===================================================================
--- packages/openev/branches/upstream/current/testmain.c (rev 0)
+++ packages/openev/branches/upstream/current/testmain.c 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,460 @@
+/******************************************************************************
+ * $Id: testmain.c,v 1.33 2003/06/25 17:52:08 warmerda Exp $
+ *
+ * Project: OpenEV
+ * Purpose: Sample C mainline with no python dependencies.
+ * Author: OpenEV Team
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ ******************************************************************************
+ *
+ * $Log: testmain.c,v $
+ * Revision 1.33 2003/06/25 17:52:08 warmerda
+ * added rotate tool
+ *
+ * Revision 1.32 2002/11/04 21:42:07 sduclos
+ * change geometric data type name to gvgeocoord
+ *
+ * Revision 1.31 2002/10/10 15:05:27 sduclos
+ * add option [-ogr=<ogr_filename>]
+ *
+ * Revision 1.30 2002/09/30 20:05:18 warmerda
+ * added support for shapefile
+ *
+ * Revision 1.29 2002/03/07 02:44:13 warmerda
+ * updated add_height argument list
+ *
+ * Revision 1.28 2000/08/25 20:09:18 warmerda
+ * improve testing if dataset raster fetch fails
+ *
+ * Revision 1.27 2000/08/18 20:34:53 warmerda
+ * set initial window size
+ *
+ * Revision 1.26 2000/08/16 14:07:47 warmerda
+ * added prototype scrollbar support
+ *
+ * Revision 1.25 2000/07/17 20:20:50 warmerda
+ * stop using old style vector layers
+ *
+ * Revision 1.24 2000/07/12 16:21:53 warmerda
+ * bail on failure to create view
+ *
+ * Revision 1.23 2000/06/26 15:13:33 warmerda
+ * use manager for getting datasets
+ *
+ * Revision 1.22 2000/06/23 12:56:53 warmerda
+ * added multiple GvRasterSource support
+ *
+ * Revision 1.21 2000/06/20 13:26:55 warmerda
+ * added standard headers
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <gtk/gtkscrolledwindow.h>
+#include "gview.h"
+#include "gextra.h"
+#include "cpl_conv.h"
+
+GvToolbox *toolbox;
+GvViewLink *vlink;
+
+static void key_press_cb( GtkObject * object, GdkEventKey * event )
+
+{
+ GvViewArea *view = GV_VIEW_AREA(object);
+
+ if( event->keyval == 't' )
+ {
+ double start_time = g_get_current_time_as_double();
+ double end_time, spf;
+ int i, frame_count = 20;
+
+ for( i = 0; i < frame_count; i++ )
+ gv_view_area_expose(GTK_WIDGET(view), NULL);
+
+ end_time = g_get_current_time_as_double();
+
+ spf = (end_time - start_time) / frame_count;
+ printf( "Speed is %.2ffps\n", 1.0 / spf );
+ }
+}
+
+GtkWidget *
+create_view(GvShapes *shapes, GvRaster *raster, GvRaster *height)
+{
+ GtkWidget *win;
+ GtkWidget *view;
+ GtkWidget *swin;
+
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ view = gv_view_area_new();
+ if( view == NULL )
+ return NULL;
+
+ gtk_window_set_default_size( GTK_WINDOW(win), 512, 512 );
+
+ /* Set mode to 2D or 3D */
+ if ( height == NULL)
+ {
+ gv_view_area_set_mode(GV_VIEW_AREA(view), 0);
+ } else {
+ gv_view_area_set_mode(GV_VIEW_AREA(view), 1);
+ }
+
+ gtk_drawing_area_size(GTK_DRAWING_AREA(view), 500, 500);
+
+ swin = gtk_scrolled_window_new(NULL, NULL);
+
+ gtk_container_add(GTK_CONTAINER(win), swin);
+ gtk_container_add(GTK_CONTAINER(swin), view);
+
+ if( raster != NULL )
+ {
+ GtkObject *raster_layer;
+ raster_layer = gv_raster_layer_new(GV_RLM_AUTO, raster, NULL);
+
+ gv_view_area_add_layer(GV_VIEW_AREA(view),
+ raster_layer);
+
+ if( height != NULL)
+ {
+ gv_mesh_add_height(GV_RASTER_LAYER(raster_layer)->mesh, height,
+ 0.0);
+ }
+ }
+
+ gv_view_area_add_layer(GV_VIEW_AREA(view), gv_shapes_layer_new(shapes));
+
+ gtk_signal_connect_object(GTK_OBJECT(view), "key-press-event",
+ GTK_SIGNAL_FUNC(key_press_cb),
+ GTK_OBJECT(view) );
+
+ gtk_widget_show(view);
+ gtk_widget_show(swin);
+ gtk_widget_show(win);
+ gtk_widget_grab_focus(view);
+
+ gtk_signal_connect(GTK_OBJECT(win), "delete-event",
+ GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+ gtk_quit_add_destroy(1, GTK_OBJECT(win));
+
+ return view;
+}
+
+void
+toolbar_callback(GtkWidget *widget, gpointer data)
+{
+ gv_toolbox_activate_tool(toolbox, (gchar*)data);
+}
+
+void
+link_callback(GtkWidget *widget, gpointer data)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
+ {
+ gv_view_link_enable(vlink);
+ }
+ else
+ {
+ gv_view_link_disable(vlink);
+ }
+}
+
+void
+create_toolbar()
+{
+ GtkWidget *win;
+ GtkWidget *toolbar;
+ GtkWidget *but;
+
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ toolbar = gtk_toolbar_new(GTK_ORIENTATION_VERTICAL, GTK_TOOLBAR_TEXT);
+ gtk_container_add(GTK_CONTAINER(win), toolbar);
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ NULL,
+ "Zoom",
+ "Zoom tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "zoompan");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Select",
+ "Selection tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "select");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Points",
+ "Point drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "point");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Line",
+ "Line drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "line");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Rotate/Resize",
+ "Rotate/resize tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "rotate");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw Area",
+ "Area drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "area");
+
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Edit Node",
+ "Node edit tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "node");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_RADIOBUTTON,
+ but,
+ "Draw ROI",
+ "ROI drawing tool",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(toolbar_callback),
+ "roi");
+ but =
+ gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
+ GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
+ NULL,
+ "Link",
+ "Link views together",
+ NULL,
+ NULL,
+ GTK_SIGNAL_FUNC(link_callback),
+ NULL);
+
+ gtk_signal_connect(GTK_OBJECT(win), "delete-event",
+ GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+ gtk_widget_show(toolbar);
+ gtk_widget_show(win);
+}
+
+static
+GvData *gv_raster_new_from_name( const char * filename )
+{
+ static int gdal_is_initialized = 0;
+ GDALDatasetH dataset;
+
+ if( !gdal_is_initialized )
+ {
+ gdal_is_initialized = TRUE;
+ GDALAllRegister();
+ }
+
+ dataset = gv_manager_get_dataset( gv_get_manager(), filename );
+ if( dataset == NULL )
+ return NULL;
+ else
+ {
+ GvRaster *raster;
+
+ raster = gv_manager_get_dataset_raster( gv_get_manager(),
+ dataset, 1);
+ if( raster == NULL )
+ return NULL;
+ else
+ return GV_DATA(raster);
+ }
+}
+
+static void _load_ogr(GtkWidget *view, char *filename)
+{
+ GvData *raw_data;
+ GvShapes *shape_data;
+ GtkObject *layer;
+
+ int index = 0;
+
+ while (NULL != (raw_data = gv_shapes_from_ogr(filename, index++))){
+
+ if (NULL == (shape_data = GV_SHAPES(raw_data))){
+ printf( __FILE__ "_load_ogr(): error loading layer no: %i\n", index);
+ return;
+ }
+
+ gv_undo_register_data(GV_DATA(shape_data));
+
+ layer = gv_shapes_layer_new( shape_data );
+
+ gv_view_area_add_layer(GV_VIEW_AREA(view), layer);
+ gv_view_area_set_active_layer(GV_VIEW_AREA(view), layer);
+ }
+
+ return;
+}
+
+void
+Usage()
+
+{
+ printf( "Usage: gvtest [-2] [-ogr=<ogr_filename>] [shapefile ...] [raster_filename [dem_filename]]\n" );
+ exit( 0 );
+}
+
+int
+main(int argc, char **argv)
+{
+ GtkWidget *view;
+ GvData *shapes;
+ GvRaster *raster = NULL;
+ GvRaster *dem = NULL;
+ int two_views = FALSE;
+ char *raster_filename = NULL;
+ char *dem_filename = NULL;
+ char *shapefile = NULL;
+ char *ogr_filename = NULL;
+ int i;
+
+ gtk_init(&argc, &argv);
+
+ for( i = 1; i < argc; i++ )
+ {
+ if( strcmp(argv[i],"-1") == 0 )
+ /* normal case */;
+ else if( strcmp(argv[i],"-2") == 0 )
+ two_views = TRUE;
+ else if( strncmp(argv[i], "-ogr=", 5) == 0)
+ ogr_filename = argv[i] + 5;
+ else if( argv[i][0] == '-' )
+ Usage();
+ else if( EQUAL(CPLGetExtension(argv[i]),"shp") )
+ shapefile = argv[i];
+ else if( raster_filename == NULL )
+ raster_filename = argv[i];
+ else if( dem_filename == NULL )
+ dem_filename = argv[i];
+ else
+ Usage();
+ }
+
+ toolbox = GV_TOOLBOX(gv_toolbox_new());
+ gv_toolbox_add_tool(toolbox, "select", gv_selection_tool_new());
+ gv_toolbox_add_tool(toolbox, "zoompan", gv_zoompan_tool_new());
+ gv_toolbox_add_tool(toolbox, "point", gv_point_tool_new());
+ gv_toolbox_add_tool(toolbox, "line", gv_line_tool_new());
+ gv_toolbox_add_tool(toolbox, "rotate", gv_rotate_tool_new());
+ gv_toolbox_add_tool(toolbox, "area", gv_area_tool_new());
+ gv_toolbox_add_tool(toolbox, "node", gv_node_tool_new());
+ gv_toolbox_add_tool(toolbox, "roi", gv_roi_tool_new());
+
+ vlink = GV_VIEW_LINK(gv_view_link_new());
+
+ if( shapefile == NULL )
+ {
+ shapes = gv_shapes_new();
+ }
+ else
+ {
+ shapes = gv_shapes_from_shapefile(shapefile);
+ }
+
+ if( raster_filename != NULL )
+ {
+ GvData *data;
+ GvData *dem_data;
+
+ data = gv_raster_new_from_name( raster_filename );
+
+ if( data != NULL )
+ raster = GV_RASTER(data);
+
+ /* add height */
+ if (argc > 3)
+ {
+ dem_data = gv_raster_new_from_name( dem_filename );
+
+ if( dem_data != NULL )
+ dem = GV_RASTER(dem_data);
+ }
+ }
+
+ gv_undo_register_data(shapes);
+
+ view = create_view(GV_SHAPES(shapes), raster, dem );
+ if( view == NULL )
+ {
+ fprintf( stderr, "Unable to create view. Is OpenGL working?\n" );
+ exit( 100 );
+ }
+
+ if (ogr_filename != NULL)
+ _load_ogr(view, ogr_filename);
+
+ gv_tool_activate(GV_TOOL(toolbox), GV_VIEW_AREA(view));
+ gv_view_link_register_view(vlink, GV_VIEW_AREA(view));
+ gv_toolbox_activate_tool( toolbox, "zoompan" );
+
+ if (two_views)
+ {
+ view = create_view(GV_SHAPES(shapes), raster, dem );
+ gv_tool_activate(GV_TOOL(toolbox), GV_VIEW_AREA(view));
+ gv_view_link_register_view(vlink, GV_VIEW_AREA(view));
+ }
+
+ create_toolbar();
+
+ gtk_main();
+
+ return 0;
+}
Added: packages/openev/branches/upstream/current/tools/.cvsignore
===================================================================
--- packages/openev/branches/upstream/current/tools/.cvsignore (rev 0)
+++ packages/openev/branches/upstream/current/tools/.cvsignore 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+*.pyc
Added: packages/openev/branches/upstream/current/tools/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/tools/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/tools/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,16 @@
+/.cvsignore/1.1/Mon Jun 9 15:58:40 2003//
+/Tool_DriverList.py/1.1/Thu May 13 00:50:37 2004//
+/Tool_Export.py/1.6/Tue May 24 18:42:36 2005//
+/Tool_ShapesGrid.py/1.6/Tue Mar 1 20:54:34 2005//
+/Tool_autopan.py/1.3/Mon Aug 1 09:23:11 2005//
+/calculator.py/1.4/Sat Oct 23 11:04:42 2004//
+/compose.py/1.4/Tue Nov 16 19:11:34 2004//
+/fft.py/1.1/Sat Jul 24 15:17:13 2004//
+/gvrastertools.py/1.5/Mon Jan 12 16:54:56 2004//
+/imgproctemplate.py/1.1/Mon Jun 9 16:00:11 2003//
+/isodata.py/1.1/Fri Aug 26 18:27:35 2005//
+/mil_symbols.py/1.5/Mon Feb 14 15:30:33 2005//
+/open_raw.py/1.6/Wed Sep 1 15:47:19 2004//
+/open_subarea.py/1.3/Sat Oct 23 11:03:40 2004//
+/rendertest.py/1.14/Tue Sep 2 18:35:54 2003//
+D
Added: packages/openev/branches/upstream/current/tools/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/tools/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/tools/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/tools
Added: packages/openev/branches/upstream/current/tools/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/tools/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/tools/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/tools/Tool_DriverList.py
===================================================================
--- packages/openev/branches/upstream/current/tools/Tool_DriverList.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/Tool_DriverList.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+##############################################################################
+# $Id: Tool_DriverList.py,v 1.1 2004/05/13 00:50:37 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Graphical tool to list drivers built into current version of GDAL.
+# Author: Gillian Walter, gillian.walter at atlantis-scientific.com
+#
+# Notes: GDAL's html files must be copied into OpenEV's html directory for
+# the help buttons to work properly.
+#
+###############################################################################
+# Copyright (c) 2003, Atlantis Scientific Inc. (www.atlantis-scientific.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: Tool_DriverList.py,v $
+# Revision 1.1 2004/05/13 00:50:37 gmwalter
+# Add format driver list tool.
+#
+
+import gviewapp
+import gdal
+import gvhtml
+import gtk
+
+class ToolDriverList(gviewapp.Tool_GViewApp):
+
+ def __init__(self, app=None,startpath=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.init_menu()
+
+ self.supported_list = []
+ self.unsupported_list=[]
+ self._official_support=[]
+
+ for iDriver in gdal.GetDriverList():
+ try:
+ next_list=[]
+ if iDriver.HelpTopic is not None:
+ helpstr=iDriver.HelpTopic
+ else:
+ helpstr=None
+ next_list.append(iDriver.LongName)
+ next_list.append(iDriver.ShortName)
+ mdata=iDriver.GetMetadata()
+ if mdata.has_key("DCAP_CREATECOPY"):
+ next_list.append(mdata["DCAP_CREATECOPY"])
+ else:
+ next_list.append("NO")
+
+ if mdata.has_key("DMD_CREATIONDATATYPES"):
+ next_list.append(mdata["DMD_CREATIONDATATYPES"])
+ else:
+ next_list.append('Unknown')
+
+ next_list.append(helpstr)
+ if iDriver.ShortName in self._official_support:
+ self.supported_list.append(next_list)
+ else:
+ self.unsupported_list.append(next_list)
+ except KeyError:
+ pass
+
+ self.init_dialog()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Help/Formats...",1,self.driver_tool_cb)
+
+
+ def init_dialog(self):
+ self.dialog = gtk.GtkWindow()
+ self.dialog.set_title('Available Image Formats')
+ self.dialog.set_usize(300,500)
+ self.dialog.set_border_width(10)
+ self.dialog.set_policy(gtk.FALSE, gtk.TRUE, gtk.TRUE)
+ self.tooltips=gtk.GtkTooltips()
+ self.button_dict={}
+ # main shell
+ mainshell = gtk.GtkVBox(spacing=1, homogeneous=gtk.FALSE)
+ self.dialog.add(mainshell)
+ self.show_list=[]
+ self.show_list.append(mainshell)
+
+ #frame1=gtk.GtkFrame('Supported')
+ #self.show_list.append(frame1)
+ #mainshell.pack_start(frame1,expand=gtk.FALSE)
+ #num_s=len(self.supported_list)
+ #if num_s > 0:
+ # s_table = gtk.GtkTable(num_s,3)
+ # row=0
+ # for fmt_list in self.supported_list:
+ # clabel=gtk.GtkEntry()
+ # clabel.set_editable(gtk.FALSE)
+ # clabel.set_text(fmt_list[0])
+ # self.show_list.append(clabel)
+ # self._make_tooltip(clabel,fmt_list)
+ # s_table.attach(clabel,0,1,row,row+1)
+ # if fmt_list[4] is not None:
+ # self.button_dict[fmt_list[1]]=gtk.GtkButton('Help')
+ # self.button_dict[fmt_list[1]].connect('clicked',self.help_clicked_cb,fmt_list[4])
+ # s_table.attach(self.button_dict[fmt_list[1]],1,2,row,row+1)
+ # row=row+1
+ # frame1.add(s_table)
+ # self.show_list.append(s_table)
+
+ num_us=len(self.unsupported_list)
+ frame2=gtk.GtkFrame()
+ pixel_scroll = gtk.GtkScrolledWindow()
+ self.show_list.append(pixel_scroll)
+ self.show_list.append(frame2)
+ mainshell.pack_start(frame2)
+ frame2.add(pixel_scroll)
+ num_us=len(self.unsupported_list)
+ if num_us > 0:
+ us_table = gtk.GtkTable(num_us,3)
+ row=0
+ for fmt_list in self.unsupported_list:
+ clabel=gtk.GtkEntry()
+ clabel.set_editable(gtk.FALSE)
+ clabel.set_text(fmt_list[0])
+ self.show_list.append(clabel)
+ self._make_tooltip(clabel,fmt_list)
+ us_table.attach(clabel,0,1,row,row+1)
+ if fmt_list[4] is not None:
+ self.button_dict[fmt_list[1]]=gtk.GtkButton('Help')
+ self.button_dict[fmt_list[1]].connect('clicked',self.help_clicked_cb,fmt_list[4])
+ us_table.attach(self.button_dict[fmt_list[1]],1,2,row,row+1)
+ row=row+1
+ pixel_scroll.add_with_viewport(us_table)
+ self.show_list.append(us_table)
+ self.button_dict['close']=gtk.GtkButton('Close')
+ self.button_dict['close'].connect('clicked',self.close)
+ mainshell.pack_start(self.button_dict['close'],expand=gtk.FALSE)
+ self.show_list.append(self.button_dict['close'])
+ self.dialog.connect('delete-event',self.close)
+ for item in self.show_list:
+ item.show()
+
+ def help_clicked_cb(self,but,topic):
+ gvhtml.LaunchHTML(topic)
+
+ def driver_tool_cb(self,*args):
+ for item in self.show_list:
+ item.show()
+ self.dialog.show_all()
+ self.dialog.get_window()._raise()
+
+ def _make_tooltip(self,clabel,info_list):
+ txt='Long Name: '+info_list[0]+'\n'
+ txt=txt+'Short Name: '+info_list[1]+'\n'
+ txt=txt+'Creation support: '+info_list[2]+'\n'
+ txt=txt+'Data types: '+info_list[3]
+ self.tooltips.set_tip(clabel,txt)
+
+ def close(self,*args):
+ self.dialog.hide()
+ return gtk.TRUE
+
+TOOL_LIST=['ToolDriverList']
Added: packages/openev/branches/upstream/current/tools/Tool_Export.py
===================================================================
--- packages/openev/branches/upstream/current/tools/Tool_Export.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/Tool_Export.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,803 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: Tool_Export.py,v 1.6 2005/05/24 18:42:36 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: Graphical tool for translating between formats.
+# Author: Gillian Walter, gillian.walter at atlantis-scientific.com
+#
+###############################################################################
+# Copyright (c) 2003, Atlantis Scientific Inc. (www.atlantis-scientific.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: Tool_Export.py,v $
+# Revision 1.6 2005/05/24 18:42:36 andrey_kiselev
+# Fix in the format list parsing code.
+#
+# Revision 1.5 2005/05/19 21:08:07 andrey_kiselev
+# Improvements in export list: all writable file types should be now supported.
+#
+# Revision 1.4 2004/10/26 14:58:33 gmwalter
+# Set default start line/start pixel text to
+# 0 for window option to avoid user confusion
+# (gdal indexes from 0).
+#
+# Revision 1.3 2004/10/07 19:02:35 gmwalter
+# Extract generic code into gvutils.py.
+#
+# Revision 1.2 2004/08/20 15:57:17 gmwalter
+# Various fixes to export tool, added
+# raw band creation to vrt utilities.
+#
+# Revision 1.1 2004/03/25 16:17:37 andrey_kiselev
+# New (moved from pymod directory).
+#
+#
+
+import gtk
+import gview, gdal, gdalconst, layerdlg, gvutils
+import GtkExtra
+import os, string
+import gviewapp
+import pgufilesel
+import gvhtml
+import vrtutils
+import pguprogress
+
+class GDALTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self, app=None,startpath=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.init_dialog()
+ self.init_menu()
+
+ # store the id for the roi-changed signal
+ # connection so it can be disconnected later
+ self.roichanged_id=None
+
+ # Set help topic
+ gvhtml.set_help_topic(self.dialog,"Tool_Export.html")
+
+ def init_menu(self):
+ self.menu_entries.set_entry("File/Export",1,self.gdal_tool_cb)
+
+ def gdal_tool_cb(self,*args):
+ # Activate the view that the export tool was launched from
+ # so that it's active layer is displayed in the input field
+ for view in self.app.view_manager.view_list:
+ if view.title == args[1]:
+ self.app.view_manager.set_active_view(view)
+
+ for item in self.show_list:
+ item.show()
+
+ if self.button_dict['Mode'].get_active() == gtk.TRUE:
+ for item in self.adv_show_list:
+ item.show()
+ else:
+ for item in self.adv_show_list:
+ item.hide()
+
+ self.dialog.show()
+
+ self.dialog.get_window()._raise()
+ self.reconnect()
+ self.refresh_cb()
+
+ def reconnect(self,*args):
+ self.roichanged_id=self.app.toolbar.roi_tool.connect('roi-changed',self.refresh_roiinfo)
+
+ def set_roitool(self, *args):
+ self.app.toolbar.roi_button.set_active(gtk.TRUE)
+
+ def refresh_cb(self,*args):
+ self.refresh_fileinfo()
+ if self.button_dict['IP_window'].get_active():
+ self.refresh_roiinfo()
+
+ def refresh_roiinfo(self,*args):
+ try:
+ roi_info = self.app.toolbar.get_roi()
+ except:
+ # if roi has been disabled (eg. if current selection
+ # mode is poi), leave it at the latest value
+ roi_info = None
+
+
+ [cview, clayer] = self.app.layerdlg.get_selected_layer()
+
+ if (cview is None) or (clayer is None):
+ # roi only makes sense in the context of a view and layer
+ return None
+
+ if roi_info is None:
+ cds=clayer.get_parent().get_dataset()
+ npix=cds.RasterXSize
+ nline=cds.RasterYSize
+ roi_info = (0,0,npix,nline)
+ else:
+ # Get a reference to the active view
+ cur_view = self.app.layerdlg.get_active_view()
+ if (cur_view.get_raw(clayer) == 0):
+ # View is not in row/col coords-- convert
+ # Note that region will not be exactly the one drawn,
+ # since a rectangle is extracted rather than a
+ # general parallelogram. Get biggest rectangle.
+
+ roi_info_nogeo = ROI_view_to_pixel(clayer,roi_info)
+
+ max_pix = roi_info_nogeo[0] + roi_info_nogeo[2]
+ min_pix = roi_info_nogeo[0]
+ max_line = roi_info_nogeo[1] + roi_info_nogeo[3]
+ min_line = roi_info_nogeo[1]
+
+ # Make sure ROI is reasonable in terms of extraction
+ if min_pix < 0:
+ print 'Warning- negative start pixel. Resetting to 0.'
+ min_pix = 0
+ if max_pix < min_pix+1:
+ max_pix = min_pix + 1
+
+ if min_line < 0:
+ print 'Warning- negative start line. Resetting to 0.'
+ min_line = 0
+ if max_line < min_line+1:
+ max_line = min_line + 1
+
+ roi_info = (min_pix,min_line,max_pix-min_pix,max_line-min_line)
+
+ self.frame_dict['IP_window'].update(roi_info)
+
+
+ def refresh_fileinfo(self,*args):
+ clayer = self.app.sel_manager.get_active_layer()
+ try:
+ fname = clayer.get_parent().get_dataset().GetDescription()
+ self.frame_dict['Files'].set_dsfile(fname,'Input')
+ except:
+ pass
+
+ def init_dialog(self):
+ self.dialog = gtk.GtkWindow()
+ self.dialog.set_title('GDAL Export Tool')
+ self.dialog.set_border_width(10)
+ self.tips=gtk.GtkTooltips()
+ #self.dialog.set_default_size(500,400)
+ self.dialog.set_policy(gtk.FALSE, gtk.TRUE, gtk.TRUE)
+
+ # main shell
+ mainshell = gtk.GtkHBox(spacing=1, homogeneous=gtk.FALSE)
+ self.dialog.add(mainshell)
+ self.show_list=[]
+ self.adv_show_list=[] # advanced show list
+ self.show_list.append(mainshell)
+
+ #navigation shell
+ navshell = gtk.GtkVBox(spacing=1, homogeneous=gtk.FALSE)
+ mainshell.pack_start(navshell)
+ self.show_list.append(navshell)
+
+ self.frame_dict={}
+ self.button_dict={}
+ self.frame_dict['Files']=gvutils.GvDataFilesFrame('Data Files',
+ sel_list=('Input','Output'))
+ self.frame_dict['Files'].set_border_width(5)
+ self.frame_dict['Files'].set_spacings(5,5)
+ self.frame_dict['Files'].show_all()
+ navshell.pack_start(self.frame_dict['Files'])
+ self.show_list.append(self.frame_dict['Files'])
+
+ bopt_frame=gtk.GtkFrame('Basic Options')
+ self.frame_dict['Basic Options']=bopt_frame
+ self.show_list.append(bopt_frame)
+ navshell.pack_start(bopt_frame,gtk.FALSE,gtk.FALSE,0)
+ bopt_table=gtk.GtkTable(2,4,gtk.FALSE)
+ bopt_table.set_border_width(5)
+ bopt_table.set_row_spacings(5)
+ bopt_table.set_col_spacings(5)
+ bopt_frame.add(bopt_table)
+ self.show_list.append(bopt_table)
+
+ # Might be nice to have more formats below, but
+ # this involves error checking to test for
+ # supported data types, etc.
+ fmtlabel=gtk.GtkLabel('Output Format: ')
+ fmtlabel.set_alignment(0,0.5)
+ self.show_list.append(fmtlabel)
+ bopt_table.attach(fmtlabel,0,1,0,1)
+
+ self.format_list = []
+ hist_idx=0
+ for iDriver in gdal.GetDriverList():
+ create = None
+ try:
+ create = iDriver.GetMetadata()["DCAP_CREATE"]
+ except KeyError:
+ try:
+ create = iDriver.GetMetadata()["DCAP_CREATECOPY"]
+ except KeyError:
+ pass
+ if create == "YES":
+ if iDriver.ShortName == 'DTED':
+ # DTED is a special case that needs certain
+ # conditions to be valid. Skip it.
+ continue
+ self.format_list.append(iDriver.ShortName)
+ self.format_list.sort()
+ # Default to GTiff if possible
+ try:
+ hist_idx=self.format_list.index('GTiff')
+ except ValueError:
+ pass
+
+ self.format_menu = gvutils.GvOptionMenu(self.format_list)
+ self.format_menu.set_history(hist_idx)
+ self.show_list.append(self.format_menu)
+ bopt_table.attach(self.format_menu,1,2,0,1)
+ self.button_dict['Format_help']=gtk.GtkButton('Help')
+ self.show_list.append(self.button_dict['Format_help'])
+ bopt_table.attach(self.button_dict['Format_help'],2,3,0,1)
+ reslabel=gtk.GtkLabel('Output Resolution: ')
+ reslabel.set_alignment(0,0.5)
+ self.show_list.append(reslabel)
+ bopt_table.attach(reslabel,0,1,1,2)
+ self.res_list = ['Full','1:2','1:4','1:8']
+ self.res_menu = gvutils.GvOptionMenu(self.res_list)
+ bopt_table.attach(self.res_menu,1,2,1,2)
+ self.show_list.append(self.res_menu)
+
+
+ self.button_dict['Mode']=gtk.GtkCheckButton('Advanced Options')
+ navshell.pack_start(self.button_dict['Mode'])
+ self.show_list.append(self.button_dict['Mode'])
+
+ self.frame_dict['IP_window']=DataWindowFrame(navshell)
+ self.adv_show_list.append(self.frame_dict['IP_window'])
+
+ iopt_frame=gtk.GtkFrame('Interactive Options')
+ self.frame_dict['Interactive Options']=iopt_frame
+ self.adv_show_list.append(iopt_frame)
+ navshell.pack_start(iopt_frame,gtk.FALSE,gtk.FALSE,0)
+ iopt_table=gtk.GtkTable(3,3,gtk.FALSE)
+ iopt_table.set_border_width(5)
+ iopt_table.set_row_spacings(5)
+ iopt_table.set_col_spacings(5)
+ iopt_frame.add(iopt_table)
+ self.adv_show_list.append(iopt_table)
+ self.button_dict['IP_window']=gtk.GtkCheckButton('Window Input File')
+ iopt_table.attach(self.button_dict['IP_window'],0,2,0,1)
+ self.adv_show_list.append(self.button_dict['IP_window'])
+ self.button_dict['Scale']=gtk.GtkCheckButton('Scale to View Settings')
+ self.tips.set_tip(self.button_dict['Scale'],'Scale the output bands '+
+ 'according to the min/max settings of the '+
+ 'currently active raster layer. This only '+
+ 'applies to real data.')
+ iopt_table.attach(self.button_dict['Scale'],0,2,1,2)
+ self.adv_show_list.append(self.button_dict['Scale'])
+
+ self.button_dict['Refresh']=gtk.GtkButton('Active Layer->Input Filename')
+ self.tips.set_tip(self.button_dict['Refresh'],'Set the input '+
+ 'filename to that of the currently active layer')
+ iopt_table.attach(self.button_dict['Refresh'],0,1,2,3)
+ self.adv_show_list.append(self.button_dict['Refresh'])
+ self.button_dict['Enable_ROI']=gtk.GtkButton('Draw ROI mode')
+ self.tips.set_tip(self.button_dict['Enable_ROI'],'Re-activate the '+
+ 'ROI mode used for interactive input file window definition')
+ iopt_table.attach(self.button_dict['Enable_ROI'],1,2,2,3)
+ self.adv_show_list.append(self.button_dict['Enable_ROI'])
+
+ self.frame_dict['Other_Advanced']=gtk.GtkFrame('')
+ self.frame_dict['Other_Advanced'].set_shadow_type(gtk.SHADOW_NONE)
+ self.adv_show_list.append(self.frame_dict['Other_Advanced'])
+ oadvbox=gtk.GtkVBox(spacing=5,homogeneous=gtk.FALSE)
+ oadvbox.set_border_width(5)
+ self.adv_show_list.append(oadvbox)
+
+ self.frame_dict['Other_Advanced'].add(oadvbox)
+
+ otable=gtk.GtkTable(2,3,gtk.FALSE)
+ otable.set_row_spacings(5)
+ otable.set_col_spacings(5)
+ self.adv_show_list.append(otable)
+ oadvbox.pack_start(otable)
+ self._overview_list=['None','Nearest','Average']
+ self.overview_menu=gvutils.GvOptionMenu(self._overview_list)
+ ovrlabel=gtk.GtkLabel('Overviews:')
+ self.tips.set_tip(self.overview_menu,'Tiled overview creation options')
+ ovrlabel.set_alignment(0,0.5)
+ self.adv_show_list.append(ovrlabel)
+ otable.attach(ovrlabel,0,1,0,1)
+ otable.attach(self.overview_menu,1,2,0,1)
+ self.adv_show_list.append(self.overview_menu)
+
+ self._geocode_list=['Default','GCP','Geotransform']
+ self.geocoding_menu = gvutils.GvOptionMenu(self._geocode_list)
+ geolabel=gtk.GtkLabel('Geocoding:')
+ self.tips.set_tip(self.geocoding_menu,
+ 'Specify the type of georeferencing '+
+ 'information to output. Default is to output '+
+ 'all available geocoding from the input file. '+
+ 'If GCP or Geotransform is selected, geocoding '+
+ 'information will only be output if it is of the '+
+ 'selected type. This may later be updated to '+
+ 'generate information of the specified form if '+
+ 'it is not present but can be accurately computed '+
+ 'from the existing information.')
+ geolabel.set_alignment(0,0.5)
+ self.adv_show_list.append(geolabel)
+ otable.attach(geolabel,0,1,1,2)
+ otable.attach(self.geocoding_menu,1,2,1,2)
+ self.adv_show_list.append(self.geocoding_menu)
+
+ opthbox=gtk.GtkHBox(spacing=5,homogeneous=gtk.FALSE)
+ self.adv_show_list.append(opthbox)
+ oadvbox.pack_start(opthbox)
+ optlabel=gtk.GtkLabel('Create Options:')
+ optlabel.set_alignment(0,0.5)
+ self.adv_show_list.append(optlabel)
+ self.optentry=gtk.GtkEntry()
+ self.optentry.set_editable(editable=gtk.TRUE)
+ self.optentry.set_usize(400,25)
+ self.optentry.set_text('')
+ self.adv_show_list.append(self.optentry)
+ opthbox.pack_start(optlabel)
+ opthbox.pack_start(self.optentry)
+
+ navshell.pack_start(self.frame_dict['Other_Advanced'],
+ gtk.FALSE,gtk.FALSE,0)
+
+ echbox=gtk.GtkHBox(spacing=5,homogeneous=gtk.FALSE)
+ echbox.set_border_width(3)
+ navshell.pack_end(echbox,gtk.FALSE,gtk.FALSE,0)
+ self.show_list.append(echbox)
+ self.button_dict['Close']=gtk.GtkButton('Close')
+ echbox.pack_end(self.button_dict['Close'],expand=gtk.TRUE)
+ self.show_list.append(self.button_dict['Close'])
+ self.button_dict['Export']=gtk.GtkButton('Export')
+ echbox.pack_end(self.button_dict['Export'],expand=gtk.TRUE)
+ self.show_list.append(self.button_dict['Export'])
+
+ self.button_dict['Format_help'].connect('clicked',
+ self.format_help_cb)
+
+ self.button_dict['Enable_ROI'].connect('clicked',self.set_roitool)
+ self.button_dict['Refresh'].connect('clicked',
+ self.refresh_fileinfo)
+ self.button_dict['Export'].connect('clicked',self.export_cb)
+ self.button_dict['Close'].connect('clicked',self.close)
+
+ self.button_dict['IP_window'].connect('toggled',
+ self.ip_window_toggled_cb)
+ self.button_dict['Mode'].connect('toggled',self.mode_toggled_cb)
+
+ self.button_dict['IP_window'].set_active(gtk.FALSE)
+ self.button_dict['Mode'].set_active(gtk.FALSE)
+ self.frame_dict['IP_window'].set_entry_sensitivities(gtk.FALSE)
+
+
+ # Trap window close event
+ self.dialog.connect('delete-event', self.close)
+
+ for item in self.show_list:
+ item.show()
+
+ if self.button_dict['Mode'].get_active():
+ for item in self.adv_show_list:
+ item.show()
+ else:
+ for item in self.adv_show_list:
+ item.hide()
+
+ def mode_toggled_cb(self,*args):
+ if self.button_dict['Mode'].get_active():
+ for item in self.adv_show_list:
+ item.show()
+ else:
+ for item in self.adv_show_list:
+ item.hide()
+
+
+ def ip_window_toggled_cb(self,*args):
+ if self.button_dict['IP_window'].get_active():
+ self.frame_dict['IP_window'].set_entry_sensitivities(gtk.TRUE)
+ self.set_roitool()
+ else:
+ self.frame_dict['IP_window'].set_entry_sensitivities(gtk.FALSE)
+
+ def format_help_cb(self,*args):
+ opformat=self.format_list[self.format_menu.get_history()]
+ driver=gdal.GetDriverByName(opformat)
+ topic=driver.HelpTopic
+ if topic is not None:
+ # hash to indicate position in html isn't
+ # recognized by mozilla. Make sure that
+ # frmt_various.html is brought up for
+ # formats that share this file.
+ ttopic=string.split(topic,"#")
+ gvhtml.LaunchHTML(ttopic[0])
+ else:
+ gvutils.warning('No html help available for '+opformat+' format')
+
+ def export_cb(self,*args):
+ ipfile=self.frame_dict['Files'].get('Input')
+ opfile=self.frame_dict['Files'].get('Output')
+ if os.path.isfile(opfile):
+ resp=GtkExtra.message_box('Confirmation',opfile +
+ ' exists. Overwrite?',('Yes','No'))
+ if resp == 'No':
+ return
+ elif len(opfile) == 0:
+ gvutils.error('No output filename entered!')
+ return
+
+ use_viewscale=0
+
+ rast = gdal.OpenShared(ipfile, gdalconst.GA_ReadOnly)
+ if rast is None:
+ if len(ipfile) == 0:
+ gvutils.error('Please specify an input file!')
+ else:
+ gvutils.error('Unable to open ' + ipfile + ' as a GDAL supported file!')
+ return
+
+ # Catch the case where the input file consists of in-memory VRT lines
+ # and the output format is also VRT. In this case, the new VRT would
+ # no longer be valid once openev was exited because the input file
+ # is not on disk (filename looks something like '<VRTDataset....').
+ # If the user is just exporting the file as-is, simply copying the
+ # original lines to disk will suffice. However, if they want to
+ # window or scale, we'd need more complicated manipulations. For now,
+ # give an error message in that case.
+ opformat=self.format_list[self.format_menu.get_history()]
+
+ if (ipfile[0] == '<') and (opformat == 'VRT'):
+ if self.res_list[self.res_menu.get_history()] != 'Full':
+ msg='Only full output resolution is currently\n'+\
+ 'supported for export of in-memory VRTs\n'+\
+ 'to on-disk VRTs.'
+ gvutils.error(msg)
+ return
+
+ if ( (self.button_dict['Mode'].get_active()) and
+ ((self.button_dict['IP_window'].get_active()) or
+ (self.button_dict['Scale'].get_active()) or
+ (len(self.optentry.get_text()) > 0))):
+ msg='Scaling, windowing, and advanced creation\n'+\
+ 'options are not yet supported for export of \n'+\
+ 'in-memory VRTs to on-disk VRTs'
+ gvutils.error(msg)
+ return
+
+ linelist=string.split(ipfile,'\n')
+ newlinelist=[]
+ for item in linelist:
+ newlinelist.append(item+'\n')
+ fh=open(opfile,'w')
+ fh.writelines(newlinelist)
+ fh.close()
+
+ ovrs=self._overview_list[self.overview_menu.get_history()]
+ if ovrs != 'None':
+ outds=gdal.OpenShared(opfile)
+ if outds is None:
+ gvutils.error('Error opening '+opfile+' for overview creation!')
+ return
+
+ progress = pguprogress.PGUProgressDialog( 'Building overviews...',
+ cancel = gtk.TRUE )
+ if ovrs is 'Nearest':
+ outds.BuildOverviews( "nearest",
+ callback = progress.ProgressCB )
+ else:
+ outds.BuildOverviews( "average_magphase",
+ callback = progress.ProgressCB )
+ progress.destroy()
+
+ return
+
+
+
+ vrt_opts=vrtutils.VRTCreationOptions(rast.RasterCount)
+
+ if self._geocode_list[self.geocoding_menu.get_history()] == 'GCP':
+ vrt_opts.set_geopref('gcps')
+ elif self._geocode_list[self.geocoding_menu.get_history()] == 'Geotransform':
+ vrt_opts.set_geopref('geotransform')
+
+ band_list = None
+
+ # Scale the output file according to the current view's
+ # min/max
+ if self.button_dict['Scale'].get_active():
+ try:
+ clayer = self.app.sel_manager.get_active_layer()
+ if clayer.get_parent().get_dataset().GetDescription() != ipfile:
+ wtxt = 'Input file and active layer file names do not match- may '
+ wtxt = wtxt + 'result in unexpected scaling!'
+ gvutils.warning(wtxt)
+ if gvutils.is_of_class(clayer.__class__,'GvRasterLayer') == 0:
+ gvutils.warning('Active layer is not a raster- view scaling ignored!')
+ else:
+ src_count=clayer.sources
+ band_list = []
+ RGBAlist=['Red','Green','Blue','Alpha']
+ for src in range(src_count):
+ # layer sources are numbered 0...3; band sources are numbered 1,2,...
+ src_bandnum=clayer.get_data(src).get_band_number()
+ band_list.append(src_bandnum)
+ vrt_opts.set_scaling((clayer.min_get(src),clayer.max_get(src),0,255),(src_bandnum,))
+ vrt_opts.set_datatype(gdal.GDT_Byte,(src_bandnum,))
+ if src_count == 3:
+ vrt_opts.set_color_interp(RGBAlist[src],
+ (src_bandnum,))
+
+ # src_count is three even when there is an alpha channel
+ # for rgb/rgba case
+ if src_count == 3:
+ try:
+ src=3
+ src_bandnum=clayer.get_data(src).get_band_number()
+ band_list.append(src_bandnum)
+ vrt_opts.set_scaling((clayer.min_get(src),
+ clayer.max_get(src),0,255),
+ (src_bandnum,))
+ vrt_opts.set_datatype(gdal.GDT_Byte,(src_bandnum,))
+ vrt_opts.set_color_interp(RGBAlist[src],
+ (src_bandnum,))
+ except:
+ pass
+
+ use_viewscale=1
+ if clayer.get_mode()==gview.RLM_COMPLEX:
+ # This doesn't deal with complex yet...
+ gvutils.error('View scaling option is not yet supported for complex data!')
+ return
+ elif rast._band[0].DataType == gdal.GDT_CInt16:
+ # This doesn't deal with complex yet...
+ gvutils.error('View scaling option is not yet supported for complex data!')
+ return
+ elif rast._band[0].DataType == gdal.GDT_CInt32:
+ # This doesn't deal with complex yet...
+ gvutils.error('View scaling option is not yet supported for complex data!')
+ return
+ elif rast._band[0].DataType == gdal.GDT_CFloat32:
+ # This doesn't deal with complex yet...
+ gvutils.error('View scaling option is not yet supported for complex data!')
+ return
+ elif rast._band[0].DataType == gdal.GDT_CFloat64:
+ # This doesn't deal with complex yet...
+ gvutils.error('View scaling option is not yet supported for complex data!')
+ return
+ except:
+ gvutils.error('Unable to find active raster layer for scaling!')
+ return
+
+ # Get windowing options
+ if self.button_dict['IP_window'].get_active():
+ try:
+ spix=int(self.frame_dict['IP_window'].entry_dict['start_pix'].get_text())
+ sline=int(self.frame_dict['IP_window'].entry_dict['start_line'].get_text())
+ npix=int(self.frame_dict['IP_window'].entry_dict['num_pix'].get_text())
+ nlines=int(self.frame_dict['IP_window'].entry_dict['num_lines'].get_text())
+ if (spix < 0) or (sline < 0):
+ gvutils.error('Negative start pixel and/or line! Aborting...')
+ return
+ if (npix+spix > rast.RasterXSize):
+ gvutils.error('Window is too large (last column in input: '+str(rast.RasterXSize)+')! Aborting...')
+ return
+ if (nlines+sline > rast.RasterYSize):
+ gvutils.error('Window is too large (last row in input: '+str(rast.RasterYSize)+')! Aborting...')
+ return
+ except:
+ gvutils.error('Error retrieving window options! Aborting...')
+ return
+ else:
+ spix=0
+ sline=0
+ npix=rast.RasterXSize
+ nlines=rast.RasterYSize
+
+ vrt_opts.set_src_window((spix,sline,npix,nlines))
+
+ if self.res_list[self.res_menu.get_history()] != 'Full':
+ ovrlevel=int(self.res_list[self.res_menu.get_history()][2])
+ else:
+ ovrlevel=1
+
+ vrt_opts.set_dst_window((0,0,npix/ovrlevel,nlines/ovrlevel))
+
+ vrt_tree=vrtutils.serializeDataset(rast,vrt_opts,band_list)
+ vrt_lines=gdal.SerializeXMLTree(vrt_tree)
+ vrtdataset=gdal.Open(vrt_lines)
+
+ driver=gdal.GetDriverByName(opformat)
+
+ # Parse creation options:
+ optstr=string.strip(self.optentry.get_text())
+ if len(optstr) > 0:
+ # should be able to deal with several
+ # types of entries, eg.
+ # 'TILED=YES','TFW=YES'
+ # and
+ # TILED=YES,TFW=YES
+
+ if optstr[0] in ["'",'"']:
+ split1=string.split(optstr,",")
+ copts=[]
+ for item in split1:
+ if len(item) > 2:
+ copts.append(item[1:len(item)-1])
+ else:
+ copts=string.split(optstr,',')
+ else:
+ copts=[]
+
+ progress = pguprogress.PGUProgressDialog( 'Export to '+opfile,
+ cancel = gtk.TRUE )
+ progress.SetDefaultMessage("translated")
+
+ outdataset=driver.CreateCopy(opfile,vrtdataset,
+ options=copts,
+ callback=progress.ProgressCB)
+ if outdataset is None:
+ progress.destroy()
+ gvutils.error('Unable to create output file '+opfile)
+ return
+
+ ovrs=self._overview_list[self.overview_menu.get_history()]
+ if ovrs is 'Nearest':
+ progress.SetDefaultMessage("overviews built")
+ outdataset.BuildOverviews( "nearest",
+ callback = progress.ProgressCB )
+
+ elif ovrs is 'Average':
+ progress.SetDefaultMessage("overviews built")
+ outdataset.BuildOverviews( "average_magphase",
+ callback = progress.ProgressCB )
+
+ progress.destroy()
+
+
+
+
+ def close(self,*args):
+ if self.roichanged_id is not None:
+ self.app.toolbar.roi_tool.disconnect(self.roichanged_id)
+ self.roichanged_id=None
+
+ self.dialog.hide()
+ return gtk.TRUE
+
+#-----------------------------------------------------------------
+# GUI STUFF
+#-----------------------------------------------------------------
+
+class DataWindowFrame:
+ def __init__(self,parent_box,title='Input Window'):
+ self.frame=gtk.GtkFrame(title)
+ self.show_list=[]
+ self.show_list.append(self.frame)
+
+ patch_table = gtk.GtkTable(2,4,gtk.FALSE)
+ self.show_list.append(patch_table)
+ self.frame.add(patch_table)
+
+ patch_table.set_border_width(5)
+ patch_table.set_col_spacings(5)
+ patch_table.set_col_spacing(1, 20)
+
+ label1 = gtk.GtkLabel('Start Line: ')
+ label1.set_alignment(0, 0.5)
+ patch_table.attach(label1, 0,1, 0, 1)
+
+ self.entry_dict={}
+
+ self.entry_dict['start_line'] = gtk.GtkEntry()
+ self.entry_dict['start_line'].set_editable(gtk.TRUE)
+ self.entry_dict['start_line'].set_usize(90, 25)
+ self.entry_dict['start_line'].set_text('0')
+ patch_table.attach(self.entry_dict['start_line'], 1,2, 0,1)
+
+ label2 = gtk.GtkLabel('Start Pixel: ')
+ label2.set_alignment(0, 0.5)
+ patch_table.attach(label2, 2,3,0, 1)
+
+ self.entry_dict['start_pix'] = gtk.GtkEntry()
+ self.entry_dict['start_pix'].set_editable(gtk.TRUE)
+ self.entry_dict['start_pix'].set_usize(90, 25)
+ self.entry_dict['start_pix'].set_text('0')
+ patch_table.attach(self.entry_dict['start_pix'], 3,4, 0,1)
+
+ label3 = gtk.GtkLabel('Num. of Lines: ')
+ label3.set_alignment(0, 0.5)
+ patch_table.attach(label3, 0,1, 1, 2)
+
+ self.entry_dict['num_lines'] = gtk.GtkEntry()
+ self.entry_dict['num_lines'].set_editable(gtk.TRUE)
+ self.entry_dict['num_lines'].set_usize(90, 25)
+ self.entry_dict['num_lines'].set_text('1')
+ patch_table.attach(self.entry_dict['num_lines'], 1,2, 1,2)
+
+ label4 = gtk.GtkLabel('Num. of Pixels: ')
+ label4.set_alignment(0, 0.5)
+ patch_table.attach(label4, 2,3,1, 2)
+
+ self.entry_dict['num_pix'] = gtk.GtkEntry()
+ self.entry_dict['num_pix'].set_editable(gtk.TRUE)
+ self.entry_dict['num_pix'].set_usize(90, 25)
+ self.entry_dict['num_pix'].set_text('1')
+ patch_table.attach(self.entry_dict['num_pix'], 3,4, 1,2)
+
+ self.show_list.append(label1)
+ self.show_list.append(label2)
+ self.show_list.append(label3)
+ self.show_list.append(label4)
+ self.show_list.append(self.entry_dict['start_line'])
+ self.show_list.append(self.entry_dict['start_pix'])
+ self.show_list.append(self.entry_dict['num_lines'])
+ self.show_list.append(self.entry_dict['num_pix'])
+
+ parent_box.pack_start(self.frame,gtk.FALSE,gtk.FALSE,0)
+
+
+ def update(self,roi_info):
+ self.entry_dict['start_line'].set_text(str(int(roi_info[1])))
+ self.entry_dict['start_pix'].set_text(str(int(roi_info[0])))
+ self.entry_dict['num_lines'].set_text(str(int(roi_info[3])))
+ self.entry_dict['num_pix'].set_text(str(int(roi_info[2])))
+
+ def set_entry_sensitivities(self,bool_val):
+ self.entry_dict['start_line'].set_sensitive(bool_val)
+ self.entry_dict['start_pix'].set_sensitive(bool_val)
+ self.entry_dict['num_lines'].set_sensitive(bool_val)
+ self.entry_dict['num_pix'].set_sensitive(bool_val)
+
+
+ def show(self,*args):
+ for item in self.show_list:
+ item.show()
+
+ def hide(self,*args):
+ for item in self.show_list:
+ item.hide()
+
+
+def ROI_view_to_pixel(clayer,roi_info):
+
+ [pixel,line] = clayer.view_to_pixel(roi_info[0],roi_info[1])
+ [pixel2,line2] = clayer.view_to_pixel(roi_info[0]+roi_info[2],
+ roi_info[1]+roi_info[3])
+ [pixel3,line3] = clayer.view_to_pixel(roi_info[0],
+ roi_info[1]+roi_info[3])
+ [pixel4,line4] = clayer.view_to_pixel(roi_info[0]+roi_info[2],
+ roi_info[1])
+
+ # Get pixel-space rectangle
+ max_pix = max(pixel,pixel2,pixel3,pixel4)
+ min_pix = min(pixel,pixel2,pixel3,pixel4)
+ max_line = max(line,line2,line3,line4)
+ min_line = min(line,line2,line3,line4)
+
+ roi_info_pixel = (min_pix,min_line,max_pix-min_pix,max_line-min_line)
+
+ return roi_info_pixel
+
+
+TOOL_LIST = ['GDALTool']
+
Added: packages/openev/branches/upstream/current/tools/Tool_ShapesGrid.py
===================================================================
--- packages/openev/branches/upstream/current/tools/Tool_ShapesGrid.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/Tool_ShapesGrid.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,633 @@
+###############################################################################
+# $Id: Tool_ShapesGrid.py,v 1.6 2005/03/01 20:54:34 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Tool using scrollable text area widget for displaying GvShapes data
+# Author:
+#
+###############################################################################
+# Copyright (c) 2003, Atlantis Scientific Inc. (www.atlantis-scientific.com)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: Tool_ShapesGrid.py,v $
+# Revision 1.6 2005/03/01 20:54:34 gmwalter
+# Fix configuration typo that was preventing
+# cell editing from starting on single click.
+#
+# Revision 1.5 2004/07/21 19:40:40 gmwalter
+# Don't sort properties before displaying.
+#
+# Revision 1.4 2004/03/23 18:08:25 gmwalter
+# Add another variant to pgugrid and update
+# comments; update shapesgrid tool to start
+# editing on single left click.
+#
+# Revision 1.3 2004/01/14 19:58:32 gmwalter
+# Make sure grid is cleared properly when active layer changes.
+#
+# Revision 1.2 2003/11/19 16:46:55 gmwalter
+# Checked into main branch.
+#
+#
+
+
+
+import gviewapp
+import gtk
+import gview
+import pgugrid
+import gvutils
+import Numeric
+
+class ShapesGridTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self, app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.layer = None
+ self.shapes = None
+ self.viewarea = None
+ self.layer_teardown_id=None
+
+ self.init_dialog()
+ self.init_menu()
+
+ def init_dialog(self):
+ self.dialog = gtk.GtkWindow()
+ self.dialog.set_title('Tabular Shapes Attribute Grid Demo')
+ self.dialog.set_default_size(300,400)
+ self.dialog.set_policy(gtk.FALSE, gtk.TRUE, gtk.TRUE)
+
+ shell = gtk.GtkVBox(spacing=5)
+ shell.set_border_width(10)
+ self.dialog.add(shell)
+
+ self.pgugrid=pgugrid.pguGrid(config=(3,2,0,2,4,2,0,0,0))
+
+
+ shell.pack_start(self.pgugrid,expand=gtk.TRUE)
+
+ hbox=gtk.GtkHBox(spacing=5)
+ shell.pack_start(hbox)
+ self.column_button=gtk.GtkCheckButton("Schema properties only")
+ self.column_button.connect("toggled",self.refresh_columns)
+ self.column_button.set_active(gtk.TRUE)
+ hbox.pack_start(self.column_button)
+
+ rbutton = gtk.GtkButton("Refresh columns")
+ rbutton.connect("clicked", self.refresh_columns)
+ hbox.pack_start(rbutton,expand=gtk.FALSE)
+
+
+ button = gtk.GtkButton("close")
+ button.connect("clicked", self.close)
+ shell.pack_start(button,expand=gtk.FALSE)
+ button.show()
+
+ shell.show_all()
+
+ # Trap window close event
+ self.dialog.connect('delete-event', self.close)
+
+ self.app.sel_manager.subscribe( 'active-layer-changed',
+ self.layer_update )
+
+ self.pgugrid.subscribe("clicked",self.clicked_cb)
+ self.pgugrid.connect("button-release-event",self.clicked_nocolumns_cb)
+ #self.pgugrid.subscribe("cell-selection-changed",self.cell_cb)
+ #self.pgugrid.subscribe("cell-changed",self.cellch_cb)
+ #self.pgugrid.subscribe("row-selection-changed",self.row_cb)
+ #self.pgugrid.subscribe("column-selection-changed",self.column_cb)
+
+ # Popup menus:
+ itemlist=[#('Configuration',None,None),
+ ('Set subset/Selected',self.set_subset_selected_cb,None),
+ ('Set subset/Unseleted',self.set_subset_unselected_cb,None),
+ ('Set subset/All',self.set_subset_all_cb,None),
+ ('New layer/Selected',self.new_layer_selected_cb,None),
+ ('New layer/Unselected',self.new_layer_unselected_cb,None),
+ ('Edit Schema',self.edit_schema,None),
+ #('Query',None,None),
+ #('Save',None,None),
+ #('Help',None,None)
+ ]
+
+ self.cell_popup_menu=[]
+ self.cell_popup_menu.append(gtk.GtkMenu())
+ for label, func, args in itemlist:
+ menu_item = gtk.GtkMenuItem(label)
+ if func is not None:
+ menu_item.connect("activate", func, args)
+ self.cell_popup_menu[0].append(menu_item)
+
+ self.cell_popup_menu[0].show_all()
+
+ itemlist2=[#('Configuration',None,None),
+ ('Set subset/Selected',self.set_subset_selected_cb,None),
+ ('Set subset/Unseleted',self.set_subset_unselected_cb,None),
+ ('Set subset/All',self.set_subset_all_cb,None),
+ ('New layer/Selected',self.new_layer_selected_cb,None),
+ ('New layer/Unselected',self.new_layer_unselected_cb,None),
+ ('Edit Schema',self.edit_schema,None),
+ ('Add property',self.add_property_column,None),
+ #('Query',None,None),
+ #('Save',None,None),
+ #('Help',None,None)
+ ]
+
+ self.cell_popup_menu.append(gtk.GtkMenu())
+ for label, func, args in itemlist2:
+ menu_item = gtk.GtkMenuItem(label)
+ if func is not None:
+ menu_item.connect("activate", func, args)
+ self.cell_popup_menu[1].append(menu_item)
+
+ self.cell_popup_menu[1].show_all()
+ # Only do actions when grid is visible
+ self.active=0
+
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Tabular Shapes Grid",1,self.show_cb)
+
+ def clicked_cb(self,*args):
+ """ Show popup menus """
+
+ if self.shapes is None:
+ return
+
+ row=args[1]
+ if row == -1:
+ return
+
+ event=args[3]
+ if ((event.button == 3) and (not
+ (event.state & gtk.GDK.CONTROL_MASK)) and (not
+ (event.state & gtk.GDK.SHIFT_MASK))):
+
+ if self.column_button.get_active() == gtk.TRUE:
+ self.cell_popup_menu[0].popup(None,None,None,event.button,
+ event.time)
+ else:
+ self.cell_popup_menu[1].popup(None,None,None,event.button,
+ event.time)
+
+ def clicked_nocolumns_cb(self,*args):
+ """ In case where source has no columns defined yet,
+ pop up a menu (since clicked_cb won't be called
+ until grid has columns defined- grid only sends
+ out clicked notification if columns have been
+ defined) """
+
+ event=args[1]
+ if self.shapes is not None:
+ cc=self.pgugrid.get_current_columns()
+ if len(cc[0]) == 0:
+ if self.column_button.get_active() == gtk.TRUE:
+ self.cell_popup_menu[0].popup(None,None,None,event.button,
+ event.time)
+ else:
+ self.cell_popup_menu[1].popup(None,None,None,event.button,
+ event.time)
+
+
+ def set_subset_selected_cb(self,*args):
+ """ Set the grid subset to selected rows only """
+
+ selected=self.pgugrid.get_selected_row_indices()
+
+ if len(selected) == 0:
+ gvutils.warning('No rows selected- ignoring!')
+ else:
+ self.pgugrid.set_subset(selected)
+
+ def set_subset_unselected_cb(self,*args):
+ """ Set the grid subset to selected rows only """
+
+ unselected=self.pgugrid.get_unselected_row_indices()
+
+ if len(unselected) == 0:
+ gvutils.warning('No rows unselected- ignoring!')
+ else:
+ self.pgugrid.set_subset(unselected)
+
+ def set_subset_all_cb(self,*args):
+ """ Set the grid to show all shapes """
+
+ self.pgugrid.set_subset(None)
+
+ def new_layer_selected_cb(self,*args):
+ """ Create new layer of only selected shapes """
+
+ sel=self.pgugrid.get_selected_row_indices()
+ if len(sel) == 0:
+ gvutils.warning('No rows selected- ignoring!')
+ return
+
+ newshps=gview.GvShapes(name='Selected')
+ src=self.shapes
+ if src is None:
+ gvutils.warning('No source layer found- ignoring!')
+ return
+
+ schema=src.get_schema()
+ for item in schema:
+ newshps.add_field(item[0],item[1],item[2],item[3])
+
+ for idx in sel:
+ if src[idx] is not None:
+ newshps.append(src[idx].copy())
+
+ gview.undo_register(newshps)
+ clayer=gview.GvShapesLayer(newshps)
+
+ cview=self.app.new_view()
+ cview.viewarea.add_layer(clayer)
+ cview.viewarea.set_active_layer(clayer)
+
+ def new_layer_unselected_cb(self,*args):
+ """ Create new layer of only selected shapes """
+
+ unselected=self.pgugrid.get_unselected_row_indices()
+
+ if len(unselected) == 0:
+ gvutils.warning('No rows unselected- ignoring!')
+ return
+
+ newshps=gview.GvShapes(name='Unselected')
+ src=self.shapes
+ if src is None:
+ gvutils.warning('No source layer found- ignoring!')
+ return
+
+ schema=src.get_schema()
+ for item in schema:
+ newshps.add_field(item[0],item[1],item[2],item[3])
+
+ for idx in unselected:
+ if src[idx] is not None:
+ newshps.append(src[idx].copy())
+
+ gview.undo_register(newshps)
+ clayer=gview.GvShapesLayer(newshps)
+
+ cview=self.app.new_view()
+ cview.viewarea.add_layer(clayer)
+ cview.viewarea.set_active_layer(clayer)
+
+ def get_columns(self,shapes):
+ """ Get the columns for a shapes object """
+
+ # should skip to except here if layer is a raster
+ shp_schema = self.shapes.get_schema()
+
+ klist=[]
+ fdict={}
+ for item in shp_schema:
+ klist.append(item[0])
+ if item[1] == 'integer':
+ fdict[item[0]]="%"+str(item[2])+"d"
+ elif item[1] == 'float':
+ fdict[item[0]]="%"+str(item[2])+"."+\
+ str(item[3])+"f"
+ else:
+ fdict[item[0]]="%"+str(item[2])+"s"
+
+ if self.column_button.get_active() == gtk.FALSE:
+ for shp in self.shapes:
+ klist.extend(shp.get_properties().keys())
+
+ #klist.sort()
+ # Get unique keys
+ set={}
+ key_list=\
+ [set.setdefault(e,e) for e in klist if not set.has_key(e)]
+
+ else:
+ #klist.sort()
+ key_list=klist
+
+ flist=[]
+ for item in key_list:
+ if fdict.has_key(item):
+ flist.append(fdict[item])
+ else:
+ flist.append("%s")
+
+ return key_list,flist
+
+ def edit_schema(self,*args):
+ """ Edit the shapes schema. """
+ if self.shapes is None:
+ return
+
+ sch=SchemaDialog(self.shapes,self)
+
+
+ def add_property_column(self,*args):
+ """ Add a property column """
+
+ import GtkExtra
+ pname=GtkExtra.input_box(title="Property Name",
+ message="Please enter a name for the property")
+
+ if ((pname is None) or (len(pname) == 0)):
+ return
+
+ current_columns=self.pgugrid.get_current_columns()
+ mems=current_columns[0]
+ titles=current_columns[1]
+ editables=current_columns[2]
+ formats=current_columns[3]
+ types=current_columns[4]
+ nodatas=current_columns[5]
+ justify=current_columns[6]
+ tjustify=current_columns[7]
+
+ mems.append(pname)
+ titles.append(pname)
+ editables.append(1)
+ formats.append(None)
+ types.append('string')
+ nodatas.append('')
+ justify.append(0)
+ tjustify.append(2)
+
+ self.pgugrid.define_columns(members=mems,titles=titles,
+ editables=editables,formats=formats,types=types,
+ nodata=nodatas,justify=justify,title_justify=tjustify)
+
+
+ def refresh_columns(self,*args):
+ """ Update column headers """
+ if self.shapes is not None:
+ key_list,fmt_list=self.get_columns(self.shapes)
+ self.pgugrid.define_columns(members=key_list,formats=fmt_list)
+
+ def show_cb(self,*args):
+ # Activate the view that the grid was launched from
+ # (confusing for user if launching the grid from
+ # one view shows the vectors for another)
+ for view in self.app.view_manager.view_list:
+ if view.title == args[1]:
+ self.app.view_manager.set_active_view(view)
+
+ self.active=1
+ self.dialog.show_all()
+ self.dialog.get_window()._raise()
+ self.layer_update()
+
+ def close(self,*args):
+ self.active=0
+ self.layer_teardown_cb()
+ self.dialog.hide()
+ return gtk.TRUE
+
+
+ def layer_update(self,*args):
+ # Disconnect from the old layer
+ if self.active == 0:
+ return
+
+ self.layer_teardown_cb()
+
+ try:
+ self.layer = self.app.sel_manager.get_active_layer()
+ self.viewarea = self.app.sel_manager.get_active_view()
+ self.shapes = self.layer.get_parent()
+
+ # should skip to except here if layer is a raster
+ shp_schema = self.shapes.get_schema()
+
+ except:
+ # Layer is None or a raster
+ self.layer = None
+ self.shapes = None
+ self.viewarea = None
+ self.pgugrid.set_source(None,expose=1)
+ self.layer_teardown_id=None
+ return
+
+ try:
+ # get display columns
+ key_list,fmt_list=self.get_columns(self.shapes)
+
+ self.pgugrid.set_source(self.layer,self.viewarea)
+ self.pgugrid.define_columns(members=key_list,formats=fmt_list)
+
+ self.layer_teardown_id = \
+ self.layer.connect('teardown',self.layer_teardown_cb)
+ except:
+ # Layer is None or a raster, or couldn't be loaded
+ self.layer = None
+ self.shapes = None
+ self.viewarea = None
+ self.layer_teardown_id=None
+ self.pgugrid.set_source(None,expose=1)
+ gvutils.warning('Unable to load shapes into grid!')
+ return
+
+ def layer_teardown_cb(self,*args):
+ self.pgugrid.clear()
+ if self.layer_teardown_id is not None:
+ self.layer.disconnect(self.layer_teardown_id)
+ self.layer_teardown_id = None
+ self.viewarea = None
+
+
+ def clicked_test_cb(self,*args):
+ """ Test the grid selection mechanism- debug code """
+ print "clicked..."
+ print "grid row: ",args[1]
+ src=self.pgugrid.grid2src(args[1])
+ print "source row: ",src
+ print "grid row 2: ",self.pgugrid.src2grid(src)
+ print "grid column: ",args[2]
+ print "dir(event): ",dir(args[3])
+
+ def cell_cb(self,*args):
+ """ Test the grid selection mechanism- debug code """
+ print "cell_cb..."
+ print "cell selection: ",args[1]
+
+ def cellch_cb(self,*args):
+ """ Test the grid selection mechanism- debug code """
+ print "cellch_cb..."
+ print "altered cell: ",args[1]
+
+ def row_cb(self,*args):
+ """ Test the grid selection mechanism- debug code """
+ print "row_cb..."
+ print "row selection: ",args[1]
+ src=self.pgugrid.src2grid(args[1])
+ print "grid row selection: ",src
+ print "row selection 2: ",self.pgugrid.grid2src(src)
+
+ def column_cb(self,*args):
+ """ Test the grid selection mechanism- debug code """
+ print "column_cb..."
+ print "column selection: ",args[1]
+
+
+class SchemaDialog(gtk.GtkWindow):
+ def __init__(self,shapes,shapesgridtool=None):
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Schema')
+ shell=gtk.GtkVBox(spacing=5)
+ shell.set_border_width(10)
+ self.add(shell)
+ self.grid=pgugrid.pguGrid(config=(2,0,0,1,4,0,0,0))
+ self.grid.subscribe("cell-changed",self.changed_field)
+ self.shapes=shapes
+ self.shapesgridtool=shapesgridtool
+ shell.pack_start(self.grid)
+
+ # New field
+ box3 = gtk.GtkTable(rows=5,cols=3)
+ box3.set_row_spacings(5)
+ box3.set_col_spacings(5)
+ box3.set_border_width(10)
+ nf_frame = gtk.GtkFrame('Add Field')
+ nf_frame.add(box3)
+ self.new_field_name_entry = gtk.GtkEntry(10)
+ self.new_field_name_entry.set_text('')
+ self.new_field_name_entry.set_editable(gtk.TRUE)
+ self.new_field_width_entry = gtk.GtkEntry(2)
+ self.new_field_width_entry.set_text('20')
+ self.new_field_width_entry.set_editable(gtk.TRUE)
+ self.new_field_precision_entry = gtk.GtkEntry(2)
+ self.new_field_precision_entry.set_text('0')
+ self.new_field_precision_entry.set_editable(gtk.FALSE)
+ self.new_field_precision_entry.set_sensitive(gtk.FALSE)
+
+ self.new_field_types = ('string','integer','float')
+ self.new_field_type_menu = gvutils.GvOptionMenu(self.new_field_types, self.new_field_precision_cb)
+ self.new_field_type_menu.set_history(0)
+ box3.attach(gtk.GtkLabel('Name'),0,1,0,1)
+ box3.attach(self.new_field_name_entry,1,2,0,1)
+ box3.attach(gtk.GtkLabel('Type'),0,1,1,2)
+ box3.attach(self.new_field_type_menu,1,2,1,2)
+ box3.attach(gtk.GtkLabel('Width'),0,1,2,3)
+ box3.attach(self.new_field_width_entry,1,2,2,3)
+ box3.attach(gtk.GtkLabel('Precision'),0,1,3,4)
+ box3.attach(self.new_field_precision_entry,1,2,3,4)
+ button = gtk.GtkButton("Add")
+ box3.attach(button,0,2,4,5)
+ button.connect("clicked", self.add_field)
+
+ shell.pack_start(nf_frame)
+ nf_frame.show_all()
+
+ # Ability to delete fields?
+ self.fill_grid()
+ self.grid.resize_to_default()
+ self.show_all()
+
+ def fill_grid(self):
+ """ Get the schema and fill the grid """
+ sch=self.shapes.get_schema()
+ schl=[]
+ for item in sch:
+ schl.append(list(item))
+ if len(schl) > 0:
+ self.grid.set_source(schl,expose=0)
+ self.grid.define_columns(titles=['Name','Type','Width','Precision'],
+ editables=[0,0,1,1])
+
+ def add_field(self,*args):
+ """ Add field """
+ import string
+
+ sch=self.shapes.get_schema()
+ name=self.new_field_name_entry.get_text()
+
+ for item in sch:
+ if string.lower(item[0]) == string.lower(name):
+ gvutils.error('Field '+name+' already present!')
+ return
+
+
+ ftype = self.new_field_types[self.new_field_type_menu.get_history()]
+
+
+ try:
+ fwidth = int(self.new_field_width_entry.get_text())
+ except:
+ gvutils.error('Field width must be an integer!')
+ return
+
+ if ftype == 'float':
+ try:
+ fprec = int(self.new_field_precision_entry.get_text())
+ except:
+ gvutils.error('Precision width must be an integer!')
+ return
+ else:
+ fprec = 0
+
+ self.shapes.add_field(name,ftype,fwidth,fprec)
+ self.fill_grid()
+ if self.shapesgridtool is not None:
+ self.shapesgridtool.refresh_columns()
+
+ def changed_field(self,*args):
+ """ User changed a field """
+ cell=args[1]
+ if cell[1] == 2:
+ # width updated
+ idx=str(cell[0]+1)
+ self.shapes.set_property('_field_width_'+str(idx),
+ self.grid.get_cell_data_string(cell[0],cell[1]))
+ if self.shapesgridtool is not None:
+ self.shapesgridtool.refresh_columns()
+
+ elif cell[1] == 3:
+ # precision updated
+ # width updated
+ idx=str(cell[0]+1)
+ if self.grid.get_cell_data_string(cell[0],1) == 'float':
+ self.shapes.set_property('_field_precision_'+str(idx),
+ self.grid.get_cell_data_string(cell[0],cell[1]))
+ if self.shapesgridtool is not None:
+ self.shapesgridtool.refresh_columns()
+
+ else:
+ if self.grid.get_cell_data_string(cell[0],cell[1]) != '0':
+ self.grid.set_cell_data_string(cell[0],cell[1],0)
+ gvutils.error('Precision can only be reset for float.')
+
+ else:
+ gvutils.error('Name and type of a field cannot be changed.')
+
+
+ def new_field_precision_cb(self,*args):
+ if self.new_field_types[self.new_field_type_menu.get_history()] ==\
+ 'float':
+ # precision is only relevant for float
+ self.new_field_precision_entry.set_editable(gtk.TRUE)
+ self.new_field_precision_entry.set_sensitive(gtk.TRUE)
+ else:
+ self.new_field_precision_entry.set_text('0')
+ self.new_field_precision_entry.set_editable(gtk.FALSE)
+ self.new_field_precision_entry.set_sensitive(gtk.FALSE)
+
+
+
+TOOL_LIST = ["ShapesGridTool"]
+
+
Added: packages/openev/branches/upstream/current/tools/Tool_autopan.py
===================================================================
--- packages/openev/branches/upstream/current/tools/Tool_autopan.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/Tool_autopan.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,586 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: Tool_autopan.py,v 1.3 2005/08/01 09:23:11 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: Test for panning capabilities (an OpenEV tool).
+# Author: Gillian Walter <gillian.walter at atlantis-scientific.com>
+#
+# Developed by Atlantis Scientific Inc. (www.atlantis-scientific.com) for
+# DRDC Ottawa
+#
+###############################################################################
+# Copyright (c) Her majesty the Queen in right of Canada as represented
+# by the Minister of National Defence, 2003.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: Tool_autopan.py,v $
+# Revision 1.3 2005/08/01 09:23:11 andrey_kiselev
+# Return empty string if LD_LIBRARY_PATH/PATH environment variables are not set.
+#
+# Revision 1.2 2005/02/22 13:22:39 gmwalter
+# Add autopan tool.
+#
+# Revision 1.1.2.1 2005/02/18 01:27:23 gmwalter
+# Added autopan test tool.
+#
+# Revision 1.9 2005/01/31 21:17:55 gwalter
+# Update autopan, fix a few gui issues.
+#
+# Revision 1.8 2005/01/29 04:14:44 gwalter
+# Add trail test.
+#
+# Revision 1.7 2005/01/20 20:11:42 gwalter
+# Update autopan to add path type option,
+# add secondary view to test tool.
+#
+# Revision 1.6 2005/01/17 21:24:13 gwalter
+# Avoid problems when window is shut and
+# then opened again.
+#
+# Revision 1.5 2005/01/17 16:36:01 gwalter
+# Updated pan test tool.
+#
+# Revision 1.4 2005/01/14 15:51:18 gwalter
+# Help and autopan updates.
+#
+# Revision 1.3 2004/11/25 21:17:17 gwalter
+# Updated.
+#
+
+import gviewapp
+import Numeric
+import gtk
+import time
+import gview
+import gvutils
+import os
+import string
+import gdal
+import vrtutils
+import pgucolorsel
+
+class PyAutopanTool(gviewapp.Tool_GViewApp):
+ def __init__(self, app=None, startpath=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.init_menu()
+ self.view=None
+ self.playing=0
+ self.id=None
+ self.speed = 0.01
+
+ gtk.quit_add(0,self.quit_cb)
+
+ def quit_cb(self,*args):
+ self.playing = 0
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/PyAutopan",1,
+ self.startpan_cb)
+
+ def startpan_cb(self, *args):
+ if self.playing == 1:
+ print 'already panning- left click to stop'
+ return
+
+ for view in self.app.view_manager.view_list:
+ if view.title == args[1]:
+ self.app.view_manager.set_active_view(view)
+ self.view = view.viewarea
+ self.viewwin = view
+
+ xmin,ymin,xmax,ymax = self.view.get_extents()
+ xwidth = xmax-xmin
+ ywidth = ymax-ymin
+ self.id=self.viewwin.connect('button-release-event',self.stoppan_cb)
+ self.playing = 1
+
+ self.xmin,self.ymin,self.xwidth,self.ywidth=xmin,ymin,xwidth,ywidth
+
+ self.set_speed(0.01)
+ self.view.fit_extents(self.centers[0][0],self.centers[0][1],
+ xwidth/8,ywidth/8)
+
+ while self.playing == 1:
+ self.view.set_translation(self.centers[self.idx][0],
+ self.centers[self.idx][1])
+ self.idx = self.idx+1
+ if self.idx > len(self.centers)-1:
+ self.idx = 0
+
+ while gtk.events_pending():
+ gtk.mainiteration()
+
+ def set_speed(self,speed):
+ self.speed = speed
+ if self.speed > 0:
+ self.speed = min(1.0,max(self.speed,0.000001))
+ else:
+ self.speed = max(-1.0,min(self.speed,-0.000001))
+
+ self.centers=[]
+ xmin,ymin,xwidth,ywidth=self.xmin,self.ymin,self.xwidth,self.ywidth
+
+ for dy in Numeric.arange(ymin,ymin+ywidth,ywidth/10):
+ for dx in Numeric.arange(xmin,xmin+xwidth,xwidth*speed/8):
+ self.centers.append((-dx,-dy))
+ if self.speed < 0:
+ self.centers.reverse()
+ self.idx = 0
+
+ def stoppan_cb(self, *args):
+ if self.playing == 0:
+ return
+
+ event=args[1]
+ if event.button == 1:
+
+ if self.id is not None:
+ self.viewwin.disconnect(self.id)
+ self.id = None
+
+ self.playing = 0
+ self.view = None
+ self.viewwin = None
+ self.id = None
+
+ elif event.button == 2:
+ self.speed = self.speed*1.25
+ self.set_speed(self.speed)
+ elif event.button == 3:
+ self.speed = self.speed/1.25
+ self.set_speed(self.speed)
+
+
+class AutopanTool(gviewapp.Tool_GViewApp):
+ def __init__(self, app=None, startpath=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+
+ self.init_menu()
+ self.view=None
+ self.second_view = None
+
+ self.playing=0
+ self.id=None
+ self.tool = gview.GvAutopanTool()
+ if os.name != 'nt':
+ lp = os.environ.get('LD_LIBRARY_PATH', '')
+ else:
+ lp = os.environ.get('PATH', '')
+
+ if string.find(lp,'Mesa') == -1:
+ self.speed = 0.001
+ self.default_speed = 0.001
+ else:
+ self.speed = 0.01
+ self.default_speed = 0.01
+
+ self.active = 0
+ self.dialog = None
+ self.ext = None
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Autopan",1,
+ self.showgui_cb)
+
+ def showgui_cb(self, *args):
+ if self.dialog is None:
+ self.dialog = gtk.GtkWindow()
+ self.dialog.connect('delete-event',self.close)
+ table = gtk.GtkTable(9,4)
+ table.set_border_width(10)
+ table.set_row_spacings(10)
+ table.set_col_spacings(10)
+ vbox = gtk.GtkVBox()
+ self.dialog.add(vbox)
+ vbox.pack_start(table)
+
+ iconbar = gtk.GtkToolbar(gtk.ORIENTATION_HORIZONTAL,
+ gtk.TOOLBAR_ICONS)
+
+ arrows = []
+ atypes = [gtk.ARROW_LEFT,gtk.ARROW_UP,
+ gtk.ARROW_DOWN,gtk.ARROW_RIGHT]
+
+ cbs = [self.rewind_cb, self.speed_up_cb, self.speed_down_cb,
+ self.play_cb]
+ for atype,cb in map(None,atypes,cbs):
+ arr = gtk.GtkButton()
+ arr.set_border_width(0)
+ arr.set_relief(gtk.RELIEF_NONE)
+ arr.add(gtk.GtkArrow(atype))
+ arr.connect('clicked',cb)
+ arrows.append(arr)
+
+ vbox = gtk.GtkVBox(spacing=0, homogeneous=gtk.FALSE)
+ vbox.pack_start(arrows[1], expand=gtk.FALSE)
+ vbox.pack_start(arrows[2], expand=gtk.FALSE)
+
+ # Now put them in the toolbar
+ iconbar.append_widget(arrows[0], 'Rewind', 'Rewind')
+ iconbar.append_widget(vbox, 'Adjust speed', 'Adjust speed')
+ iconbar.append_widget(arrows[3], 'Play', 'Play')
+
+ table.attach(iconbar,0,1,0,1)
+ but = gtk.GtkButton('Stop')
+ table.attach(but,1,2,0,1)
+ but.connect('clicked',self.stop_pan_cb)
+
+ but = gtk.GtkButton('Pause')
+ table.attach(but,2,3,0,1)
+ but.connect('clicked',self.pause_pan_cb)
+
+ label = gtk.GtkLabel('Block Size Mode:')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,1,2)
+ self.block_size_menu = gvutils.GvOptionMenu(
+ ('Relative to Pan Extents','View Coordinates','Constant Resolution'),
+ self.block_mode_changed)
+ table.attach(self.block_size_menu,1,3,1,2)
+
+ self.block_label_list=['Block x size (0-1):',
+ 'Block x size:',
+ 'View units/Pixel:']
+ self.block_label = gtk.GtkLabel(self.block_label_list[0])
+ self.block_label.set_alignment(0,0.5)
+ table.attach(self.block_label,0,1,2,3)
+ self.block_entry = gtk.GtkEntry()
+ self.block_entry.set_editable(gtk.TRUE)
+ self.block_entry.set_text('0.125')
+ self.block_entry.connect('leave-notify-event',
+ self.block_size_changed)
+ table.attach(self.block_entry,1,3,2,3)
+
+ label = gtk.GtkLabel('Overlap (0-1):')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,3,4)
+ self.overlap_entry = gtk.GtkEntry()
+ self.overlap_entry.set_editable(gtk.TRUE)
+ self.overlap_entry.set_text('0.1')
+ self.overlap_entry.connect('leave-notify-event',
+ self.overlap_changed)
+ table.attach(self.overlap_entry,1,3,3,4)
+
+ label = gtk.GtkLabel('Path type:')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,4,5)
+ self.path_menu = gvutils.GvOptionMenu(
+ ('0','1','2','3','4'),
+ self.path_changed)
+ table.attach(self.path_menu,1,3,4,5)
+
+ label = gtk.GtkLabel('Show trail:')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,5,6)
+ self.trail_menu = gvutils.GvOptionMenu(
+ ('No','Yes'),
+ self.trail_changed)
+ table.attach(self.trail_menu,1,2,5,6)
+ button = gtk.GtkButton('Clear Trail')
+ table.attach(button,2,3,5,6)
+ button.connect('clicked', self.clear_trail)
+
+ label = gtk.GtkLabel('Trail Color:')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,6,7)
+
+ self.trail_color = pgucolorsel.ColorControl('Trail Color',
+ self.trail_color_cb)
+ table.attach(self.trail_color,1,3,6,7)
+ self.trail_color.set_color((1.0,0.75,0.0,0.5))
+ self.second_view = gview.GvViewArea()
+ self.second_view.set_usize(300,300)
+
+ table.attach(self.second_view,0,3,7,8)
+
+ self.dialog.show_all()
+ self.dialog.connect('delete-event',self.close)
+
+ self.viewtitle = args[1]
+ self.dialog.show()
+ self.dialog.get_window()._raise()
+
+ def close(self,*args):
+ if self.view is not None:
+ self.tool.deactivate(self.view)
+ self.playing = 0
+ self.active = 0
+ self.view = None
+ self.dialog.hide()
+ return gtk.TRUE
+
+ def path_changed(self, *args):
+ path_type = int(self.path_menu.get_history())
+ self.tool.set_standard_path(path_type)
+
+ def block_mode_changed(self,*args):
+ mode = self.block_size_menu.get_history()
+ self.block_label.set_text(self.block_label_list[mode])
+ self.block_size_changed()
+
+ def trail_changed(self, *args):
+ if self.view is None:
+ return
+
+ self.tool.set_trail_mode(self.second_view,
+ self.trail_menu.get_history())
+
+ def trail_color_cb(self,*args):
+ if self.view is not None:
+ self.tool.set_trail_color(self.second_view,
+ self.trail_color.current_color[0],
+ self.trail_color.current_color[1],
+ self.trail_color.current_color[2],
+ self.trail_color.current_color[3])
+
+
+ def clear_trail(self, *args):
+ self.tool.clear_trail()
+
+ def block_size_changed(self, *args):
+ if self.active == 0 or self.playing == 0:
+ return
+ mode = self.block_size_menu.get_history()
+ defaults = [0.1, 0.1*self.ext[2], 0.1*self.ext[2]]
+ try:
+ xorres = abs(float(self.block_entry.get_text()))
+ except:
+ if mode == 0:
+ msg = 'Relative block size must be a number, 0-1!'
+ elif mode == 1:
+ msg = 'Block size must be a number!'
+ elif mode == 2:
+ msg = 'Resolution must be a number!'
+ gvutils.error(msg)
+ xorres = defaults[mode]
+ self.block_size_entry.set_text(str(xorres))
+
+ if (mode == 0) and ((xorres < 0) or (xorres > 1)):
+ msg = 'Relative block size must be a number, 0-1!'
+ gvutils.error(msg)
+ xorres = defaults[mode]
+ self.block_size_entry.set_text(str(xorres))
+
+ if mode < 2:
+ self.tool.set_block_x_size(xorres, mode)
+ else:
+ self.tool.set_x_resolution(xorres)
+
+ def overlap_changed(self,*args):
+ if self.active == 0:
+ return
+ txt = self.overlap_entry.get_text()
+ try:
+ val = float(txt)
+ except:
+ gvutils.error('Overlap must be a number, 0 <= overlap < 1!')
+ val = 0.1
+ self.overlap_entry.set_text('0.1')
+
+ if (val < 0) or (val >= 1):
+ gvutils.error('Overlap must be a number, 0 <= overlap < 1!')
+ val = 0.1
+ self.overlap_entry.set_text('0.1')
+
+ self.tool.set_overlap(val)
+
+
+ def pause_pan_cb(self, *args):
+ self.playing = 2
+ self.tool.pause()
+
+ def stop_pan_cb(self, *args):
+ self.tool.pause()
+ self.playing = 0
+ if self.ext is not None:
+ if self.view is not None:
+ self.view.fit_extents(self.ext[0],self.ext[1],
+ self.ext[2],self.ext[3])
+ self.tool.deactivate(self.view)
+ self.ext = None
+ self.view = None
+
+ def speed_up_cb(self, *args):
+ if self.active == 0:
+ return
+ self.speed *= 1.25
+ self.tool.set_speed(self.speed)
+
+ def speed_down_cb(self, *args):
+ if self.active == 0:
+ return
+ self.speed /= 1.25
+ self.tool.set_speed(self.speed)
+
+ def rewind_cb(self, *args):
+ self.speed = -1*self.default_speed
+ if self.playing == 1:
+ self.tool.set_speed(self.speed)
+ return
+
+ if self.playing == 2:
+ self.tool.set_speed(self.speed)
+ self.tool.play()
+ return
+
+ self.setup_playing()
+
+
+ def play_cb(self, *args):
+ self.speed = self.default_speed
+ if self.playing == 1:
+ self.tool.set_speed(self.speed)
+ return
+
+ if self.playing == 2:
+ self.tool.set_speed(self.speed)
+ self.tool.play()
+ return
+
+ self.setup_playing()
+
+ def setup_playing(self, *args):
+ if self.view is not None:
+ self.tool.deactivate(self.view)
+
+ for view in self.app.view_manager.view_list:
+ if view.title == self.viewtitle:
+ self.app.view_manager.set_active_view(view)
+ self.view = view.viewarea
+ self.tool.activate(self.view)
+ self.tool.register_view(self.second_view,0,1,
+ self.trail_menu.get_history())
+ self.tool.set_trail_color(self.second_view,
+ self.trail_color.current_color[0],
+ self.trail_color.current_color[1],
+ self.trail_color.current_color[2],
+ self.trail_color.current_color[3])
+
+
+ # update the secondary view with a background raster
+ plyr = self.view.active_layer()
+ rst = None
+ ds = None
+ try:
+ rst = plyr.get_parent()
+ ds = rst.get_dataset()
+ except:
+ llist = self.view.list_layers()
+ llist.reverse()
+ for plyr in llist:
+ try:
+ rst = plyr.get_parent()
+ ds = rst.get_dataset()
+ break
+ except:
+ pass
+
+ if ds is None:
+ gvutils.error('Error- no raster to pan over in active view!')
+ return
+
+ dtype = gdal.GetDataTypeName(ds.GetRasterBand(1).DataType)
+
+ xsize = ds.RasterXSize
+ ysize = ds.RasterYSize
+ while (xsize > 512) and (ysize > 512):
+ xsize = xsize/2
+ ysize = ysize/2
+
+ srcrect = [0,0,ds.RasterXSize, ds.RasterYSize]
+ dstrect = [0,0,xsize,ysize]
+
+ vrt = vrtutils.VRTDatasetConstructor(xsize,ysize)
+
+ fname = ds.GetDescription()
+
+ lyrs = self.second_view.list_layers()
+ for lyr in lyrs:
+ self.second_view.remove_layer(lyr)
+
+ gcps = ds.GetGCPs()
+ if len(gcps) > 0:
+ vrt.SetGCPs(gcps,ds.GetGCPProjection(),None,
+ srcrect,dstrect)
+ else:
+ gt = ds.GetGeoTransform()
+ if gt != (0.0,1.0,0.0,0.0,0.0,1.0):
+ vrt.SetSRS(ds.GetProjection())
+ vrt.SetGeoTransform(gt,srcrect,dstrect,1)
+
+ for idx in range(0,plyr.sources):
+ rst = plyr.get_data(idx)
+ if rst is not None:
+ cmin = plyr.min_get(idx)
+ cmax = plyr.max_get(idx)
+ srcdiff=cmax-cmin
+ if abs(srcdiff) > 0.0:
+ ratio = 255/srcdiff
+ else:
+ ratio = 1.0
+ offset = -cmin*ratio
+
+ vrt.AddSimpleBand(fname,rst.get_band_number(),dtype,
+ srcrect,dstrect,ScaleOffset=offset,
+ ScaleRatio = ratio)
+
+ ds2 = gview.manager.get_dataset(vrt.GetVRTString())
+ raster = gview.manager.get_dataset_raster( ds2, 1 )
+ options = []
+ if ( ds2.RasterCount == 1 ):
+ raster_layer = gview.GvRasterLayer( raster, options,
+ rl_mode = gview.RLM_AUTO )
+ else:
+ raster_layer = gview.GvRasterLayer( raster, options,
+ rl_mode = gview.RLM_RGBA )
+
+ if ( raster_layer.get_mode() == gview.RLM_RGBA ):
+
+ green_raster = gview.manager.get_dataset_raster( ds2, 2)
+ raster_layer.set_source( 1, green_raster )
+ if ( ds2.RasterCount > 2 ):
+ blue_raster = \
+ gview.manager.get_dataset_raster( ds2, 3 )
+ raster_layer.set_source( 2, blue_raster )
+
+ if ( ds2.RasterCount > 3 ):
+ band = ds2.GetRasterBand(4)
+ if ( band.GetRasterColorInterpretation() ==
+ gdal.GCI_AlphaBand ):
+ raster_layer.blend_mode_set(
+ gview.RL_BLEND_FILTER )
+ alpha_raster = \
+ gview.manager.get_dataset_raster( ds2, 4 )
+ raster_layer.set_source( 3, alpha_raster )
+
+ self.second_view.add_layer(raster_layer)
+
+ self.active = 1
+ xmin,ymin,xmax,ymax = self.view.get_extents()
+ xwidth = xmax-xmin
+ ywidth = ymax-ymin
+ self.ext = (xmin,ymin,xwidth,ywidth)
+ self.tool.set_extents((xmin,ymin,xwidth,ywidth))
+ self.playing = 1
+ self.tool.set_speed(self.speed)
+ self.block_size_changed()
+ self.overlap_changed()
+ self.tool.play()
+
+TOOL_LIST = ['AutopanTool']
Added: packages/openev/branches/upstream/current/tools/calculator.py
===================================================================
--- packages/openev/branches/upstream/current/tools/calculator.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/calculator.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1061 @@
+##############################################################################
+# $Id: calculator.py,v 1.4 2004/10/23 11:04:42 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: Interactive tool to perform calculations on pair of images.
+# Authors: Iscander Latypov
+# Andrey Kiselev, dron at remotesensing.org
+#
+###############################################################################
+# Copyright (c) 2004, American Museum of Natural History. All rights reserved.
+# This software is based upon work supported by NASA under award
+# number NAG5-12333
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: calculator.py,v $
+# Revision 1.4 2004/10/23 11:04:42 andrey_kiselev
+# Can work with the layers, opened via 'Open Subarea' dialog.
+#
+# Revision 1.3 2004/07/04 09:50:41 andrey_kiselev
+# More checks for valid raster layer.
+#
+# Revision 1.2 2004/04/21 13:25:38 andrey_kiselev
+# Added differently styled RCalculatorDialog.
+#
+# Revision 1.1 2004/02/25 21:08:56 andrey_kiselev
+# New.
+#
+#
+
+from gtk import *
+
+import Numeric
+from Numeric import cos,log,exp,sin,sqrt,maximum,minimum,tan,arcsin,arccos
+from Numeric import arctan,bitwise_and,bitwise_or,bitwise_xor,invert,hypot
+from Numeric import left_shift,right_shift
+
+import gview
+import gvutils
+import gviewapp
+import gdal
+from gdalconst import *
+import gdalnumeric
+
+
+"""Image Calculator is the tool, that operate with the pair of images.
+ The source images are the bands of opened layers, the result
+ is new layer with only band, that contains image computed from
+ sources by given formula. The coefficients for calculation
+ defined by user in dialog box."""
+
+########################################################################
+def get_raster_size(_layer):
+ w = _layer.get_parent().get_dataset().GetRasterBand(1).XSize
+ h = _layer.get_parent().get_dataset().GetRasterBand(1).YSize
+ return (w,h)
+
+########################################################################
+def get_list_of_layers_as_dict():
+ """Returns dictionary of opened layers. The key of dictionary is
+ the name of layer, members of dictionary are view object (index = 0)
+ and layer object (index = 1)"""
+
+ dict = {}
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ dict[curname] = (curview,curlayer)
+ if dict is None:
+ return None
+ return dict
+
+########################################################################
+def get_list_of_layers_as_menu():
+ """Returns GtkMenu object for selecting of opened layers.
+ If number of opened layers is zero, the result is None"""
+ menu = GtkMenu()
+ group = None
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ menuitem = GtkRadioMenuItem(group,curname)
+ group = menuitem
+ menu.append(menuitem)
+ menuitem.show()
+ if group is None:
+ return None
+ return menu
+
+#########################################################################
+def layer_is_raster(layer):
+ """returns TRUE if layer is raster and FALSE if else"""
+ try:
+ layer.get_nodata(0)
+ return TRUE
+ except:
+ return FALSE
+
+#########################################################################
+def get_filename_from_vrtdataset(vrt_dataset_name):
+ if vrt_dataset_name[:11] != "<VRTDataset": return vrt_dataset_name
+ ss = vrt_dataset_name.find("<SourceFilename relativeToVRT")
+ ss = vrt_dataset_name.find(">",ss)
+ se = vrt_dataset_name.find("</SourceFilename",ss)
+ return "SubArea_"+vrt_dataset_name[ss+1:se]
+
+
+########################################################################
+def get_list_of_bands_as_dict():
+ """Returns dictionary of the bands of the opened layers. The key
+ of dictionary is the name of layer+band number, members of dictionary
+ are view-object (index = 0), layer-object (index = 1) and band-number"""
+
+ active_layer = gview.app.sel_manager.get_active_layer()
+ if not layer_is_raster(active_layer):
+ return None
+ _size = get_raster_size(active_layer)
+ dict = {}
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ if not layer_is_raster(curlayer):
+ continue
+ curname = curlayer.get_name()
+ curname = get_filename_from_vrtdataset(curname)
+ cursize = get_raster_size(curlayer)
+ if cursize == _size:
+ num_bands = curlayer.get_parent().get_dataset().RasterCount
+ for i in range(num_bands):
+ curband = curname + '.band['+ str(i) + ']'
+ dict[curband] = (curview,curlayer,i)
+ return dict
+
+#########################################################################
+def clip_result(numtype, array):
+ if numtype is Numeric.UnsignedInt8:
+ return Numeric.clip(array, 0.0, 255.0)
+ elif numtype is Numeric.Int16:
+ return Numeric.clip(array, -32768.0, 32767.0)
+ elif numtype is Numeric.Int32:
+ return Numeric.clip(array, -2147483648.0, 2147483647.0)
+ else:
+ return array
+
+############################################################################
+#
+#
+############################################################################
+class CalculatorTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ try:
+ self.win = CalculatorDialog()
+ except:
+ gvutils.error("Please select a raster layer.");
+ return
+
+ self.win.update_gui()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image/Calculator...",2,
+ self.launch_dialog)
+
+############################################################################
+class CalculatorDialog(GtkWindow):
+
+ def __init__(self,app=None):
+ rlayer = gview.app.sel_manager.get_active_layer()
+ if rlayer is None:
+ raise TypeError
+ try:
+ gdal_dataset = rlayer.get_data().get_dataset()
+ except:
+ raise TypeError
+
+ GtkWindow.__init__(self)
+ self.set_title('Image Calculator')
+ self.set_policy(FALSE, TRUE, TRUE)
+
+ try:
+ self.create_gui()
+ except:
+ raise TypeError
+
+ GtkWindow.show_all(self)
+
+ def close(self,*args):
+ self.destroy()
+ return TRUE
+
+ def create_gui(self):
+ self.dict_of_bands = get_list_of_bands_as_dict()
+ if self.dict_of_bands is None:
+ raise
+ self.list_of_bands = self.dict_of_bands.keys()
+
+ title_width = 120
+
+ box1 = GtkVBox(spacing=5)
+ self.add(box1)
+ box1.show()
+
+#### OPERATIONS ####################################################
+ box_op = GtkHBox(spacing=10)
+ box1.set_border_width(10)
+ box1.pack_start(box_op, expand=FALSE)
+ box_op.show()
+
+ op_label = GtkLabel('Operation:')
+ op_label.set_alignment(0, 0.5)
+ box_op.pack_start(op_label, expand=FALSE)
+
+# The item <operations_dict> is the dictionary, that contains
+# the list of calculator operation names as keys and the set
+# of corresponding functions.
+ self.operations_dict = {}
+ self.operations_dict['Add [Res = A * X + B * Y + C]'] = \
+ (3,self.add_bands)
+ self.operations_dict['Multiply [Res = X * Y]'] = \
+ (0,self.multiply_bands)
+ self.operations_dict['Divide [Res = A * X / (Y + B) + C]'] = \
+ (3,self.divide_bands)
+ self.operations_dict['Vegetation Index [Res = A * (X - Y) / ( X + Y) + B]'] = (2,self.veg_index)
+
+ self.operations_list = self.operations_dict.keys()
+
+ self.operation = \
+ gvutils.GvOptionMenu(self.operations_list,self.update_gui)
+ box_op.pack_start(self.operation)
+ self.operation.show()
+
+### COEFFICIENTS ######################################################
+ self.box_coeffs = GtkHBox(spacing = 10)
+ box1.pack_start(self.box_coeffs, expand=FALSE)
+ self.box_coeffs.show()
+
+ self.box_coeff_a = GtkHBox(spacing = 5)
+ self.box_coeffs.pack_start(self.box_coeff_a, expand=FALSE)
+ self.box_coeff_a.show()
+
+ a_label = GtkLabel('A =')
+ a_label.set_alignment(0, 0.5)
+ self.box_coeff_a.pack_start(a_label)
+
+ self.a_const = GtkEntry()
+ self.a_const.set_usize(80,30)
+ self.a_const.set_text('1')
+ self.box_coeff_a.pack_start(self.a_const, expand=FALSE)
+ self.a_const.show()
+
+ self.box_coeff_b = GtkHBox(spacing = 5)
+ self.box_coeffs.pack_start(self.box_coeff_b, expand=FALSE)
+ self.box_coeff_b.show()
+
+ b_label = GtkLabel('B =')
+ b_label.set_alignment(0, 0.5)
+ self.box_coeff_b.pack_start(b_label)
+
+ self.b_const = GtkEntry()
+ self.b_const.set_usize(80,30)
+ self.b_const.set_text('1')
+ self.box_coeff_b.pack_start(self.b_const, expand=FALSE)
+ self.b_const.show()
+
+ self.box_coeff_c = GtkHBox(spacing = 5)
+ self.box_coeffs.pack_start(self.box_coeff_c, expand=FALSE)
+ self.box_coeff_c.show()
+
+ c_label = GtkLabel('C =')
+ c_label.set_alignment(0, 0.5)
+ self.box_coeff_c.pack_start(c_label)
+
+ self.c_const = GtkEntry()
+ self.c_const.set_usize(80,30)
+ self.c_const.set_text('1')
+ self.box_coeff_c.pack_start(self.c_const, expand=FALSE)
+ self.c_const.show()
+
+ self.coeffs_vis = [self.box_coeff_a,self.box_coeff_b,self.box_coeff_c]
+
+### source1 #############################################################
+ frame1 = GtkFrame("Select Image Bands To Compute")
+ frame1.show()
+ box1.pack_start(frame1, expand=FALSE)
+
+ box2 = GtkVBox(spacing=10)
+ box2.set_border_width(10)
+ frame1.add(box2)
+ box2.show()
+
+
+ box_s1 = GtkHBox(spacing=10)
+ box2.pack_start(box_s1, expand=FALSE)
+ box_s1.show()
+
+ source1_label = GtkLabel('Source 1 < X >:')
+ source1_label.set_alignment(0, 0.5)
+ box_s1.pack_start(source1_label,expand=FALSE)
+
+ self.s1_list = gvutils.GvOptionMenu(self.list_of_bands)
+ box_s1.pack_start(self.s1_list)
+ self.s1_list.show()
+
+## source2 ##############################################################
+ box_s2 = GtkHBox(spacing=10)
+ box2.pack_start(box_s2, expand=FALSE)
+ box_s2.show()
+
+ source2_label = GtkLabel('Source 2 < Y >:')
+ source2_label.set_alignment(0, 0.5)
+ box_s2.pack_start(source2_label,expand=FALSE)
+
+ self.s2_list = gvutils.GvOptionMenu(self.list_of_bands)
+ box_s2.pack_start(self.s2_list)
+ self.s2_list.show()
+
+#####OUT TYPES#########################################################
+ box_types = GtkHBox(spacing=10)
+ box2.pack_start(box_types, expand=FALSE)
+ box_types.show()
+
+ types_label = GtkLabel('Image data type:')
+ types_label.set_alignment(0, 0.5)
+ box_types.pack_start(types_label, expand=FALSE)
+
+ self.types_list = []
+ i = GDT_Byte
+ while i < GDT_TypeCount:
+ self.types_list.append(gdal.GetDataTypeName(i))
+ i += 1
+
+ self.types = gvutils.GvOptionMenu(self.types_list)
+ box_types.pack_start(self.types)
+ self.types.show()
+
+
+#### NEW VIEW ##########################################################
+ self.switch_new_view = GtkCheckButton("Create New View")
+ box1.pack_start(self.switch_new_view)
+ self.switch_new_view.show()
+
+#### BUTTONS ###########################################################
+ box_buttons = GtkHBox(spacing=15)
+ box1.pack_start(box_buttons, expand=FALSE)
+ box_buttons.show()
+
+ self.ok_btn = GtkButton("Ok")
+ self.ok_btn.connect("clicked", self.compute)
+ box_buttons.pack_start(self.ok_btn)
+
+ self.cancel_btn = GtkButton("Cancel")
+ self.cancel_btn.connect("clicked", self.close)
+ box_buttons.pack_start(self.cancel_btn)
+
+ return TRUE
+
+#########################################################################
+#########################################################################
+ def update_gui(self,*args):
+ i = self.operation.get_history()
+ self.op = self.operations_list[i]
+ k = self.operations_dict[self.op][0]
+ if k == 0:
+ self.box_coeffs.hide()
+ else:
+ self.box_coeffs.show()
+ for j in range(3):
+ if j < k:
+ self.coeffs_vis[j].show()
+ else:
+ self.coeffs_vis[j].hide()
+#########################################################################
+ def compute(self,*args):
+ def get_band(name):
+ layer = self.dict_of_bands[name][1]
+ b_num = self.dict_of_bands[name][2]
+ band = layer.get_parent().get_dataset().GetRasterBand(b_num+1)
+ return band
+
+ def create_new_layer(pview,player,w,h):
+ """Creates new raster layer like <player> with width = w
+ and height = h"""
+
+ gview.app.view_manager.set_active_view(pview)
+ pview.viewarea.set_active_layer(player)
+ target_ds = player.get_parent().get_dataset()
+ rl_mode_value = player.get_mode()
+ new_layer = gview.GvRasterLayer( \
+ gview.GvRaster(dataset = target_ds,real=1), \
+ rl_mode = rl_mode_value)
+ pview.viewarea.list_layers().append(new_layer)
+ return new_layer
+
+
+ # extract computing parameters
+ b1_name = self.list_of_bands[self.s1_list.get_history()]
+ b2_name = self.list_of_bands[self.s2_list.get_history()]
+ if b1_name <> None:
+ if self.switch_new_view.get_active():
+ gview.app.new_view()
+ op_index = self.operation.get_history()
+ type_index = self.types.get_history()
+
+ a = float(self.a_const.get_text())
+ b = float(self.b_const.get_text())
+ c = float(self.c_const.get_text())
+ b1 = get_band(b1_name)
+ b2 = get_band(b2_name)
+
+ type = \
+ gdal.GetDataTypeByName(self.types_list[self.types.get_history()])
+ self.numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(type)
+ if self.numtype == None:
+ gvutils.error("Error! Type " + self.numtype + " is not supported!")
+ return FALSE
+
+ proto_ds = self.dict_of_bands[b1_name][1].get_parent().get_dataset()
+ op_func = self.operations_dict[self.op][1]
+ self.out_buf = Numeric.zeros((b1.YSize, b1.XSize), self.numtype)
+ try:
+ op_func(s1=b1,s2=b2,a=a,b=b,c=c)
+ except:
+ gvutils.error("Try to change coefficients.")
+ return FALSE
+ res_ds = gdalnumeric.OpenArray(self.out_buf,proto_ds)
+ gview.app.open_gdal_dataset(res_ds)
+ self.close()
+ else:
+ gvutils.error("Source1 and Source2 have to differ!")
+ return FALSE
+
+#########################################################################
+ def add_bands(self,s1,s2,a,b,c):
+ """<add_bands> method computes the linear combination of the bands
+ Arguments:
+ s1 - first source band;
+ s2 - second source band;
+ a,b,c - linear combination coefficients;
+ The output raster pixel density is calculated by formula
+ res = a * X + b * Y + c
+ where X and Y are densities of first and second source bands
+ """
+ for i in range(s1.YSize):
+ s1_buf = gdalnumeric.BandReadAsArray(s1,0,i,s1.XSize,1)[0]
+ s2_buf = gdalnumeric.BandReadAsArray(s2,0,i,s1.XSize,1)[0]
+ temp_buf = a * s1_buf + b * s2_buf + c
+ self.out_buf[i, 0:] = \
+ clip_result(self.numtype, temp_buf).astype(self.numtype)
+
+#########################################################################
+ def multiply_bands(self,s1,s2,a,b,c):
+ """Method <multiply_bands> computes the production of the bands
+ Arguments:
+ s1 - first source band;
+ s2 - second source band;
+ a,b,c - unusable;
+ The output raster pixel density is calculated by formula
+ res = X * Y
+ where X and Y are densities of first and second source bands.
+ """
+ for i in range(s1.YSize):
+ s1_buf = gdalnumeric.BandReadAsArray(s1,0,i,s1.XSize,1)[0]
+ s2_buf = gdalnumeric.BandReadAsArray(s2,0,i,s1.XSize,1)[0]
+ temp_buf = 1. * s1_buf * s2_buf
+ self.out_buf[i, 0:] = \
+ clip_result(self.numtype, temp_buf).astype(self.numtype)
+
+#########################################################################
+ def divide_bands(self,s1,s2,a,b,c):
+ """<divide_bands> method executes the division of the bands
+ Arguments:
+ s1 - first source band;
+ s2 - second source band;
+ a,b,c - coefficients;
+ The output raster pixel density is calculated by formula
+ res = a * X / (b + Y) + c
+ where X and Y are densities of first and second source bands
+ """
+ for i in range(s1.YSize):
+ s1_buf = gdalnumeric.BandReadAsArray(s1,0,i,s1.XSize,1)[0]
+ s2_buf = gdalnumeric.BandReadAsArray(s2,0,i,s1.XSize,1)[0]
+ try:
+ temp_buf = a * s1_buf / ( b + s2_buf) + c
+ except:
+ raise
+ self.out_buf[i, 0:] = \
+ clip_result(self.numtype, temp_buf).astype(self.numtype)
+
+#########################################################################
+ def veg_index(self,s1,s2,a,b,c):
+ """Method <veg_index> computes the vegetation index for pair of the bands
+ Arguments:
+ s1 - first source band;
+ s2 - second source band;
+ a,b - coefficients;
+ c - unusable;
+ The output raster pixel density is calculated by formula
+ res = a * (X - Y) / (X + Y) + b
+ where X and Y are densities of first and second source bands.
+ """
+ for i in range(s1.YSize):
+ s1_buf = gdalnumeric.BandReadAsArray(s1,0,i,s1.XSize,1)[0]
+ s2_buf = gdalnumeric.BandReadAsArray(s2,0,i,s1.XSize,1)[0]
+ temp_buf1 = s1_buf + s2_buf + 1
+ temp_buf = a * (s1_buf-s2_buf) / temp_buf1 + b
+ self.out_buf[i, 0:] = \
+ clip_result(self.numtype, temp_buf).astype(self.numtype)
+
+############################################################################
+#
+#
+############################################################################
+class RCalculatorTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ try:
+ self.win = RCalculatorDialog()
+ except:
+ gvutils.error("Please select a raster layer.")
+ return
+
+ self.win.update_gui()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image/Raster Calculator...", 2,
+ self.launch_dialog)
+
+############################################################################
+class RCalculatorDialog(GtkWindow):
+
+ def __init__(self,app=None):
+ rlayer = gview.app.sel_manager.get_active_layer()
+ if rlayer is None:
+ raise TypeError
+ try:
+ gdal_dataset = rlayer.get_data().get_dataset()
+ except:
+ raise TypeError
+
+ GtkWindow.__init__(self)
+ self.set_title('Image Calculator')
+ self.set_policy(FALSE, TRUE, TRUE)
+ self.text_pos = 0
+ self.tooltips = GtkTooltips()
+ self.expression = ""
+
+ try:
+ self.create_gui()
+ except:
+ raise TypeError
+
+ GtkWindow.show_all(self)
+
+ def close(self,*args):
+ self.destroy()
+ return TRUE
+
+######################################################################
+ def bit_operations_group(self,funcbox):
+
+ self.bfunc_table = GtkTable(4,2)
+ self.bfunc_table.set_border_width(5)
+ self.bfunc_table.set_row_spacings(5)
+ self.bfunc_table.set_col_spacings(5)
+ funcbox.pack_start(self.bfunc_table, expand=FALSE)
+
+ btn = GtkButton("AND")
+ btn.connect("clicked",self.fbutton_pressed,"AND()")
+ self.bfunc_table.attach(btn,0,1,0,1)
+
+ btn = GtkButton("OR")
+ btn.connect("clicked",self.fbutton_pressed,"OR()")
+ self.bfunc_table.attach(btn,1,2,0,1)
+
+ btn = GtkButton("XOR")
+ btn.connect("clicked",self.fbutton_pressed,"XOR()")
+ self.bfunc_table.attach(btn,0,1,1,2)
+
+ btn = GtkButton("invert")
+ btn.connect("clicked",self.fbutton_pressed,"invert()")
+ self.bfunc_table.attach(btn,1,2,1,2)
+
+ btn = GtkButton("LShift")
+ btn.connect("clicked",self.fbutton_pressed,"LShift()")
+ self.bfunc_table.attach(btn,0,1,2,3)
+
+ btn = GtkButton("RShift")
+ btn.connect("clicked",self.fbutton_pressed,"RShift()")
+ self.bfunc_table.attach(btn,1,2,2,3)
+
+ self.bfunc_table.hide()
+
+############################################################################
+ def mathematics_group(self,funcbox):
+ self.mfunc_table = GtkTable(4,2)
+ self.mfunc_table.set_border_width(5)
+ self.mfunc_table.set_row_spacings(5)
+ self.mfunc_table.set_col_spacings(5)
+ funcbox.pack_start(self.mfunc_table, expand=FALSE)
+
+ btn = GtkButton("log")
+ btn.connect("clicked",self.fbutton_pressed,"log()")
+ self.mfunc_table.attach(btn,0,1,0,1)
+
+ btn = GtkButton("exp")
+ btn.connect("clicked",self.fbutton_pressed,"exp()")
+ self.mfunc_table.attach(btn,1,2,0,1)
+
+ btn = GtkButton("sin")
+ btn.connect("clicked",self.fbutton_pressed,"sin()")
+ self.mfunc_table.attach(btn,0,1,1,2)
+
+ btn = GtkButton("cos")
+ btn.connect("clicked",self.fbutton_pressed,"cos()")
+ self.mfunc_table.attach(btn,1,2,1,2)
+
+ btn = GtkButton("sqrt")
+ btn.connect("clicked",self.fbutton_pressed,"sqrt()")
+ self.mfunc_table.attach(btn,0,1,2,3)
+
+ btn = GtkButton("tan")
+ btn.connect("clicked",self.fbutton_pressed,"tan()")
+ self.mfunc_table.attach(btn,1,2,2,3)
+
+ btn = GtkButton("max")
+ btn.connect("clicked",self.fbutton_pressed,"max()")
+ self.mfunc_table.attach(btn,0,1,3,4)
+
+ btn = GtkButton("min")
+ btn.connect("clicked",self.fbutton_pressed,"min()")
+ self.mfunc_table.attach(btn,1,2,3,4)
+
+ self.mfunc_table.hide()
+
+######################################################################
+ def trigonometry_group(self,funcbox):
+ self.tfunc_table = GtkTable(4,2)
+ self.tfunc_table.set_border_width(5)
+ self.tfunc_table.set_row_spacings(5)
+ self.tfunc_table.set_col_spacings(5)
+ funcbox.pack_start(self.tfunc_table, expand=FALSE)
+
+ btn = GtkButton("sin")
+ btn.connect("clicked",self.fbutton_pressed,"sin()")
+ self.tfunc_table.attach(btn,0,1,0,1)
+
+ btn = GtkButton("cos")
+ btn.connect("clicked",self.fbutton_pressed,"cos()")
+ self.tfunc_table.attach(btn,1,2,0,1)
+
+ btn = GtkButton("tan")
+ btn.connect("clicked",self.fbutton_pressed,"tan()")
+ self.tfunc_table.attach(btn,0,1,1,2)
+
+ btn = GtkButton("asin")
+ btn.connect("clicked",self.fbutton_pressed,"asin()")
+ self.tfunc_table.attach(btn,1,2,1,2)
+
+ btn = GtkButton("acos")
+ btn.connect("clicked",self.fbutton_pressed,"acos()")
+ self.tfunc_table.attach(btn,0,1,2,3)
+
+ btn = GtkButton("atan")
+ btn.connect("clicked",self.fbutton_pressed,"atan()")
+ self.tfunc_table.attach(btn,1,2,2,3)
+
+ btn = GtkButton("hypot")
+ btn.connect("clicked",self.fbutton_pressed,"hypot()")
+ self.tfunc_table.attach(btn,0,1,3,4)
+
+ btn = GtkButton("atan2")
+ btn.connect("clicked",self.fbutton_pressed,"atan2()")
+ self.tfunc_table.attach(btn,1,2,3,4)
+
+ self.tfunc_table.hide()
+
+######################################################################
+ def special_funcs_group(self,funcbox):
+
+ self.sfunc_table = GtkTable(4,2)
+ self.sfunc_table.set_border_width(5)
+ self.sfunc_table.set_row_spacings(5)
+ self.sfunc_table.set_col_spacings(5)
+ funcbox.pack_start(self.sfunc_table, expand=FALSE)
+
+ btn = GtkButton("NDVI")
+ btn.connect("clicked",self.fbutton_pressed,"NDVI()")
+ self.sfunc_table.attach(btn,0,1,0,1)
+ self.tooltips.set_tip(btn, 'NDVI(X,Y) = (Y - X)/(X + Y) * 128 + 128')
+
+ self.sfunc_table.hide()
+
+##############################################################################
+
+ def create_gui(self):
+ self.dict_of_bands = get_list_of_bands_as_dict()
+ if self.dict_of_bands is None:
+ raise TypeError
+ self.list_of_bands = self.dict_of_bands.keys()
+ self.list_of_bands.sort()
+
+ title_width = 120
+
+ box1 = GtkVBox(spacing=10)
+ box1.set_border_width(10)
+ self.add(box1)
+ box1.show()
+
+ box2 = GtkVBox(spacing=5)
+ box2.set_border_width(5)
+ box1.pack_start(box2)
+ box2.show()
+
+ self.expression_unit = GtkEntry()
+ self.expression_unit.set_text(self.expression)
+ self.expression_unit.connect("changed",self.expression_edit_cb)
+ box2.pack_start(self.expression_unit)
+ self.expression_unit.show()
+
+ box3 = GtkHBox(spacing=5)
+ box1.pack_start(box3)
+ box3.show()
+
+#####
+ funcbox = GtkVBox(spacing=5)
+ funcbox.set_border_width(10)
+ box3.pack_start(funcbox)
+ funcbox.show()
+
+ fg_list = ["Mathematics","Bit Operations","Trigionometry","Special"]
+ self.fun_group_list = gvutils.GvOptionMenu(fg_list,self.group_changed)
+ funcbox.pack_start(self.fun_group_list, expand=FALSE)
+
+
+ self.mathematics_group(funcbox)
+ self.bit_operations_group(funcbox)
+ self.trigonometry_group(funcbox)
+ self.special_funcs_group(funcbox)
+
+#####
+ digitbox = GtkVBox(spacing=10)
+ digitbox.set_border_width(10)
+ box3.pack_start(digitbox)
+ digitbox.show()
+
+ digit_table = GtkTable(5,5)
+ digit_table.set_border_width(5)
+ digit_table.set_row_spacings(5)
+ digit_table.set_col_spacings(5)
+ digitbox.pack_start(digit_table)
+ digit_table.show()
+
+ btn = GtkButton("Back")
+ btn.connect("clicked", self.back_button_pressed)
+ digit_table.attach(btn,1,3,0,1)
+
+ btn = GtkButton("C")
+ btn.connect("clicked", self.clear_button_pressed)
+ digit_table.attach(btn,3,5,0,1)
+
+ btn = GtkButton("7")
+ btn.connect("clicked", self.button_pressed,"7")
+ digit_table.attach(btn,0,1,1,2)
+
+ btn = GtkButton("8")
+ btn.connect("clicked", self.button_pressed,"8")
+ digit_table.attach(btn,1,2,1,2)
+
+ btn = GtkButton("9")
+ btn.connect("clicked", self.button_pressed,"9")
+ digit_table.attach(btn,2,3,1,2)
+
+ btn = GtkButton(" / ")
+ btn.connect("clicked", self.button_pressed,"/")
+ digit_table.attach(btn,3,4,1,2)
+
+ btn = GtkButton("(")
+ btn.connect("clicked", self.button_pressed,"(")
+ digit_table.attach(btn,4,5,1,2)
+
+ btn = GtkButton("4")
+ btn.connect("clicked", self.button_pressed,"4")
+ digit_table.attach(btn,0,1,2,3)
+
+ btn = GtkButton("5")
+ btn.connect("clicked", self.button_pressed,"5")
+ digit_table.attach(btn,1,2,2,3)
+
+ btn = GtkButton("6")
+ btn.connect("clicked", self.button_pressed,"6")
+ digit_table.attach(btn,2,3,2,3)
+
+ btn = GtkButton("*")
+ btn.connect("clicked", self.button_pressed,"*")
+ digit_table.attach(btn,3,4,2,3)
+
+ btn = GtkButton(")")
+ btn.connect("clicked", self.button_pressed,")")
+ digit_table.attach(btn,4,5,2,3)
+
+ btn = GtkButton("1")
+ btn.connect("clicked", self.button_pressed,"1")
+ digit_table.attach(btn,0,1,3,4)
+
+ btn = GtkButton("2")
+ btn.connect("clicked", self.button_pressed,"2")
+ digit_table.attach(btn,1,2,3,4)
+
+ btn = GtkButton("3")
+ btn.connect("clicked", self.button_pressed,"3")
+ digit_table.attach(btn,2,3,3,4)
+
+ btn = GtkButton("-")
+ btn.connect("clicked", self.button_pressed,"-")
+ digit_table.attach(btn,3,4,3,4)
+
+ btn = GtkButton("End")
+ btn.connect("clicked", self.end_button_pressed)
+ digit_table.attach(btn,4,5,3,4)
+
+ btn = GtkButton("0")
+ btn.connect("clicked", self.button_pressed,"0")
+ digit_table.attach(btn,0,1,4,5)
+
+ btn = GtkButton(",")
+ btn.connect("clicked", self.button_pressed,",")
+ digit_table.attach(btn,1,2,4,5)
+
+ btn = GtkButton(".")
+ btn.connect("clicked", self.button_pressed,".")
+ digit_table.attach(btn,2,3,4,5)
+
+ btn = GtkButton("+")
+ btn.connect("clicked", self.button_pressed,"+")
+ digit_table.attach(btn,3,4,4,5)
+
+ btn = GtkButton("=")
+ btn.connect("clicked", self.compute)
+ digit_table.attach(btn,4,5,4,5)
+
+#####
+ rastersbox = GtkVBox(spacing=5)
+ box1.pack_start(rastersbox)
+ rastersbox.show()
+
+### source list #############################################################
+ frame1 = GtkFrame("Select Image Bands To Compute")
+ frame1.show()
+ box1.pack_start(frame1, expand=FALSE)
+
+ box2r = GtkVBox(spacing=10)
+ box2r.set_border_width(10)
+ frame1.add(box2r)
+ box2r.show()
+
+ self.s1_list = \
+ gvutils.GvOptionMenu(self.list_of_bands, self.raster_selected_cb)
+ box2r.pack_start(self.s1_list)
+ self.s1_list.set_history(-1)
+ self.s1_list.show()
+
+##### OUT TYPES #########################################################
+ box_types = GtkHBox(spacing=10)
+ box2r.pack_start(box_types)
+ box_types.show()
+
+ types_label = GtkLabel('Image Data Type:')
+ types_label.set_alignment(0, 0.5)
+ box_types.pack_start(types_label, expand=FALSE)
+
+ self.types_list = []
+ i = GDT_Byte
+ while i < GDT_TypeCount:
+ self.types_list.append(gdal.GetDataTypeName(i))
+ i += 1
+
+ self.types = gvutils.GvOptionMenu(self.types_list)
+ box_types.pack_start(self.types)
+ self.types.show()
+
+#### NEW VIEW ##########################################################
+ self.switch_new_view = GtkCheckButton("Create New View")
+ box1.pack_start(self.switch_new_view)
+ self.switch_new_view.show()
+
+ return TRUE
+
+#########################################################################
+ def expression_edit_cb(self,*args):
+ self.expression = self.expression_unit.get_text()
+
+#########################################################################
+ def button_pressed(self,widget,txt):
+ s = self.expression
+ self.expression = s[:self.text_pos] + txt + s[self.text_pos:]
+ self.expression_unit.set_text(self.expression)
+ self.text_pos += len(txt)
+
+#########################################################################
+ def fbutton_pressed(self,widget,txt):
+ s = self.expression
+ self.expression = s[:self.text_pos] + txt + s[self.text_pos:]
+ self.expression_unit.set_text(self.expression)
+ self.text_pos += len(txt) - 1
+
+#########################################################################
+ def clear_button_pressed(self,*args):
+ self.expression = ""
+ self.text_pos = 0
+ self.expression_unit.set_text(self.expression)
+ self.expression_unit.set_position(self.text_pos)
+
+#########################################################################
+ def back_button_pressed(self,*args):
+ self.expression = \
+ self.expression[:self.text_pos-1]+self.expression[self.text_pos:]
+ self.text_pos -= 1
+ self.expression_unit.set_text(self.expression)
+
+#########################################################################
+ def raster_selected_cb(self,*args):
+ i_band = self.s1_list.get_history() + 1
+ if i_band > 0:
+ s_band = "%" + str(i_band)
+ s = self.expression
+ self.expression = s[:self.text_pos]+s_band+s[self.text_pos:]
+ self.text_pos += len(s_band)
+ self.expression_unit.set_text(self.expression)
+ self.s1_list.set_history(-1)
+
+#########################################################################
+ def end_button_pressed(self,*args):
+ self.text_pos = len(self.expression)
+ self.expression_unit.set_position(self.text_pos)
+
+#########################################################################
+ def update_gui(self,*args):
+ self.group_changed(self.fun_group_list)
+
+#########################################################################
+ def group_changed(self,widget):
+ i = self.fun_group_list.get_history()
+ self.mfunc_table.hide()
+ self.tfunc_table.hide()
+ self.bfunc_table.hide()
+ self.sfunc_table.hide()
+ if i == 0:
+ self.mfunc_table.show()
+ elif i == 1:
+ self.bfunc_table.show()
+ elif i == 2:
+ self.tfunc_table.show()
+ else:
+ self.sfunc_table.show()
+#########################################################################
+ def get_band(self,name):
+ layer = self.dict_of_bands[name][1]
+ b_num = self.dict_of_bands[name][2]
+ band = layer.get_parent().get_dataset().GetRasterBand(b_num+1)
+ return band
+########################################################################
+ def NDVI(self,s1,s2):
+ rb = 128.+ 128. *(s2-s1)/(s1+s2)
+ return rb
+#########################################################################
+ def compute(self,*args):
+ import re
+ ex_exp = self.expression
+
+ type = gdal.GetDataTypeByName(self.types_list[self.types.get_history()])
+ numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(type)
+ if numtype == None:
+ gvutils.error("Error! Type " + numtype + " is not supported!")
+ return FALSE
+
+ fun_names_dict = {}
+ fun_names_dict["max"] = ("maximum",2)
+ fun_names_dict["min"] = ("minimum",2)
+ fun_names_dict["asin"] = ("arcsin",1)
+ fun_names_dict["acos"] = ("arccos",1)
+ fun_names_dict["atan"] = ("arctan",1)
+ fun_names_dict["AND"] = ("bitwise_and",2)
+ fun_names_dict["OR"] = ("bitwise_or",2)
+ fun_names_dict["XOR"] = ("bitwise_xor",2)
+ fun_names_dict["inv"] = ("invert",1)
+ fun_names_dict["LShift"] = ("left_shift",2)
+ fun_names_dict["RShift"] = ("right_shift",1)
+ fun_names_dict['NDVI'] = ("self.NDVI",2)
+
+ sh_names_list = fun_names_dict.keys()
+ for item in sh_names_list:
+ ex_exp = re.sub(item,fun_names_dict[item][0],ex_exp)
+
+ test_exp = ex_exp
+ test_array = Numeric.zeros((1, 5), numtype)
+ for i in range(len(self.list_of_bands)):
+ patt_i = "%"+str(i+1)
+ repl_i = "sb["+str(i)+"]"
+ ex_exp = re.sub(patt_i,repl_i,ex_exp)
+ test_exp = re.sub(patt_i,"test_array",test_exp)
+ ex_exp = "rb="+ex_exp
+ test_exp = "test_res="+test_exp
+
+ try:
+ exec test_exp
+ except:
+ gvutils.error("Illegal expression!")
+ return FALSE
+
+ if self.switch_new_view.get_active():
+ gview.app.new_view()
+
+ b1_name = self.list_of_bands[self.s1_list.get_history()]
+ band_list = []
+ for i in range(len(self.list_of_bands)):
+ band_list.append(self.get_band(self.list_of_bands[i]))
+ b1 = self.get_band(b1_name)
+ proto_ds = self.dict_of_bands[b1_name][1].get_parent().get_dataset()
+ self.out_buf = Numeric.zeros((b1.YSize, b1.XSize), numtype)
+
+ sb = range(len(self.list_of_bands))
+ for y in range(b1.YSize):
+ for i in range(len(self.list_of_bands)):
+ sb[i] = \
+ gdalnumeric.BandReadAsArray(band_list[i],0,y,b1.XSize,1)[0]
+ try:
+ exec ex_exp
+ except:
+ gvutils.error("ZeroDivide?")
+ return FALSE
+ self.out_buf[y, 0:] = clip_result(numtype, rb).astype(numtype)
+
+ res_ds = gdalnumeric.OpenArray(self.out_buf,proto_ds)
+ gview.app.open_gdal_dataset(res_ds)
+
+
+TOOL_LIST = ['CalculatorTool', 'RCalculatorTool']
+
Added: packages/openev/branches/upstream/current/tools/compose.py
===================================================================
--- packages/openev/branches/upstream/current/tools/compose.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/compose.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,1218 @@
+##############################################################################
+# $Id: compose.py,v 1.4 2004/11/16 19:11:34 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Tool for combining/merging datasets without loading
+# them directly into memory.
+#
+# Author: Andrey Kiselev, dron at remotesensing.org
+# Iscander Latypov
+# Gillian Walter (modifications)
+#
+###############################################################################
+# Copyright (c) 2004, American Museum of Natural History. All rights reserved.
+# This software is based upon work supported by NASA under award
+# number NAG5-12333
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: compose.py,v $
+# Revision 1.4 2004/11/16 19:11:34 gmwalter
+# Fixed typo.
+#
+# Revision 1.3 2004/09/01 15:52:55 gmwalter
+# Updated to use VRT instead of numpy, and
+# also to add the ability to specify
+# geocoding information.
+#
+# Revision 1.2 2004/04/21 13:24:04 andrey_kiselev
+# Check whether we have a raster layer on input.
+#
+# Revision 1.1 2004/03/09 11:01:08 andrey_kiselev
+# New.
+#
+#
+
+#
+# To do: 1) Nicer editing windows for projection info? WKT
+# strings can be a bit hard to follow.
+# 2) Add Metadata frame and colour interpretation frame
+#
+
+
+import gtk
+import gview
+import string
+import gvutils
+import gviewapp
+import Numeric
+import os
+import GtkExtra
+import gdal
+import osr
+import gdalnumeric
+import pgugrid
+import vrtutils
+import gvsignaler
+
+spc=5
+
+class ComposeTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = DatasetComposeDialog(self.app)
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image/Compose...",1,
+ self.launch_dialog)
+
+
+class DatasetComposeDialog(gtk.GtkWindow):
+ def __init__(self,app=None):
+ gtk.GtkWindow.__init__(self)
+ self.set_title('Compose Dataset')
+ self.set_policy(gtk.FALSE, gtk.TRUE, gtk.TRUE)
+ self.set_border_width(10)
+ self.shell=gtk.GtkVBox(spacing=spc)
+ self.add(self.shell)
+ self.tips=gtk.GtkTooltips()
+ self.input_frame=InputFrame(self, self.tips)
+ self.show_list=[]
+ self.adv_show_list=[]
+ self.show_list.append(self.input_frame)
+ self.app=app
+
+ self.button_dict={}
+ self.button_dict['Mode']=gtk.GtkCheckButton('Advanced Options')
+ self.shell.pack_start(self.button_dict['Mode'])
+ self.show_list.append(self.button_dict['Mode'])
+
+
+ self.adv_notebook = gtk.GtkNotebook()
+ self.shell.pack_start(self.adv_notebook)
+ self.adv_show_list.append(self.adv_notebook)
+ self.geo_frame=GeocodingFrame(self.tips)
+ self.adv_notebook.append_page(self.geo_frame,
+ gtk.GtkLabel('Geocoding'))
+
+ echbox=gtk.GtkHBox(spacing=5,homogeneous=gtk.FALSE)
+ echbox.set_border_width(3)
+ self.shell.pack_end(echbox,gtk.FALSE,gtk.FALSE,0)
+ self.show_list.append(echbox)
+
+ self.button_dict['Close']=gtk.GtkButton('Close')
+ echbox.pack_end(self.button_dict['Close'],expand=gtk.TRUE)
+ self.button_dict['Save']=gtk.GtkButton('Save VRT')
+ echbox.pack_end(self.button_dict['Save'],expand=gtk.TRUE)
+ self.button_dict['New']=gtk.GtkButton('New View')
+ echbox.pack_end(self.button_dict['New'],expand=gtk.TRUE)
+ self.button_dict['Current']=gtk.GtkButton('Current View')
+ echbox.pack_end(self.button_dict['Current'],expand=gtk.TRUE)
+
+ self.tips.set_tip(self.button_dict['Close'],
+ 'Exit the Compose Dataset tool')
+ self.tips.set_tip(self.button_dict['Save'],
+ 'Create dataset and save to a VRT format file')
+ self.tips.set_tip(self.button_dict['New'],
+ 'Create dataset and display in a new view')
+ self.tips.set_tip(self.button_dict['Current'],
+ 'Create dataset and display in current view')
+
+ for item in self.show_list:
+ item.show_all()
+ item.show()
+
+ # geocode frame hides some of its contents
+ self.geo_frame.show()
+
+ self.button_dict['Save'].connect('clicked',self.create_cb,'Save')
+ self.button_dict['New'].connect('clicked',self.create_cb,'New')
+ self.button_dict['Current'].connect('clicked',self.create_cb,'Current')
+ self.button_dict['Close'].connect('clicked',self.close)
+ self.button_dict['Mode'].connect('toggled',self.mode_toggled_cb)
+
+ self.input_frame.subscribe('output-bands-empty', self.clear_defaults)
+ self.input_frame.subscribe('output-bands-notempty',
+ self.update_defaults)
+
+ self.button_dict['Mode'].set_active(0)
+ self.mode_toggled_cb()
+ self.shell.show()
+
+ def mode_toggled_cb(self,*args):
+ if self.button_dict['Mode'].get_active():
+ for item in self.adv_show_list:
+ item.show()
+ else:
+ for item in self.adv_show_list:
+ item.hide()
+
+ def close(self,*args):
+ self.destroy()
+
+ def create_cb(self,*args):
+ bands = self.input_frame.get_output_bands()
+ if len(bands) == 0:
+ gvutils.error('No output bands specified!')
+ return
+
+ vrtbase = [gdal.CXT_Element,'VRTDataset']
+ vrtbase.append([gdal.CXT_Attribute,'rasterXSize',
+ [gdal.CXT_Text,str(bands[0][0].RasterXSize)]])
+ vrtbase.append([gdal.CXT_Attribute,'rasterYSize',
+ [gdal.CXT_Text,str(bands[0][0].RasterYSize)]])
+
+ # Metadata is currently taken from first output band.
+ # This may be updatable later.
+ mbase = vrtutils.serializeMetadata(bands[0][0])
+ if mbase is not None:
+ vrtbase.append(mbase)
+
+ gbase = self.geo_frame.get_geocoding()
+ for item in gbase:
+ vrtbase.append(item)
+
+ outband = 1
+ for item in bands:
+ dict={}
+ dict['band']=outband
+ dict['SourceBand'] = item[1]
+ dict['ColorInterp'] = 'Undefined'
+ bbase = vrtutils.serializeBand(item[0],opt_dict=dict)
+ vrtbase.append(bbase)
+ outband=outband+1
+
+ vrtlines = gdal.SerializeXMLTree(vrtbase)
+
+ vrtds = gdal.OpenShared(vrtlines)
+
+ if args[1] == 'Save':
+ fname = GtkExtra.file_sel_box(title="Save File")
+ if fname is None:
+ return
+ driver = gdal.GetDriverByName('VRT')
+ driver.CreateCopy(fname,vrtds)
+ elif args[1] == 'New':
+ self.app.new_view()
+ self.app.open_gdal_dataset(vrtds)
+ else:
+ self.app.open_gdal_dataset(vrtds)
+
+ def update_defaults(self, *args):
+ bands = self.input_frame.get_output_bands()
+ self.geo_frame.update_default_frame(bands[0][0].GetDescription())
+ self.geo_frame.update_gcp_frame_to_defaults()
+ self.geo_frame.update_geotransform_frame_to_defaults()
+
+ def clear_defaults(self, *args):
+ self.geo_frame.update_default_frame(None)
+ self.geo_frame.clear_gcp_frame()
+ self.geo_frame.clear_geotransform_frame()
+
+class GeocodingFrame(gtk.GtkVBox):
+ def __init__(self,tips):
+ gtk.GtkVBox.__init__(self)
+
+ self.frames = {}
+ self.tips=tips
+
+ hbox=gtk.GtkHBox()
+ hbox.set_border_width(spc)
+ self.pack_start(hbox)
+ label=gtk.GtkLabel("Input Geocoding: ")
+ label.set_alignment(0,0.5)
+ hbox.pack_start(label)
+ self.geocode_menu_list=['Default','GCPs','Geotransform']
+ self.geocode_menu = gvutils.GvOptionMenu(self.geocode_menu_list,
+ self.geotype_toggled_cb)
+ self.tips.set_tip(self.geocode_menu,
+ 'Default: Derive geocoding from input bands\n'+
+ 'GCPs: Define new ground control points\n'+
+ 'Geotransform: Define a new affine transformation')
+ hbox.pack_start(self.geocode_menu)
+ hbox.show_all()
+ self.create_default_frame()
+ self.create_gcp_frame()
+ self.create_geotransform_frame()
+ self.geocode_menu.set_history(0)
+ self.geotype_toggled_cb()
+
+ self.default_fname=None # dataset to use for default info
+ self.default_geotransform=None
+ self.default_gcps=None
+ self.default_prj=''
+
+ def geotype_toggled_cb(self,*args):
+ hist=self.geocode_menu.get_history()
+ for idx in range(len(self.geocode_menu_list)):
+ if idx == hist:
+ self.frames[self.geocode_menu_list[idx]].show()
+ else:
+ self.frames[self.geocode_menu_list[idx]].hide()
+
+
+ def create_default_frame(self):
+ self.frames['Default']=gtk.GtkFrame('')
+ self.frames['Default'].set_shadow_type(gtk.SHADOW_NONE)
+ vbox=gtk.GtkVBox()
+ vbox.set_spacing(spc)
+ self.frames['Default'].add(vbox)
+ self.default_scrolled_text = gtk.GtkText()
+ self.default_scrolled_text.set_line_wrap(gtk.FALSE)
+ self.default_scrolled_text.set_word_wrap(gtk.FALSE)
+ self.default_scrolled_text.set_editable(gtk.FALSE)
+ self.default_scrolled_win = gtk.GtkScrolledWindow()
+ self.default_scrolled_win.set_usize(200,200)
+ self.default_scrolled_win.add( self.default_scrolled_text)
+ vbox.pack_start(self.default_scrolled_win,expand=gtk.TRUE)
+ self.frames['Default'].show_all()
+
+ self.pack_start(self.frames['Default'])
+
+
+ def create_gcp_frame(self):
+ self.frames['GCPs']=gtk.GtkFrame('')
+ self.frames['GCPs'].set_shadow_type(gtk.SHADOW_NONE)
+ vbox=gtk.GtkVBox()
+ vbox.set_spacing(spc)
+ self.frames['GCPs'].add(vbox)
+ self.gcpgrid = pgugrid.pguGrid((3,1,0,1,7,0,0,0,3))
+ self.gcpgrid.set_usize(200,200)
+ self.gcplist=[]
+ self.gcpgrid.set_source(self.gcplist,
+ members=['Id','GCPPixel','GCPLine','GCPX','GCPY','GCPZ'],
+ titles = ['ID','Pixel','Line','X','Y','Z'],
+ types = ['string','float','float','float','float','float'])
+ vbox.pack_start(self.gcpgrid)
+ hbox=gtk.GtkHBox()
+ hbox.set_spacing(spc)
+ vbox.pack_start(hbox)
+ self.add_gcp_button=gtk.GtkButton(' Add GCP ')
+ self.add_gcp_button.connect('clicked',self.add_gcp_cb)
+ hbox.pack_start(self.add_gcp_button, expand=gtk.FALSE)
+ self.tips.set_tip(self.add_gcp_button,'Add a new GCP')
+ self.load_gcp_button=gtk.GtkButton('Load GCPs')
+ self.tips.set_tip(self.load_gcp_button,
+ 'Clear existing GCPs and load '+
+ 'new ones from a text file')
+ self.load_gcp_button.connect('clicked',self.load_gcps_cb)
+ hbox.pack_start(self.load_gcp_button, expand=gtk.FALSE)
+ self.copy_gcp_button=gtk.GtkButton('Copy GCPs')
+ self.copy_gcp_button.connect('clicked',self.copy_gcps_cb)
+ self.tips.set_tip(self.copy_gcp_button,
+ 'Clear existing GCPs and copy new '+
+ 'ones from another GDAL dataset')
+ hbox.pack_start(self.copy_gcp_button, expand=gtk.FALSE)
+ self.clear_gcp_button=gtk.GtkButton('Clear GCPs')
+ self.clear_gcp_button.connect('clicked',self.clear_gcps)
+ self.tips.set_tip(self.clear_gcp_button,
+ 'Clear all GCPs')
+ hbox.pack_start(self.clear_gcp_button, expand=gtk.FALSE)
+ self.gcpprjbox=ProjectionBox(self.tips)
+ vbox.pack_start(self.gcpprjbox)
+ self.frames['GCPs'].show_all()
+ self.pack_start(self.frames['GCPs'])
+
+ def load_gcps_cb(self,*args):
+ """ Load gcps from a text file """
+ self.clear_gcps()
+ info=getgcpfile()
+ if info is None:
+ # user pressed cancel
+ return
+ if ((info[2] is None) or (info[3] is None) or
+ (info[4] is None) or (info[5] is None)):
+ gvutils.error('Invalid column info for GCP text file!')
+ return
+
+ try:
+ fh=open(info[0],'r')
+ flines=fh.readlines()
+ except:
+ gvutils.error('Unable to read GCP text file!')
+ return
+
+ idx=0
+ for cline in flines:
+ if string.strip(info[1]) == '':
+ # whitespace delimited
+ sline=string.split(cline)
+ else:
+ sline=string.split(cline,info[1])
+ try:
+ gcp=gdal.GCP()
+ gcp.GCPPixel=float(string.strip(sline[info[2]-1]))
+ gcp.GCPLine=float(string.strip(sline[info[3]-1]))
+ gcp.GCPX=float(string.strip(sline[info[4]-1]))
+ gcp.GCPY=float(string.strip(sline[info[5]-1]))
+ if info[6] is not None:
+ gcp.GCPZ=float(string.strip(sline[info[6]-1]))
+ if info[7] is not None:
+ gcp.Id=string.strip(sline[info[7]-1])
+ if info[8] is not None:
+ gcp.Info=string.strip(sline[info[8]-1])
+ self.gcplist.append(gcp)
+ except:
+ # first line might have column names, so
+ # ignore errors. otherwise, report invalid
+ # lines
+ if idx != 0:
+ print 'Warning: invalid line '+str(idx)+' in GCP file!'
+
+ idx=idx+1
+
+ self.gcpgrid.refresh()
+
+ def clear_gcp_frame(self):
+ self.clear_gcps()
+ self.gcpprjbox.set_input_projection('')
+ self.gcpprjbox.set_output_projection('')
+
+ def update_gcp_frame_to_defaults(self):
+ self.clear_gcp_frame()
+ if self.default_gcps is not None:
+ for item in self.default_gcps:
+ gcp=CopyGDALGCP(item) # copy so original doesn't get changed
+ self.gcplist.append(gcp)
+
+ self.gcpgrid.refresh()
+
+ self.gcpprjbox.set_input_projection(self.default_prj)
+ self.gcpprjbox.set_output_projection(self.default_prj)
+
+ def clear_gcps(self,*args):
+ while len(self.gcplist) > 0:
+ self.gcplist.pop()
+ self.gcpgrid.refresh()
+
+ def copy_gcps_cb(self,*args):
+ """ Copy gcps from an existing gdal dataset. """
+ fname=GtkExtra.file_sel_box(title="Select GDAL Dataset")
+ if fname is None:
+ return
+
+ try:
+ fh=gdal.OpenShared(fname)
+ except:
+ gvutils.error('Unable to open '+fname+' as a GDAL dataset!')
+ return
+
+ gcps=fh.GetGCPs()
+ prj=fh.GetGCPProjection()
+ self.clear_gcps()
+ for gcp in gcps:
+ ngcp=CopyGDALGCP(gcp)
+ self.gcplist.append(ngcp)
+ self.gcpgrid.refresh()
+
+ self.gcpprjbox.set_input_projection(prj)
+
+ def add_gcp_cb(self,*args):
+ self.gcplist.append(gdal.GCP())
+ self.gcpgrid.refresh()
+
+ def create_geotransform_frame(self):
+ self.frames['Geotransform']=gtk.GtkFrame('')
+ self.frames['Geotransform'].set_shadow_type(gtk.SHADOW_NONE)
+ vbox=gtk.GtkVBox()
+ vbox.set_spacing(spc)
+ self.frames['Geotransform'].add(vbox)
+ label=gtk.GtkLabel('Xgeo = GT(0) + XPixel*GT(1) + YLine*GT(2)')
+ label.set_alignment(0,0.5)
+ vbox.pack_start(label)
+ label=gtk.GtkLabel('Ygeo = GT(3) + XPixel*GT(4) + YLine*GT(5)')
+ label.set_alignment(0,0.5)
+ vbox.pack_start(label)
+ table=gtk.GtkTable(rows=6,cols=3)
+ self.geotransform_entries=[]
+ for idx in range(6):
+ label=gtk.GtkLabel('GT('+str(idx)+'):')
+ label.set_alignment(0,0.5)
+ table.attach(label,0,1,idx,idx+1)
+ newentry=gtk.GtkEntry()
+ self.geotransform_entries.append(newentry)
+ table.attach(newentry,1,2,idx,idx+1)
+ vbox.pack_start(table)
+ self.geotransformprjbox=ProjectionBox(self.tips)
+ vbox.pack_start(self.geotransformprjbox)
+ self.frames['Geotransform'].show_all()
+ self.pack_start(self.frames['Geotransform'])
+
+ def clear_geotransform_frame(self):
+ for item in self.geotransform_entries:
+ item.set_text('')
+
+ self.geotransformprjbox.set_input_projection('')
+ self.geotransformprjbox.set_output_projection('')
+
+ def update_geotransform_frame_to_defaults(self):
+ self.clear_geotransform_frame()
+ if self.default_geotransform is not None:
+ for idx in range(6):
+ self.geotransform_entries[idx].set_text(
+ "%f" % self.default_geotransform[idx])
+ self.geotransformprjbox.set_input_projection(self.default_prj)
+ self.geotransformprjbox.set_output_projection(self.default_prj)
+
+ def update_default_frame(self,fname):
+ nchars=self.default_scrolled_text.get_length()
+ self.default_scrolled_text.backward_delete(nchars)
+ if fname is None:
+ self.default_fname=None
+ self.default_geotransform=None
+ self.default_gcps=None
+ self.default_prj=''
+ return
+
+ sr=osr.SpatialReference()
+
+ fh=gdal.OpenShared(fname)
+ prj=''
+ geot=fh.GetGeoTransform()
+ if ((tuple(geot) == (0,1,0,0,0,1)) or
+ (tuple(geot) == (0.0,1.0,0.0,0.0,0.0,1.0))):
+ self.default_geotransform=None
+ gcps = fh.GetGCPs()
+ if len(gcps) > 0:
+ self.default_gcps=gcps
+ txt='Type of Geocoding: GCPs ('+str(len(gcps))+')\n\n'
+ prj=fh.GetGCPProjection()
+ if sr.ImportFromWkt(prj) == 0:
+ prjtxt=sr.ExportToPrettyWkt(simplify=1)
+ else:
+ prjtxt=''
+ txt=txt+'Projection: '+prjtxt
+ else:
+ self.default_gcps=None
+ txt='Type of Geocoding: None\n\nProjection: None'
+ else:
+ self.default_geotransform=geot
+ self.default_gcps=None
+ txt='Type of Geocoding: Geotransform\n\n'
+ prj=fh.GetProjection()
+ if sr.ImportFromWkt(prj) == 0:
+ prjtxt=sr.ExportToPrettyWkt(simplify=1)
+ else:
+ prjtxt=''
+ txt=txt+'Projection: '+prjtxt
+
+ self.default_scrolled_text.insert_defaults(txt)
+ self.default_prj=prj
+ self.default_fname=fname
+
+ def clear_defaults(self,*args):
+ self.update_default_frame(None)
+
+ def get_geocoding(self):
+ # returns serialized geocoding information as a list
+ gt=self.geocode_menu_list[self.geocode_menu.get_history()]
+ serialtxt=[]
+ if gt == 'Default':
+ if self.default_geotransform is not None:
+ if self.default_prj != '':
+ serialtxt.append([gdal.CXT_Element,'SRS',[gdal.CXT_Text,
+ self.default_prj]])
+
+ gtxt = vrtutils.serializeGeoTransform(
+ geotransform=self.default_geotransform)
+ if gtxt is not None:
+ serialtxt.append(gtxt)
+
+ elif self.default_gcps is not None:
+ serialtxt.append(vrtutils.serializeGCPs(
+ gcplist=self.default_gcps,
+ with_Z=1,projection_attr_txt=self.default_prj))
+ else:
+ return []
+
+ elif gt == 'GCPs':
+ if len(self.gcplist) == 0:
+ return []
+
+ inprj,outprj=self.gcpprjbox.get_projections()
+ if (outprj == '') or (outprj == inprj) or (inprj == ''):
+ reproj=None
+ if (outprj != '') and (inprj == ''):
+ gvutils.warning('Warning: output projection specified,\n'+
+ 'but no input projection. Cannot\n'+
+ 'reproject!')
+ else:
+ reproj=outprj
+ gcplistcopy=CopyGDALGCPs(self.gcplist)
+ serialtxt.append(vrtutils.serializeGCPs(
+ gcplist=gcplistcopy,with_Z=1,
+ projection_attr_txt=inprj,
+ reproj=reproj))
+ else:
+ inprj,outprj=self.geotransformprjbox.get_projections()
+ gt=[]
+ try:
+ for idx in range(6):
+ gt.append(float(
+ self.geotransform_entries[idx].get_text()))
+ except:
+ gvutils.warning('Invalid Geotransform information- '+
+ 'ignoring!')
+ return []
+
+ if (outprj == '') or (outprj == inprj) or (inprj == ''):
+ reproj=None
+ if (outprj != '') and (inprj == ''):
+ gvutils.warning('Warning: output projection specified,\n'+
+ 'but no input projection. Cannot\n'+
+ 'reproject!')
+
+ if inprj != '':
+ serialtxt.append([gdal.CXT_Element,'SRS',
+ [gdal.CXT_Text,inprj]])
+
+ gbase=vrtutils.serializeGeoTransform(geotransform=gt)
+ if gbase is not None:
+ serialtxt.append(gbase)
+
+ else:
+ ds=gdal.OpenShared(self.default_fname)
+ gcps=vrtutils.GeoTransformToGCPs(gt,ds.RasterXSize,
+ ds.RasterYSize,grid=2)
+ serialtxt.append(vrtutils.serializeGCPs(gcplist=gcps,with_Z=1,
+ projection_attr_txt=inprj,
+ reproj=outprj))
+
+ return serialtxt
+
+
+def getprjinfo():
+ fname=GtkExtra.file_sel_box(title="Select GDAL Dataset or WKT text file")
+ if fname is None:
+ return None
+ try:
+ fh=gdal.OpenShared(fname)
+ prj=fh.GetProjection()
+ if prj == '':
+ prj=fh.GetGCPProjection()
+ except:
+ fh=open(fname,'r')
+ prj=string.strip(fh.readline())
+ # prj files from shapes seem to have
+ # an extra character at the end
+ if prj[-1:] == '\x00':
+ prj=prj[:-1]
+
+ sr=osr.SpatialReference()
+ val=sr.ImportFromWkt(prj)
+ if val != 0:
+ gvutils.error('Invalid projection information in '+fname+'!')
+ return None
+
+ return prj
+
+def editprjinfo(wktinit=''):
+ win=editprjwin("Projection (Well Known Text string)",wktinit)
+ win.show()
+ gtk.mainloop()
+ prj=win.ret
+ if prj is None:
+ return
+
+ if len(prj) == 0:
+ return ''
+
+ sr=osr.SpatialReference()
+ val=sr.ImportFromWkt(prj)
+ if val != 0:
+ gvutils.error('Invalid projection information entered!')
+ return ''
+
+ return prj
+
+class editprjwin(gtk.GtkWindow):
+ def __init__(self,title,wkt):
+ gtk.GtkWindow.__init__(self)
+ self.set_title(title)
+ self.set_usize(350,300)
+ vbox=gtk.GtkVBox()
+ self.add(vbox)
+ self.text=gtk.GtkText()
+ self.text.set_editable(gtk.TRUE)
+ self.text.insert_defaults(wkt)
+ vbox.pack_start(self.text)
+ hbox=gtk.GtkHBox()
+ vbox.pack_start(hbox,expand=gtk.FALSE)
+ self.cancel_button=gtk.GtkButton(' Cancel ')
+ self.ok_button=gtk.GtkButton(' OK ')
+ hbox.pack_end(self.cancel_button,expand=gtk.FALSE)
+ hbox.pack_end(self.ok_button,expand=gtk.FALSE)
+
+ self.cancel_button.connect('clicked', self.quit)
+ self.ok_button.connect('clicked', self.ok_cb)
+ self.ret=None
+ self.show_all()
+
+ def quit(self, *args):
+ self.hide()
+ self.destroy()
+ gtk.mainquit()
+
+ def ok_cb(self, b):
+ self.ret = self.text.get_chars(0,self.text.get_length())
+ self.quit()
+
+
+def getgcpfile():
+ win=GCPFileDialog()
+ win.show()
+ gtk.mainloop()
+ return win.ret
+
+class GCPFileDialog(gtk.GtkFileSelection):
+ def __init__(self):
+ gtk.GtkFileSelection.__init__(self)
+ self.set_title('Select GCP Text File')
+ self.connect("destroy", self.quit)
+ self.connect("delete_event", self.quit)
+ gtk.grab_add(self) # is modal
+ table=gtk.GtkTable(rows=8,cols=3)
+ self.entries=[]
+ labels=['Delimiter: ',
+ 'Pixel Column # (1-N: required): ',
+ 'Line Column # (required): ',
+ 'X (East/West) Column # (required): ',
+ 'Y (North/South) Column # (required): ',
+ 'Z (Height) Column # (optional): ',
+ 'ID Column # (optional): ',
+ 'Info Column # (optional): ']
+ for idx in range(len(labels)):
+ nl=gtk.GtkLabel(labels[idx])
+ nl.set_alignment(0,0.5)
+ self.entries.append(gtk.GtkEntry(maxlen=3))
+ table.attach(nl,0,1,idx,idx+1)
+ table.attach(self.entries[idx],1,2,idx,idx+1)
+ self.main_vbox.pack_end(table)
+ table.show_all()
+ self.cancel_button.connect('clicked', self.quit)
+ self.ok_button.connect('clicked', self.ok_cb)
+ self.ret = None
+
+ def quit(self, *args):
+ self.hide()
+ self.destroy()
+ gtk.mainquit()
+
+ def ok_cb(self, b):
+ ret=[self.get_filename(),self.entries[0].get_text()]
+ for idx in range(1,len(self.entries)):
+ try:
+ val=int(self.entries[idx].get_text())
+ except:
+ val=None
+ ret.append(val)
+ self.ret = tuple(ret)
+ self.quit()
+
+class ProjectionBox(gtk.GtkTable):
+ def __init__(self,tips):
+ gtk.GtkTable.__init__(self,rows=2,cols=7,homogeneous=gtk.FALSE)
+ self.set_row_spacings(spc)
+ self.set_col_spacings(spc)
+ self.set_col_spacing(2,3*spc)
+ label=gtk.GtkLabel('Input Projection: ')
+ label.set_alignment(0,0.5)
+ self.attach(label,0,1,0,1)
+ self.buttons={}
+ self.buttons['input-edit']=gtk.GtkButton(' Edit ')
+ self.buttons['input-load']=gtk.GtkButton('Load From File')
+ self.buttons['input-view']=gtk.GtkButton('Load From View')
+ tips.set_tip(self.buttons['input-edit'],
+ 'Edit projection information (should '+
+ 'be a Well Known Text string)')
+ tips.set_tip(self.buttons['input-load'],
+ 'Load projection information from a GDAL '+
+ 'dataset, or a file with a single line '+
+ 'of Well Known Text specifying a projection.')
+ tips.set_tip(self.buttons['input-view'],
+ 'Load projection information from the '+
+ 'currently active view.')
+ self.attach(self.buttons['input-edit'],0,1,1,2)
+ self.attach(self.buttons['input-view'],1,2,1,2)
+ self.attach(self.buttons['input-load'],2,3,1,2)
+ self.inprj=''
+
+ label=gtk.GtkLabel('Output Projection: ')
+ self.attach(label,3,4,0,1)
+ self.out_toggle_useinput=gtk.GtkRadioButton(label='Use Input')
+ tips.set_tip(self.out_toggle_useinput,
+ 'Geocoding information entered above '+
+ 'will not be reprojected.')
+ self.out_toggle_reproj=gtk.GtkRadioButton(label='Reproject',
+ group=self.out_toggle_useinput)
+ tips.set_tip(self.out_toggle_reproj,
+ 'Attempt to reproject geocoding information '+
+ 'entered above to the Output projection. No '+
+ 'resampling of the binary data will take place. '+
+ 'If the input '+
+ 'geocoding is a Geotransform, it will be '+
+ 'converted to 16 GCPs prior to reprojection. '+
+ 'Note that applications that do not use GDAL '+
+ 'may not recognize this information, as it '+
+ 'is less common for applications to recognize '+
+ 'GCPs than Geotransforms.')
+ self.out_toggle_useinput.connect('toggled',self.toggle_output_cb)
+ self.attach(self.out_toggle_useinput,4,5,0,1)
+ self.attach(self.out_toggle_reproj,5,6,0,1)
+ self.buttons['output-edit']=gtk.GtkButton('Edit')
+ self.buttons['output-view']=gtk.GtkButton('Load From View')
+ self.buttons['output-load']=gtk.GtkButton('Load From File')
+ tips.set_tip(self.buttons['output-edit'],
+ 'Edit projection information (should '+
+ 'be a Well Known Text string)')
+ tips.set_tip(self.buttons['output-load'],
+ 'Load projection information from a GDAL '+
+ 'dataset, or a file with a single line '+
+ 'of Well Known Text specifying a projection.')
+ tips.set_tip(self.buttons['output-view'],
+ 'Load projection information from the '+
+ 'currently active view.')
+ self.attach(self.buttons['output-edit'],3,4,1,2)
+ self.attach(self.buttons['output-view'],4,5,1,2)
+ self.attach(self.buttons['output-load'],5,6,1,2)
+ self.outprj=''
+
+ self.buttons['input-load'].connect('clicked',self.load_input_cb)
+ self.buttons['input-view'].connect('clicked',self.view_input_cb)
+ self.buttons['output-load'].connect('clicked',self.load_output_cb)
+ self.buttons['output-view'].connect('clicked',self.view_output_cb)
+ self.buttons['input-edit'].connect('clicked',self.edit_input_cb)
+ self.buttons['output-edit'].connect('clicked',self.edit_output_cb)
+
+ self.toggle_output_cb()
+
+ def load_input_cb(self,*args):
+ prj=getprjinfo()
+ if prj is not None:
+ self.inprj=prj
+
+ def load_output_cb(self,*args):
+ prj=getprjinfo()
+ if prj is not None:
+ self.outprj=prj
+
+ def view_input_cb(self,*args):
+ prj=gview.app.sel_manager.get_active_view().get_projection()
+ if prj is None:
+ gvutils.error('Current view does not contain projection info!')
+ self.inprj=''
+ return
+
+ if len(prj) == 0:
+ gvutils.error('Current view does not contain projection info!')
+ self.inprj=''
+ return
+
+ sr=osr.SpatialReference()
+ val=sr.ImportFromWkt(prj)
+ if val == 0:
+ self.inprj=prj
+ else:
+ gvutils.error('Current view contains invalid projection info!')
+ self.inprj=''
+
+ def view_output_cb(self,*args):
+ prj=gview.app.sel_manager.get_active_view().get_projection()
+ if prj is None:
+ gvutils.error('Current view does not contain projection info!')
+ self.outprj=''
+ return
+
+ if len(prj) == 0:
+ gvutils.error('Current view does not contain projection info!')
+ self.outprj=''
+ return
+
+ sr=osr.SpatialReference()
+ val=sr.ImportFromWkt(prj)
+ if val == 0:
+ self.outprj=prj
+ else:
+ gvutils.error('Current view contains invalid projection info!')
+ self.outprj=''
+
+ def edit_input_cb(self,*args):
+ prj=editprjinfo(self.inprj)
+ if prj is not None:
+ self.inprj=prj
+
+ def edit_output_cb(self,*args):
+ prj=editprjinfo(self.outprj)
+ if prj is not None:
+ self.outprj=prj
+
+ def set_input_projection(self,prj):
+ self.inprj=prj
+
+ def set_output_projection(self,prj):
+ self.outprj=prj
+
+ def toggle_output_cb(self,*args):
+ if self.out_toggle_useinput.get_active() == 1:
+ self.buttons['output-load'].set_sensitive(0)
+ self.buttons['output-view'].set_sensitive(0)
+ self.buttons['output-edit'].set_sensitive(0)
+ else:
+ self.buttons['output-load'].set_sensitive(1)
+ self.buttons['output-view'].set_sensitive(1)
+ self.buttons['output-edit'].set_sensitive(1)
+
+ def get_projections(self,*args):
+ if self.out_toggle_useinput.get_active() == 1:
+ return (self.inprj, self.inprj)
+ else:
+ return (self.inprj, self.outprj)
+
+class InputFrame(gvsignaler.Signaler):
+ def __init__(self,parent,tips):
+ self.frame=gtk.GtkFrame('Raster Bands')
+ self.tips=tips
+ self.input_bands=get_list_of_bands_as_dict()
+ self.output_bands={}
+
+ hbox1=gtk.GtkHBox(spacing=spc)
+ hbox1.set_border_width(spc)
+ self.frame.add(hbox1)
+
+ # source (input)
+ srcvbox=gtk.GtkVBox(spacing=spc)
+ label=gtk.GtkLabel('Input:')
+ label.set_alignment(0,0.5)
+ srcvbox.pack_start(label,expand=gtk.FALSE)
+ hbox1.pack_start(srcvbox)
+ source_win = gtk.GtkScrolledWindow()
+ source_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ source_win.set_usize(300,200)
+ srcvbox.pack_start(source_win)
+
+ source_list = gtk.GtkList()
+ source_list.set_selection_mode(gtk.SELECTION_MULTIPLE)
+ source_win.add_with_viewport(source_list)
+ source_list.append_items(self.input_bands.keys())
+
+ # signals sent up to top level so that defaults can
+ # be updated. Defaults are updated whenever the output
+ # bands are cleared, or the first one is specified.
+ self.publish('output-bands-empty')
+ self.publish('output-bands-notempty')
+
+ def src_load(_button,*args):
+ fname=GtkExtra.file_sel_box(title="Select GDAL Dataset")
+ if fname is None:
+ return
+ ds=gdal.OpenShared(fname)
+ if ds is None:
+ gvutils.error('Not a valid gdal dataset!')
+ return
+
+ dict={}
+ for i in range(1,ds.RasterCount+1):
+ curband=fname + '.band[' + str(i) + ']'
+ dict[gtk.GtkListItem(curband)] = (ds,i,curband)
+
+ if srctoggle.get_active() == gtk.TRUE:
+ slist=vrtutils.GetSimilarFiles(fname)
+ for nname in slist:
+ ds = gdal.OpenShared(nname)
+ if ds is None:
+ continue
+ for i in range(1,ds.RasterCount+1):
+ curband=nname + '.band[' + str(i) + ']'
+ dict[gtk.GtkListItem(curband)] = (ds,i,curband)
+
+ self.add_input_bands(dict)
+
+ def src_get_active_layers(_button,*args):
+ size=None
+ if len(self.input_bands) > 0:
+ ckey=self.input_bands.keys()[0]
+ size=(self.input_bands[ckey][0].RasterXSize,
+ self.input_bands[ckey][0].RasterYSize)
+ new_dict=get_list_of_bands_as_dict(size)
+ self.add_input_bands(new_dict)
+
+ def src_clear(_button,*args):
+ self.clear_input_bands()
+
+ self.source_list=source_list
+
+ # source control buttons
+ srcbbox=gtk.GtkHBox(spacing=spc)
+ srcvbox.pack_start(srcbbox,expand=gtk.FALSE)
+ load_btn=gtk.GtkButton("Load File")
+ self.tips.set_tip(load_btn,'Add bands from a file to the input list')
+ srcbbox.pack_start(load_btn)
+ load_btn.connect("clicked",src_load)
+ act_btn=gtk.GtkButton("Views->List")
+ self.tips.set_tip(act_btn,'Add bands from views to the input list')
+ srcbbox.pack_start(act_btn)
+ act_btn.connect("clicked",src_get_active_layers)
+ clear_btn=gtk.GtkButton("Clear")
+ srcbbox.pack_start(clear_btn)
+ clear_btn.connect("clicked",src_clear)
+
+ srctoggle=gtk.GtkCheckButton("Include Similar")
+ self.tips.set_tip(srctoggle,'Include bands from same-size files '+
+ 'in the same directory when using Load File.')
+ srcbbox.pack_start(srctoggle,expand=gtk.FALSE)
+ srctoggle.set_active(gtk.TRUE)
+
+ # destination
+ btn_box = gtk.GtkVBox(spacing=10)
+ btn_box.set_border_width(10)
+ hbox1.pack_start(btn_box,expand=gtk.FALSE)
+ btn_box.show()
+
+ def dest_add(_button,*args):
+ sel = source_list.get_selection()
+ sel.reverse() # add in order of selection
+ if len(self.output_bands.keys()) == 0:
+ refreshflag = 1
+ else:
+ refreshflag = 0
+
+ for i in sel:
+ list_item = gtk.GtkListItem(self.input_bands[i][2])
+ self.dest_list.append_items([list_item])
+ list_item.show()
+ self.dest_list.select_child(self.dest_list.children()[-1])
+ self.output_bands[list_item] = self.input_bands[i]
+
+ if (refreshflag == 1) and (len(sel) > 0):
+ self.notify('output-bands-notempty')
+
+ def dest_del(_button,*args):
+ selection = self.dest_list.get_selection()
+ self.dest_list.remove_items(selection)
+ for i in selection:
+ del self.output_bands[i]
+ i.destroy()
+ rest = self.dest_list.children()
+ if len(rest) > 0:
+ self.dest_list.select_child(self.dest_list.children()[-1])
+ else:
+ self.notify('output-bands-empty')
+
+ def dest_raise(_button, *args):
+ selection = self.dest_list.get_selection()
+ if len(selection) != 1:
+ return
+ pos=self.dest_list.child_position(selection[0])
+ if pos < 1:
+ return
+ self.dest_list.remove_items(selection)
+ self.dest_list.insert_items(selection,pos-1)
+ self.dest_list.select_item(pos-1)
+
+ def dest_lower(_button, *args):
+ selection = self.dest_list.get_selection()
+ if len(selection) != 1:
+ return
+ pos=self.dest_list.child_position(selection[0])
+ if pos > len(self.output_bands)-2:
+ return
+ self.dest_list.remove_items(selection)
+ self.dest_list.insert_items(selection,pos+1)
+ self.dest_list.select_item(pos+1)
+
+
+ add_btn = gtk.GtkButton("Add->")
+ add_btn.connect("clicked", dest_add)
+ # The label below just makes things align more nicely (adds space)
+ btn_box.pack_start(gtk.GtkLabel(''),expand=gtk.FALSE)
+ btn_box.pack_start(add_btn,expand=gtk.FALSE)
+
+
+ destvbox=gtk.GtkVBox(spacing=spc)
+ label=gtk.GtkLabel('Output:')
+ label.set_alignment(0,0.5)
+ destvbox.pack_start(label,expand=gtk.FALSE)
+ dest_win = gtk.GtkScrolledWindow()
+ dest_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ dest_win.set_usize(300,200)
+ destvbox.pack_start(dest_win)
+
+ hbox1.pack_start(destvbox)
+ destbbox=gtk.GtkHBox(spacing=spc)
+ destvbox.pack_start(destbbox,expand=gtk.FALSE)
+ del_btn = gtk.GtkButton()
+ del_btn.add(gtk.GtkPixmap(parent,
+ os.path.join(gview.home_dir,'pics','delete.xpm')))
+ del_btn.connect("clicked", dest_del)
+ destbbox.pack_start(del_btn,expand=gtk.FALSE)
+ r_btn = gtk.GtkButton()
+ r_btn.add(gtk.GtkPixmap(parent,
+ os.path.join(gview.home_dir,'pics','raise.xpm')))
+ r_btn.connect("clicked", dest_raise)
+ destbbox.pack_start(r_btn,expand=gtk.FALSE)
+ l_btn = gtk.GtkButton()
+ l_btn.add(gtk.GtkPixmap(parent,
+ os.path.join(gview.home_dir,'pics','lower.xpm')))
+ l_btn.connect("clicked", dest_lower)
+ destbbox.pack_start(l_btn,expand=gtk.FALSE)
+
+ self.dest_list = gtk.GtkList()
+ self.dest_list.set_selection_mode(gtk.SELECTION_BROWSE)
+ dest_win.add_with_viewport(self.dest_list)
+
+ parent.shell.pack_start(self.frame)
+
+ def clear_input_bands(self):
+ self.input_bands={}
+ self.source_list.select_all()
+ sel=self.source_list.get_selection()
+ self.source_list.remove_items(sel)
+
+ def set_input_bands(self,bands):
+ self.input_bands=bands
+ self.clear_input_bands()
+ self.source_list.append_items(self.input_bands.keys())
+ for item in self.input_bands.keys():
+ item.show()
+
+ def add_input_bands(self,bands):
+ if len(self.output_bands) > 0:
+ keys=self.output_bands.keys()
+ xsize,ysize=(self.output_bands[keys[0]][0].RasterXSize,
+ self.output_bands[keys[0]][0].RasterYSize)
+ elif len(self.input_bands) > 0:
+ keys=self.input_bands.keys()
+ xsize,ysize=(self.input_bands[keys[0]][0].RasterXSize,
+ self.input_bands[keys[0]][0].RasterYSize)
+ else:
+ keys=bands.keys()
+ xsize,ysize=(bands[keys[0]][0].RasterXSize,
+ bands[keys[0]][0].RasterYSize)
+
+ # Only add bands that are of the same size
+ invalid=0
+ oldbands=[]
+ for ckey in self.input_bands.keys():
+ oldbands.append(self.input_bands[ckey][2])
+
+ newbands=[]
+ for ckey in bands.keys():
+ cxsize,cysize=(bands[ckey][0].RasterXSize,
+ bands[ckey][0].RasterYSize)
+ if (cxsize == xsize) and (cysize == ysize):
+ if ((bands[ckey][2] not in oldbands) and
+ (bands[ckey][2] not in newbands)):
+ self.input_bands[ckey]=bands[ckey]
+ newbands.append(self.input_bands[ckey][2])
+ else:
+ invalid=1
+
+ if invalid != 0:
+ txt='Bands for composed dataset must all\n'+\
+ 'be the same size. Bands that are not\n'+\
+ str(xsize)+' pixels x '+str(ysize)+' lines\n'+\
+ 'will be excluded from the input list.'
+ gvutils.warning(txt)
+ print 'Xsize: ',xsize,' Ysize: ',ysize
+ # clear old list in case some of the new keys replace
+ # older ones
+ self.source_list.select_all()
+ sel=self.source_list.get_selection()
+ self.source_list.remove_items(sel)
+ self.source_list.append_items(self.input_bands.keys())
+ for item in self.input_bands.keys():
+ item.show()
+
+ def get_output_bands(self):
+ """ Return a list of bands. Each list is
+ a tuple- (gdal dataset, band number)
+ """
+ dlist=self.dest_list.children()
+ out_list=[]
+ for item in dlist:
+ out_list.append((self.output_bands[item][0],
+ self.output_bands[item][1]))
+ return out_list
+
+ def show_all(self,*args):
+ self.frame.show_all()
+
+ def show(self,*args):
+ self.frame.show()
+
+
+def CopyGDALGCP(gcp):
+ ngcp=gdal.GCP()
+ ngcp.GCPPixel=gcp.GCPPixel
+ ngcp.GCPLine=gcp.GCPLine
+ ngcp.GCPX=gcp.GCPX
+ ngcp.GCPY=gcp.GCPY
+ ngcp.GCPZ=gcp.GCPZ
+ ngcp.Id=gcp.Id
+ ngcp.Info=gcp.Info
+
+ return ngcp
+
+def CopyGDALGCPs(gcplist):
+ ngcplist=[]
+ for gcp in gcplist:
+ ngcplist.append(CopyGDALGCP(gcp))
+ return ngcplist
+
+
+########################################################################
+def get_raster_size(_layer):
+ w = _layer.get_parent().get_dataset().GetRasterBand(1).XSize
+ h = _layer.get_parent().get_dataset().GetRasterBand(1).YSize
+ return (w,h)
+
+
+#########################################################################
+def get_list_of_bands_as_dict(size=None):
+ """Returns dictionary of the bands of the opened layers. The key
+ of dictionary is the GtkListItem object produced from the name of
+ layer+band number, members of dictionary are view-object (index = 0),
+ layer-object (index = 1), band-number and name"""
+
+ layer = gview.app.sel_manager.get_active_layer()
+ if layer is None:
+ return {}
+ if size is None:
+ size = get_raster_size(layer)
+ dict = {}
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ cursize = get_raster_size(curlayer)
+ if cursize == size:
+ num_bands = curlayer.get_parent().get_dataset().RasterCount
+ ds=curlayer.get_parent().get_dataset()
+ for i in range(1,num_bands+1):
+ curband = curname + '.band['+ str(i) + ']'
+ dict[gtk.GtkListItem(curband)] = (ds,i,curband)
+ if dict is None:
+ return None
+ return dict
+
+
+TOOL_LIST = ['ComposeTool']
+
Added: packages/openev/branches/upstream/current/tools/fft.py
===================================================================
--- packages/openev/branches/upstream/current/tools/fft.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/fft.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,135 @@
+###############################################################################
+# $Id: fft.py,v 1.1 2004/07/24 15:17:13 andrey_kiselev Exp $
+#
+# Project: OpenEV Python tools
+# Purpose: Tool to calculate forward or inverse Fast Fourier Transform
+# Author: Andrey Kiselev, dron at remotesensing.org
+#
+###############################################################################
+# Copyright (c) 2004, Andrey Kiselev <dron at remotesensing.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+#
+# $Log: fft.py,v $
+# Revision 1.1 2004/07/24 15:17:13 andrey_kiselev
+# New.
+#
+#
+
+from gtk import *
+
+import gview
+import gviewapp
+import gdalnumeric
+import gvutils
+import FFT
+
+def layer_is_raster(layer):
+ """Return TRUE if layer is raster and FALSE otherwise"""
+ try:
+ layer.get_nodata(0)
+ return TRUE
+ except:
+ return FALSE
+
+class FFTTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = FFTDialog()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Filter/FFT",2,self.launch_dialog)
+
+class FFTDialog(GtkWindow):
+ def __init__(self,app=None):
+
+ GtkWindow.__init__(self)
+ self.set_title('Fast Fourier Transform')
+ self.create_gui()
+ self.show()
+
+ def show(self):
+ GtkWindow.show_all(self)
+
+ def close(self, *args):
+ self.hide()
+ self.visibility_flag = 0
+ return TRUE
+
+ def create_gui(self):
+ box1 = GtkVBox(spacing = 10)
+ box1.set_border_width(10)
+ self.add(box1)
+ box1.show()
+
+ self.switch_forward = GtkRadioButton(None, "Forward")
+ box1.pack_start(self.switch_forward)
+ self.switch_forward.show()
+ self.switch_inverse = GtkRadioButton(self.switch_forward, "Inverse")
+ box1.pack_start(self.switch_inverse)
+ self.switch_inverse.show()
+
+ separator = GtkHSeparator()
+ box1.pack_start(separator, expand=FALSE)
+
+ self.switch_new_view = GtkCheckButton("Create new view")
+ box1.pack_start(self.switch_new_view)
+ self.switch_new_view.show()
+
+ separator = GtkHSeparator()
+ box1.pack_start(separator, expand=FALSE)
+
+ box2 = GtkHBox(spacing=10)
+ box1.pack_start(box2, expand=FALSE)
+ box2.show()
+
+ execute_btn = GtkButton("Ok")
+ execute_btn.connect("clicked", self.execute_cb)
+ box2.pack_start(execute_btn)
+
+ close_btn = GtkButton("Cancel")
+ close_btn.connect("clicked", self.close)
+ box2.pack_start(close_btn)
+
+ def execute_cb( self, *args ):
+ layer = gview.app.sel_manager.get_active_layer()
+ if not layer_is_raster(layer):
+ gvutils.error("Please select a raster layer.");
+ return
+ ds = layer.get_parent().get_dataset()
+ data = gdalnumeric.DatasetReadAsArray(ds)
+
+ if self.switch_forward.get_active():
+ data_tr = FFT.fft2d(data)
+ else:
+ data_tr = FFT.inverse_fft2d(data)
+
+ array_name = gdalnumeric.GetArrayFilename(data_tr)
+ if self.switch_new_view.get_active():
+ gview.app.new_view()
+ gview.app.file_open_by_name(array_name)
+
+TOOL_LIST = ['FFTTool']
+
Added: packages/openev/branches/upstream/current/tools/gvrastertools.py
===================================================================
--- packages/openev/branches/upstream/current/tools/gvrastertools.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/gvrastertools.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,232 @@
+###############################################################################
+# $Id: gvrastertools.py,v 1.5 2004/01/12 16:54:56 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Raster tools for OpenEV built using Gillian's Tool Architecture.
+# Currently just Histogram.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: gvrastertools.py,v $
+# Revision 1.5 2004/01/12 16:54:56 warmerda
+# Properly apply scaling for histogram data.
+# http://bugzilla.remotesensing.org/show_bug.cgi?id=457
+#
+# Revision 1.4 2002/07/07 21:08:18 warmerda
+# avoid depending on Numeric at the top level
+#
+# Revision 1.3 2002/04/25 15:19:58 gmwalter
+# Updated the menu extension mechanism to get rid of the extend_menu function and to allow the help menu to remain on the right side of the menubar. Got rid of some extra print statements and the gnuplot 0 y-range warning in the histogram tool initialization.
+#
+# Revision 1.2 2002/04/18 20:36:09 warmerda
+# ensure the histogram dialog gets initialized
+#
+# Revision 1.1 2002/04/18 20:23:24 warmerda
+# New
+#
+
+import gviewapp
+import gtk
+import os
+import gdal
+import string
+import gvsignaler
+import toolexample
+
+FALSE = gtk.FALSE
+TRUE = gtk.TRUE
+import gview,gvutils
+
+
+class HistogramROITool(toolexample.GeneralROITool):
+
+ def __init__(self,app=None):
+ toolexample.GeneralROITool.__init__(self,app)
+
+ def init_dialog(self):
+ self.RP_ToolDlg = Histogram_ToolDlg()
+
+ def init_menu(self):
+ # print 'in Histogram init_menu()'
+ self.menu_entries.set_entry("Tools/Histogram Tool",2,
+ self.roipoitool_cb)
+
+ def update_dlgroi_frame(self,*args):
+ # Update frame as in general tool
+ if self.RP_ToolDlg.is_active():
+ roi_info = self.RP_Stored.roi
+ self.RP_ToolDlg.update_roiframe(roi_info)
+
+ else:
+ return
+
+ self.update_roi_view()
+
+ if self.RP_ToolDlg.is_auto_updating():
+ # Automatic analysis is on
+ self.RP_ToolDlg.analyze_cb(self)
+
+ def update_roi_view(self,*args):
+ pass
+
+ def analyze_cb(self,*args):
+ # Find the view and layer
+ cview = self.app.view_manager.get_active_view_window().title
+ clayer = self.app.sel_manager.get_active_layer()
+ if (cview is None) or (clayer is None):
+ # analysis only makes sense in the context of a view and layer
+ gvutils.error('No View/Layer selected!')
+ return
+
+ text = self.basic_region_analysis(cview,clayer)
+
+ def basic_region_analysis(self,cview,clayer):
+ import Numeric, gdalnumeric
+
+ line = int(self.RP_ToolDlg.entry_dict['start_line'].get_text())
+ pix = int(self.RP_ToolDlg.entry_dict['start_pix'].get_text())
+ sl = int(self.RP_ToolDlg.entry_dict['num_lines'].get_text())
+ sp = int(self.RP_ToolDlg.entry_dict['num_pix'].get_text())
+
+ clayer = self.app.sel_manager.get_active_layer()
+ if clayer is None:
+ # Target can only be extracted if a layer is selected
+ return 'No selected raster layer'
+
+ dsb = clayer.get_parent().get_band()
+
+ # Modify default to be whole image.
+ if sl is 1 and sp is 1 and line is 1 and pix is 1:
+ sl = dsb.YSize - line + 1
+ sp = dsb.XSize - pix + 1
+
+ # Create a temporary band for sampling if we have a subrect.
+ temp_copy = 0
+ if line != 1 or pix != 1 or sp != dsb.XSize or sl != dsb.YSize:
+ # print line, pix, sp, sl
+ temp_copy = 1
+ filename = clayer.get_parent().get_dataset().GetDescription()
+ target_data = gdalnumeric.LoadFile(filename,pix-1,line-1,sp,sl)
+ target_ds = gdalnumeric.OpenArray(target_data)
+ dsb = target_ds.GetRasterBand(1)
+
+ # Compute the histogram.
+
+ min = clayer.min_get(0)
+ max = clayer.max_get(0)
+ histogram = dsb.GetHistogram( min, max, 256, 1, 0 )
+
+ (pm, mask) = self.RP_ToolDlg.get_histview( histogram, min, max )
+
+ self.RP_ToolDlg.viewarea.set(pm,mask)
+
+class Histogram_ToolDlg(toolexample.General_ROIToolDlg):
+ def __init__(self):
+ toolexample.General_ROIToolDlg.__init__(self)
+
+ def init_setup_window(self):
+ self.set_title('Raster Histogram Tool')
+ self.set_border_width(10)
+
+ def init_customize_gui_panel(self):
+ # Inherit all the usual stuff...
+ toolexample.General_ROIToolDlg.init_customize_gui_panel(self)
+
+ # Add new frame with pixel info, keeping track of
+ # the frame and text object...
+ self.frame_dict['histogram_frame'] = gtk.GtkFrame()
+ self.show_list.append(self.frame_dict['histogram_frame'])
+
+ # Initialize with dummy histogram.
+
+ histogram = []
+ for i in range(256):
+ histogram.append( 0 )
+
+ (pm, mask) = self.get_histview(histogram,0,256,-1,1)
+ self.viewarea = gtk.GtkPixmap(pm,mask)
+ self.entry_dict['histogram_view'] = self.viewarea
+ self.show_list.append(self.viewarea)
+ self.frame_dict['histogram_frame'].add(self.viewarea)
+
+ self.main_panel.pack_start(self.frame_dict['histogram_frame'],
+ gtk.TRUE,gtk.TRUE,0)
+
+ def set_entry_sensitivities(self,bool_val):
+ self.entry_dict['start_line'].set_sensitive(bool_val)
+ self.entry_dict['start_pix'].set_sensitive(bool_val)
+ self.entry_dict['num_lines'].set_sensitive(bool_val)
+ self.entry_dict['num_pix'].set_sensitive(bool_val)
+
+ def activate_toggled(self,*args):
+ if self.button_dict['Activate'].get_active():
+ self.set_entry_sensitivities(gtk.TRUE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.TRUE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.TRUE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.TRUE)
+ self.notify('re-activated')
+ else:
+ self.set_entry_sensitivities(gtk.FALSE)
+ self.button_dict['Auto Update'].set_active(gtk.FALSE)
+ self.button_dict['Auto Update'].set_sensitive(gtk.FALSE)
+ self.button_dict['Analyze'].set_sensitive(gtk.FALSE)
+ self.button_dict['Set Tool'].set_sensitive(gtk.FALSE)
+
+ def get_histview( self, histogram, min, max,set_ymin=None,set_ymax=None ):
+
+ # Prepare histogram plot
+
+ data = []
+ bucket_width = (max - min) / 256.0
+ for bucket_index in range(256):
+ data.append( (min + bucket_width * bucket_index,
+ histogram[bucket_index]) )
+
+ # Generate histogram graph
+
+ import gvplot
+
+ xpm_file = gvutils.tempnam(extension='xpm')
+ if ((set_ymin is not None) and (set_ymax is not None)):
+ # Allows you to explicitly set ymin/ymax at startup
+ # to avoid the gnuplot 0 y-range warning.
+ gvplot.plot( data, xaxis = 'Pixel Value', yaxis = 'Count',
+ xmin = min, xmax = max, ymin = set_ymin,
+ ymax = set_ymax, output = xpm_file,
+ title = 'Histogram', terminal = 'xpm' )
+ else:
+ gvplot.plot( data, xaxis = 'Pixel Value', yaxis = 'Count',
+ xmin = min, xmax = max, output = xpm_file,
+ title = 'Histogram', terminal = 'xpm' )
+
+ # apply it to display.
+
+ gdk_pixmap, gdk_mask = \
+ gtk.create_pixmap_from_xpm(self,None,xpm_file)
+
+ os.unlink( xpm_file )
+
+ return (gdk_pixmap, gdk_mask)
+
+
+TOOL_LIST = ['HistogramROITool']
+
Added: packages/openev/branches/upstream/current/tools/imgproctemplate.py
===================================================================
--- packages/openev/branches/upstream/current/tools/imgproctemplate.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/imgproctemplate.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,193 @@
+###############################################################################
+# $Id: imgproctemplate.py,v 1.1 2003/06/09 16:00:11 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Template Image Processing "tool". Seach for CHANGEME.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: imgproctemplate.py,v $
+# Revision 1.1 2003/06/09 16:00:11 warmerda
+# New
+#
+#
+
+from gtk import *
+
+import gview
+import string
+import gvutils
+import GtkExtra
+import os
+import sys
+import gviewapp
+import gdalnumeric
+
+class ImageProcTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = ImageProcDialog()
+ self.win.update_gui()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Image Processing",2,
+ self.launch_dialog)
+
+class ImageProcDialog(GtkWindow):
+
+ def __init__(self,app=None):
+ GtkWindow.__init__(self)
+
+ self.set_title('Image Processing')
+
+ self.create_gui()
+ self.show()
+
+ def show(self):
+ GtkWindow.show_all(self)
+
+ def close(self, *args):
+ self.hide()
+ self.visibility_flag = 0
+ return TRUE
+
+ def create_gui(self):
+ box1 = GtkVBox()
+ self.add(box1)
+ box1.show()
+
+ text = GtkText()
+ text.set_usize(400,150)
+ text.set_line_wrap(FALSE)
+ text.set_word_wrap(FALSE)
+ text.set_editable(FALSE)
+ text.show()
+ self.text = text
+ box1.pack_start(text, expand=TRUE)
+
+ box2 = GtkHBox()
+ box1.pack_start(box2, expand=FALSE)
+ box2.show()
+
+ self.execute_btn = GtkButton("Execute")
+ self.execute_btn.connect("clicked", self.execute_cb)
+ box2.pack_start(self.execute_btn)
+
+ self.close_btn = GtkButton("Close")
+ self.close_btn.connect("clicked", self.close)
+ box2.pack_start(self.close_btn)
+
+ def update_gui(self,*args):
+ pass
+
+ ##########################################################################
+ # Return the currently selected raster layer.
+ #
+ # Reports an error and returns None if there isn't a suitable raster
+ # layer selected
+ #
+ def get_cur_rlayer(self):
+
+ rlayer = gview.app.sel_manager.get_active_layer()
+
+ if rlayer is None:
+ gvutils.error( 'Please select a raster layer.' )
+ return None
+
+ # This will only work for a real GvRasterLayer
+ try:
+ nd = rlayer.get_nodata(0)
+ return rlayer
+
+ except:
+ gvutils.error( 'Please select a raster layer.' )
+ return None
+
+ ##########################################################################
+ # Load indicated raster layer into a memory array.
+ #
+ # Note that all bands are loaded, not just the ones being displayed in
+ # in the view.
+
+ def load_layer(self, rl, xoff=0, yoff=0, xsize=None, ysize=None ):
+ filename = rl.get_parent().get_dataset().GetDescription()
+ target_data = gdalnumeric.LoadFile(filename,xoff,yoff,xsize,ysize)
+ return target_data;
+
+ ##########################################################################
+ # Save image array into existing raster file.
+ #
+
+ def save_layer(self, rl, rd, xoff=0, yoff=0 ):
+ ds = rl.get_parent().get_dataset()
+
+ if len(rd.shape) == 3:
+ for iBand in range(len(rd.shape)):
+ gdal_band = ds.GetRasterBand(iBand+1)
+ rd_band = rd[iBand]
+
+ gdal_band.WriteArray( rd_band, xoff, yoff )
+ else:
+ gdal_band = ds.GetRasterBand(1)
+ gdal_band.WriteArray( rd, xoff, yoff )
+
+ ##########################################################################
+ # Main algorithm execution callback.
+
+ def execute_cb( self, *args ):
+
+ print 'Entering execute_cb()'
+
+ try:
+ # Determine the currently selected raster layer.
+ rl = self.get_cur_rlayer()
+ if rl is None:
+ print 'didnt get rlayer'
+ return
+
+ # Load it into memory.
+ rd = self.load_layer( rl )
+ if rd is None:
+ print 'didnt load layer'
+ return
+
+ # Apply algorithm to raster data. *** CHANGEME ***
+ rd = rd * 0.5
+
+ # Save results back into source raster layer.
+ self.save_layer( rl, rd )
+ rl.refresh()
+
+ except:
+ print 'Trapped Error'
+ sys.excepthook(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ print 'Exiting execute_cb()'
+
+TOOL_LIST = ['ImageProcTool']
+
Added: packages/openev/branches/upstream/current/tools/isodata.py
===================================================================
--- packages/openev/branches/upstream/current/tools/isodata.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/isodata.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,561 @@
+##############################################################################
+# $Id: isodata.py,v 1.1 2005/08/26 18:27:35 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: ISODATA clustering
+# Author: Iscander Latypov
+# Andrey Kiselev, dron at remotesensing.org
+#
+###############################################################################
+# Copyright (c) 2004, American Museum of Natural History. All rights reserved.
+# This software is based upon work supported by NASA under award
+# number NAG5-12333
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: isodata.py,v $
+# Revision 1.1 2005/08/26 18:27:35 andrey_kiselev
+# New.
+#
+#
+
+from gtk import *
+
+from Numeric import *
+import gview
+import gvutils
+import gviewapp
+import gdal
+from gdalconst import *
+import gdalnumeric
+
+
+
+########################################################################
+def get_raster_size(_layer):
+ w = _layer.get_parent().get_dataset().GetRasterBand(1).XSize
+ h = _layer.get_parent().get_dataset().GetRasterBand(1).YSize
+ return (w,h)
+
+########################################################################
+def get_list_of_layers_as_dict():
+ """Returns dictionary of opened layers. The key of dictionary is
+ the name of layer, members of dictionary are view object (index = 0)
+ and layer object (index = 1)"""
+
+ dict = {}
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ dict[curname] = (curview,curlayer)
+ if dict is None:
+ return None
+ return dict
+
+########################################################################
+def get_list_of_layers_as_menu():
+ """Returns GtkMenu object for selecting of opened layers.
+ If number of opened layers is zero, the result is None"""
+ menu = GtkMenu()
+ group = None
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ menuitem = GtkRadioMenuItem(group,curname)
+ group = menuitem
+ menu.append(menuitem)
+ menuitem.show()
+ if group is None:
+ return None
+ return menu
+
+#########################################################################
+def get_list_of_bands_as_dict():
+ """Returns dictionary of the bands of the opened layers. The key
+ of dictionary is the name of layer+band number, members of dictionary
+ are view-object (index = 0), layer-object (index = 1) and band-number"""
+
+ _size = get_raster_size(gview.app.sel_manager.get_active_layer())
+ dict = {}
+ for curview in gview.app.view_manager.view_list:
+ for curlayer in curview.viewarea.list_layers():
+ curname = curlayer.get_name()
+ cursize = get_raster_size(curlayer)
+ if cursize == _size:
+ num_bands = curlayer.get_parent().get_dataset().RasterCount
+ for i in range(num_bands):
+ curband = curname + '['+ str(i) + ']'
+ dict[curband] = (curview,curlayer,i)
+ if dict is None:
+ return None
+ return dict
+
+############################################################################
+#
+#
+############################################################################
+def L1(v1,v2):
+ return sum(abs(v1-v2))
+###########################################################################
+def L2(v1,v2):
+ delta = (v1-v2)
+ return dot(delta,delta)
+###########################################################################
+def L3(v1,v2):
+ delta = abs(v1-v2)
+ return max(delta)
+###########################################################################
+class IsodataTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = ISODATADialog()
+ if self.win is None:
+ return
+ else:
+ self.win.update_gui()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Image/Classification/ISOData",2,
+ self.launch_dialog)
+
+############################################################################
+class ClassesTable(GtkWindow):
+ def __init__(self,nBands,app=None):
+ GtkWindow.__init__(self)
+ self.set_title('Classification Info')
+ self.nBands = nBands
+ self.create_gui()
+ self.stop_flag = FALSE
+ GtkWindow.show_all(self)
+
+ def close(self,*args):
+ self.destroy()
+ return TRUE
+
+ def create_gui(self):
+ box1 = GtkVBox(spacing=5)
+ self.add(box1)
+ box1.show()
+
+ self.line_label = GtkLabel()
+ box1.pack_start(self.line_label)
+
+ self.it_label = GtkLabel()
+ box1.pack_start(self.it_label)
+
+ self.data_list = GtkCList(cols=self.nBands+1)
+ self.data_list.set_selection_mode(SELECTION_SINGLE)
+ self.data_list.set_column_width(0,20)
+ for i in range(self.nBands):
+ self.data_list.set_column_width(i+1,60)
+ box1.pack_start(self.data_list)
+ self.data_list.show()
+
+ self.progress_bar = GtkProgressBar()
+ box1.pack_start(self.progress_bar)
+
+ self.stop_button = GtkButton("Stop process")
+ self.stop_button.connect("clicked",self.stop_cb)
+ box1.pack_start(self.stop_button)
+
+ def set_data(self,centres,n_iter):
+ self.it_label.set_text("Classes after "+str(n_iter+1)+" iterations")
+ self.data_list.freeze()
+ self.data_list.clear()
+ for i in range(len(centres)):
+ cur_list = [str(i)]
+ for j in range(self.nBands):
+ #c = str(centres[i][j])
+ c = "%7.2f"%centres[i][j]
+ cur_list.append(c)
+ self.data_list.append(cur_list)
+
+ self.data_list.thaw()
+
+ def stop_cb(self,*args):
+ self.stop_flag = TRUE
+ self.progress_bar.hide()
+ self.stop_button.hide()
+
+ def stop_pressed(self,*args):
+ return self.stop_flag
+
+ def show_progress(self,percents,line):
+ self.line_label.set_text("Current Line Number "+str(line))
+ self.progress_bar.set_percentage(percents/100.)
+ while events_pending():
+ mainiteration(FALSE)
+
+ def finish(self):
+ self.line_label.hide()
+ self.it_label.set_text("Classification Complete")
+############################################################################
+class ISODATADialog(GtkWindow):
+
+ def __init__(self,app=None):
+ GtkWindow.__init__(self)
+ self.set_title('ISODATA Classification')
+ self.set_policy(FALSE, TRUE, TRUE)
+ self.text_pos = 0
+ self.tooltips = GtkTooltips()
+
+ try:
+ gdal_dataset = gview.app.sel_manager.get_active_layer().get_data().get_dataset()
+ except:
+ gvutils.error("Active Layer is not a raster layer")
+ return None
+
+ self.band_list_to_classify = []
+
+ gui_OK = self.create_gui()
+ if gui_OK is FALSE:
+ return None
+ else:
+ GtkWindow.show_all(self)
+
+ def close(self,*args):
+ self.destroy()
+ return TRUE
+
+######################################################################
+ def create_gui(self):
+
+ self.dict_of_bands = get_list_of_bands_as_dict()
+ self.list_of_bands = self.dict_of_bands.keys()
+ self.list_of_bands.sort()
+
+ title_width = 120
+ self.metric_num = 0
+
+ box1 = GtkVBox(spacing=5)
+ self.add(box1)
+ box1.show()
+
+ rastersbox = GtkVBox(spacing=5)
+ box1.pack_start(rastersbox)
+ rastersbox.show()
+
+### source list #############################################################
+ frame1 = GtkFrame("Raster Specifications")
+ frame1.show()
+ rastersbox.pack_start(frame1, expand=FALSE)
+
+ box2r = GtkHBox(spacing=10)
+ box2r.set_border_width(10)
+ frame1.add(box2r)
+ box2r.show()
+
+ box2r1 = GtkVBox(spacing=5)
+ box2r.add(box2r1)
+ box2r1.show()
+
+ self.src_list = GtkCList(cols=1)
+ self.src_list.set_selection_mode(SELECTION_SINGLE)
+ self.src_list.set_column_width(0,120)
+ self.src_list.connect('button-press-event',self.src_band_selected_cb)
+ self.src_list.freeze()
+ self.src_list.clear()
+
+ for name in self.list_of_bands:
+ self.src_list.append([name])
+ self.src_list.thaw()
+ box2r1.pack_start(self.src_list)
+ self.src_list.show()
+
+ box2r2 = GtkVBox(spacing=5)
+ box2r.add(box2r2)
+ box2r2.show()
+
+ button_copy = GtkButton(">>")
+ box2r2.pack_start(button_copy)
+ button_copy.connect("clicked",self.copy_band_cb)
+ button_remove = GtkButton("<<")
+ box2r2.pack_start(button_remove)
+ button_remove.connect("clicked",self.remove_band_cb)
+
+ box2r3 = GtkVBox(spacing=5)
+ box2r.add(box2r3)
+ box2r3.show()
+
+ self.sel_list = GtkCList(cols=1)
+ self.sel_list.set_selection_mode(SELECTION_SINGLE)
+ self.sel_list.connect('button-press-event',self.sel_band_selected_cb)
+ self.sel_list.set_column_width(0,120)
+ box2r3.pack_start(self.sel_list)
+ self.sel_list.show()
+
+ self.src_row_to_copy = -1
+ self.sel_row_to_delete = -1
+
+#### Entries ###########################################################
+ entries_table = GtkTable(3,4)
+ entries_table.set_border_width(5)
+ box1.pack_start(entries_table)
+
+ label = GtkLabel("Desirable Number of Clusters")
+ entries_table.attach(label,0,2,0,1)
+ self.clusters = GtkEntry()
+ self.clusters.set_text("8")
+ entries_table.attach(self.clusters,2,3,0,1)
+
+
+ label = GtkLabel("Maximal Number of Iterations")
+ entries_table.attach(label,0,2,1,2)
+ self.maxiter = GtkEntry()
+ self.maxiter.set_text("20")
+ entries_table.attach(self.maxiter,2,3,1,2)
+
+ label = GtkLabel("Minimal Cluster Volume")
+ entries_table.attach(label,0,2,2,3)
+ self.min_volume = GtkEntry()
+ self.min_volume.set_text("1000")
+ entries_table.attach(self.min_volume,2,3,2,3)
+
+ label = GtkLabel("Movement Classes Treshold")
+ entries_table.attach(label,0,2,3,4)
+ self.mov_treshold = GtkEntry()
+ self.mov_treshold.set_text("0.1")
+ entries_table.attach(self.mov_treshold,2,3,3,4)
+#######################################################################
+ metric_box = GtkHBox(spacing=10)
+ box1.pack_start(metric_box)
+
+ metric_list = ["Manhattan Metric","Euclidian Metric","Chebyshev Metric"]
+ self.metric_menu = gvutils.GvOptionMenu(metric_list,self.metrics_selected_cb)
+ metric_box.pack_start(self.metric_menu)
+#### Buttons ###########################################################
+ button_box = GtkHBox(spacing = 10)
+ button_box.set_border_width(10)
+ box1.pack_start(button_box)
+
+ button_ok = GtkButton("Classify")
+ button_ok.connect("clicked",self.classify_cb)
+ button_box.pack_start(button_ok)
+
+ button_cancel = GtkButton("Cancel")
+ button_cancel.connect("clicked",self.close)
+ button_box.pack_start(button_cancel)
+
+ return TRUE
+########################################################################
+ def metrics_selected_cb(self,*args):
+ self.metric_num = self.metric_menu.get_history()
+########################################################################
+ def src_band_selected_cb(self,widget,event,*args):
+ try:
+ row,col = widget.get_selection_info(int(event.x),int(event.y))
+ except:
+ return
+ self.src_row_to_copy = row
+########################################################################
+ def sel_band_selected_cb(self,widget,event,*args):
+ try:
+ row,col = widget.get_selection_info(int(event.x),int(event.y))
+ except:
+ return
+ self.sel_row_to_delete = row
+########################################################################
+ def copy_band_cb(self,*args):
+ if self.src_row_to_copy > -1:
+ text = self.src_list.get_text(self.src_row_to_copy,0)
+ self.sel_list.freeze()
+ self.sel_list.append([text])
+ self.sel_list.thaw()
+ self.src_list.remove(self.src_row_to_copy)
+ self.src_row_to_copy = -1
+ self.band_list_to_classify.append(self.get_band(text))
+########################################################################
+ def remove_band_cb(self,*args):
+ if self.sel_row_to_delete > -1:
+ self.sel_list.freeze()
+ text = self.sel_list.get_text(self.sel_row_to_delete,0)
+ self.sel_list.remove(self.sel_row_to_delete)
+ self.sel_list.thaw()
+ self.src_list.append([text])
+ self.sel_row_to_delete = -1
+ self.band_list_to_classify.delete(self.get_band(text))
+#########################################################################
+ def update_gui(self,*args):
+ pass
+#########################################################################
+ def get_band(self,name):
+ layer = self.dict_of_bands[name][1]
+ b_num = self.dict_of_bands[name][2]
+ band = layer.get_parent().get_dataset().GetRasterBand(b_num+1)
+ return band
+#########################################################################
+ def classify_cb(self,*args):
+ if len(self.band_list_to_classify) < 2:
+ return
+ if self.metric_num == 0:
+ distance = L1
+ elif self.metric_num == 2:
+ distance = L3
+ else:
+ distance = L2
+ nClusters = int(self.clusters.get_text())
+ minvol = int(self.min_volume.get_text())
+ maxit = int(self.maxiter.get_text())
+ movement_treshold = float(self.mov_treshold.get_text())
+ nBands = len(self.band_list_to_classify)
+ cl_table = ClassesTable(nBands)
+ self.hide()
+
+ gview.app.new_view()
+
+ b1_name = self.sel_list.get_text(0,0)
+ band_list = self.band_list_to_classify
+ b1 = self.get_band(b1_name)
+ proto_ds = self.dict_of_bands[b1_name][1].get_parent().get_dataset()
+ self.out_buf = zeros((b1.YSize, b1.XSize),UnsignedInt8)
+
+
+ sb = range(len(band_list))
+ cp = zeros(nBands)
+ d_means = zeros(nClusters,Float)
+ volumes = range(nClusters)
+
+ centres = []
+ disp = []
+ maxVal = 256.
+ ymax = b1.YSize / 20
+ ys = 20
+ max_percent_val = 11 * maxit * b1.YSize / 40
+ cur_percent_val = 0
+ for i in range(nClusters):
+ centres.append(((ones(nBands,Float)*i)*maxVal)/nClusters)
+ disp.append(zeros(nBands,Float))
+ for kit in range(maxit):
+ centres_s = []
+ for i in range(len(centres)):
+ volumes[i] = 0
+ centres_s.append(zeros(nBands,Float))
+ flag = 0
+ nc = len(centres)
+ if kit >= maxit/2:
+ ymax = b1.YSize
+ ys = 1
+ for yc in range(ymax):
+ y = yc * ys
+ for i in range(nBands):
+ sb[i] = gdalnumeric.BandReadAsArray(band_list[i],0,y,b1.XSize,1)[0]
+
+ rb = self.out_buf[y,0:]
+ for x in range(b1.XSize):
+ for i in range(nBands):
+ cp[i] = sb[i][x]
+ mind = 1e29
+ for i in range(nc):
+ d = distance(centres[i],cp)
+ if d < mind:
+ mind = d
+ ic = i
+ if rb[x] != ic:
+ rb[x] = ic
+ flag = 1
+ centres_s[ic] += cp
+ disp[ic] += cp * cp
+ volumes[ic] += 1
+ if (distance == L2):
+ d_means[ic] += sqrt(mind)
+ else:
+ d_means[ic] += mind
+ self.out_buf[y, 0:] = rb
+ if y%2 == 0:
+ cur_percent_val += 1
+ cl_table.show_progress(100.*cur_percent_val/max_percent_val,y)
+ ##########################################################
+ new_centres = []
+ d_tresh = sum(d_means)/sum(volumes)
+ for i in range(len(centres)):
+ cur_vol = volumes[i]
+ if cur_vol > minvol/ys:
+ cur_centre = centres_s[i]/cur_vol
+ disp[i] = disp[i] / cur_vol - cur_centre * cur_centre
+ disp[i] = sqrt(disp[i])
+ d_means[i] /= cur_vol
+ if len(centres) < nClusters and cur_vol > 2 * minvol/ys and d_means[i] > d_tresh:
+ new_centres.append(cur_centre-disp[i])
+ new_centres.append(cur_centre+disp[i])
+ else:
+ new_centres.append(cur_centre)
+
+ ncl = len(new_centres)
+ if ncl > nClusters:
+ mind = 1e29
+ for i in range(ncl):
+ for j in range(i):
+ d = distance(new_centres[i],new_centres[j])
+ if d < mind:
+ mind = d
+ i1 = i
+ i2 = j
+ new_centres[i1] += new_centres[i2]
+ new_centres[i1] /= 2
+ new_centres.remove(new_centres[i2])
+
+ cl_table.set_data(new_centres,kit)
+
+ if cl_table.stop_pressed():
+ if ys > 1:
+ ymax = b1.YSize
+ ys = 1
+ else:
+ break #stop_pressed
+
+ if len(centres) == len(new_centres):
+ movement_flag = 0
+ for i in range(len(centres)):
+ d = distance(centres[i],new_centres[i])
+ d /= d_tresh
+ if d > movement_treshold:
+ movement_flag = 1
+
+ if movement_flag == 0:
+ if ys > 1:
+ ymax = b1.YSize
+ ys = 1
+ else:
+ break # centres movement less then treshold
+
+ centres = new_centres
+ disp = []
+ for i in range(len(centres)):
+ disp.append(zeros(nBands,Float))
+ volumes = zeros(len(centres))
+ d_means = zeros(len(centres))
+
+
+ if flag == 0:
+ if ys > 1:
+ ymax = b1.YSize
+ ys = 1
+ else:
+ break #no changed points
+
+ cl_table.finish()
+ res_ds = gdalnumeric.OpenArray(self.out_buf,proto_ds)
+ gview.app.open_gdal_dataset(res_ds)
+ self.close()
+
+TOOL_LIST = ['IsodataTool']
+
Added: packages/openev/branches/upstream/current/tools/mil_symbols.py
===================================================================
--- packages/openev/branches/upstream/current/tools/mil_symbols.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/mil_symbols.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,566 @@
+###############################################################################
+# $Id: mil_symbols.py,v 1.5 2005/02/14 15:30:33 zjamesatdm Exp $
+#
+# Purpose: test page for military symbols
+# Author: Paul Spencer (pgs at magma.ca)
+#
+###############################################################################
+# Copyright (c) 2003, Paul Spencer (pgs at magma.ca)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: mil_symbols.py,v $
+# Revision 1.5 2005/02/14 15:30:33 zjamesatdm
+# removed project comment
+#
+# Revision 1.4 2003/05/16 17:44:07 warmerda
+# symbol_offset now the same as tf_offset.
+#
+# Revision 1.3 2003/05/16 11:42:33 pgs
+# cleaned up code
+#
+# Revision 1.2 2003/05/15 21:08:13 pgs
+# added some task force indicators
+#
+# Revision 1.1 2003/05/15 18:50:58 pgs
+# new file
+#
+#
+
+from gtk import *
+
+import gview
+import string
+import gvutils
+import GtkExtra
+import os
+import gviewapp
+
+class MilitarySymbolTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = RenderTest()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Military Symbols",2,
+ self.launch_dialog)
+
+class RenderTest(GtkWindow):
+
+ def __init__(self,app=None):
+ GtkWindow.__init__(self)
+
+ self.set_title('Military Symbols')
+
+ self.view = gview.app.sel_manager.get_active_view()
+
+ self.text_contents = ''
+ self.selected_shape = None
+ self.layer = None
+ self.create_gui()
+
+ self.step_list = [ self.startup,
+ self.size_symbols ]
+ self.step = 0
+ self.cleanup_func = None
+
+ def show(self):
+ GtkWindow.show_all(self)
+ self.show_step()
+
+ def close(self, *args):
+ self.hide()
+ self.visibility_flag = 0
+ return TRUE
+
+ def create_gui(self):
+ box1 = GtkVBox()
+ self.add(box1)
+ box1.show()
+
+ text = GtkText()
+ text.set_usize(400,150)
+ text.set_line_wrap(FALSE)
+ text.set_word_wrap(FALSE)
+ text.set_editable(FALSE)
+ text.show()
+ self.text = text
+ box1.pack_start(text, expand=TRUE)
+
+ box2 = GtkHBox()
+ box1.pack_start(box2, expand=FALSE)
+ box2.show()
+
+ self.prev_btn = GtkButton("<--- Previous")
+ self.prev_btn.connect("clicked", self.prev_cb)
+ box2.pack_start(self.prev_btn)
+
+ self.next_btn = GtkButton("Next --->")
+ self.next_btn.connect("clicked", self.next_cb)
+ box2.pack_start(self.next_btn)
+
+ def next_cb( self, *args ):
+ if self.step < len(self.step_list)-1:
+ self.step = self.step + 1
+ self.show_step()
+
+ def prev_cb( self, *args ):
+ if self.step > 0:
+ self.step = self.step - 1
+ self.show_step()
+
+ def show_step( self ):
+ self.cleanup()
+
+ func = self.step_list[self.step]
+ func()
+
+ def cleanup( self ):
+ if self.cleanup_func is not None:
+ self.cleanup_func()
+
+ layer_list = self.view.list_layers()
+ for layer in layer_list:
+ self.view.remove_layer( layer )
+
+ def set_step_name( self, text ):
+ self.set_title( '%d: %s' % (self.step, text) )
+
+ def set_text( self, text ):
+
+ self.text.freeze()
+ self.text.delete_text(0,-1)
+ self.text.insert_defaults( text )
+ self.text.thaw()
+
+###############################################################################
+# Initial test screen.
+
+ def startup( self ):
+ self.set_step_name( 'Military Symbols Introduction' )
+ self.set_text( 'Welcome to the military symbols rendering tool.' )
+
+
+###############################################################################
+# Vector symbols (GvShapes via symbolmanager requested via ogrfs).
+
+ def size_symbols( self ):
+ self.set_step_name( 'Military Size Symbols' )
+ self.set_text( \
+ 'Here you will see each of the size designators for various sizes\n'
+ + 'of military symbols\n' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ sm = gview.GvSymbolManager()
+
+ #symbol_size * base_size * 2 define the size of the symbol on screen.
+ base_size = 1.0
+ symbol_size = 3.0
+
+ #the number of pixels wide to make the task force indicator
+ tf_offset = ( symbol_size * base_size * 2 ) + 2
+ symbol_offset = tf_offset
+
+ #create the circle symbol as a multiline with n points
+ import math
+ circle = gview.GvShape( type=gview.GVSHAPE_LINE )
+ filled_circle = gview.GvShape( type=gview.GVSHAPE_AREA )
+ n = 8
+ radius = base_size
+ for i in range( n + 1 ):
+ angle = (float(i)*(360.0/float(n))) / (180.0/math.pi)
+ x = math.sin( angle ) * radius
+ y = math.cos( angle ) * radius
+ circle.add_node( x, y, 0.0 )
+ filled_circle.add_node( x, y, 0.0 )
+ circle.set_property( "_gv_ogrfs", "PEN(w:1)" )
+ filled_circle.set_property( "_gv_ogrfs", "PEN(w:1);BRUSH()" )
+ sm.inject_vector_symbol( "%scircle" % os.sep, circle )
+ sm.inject_vector_symbol( "%sfilled_circle" % os.sep, filled_circle)
+
+ #create a vertical bar symbol
+ shape = gview.GvShape(type=gview.GVSHAPE_LINE )
+ shape.add_node( 0.0, -base_size, 0.0 )
+ shape.add_node( 0.0, base_size, 0.0 )
+ shape.set_property( "_gv_ogrfs", "PEN(w:1)" )
+ sm.inject_vector_symbol( "%svertical_bar" % os.sep, shape )
+
+ #now create a cross from rotated vertical bars
+ shape = gview.GvShape(type=gview.GVSHAPE_LINE )
+ shape.add_node( -base_size, -base_size, 0.0 )
+ shape.add_node( base_size, base_size, 0.0 )
+ shape.set_property( "_gv_ogrfs", "PEN(w:1)" )
+ sm.inject_vector_symbol( "%sline_45" % os.sep, shape )
+
+ shape = gview.GvShape(type=gview.GVSHAPE_LINE )
+ shape.add_node( -base_size, base_size, 0.0 )
+ shape.add_node( base_size, -base_size, 0.0 )
+ shape.set_property( "_gv_ogrfs", "PEN(w:1)" )
+ sm.inject_vector_symbol( "%sline_315" % os.sep, shape )
+
+ shape = gview.GvShape(type=gview.GVSHAPE_POINT )
+ shape.add_node( 0.0, 0.0, 0.0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(id:%sline_45);SYMBOL(id:%sline_315)" % ( os.sep, os.sep ) )
+ sm.inject_vector_symbol( "%scross" % os.sep, shape )
+
+ #taskforce 1
+ shape = self.create_taskforce_indicator( 1, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_1" % os.sep, shape )
+
+ #taskforce 2
+ shape = self.create_taskforce_indicator( 2, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_2" % os.sep, shape )
+
+ #taskforce 3
+ shape = self.create_taskforce_indicator( 3, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_3" % os.sep, shape )
+
+ #taskforce 4
+ shape = self.create_taskforce_indicator( 4, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_4" % os.sep, shape )
+
+ #taskforce 5
+ shape = self.create_taskforce_indicator( 5, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_5" % os.sep, shape )
+
+ #taskforce 6
+ shape = self.create_taskforce_indicator( 6, symbol_size * base_size, tf_offset )
+ sm.inject_vector_symbol( "%stf_6" % os.sep, shape )
+
+
+ #team symbol
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 0.0, 0.0, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(id:%scircle,s:%s);SYMBOL(id:%sline_45,s:%s)" % (os.sep, symbol_size, os.sep, symbol_size) )
+ sm.inject_vector_symbol( "%steam" % os.sep, shape )
+
+ #squad symbol
+ shape = self.create_size_indicator( "filled_circle", 1, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%ssquad" % os.sep, shape )
+
+ #section symbol
+ shape = self.create_size_indicator( "filled_circle", 2, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%ssection" % os.sep, shape )
+
+ #platoon symbol
+ shape = self.create_size_indicator( "filled_circle", 3, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%splatoon" % os.sep, shape )
+
+ #company symbol
+ shape = self.create_size_indicator( "vertical_bar", 1, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%scompany" % os.sep, shape )
+
+ #battalion symbol
+ shape = self.create_size_indicator( "vertical_bar", 2, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sbattalion" % os.sep, shape )
+
+ #regiment symbol
+ shape = self.create_size_indicator( "vertical_bar", 3, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sregiment" % os.sep, shape )
+
+ #brigade symbol
+ shape = self.create_size_indicator( "cross", 1, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sbrigade" % os.sep, shape )
+
+ #division symbol
+ shape = self.create_size_indicator( "cross", 2, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sdivision" % os.sep, shape )
+
+ print 'Division:' + shape.get_property('_gv_ogrfs')
+
+ #corps symbol
+ shape = self.create_size_indicator( "cross", 3, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%scorps" % os.sep, shape )
+
+ #army symbol
+ shape = self.create_size_indicator( "cross", 4, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sarmy" % os.sep, shape )
+
+ #armygroup symbol
+ shape = self.create_size_indicator( "cross", 5, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sarmygroup" % os.sep, shape )
+
+ #region symbol
+ shape = self.create_size_indicator( "cross", 6, symbol_size, symbol_offset )
+ sm.inject_vector_symbol( "%sregion" % os.sep, shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 10, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"team\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 10, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%steam)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 10, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%steam);SYMBOL(c:#00FFFF,id:%stf_1" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 15, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"squad\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 15, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%ssquad)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 15, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%ssquad);SYMBOL(c:#00FFFF,id:%stf_1" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 20, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"section\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 20, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%ssection)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 20, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%ssection);SYMBOL(c:#00FFFF,id:%stf_2" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 25, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"platoon\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 25, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%splatoon)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 25, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%splatoon);SYMBOL(c:#00FFFF,id:%stf_3" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 30, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"company\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 30, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%scompany)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 30, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%scompany);SYMBOL(c:#00FFFF,id:%stf_1" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 35, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"battalion\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 35, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sbattalion)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 35, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sbattalion);SYMBOL(c:#00FFFF,id:%stf_2" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 40, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"regiment\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 40, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sregiment)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 40, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sregiment);SYMBOL(c:#00FFFF,id:%stf_3" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 45, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"brigade\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 45, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sbrigade)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 45, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sbrigade);SYMBOL(c:#00FFFF,id:%stf_1" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 50, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"division\")")
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 50, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sdivision)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sdivision);SYMBOL(c:#00FFFF,id:%stf_2" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 55, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"corps\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 55, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%scorps)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 55, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%scorps);SYMBOL(c:#00FFFF,id:%stf_3" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 60, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"army\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 60, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sarmy)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 60, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sarmy);SYMBOL(c:#00FFFF,id:%stf_4" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 65, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"armygroup\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 65, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sarmygroup)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 65, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sarmygroup);SYMBOL(c:#00FFFF,id:%stf_5" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 10, 70, node=0 )
+ shape.set_property( "_gv_ogrfs", "LABEL(c:#00FFFF,t:\"region\")" )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 70, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sregion)" % os.sep )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 70, node=0 )
+ shape.set_property( "_gv_ogrfs", "SYMBOL(c:#00FFFF,id:%sregion);SYMBOL(c:#00FFFF,id:%stf_6" % (os.sep,os.sep) )
+ shapes.append( shape )
+
+ # Create the layer and display
+
+ #turn off display lists for now.
+ #gview.set_preference('display_lists', "OFF" )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ layer.set_property( "_gl_antialias", "1" )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+ def create_size_indicator( self, sym_name, repeat, size, offset ):
+ """
+ compose a size indicator based on some number (repeat) of symbols
+ (sym_name) drawn at scale (size). The symbols are drawn horizontally
+ spaced at (offset) pixels apart, centered at 0.
+ """
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 0.0, 0.0, node=0 )
+ ogrfs = ""
+ dx_val = -1 * (offset / 2) * (repeat - 1)
+ for i in range( repeat ):
+ dx = ""
+ if abs(dx_val) > 0.001:
+ dx = ",dx:%spx" % dx_val
+ sym = "SYMBOL(id:%s%s%s,s:%s)" % (os.sep, sym_name, dx, size)
+ if ogrfs != "":
+ ogrfs = ogrfs + ";"
+ ogrfs = ogrfs + sym
+ dx_val = dx_val + offset
+ shape.set_property( "_gv_ogrfs", ogrfs )
+
+ return shape
+
+ def create_taskforce_indicator( self, repeat, size, offset ):
+ """
+ create a taskforce indicator which is a rectangle with
+ no bottom that fits over a size indicator. Repeat is the
+ number of size indicator symbols to cover. Offset is
+ the number of pixels apart that they are. Size is the
+ vertical size of the symbol.
+ """
+
+ dx = ((offset/2.0) * (repeat)) + 2
+ dy = size + 2
+
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+
+ shape.add_node( -dx, -dy )
+ shape.add_node( -dx, dy )
+ shape.add_node( dx, dy )
+ shape.add_node( dx, -dy )
+
+ return shape
+
+
+
+
+
+
+TOOL_LIST = ['MilitarySymbolTool']
+
Added: packages/openev/branches/upstream/current/tools/open_raw.py
===================================================================
--- packages/openev/branches/upstream/current/tools/open_raw.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/open_raw.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,512 @@
+###############################################################################
+# $Id: open_raw.py,v 1.6 2004/09/01 15:47:19 gmwalter Exp $
+#
+# Project: OpenEV
+# Purpose: Interactive tool to open raw image files.
+# Author: Andrey Kiselev, dron at remotesensing.org
+#
+###############################################################################
+# Copyright (c) 2004, American Museum of Natural History. All rights reserved.
+# This software is based upon work supported by NASA under award
+# number NAG5-12333
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: open_raw.py,v $
+# Revision 1.6 2004/09/01 15:47:19 gmwalter
+# Fix default path settings.
+#
+# Revision 1.5 2004/08/31 20:52:10 gmwalter
+# Updated to use VRT.
+#
+# Revision 1.4 2004/03/25 16:16:04 andrey_kiselev
+# Fix swapped/unswapped misinterpreting.
+#
+# Revision 1.3 2004/03/21 16:20:59 andrey_kiselev
+# Added geometry guessing feature.
+#
+# Revision 1.2 2004/03/09 10:05:09 andrey_kiselev
+# Few fixes.
+#
+# Revision 1.1 2004/01/18 16:39:56 andrey_kiselev
+# New.
+#
+#
+
+
+# TO DO:
+#
+# 1) Allow output of more header types by adding a header-only
+# creation option for flat binary raster + header type images?
+#
+# 2) Add advanced option to window the input file: The current
+# implementation doesn't make full use of vrt flexibility- the
+# user is forced to load the whole image. The
+# LineOffset, PixelOffset, and ImageOffset parameters could
+# also be used to load a sub image rather than the whole thing.
+# The user would have to specify the existing parameters
+# (which describe the whole file) plus line/pixel offsets and
+# sizes for the subwindow.
+
+from gtk import *
+import GtkExtra
+
+from stat import *
+import os
+import os.path
+import sys
+import math
+import Numeric
+
+import gdal
+import gdalnumeric
+import gview
+import gviewapp
+import gvutils
+import string
+import vrtutils
+import pgufilesel
+
+class OpenRaw(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ self.wins = {}
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ win=OpenRawDialog(self.app)
+ win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("File/Open Raw",2,self.launch_dialog)
+
+class OpenRawDialog(GtkWindow):
+
+ def __init__(self,app=None):
+ self.wins = {}
+ GtkWindow.__init__(self)
+ self.set_title('Open Raw Image File')
+ self.create_gui()
+ self.show()
+ self.app=app
+
+ def show(self):
+ GtkWindow.show_all(self)
+
+ def close(self, *args):
+ self.destroy()
+
+ def create_gui(self):
+ box1 = GtkVBox(spacing = 10)
+ box1.set_border_width(10)
+ self.add(box1)
+ self.tips=GtkTooltips()
+ box1.show()
+
+ # File open controls
+ frame1 = GtkFrame('Select raw image file')
+ frame1.show()
+ box1.pack_start(frame1, expand=FALSE)
+ box2 = GtkHBox(spacing = 5)
+ box2.set_border_width(5)
+ box2.show()
+
+ open_btn = GtkButton('Open...')
+ open_btn.connect("clicked", self.open_cb)
+ box2.pack_start(open_btn)
+ self.open_entry = GtkEntry()
+ self.open_entry.set_editable(TRUE)
+ self.open_entry.set_text('')
+ box2.pack_start(self.open_entry)
+ frame1.add(box2)
+
+ # Image geometry controls
+ frame2 = GtkFrame('Set image geometry')
+ frame2.show()
+ box1.pack_start(frame2, expand=FALSE)
+ tbl = GtkTable(4, 5)
+ tbl.set_border_width(5)
+ tbl.set_row_spacings(5)
+ tbl.set_col_spacings(5)
+ tbl.show()
+
+ width_label = GtkLabel('Image width:')
+ width_label.set_alignment(0, 0.5)
+ tbl.attach(width_label, 0, 1, 0, 1)
+ self.width_entry = GtkEntry()
+ self.width_entry.set_text('0')
+ self.width_entry.set_editable(TRUE)
+ tbl.attach(self.width_entry, 1, 2, 0, 1)
+
+ height_label = GtkLabel('Image height:')
+ height_label.set_alignment(0, 0.5)
+ tbl.attach(height_label, 0, 1, 1, 2)
+ self.height_entry = GtkEntry()
+ self.height_entry.set_text('0')
+ self.height_entry.set_editable(TRUE)
+ tbl.attach(self.height_entry, 1, 2, 1, 2)
+
+ bands_label = GtkLabel('Number of bands:')
+ bands_label.set_alignment(0, 0.5)
+ tbl.attach(bands_label, 0, 1, 2, 3)
+ self.bands_entry = GtkEntry()
+ self.bands_entry.set_text('1')
+ self.bands_entry.set_editable(TRUE)
+ tbl.attach(self.bands_entry, 1, 2, 2, 3)
+
+ header_label = GtkLabel('Image header size:')
+ header_label.set_alignment(0, 0.5)
+ tbl.attach(header_label, 0, 1, 3, 4)
+ self.header_entry = GtkEntry()
+ self.header_entry.set_text('0')
+ self.header_entry.set_editable(TRUE)
+ tbl.attach(self.header_entry, 1, 2, 3, 4)
+
+ guess_btn = GtkButton("Guess image geometry")
+ guess_btn.connect("clicked", self.guess_cb)
+ tbl.attach(guess_btn, 0, 2, 4, 5)
+
+ size_label = GtkLabel('File size in bytes:')
+ size_label.set_alignment(0, 0.5)
+ tbl.attach(size_label, 2, 3, 0, 1)
+ self.bytes_label = GtkLabel('')
+ self.bytes_label.set_alignment(0, 0.5)
+ tbl.attach(self.bytes_label, 3, 4, 0, 1)
+
+ type_label = GtkLabel('Image data type:')
+ type_label.set_alignment(0, 0.5)
+ tbl.attach(type_label, 2, 3, 1, 2)
+ self.type_list = ['Byte', 'UInt16', 'Int16', 'UInt32','Int32',
+ 'Float32','Float64','CInt16','CInt32',
+ 'CFloat32','CFloat64']
+ self.type_menu = gvutils.GvOptionMenu(self.type_list)
+ tbl.attach(self.type_menu, 3, 4, 1, 2)
+
+ swap_label = GtkLabel('Byte Order:')
+ swap_label.set_alignment(0, 0.5)
+ tbl.attach(swap_label, 2, 3, 2, 3)
+ swap_list = ['LSB (Swapped)', 'MSB (Unswapped)']
+ self.swap_menu = gvutils.GvOptionMenu(swap_list)
+ tbl.attach(self.swap_menu, 3, 4, 2, 3)
+
+ interleave_label = GtkLabel('Type of interleaving:')
+ interleave_label.set_alignment(0, 0.5)
+ tbl.attach(interleave_label, 2, 3, 3, 4)
+ self.interleave_list = ['Pixel', 'Band', 'Line']
+ self.interleave_menu = gvutils.GvOptionMenu(self.interleave_list)
+ tbl.attach(self.interleave_menu, 3, 4, 3, 4)
+
+ frame2.add(tbl)
+
+ # Output header format. A possible route for future
+ # improvement would be adding a creation option to CreateCopy for the
+ # simple-flat-binary-raster-plus-header formats that specifies
+ # header-only output and avoids copying all the associated binary data.
+ # We might also want to add a GDAL_DMD-type metadata item to the driver
+ # so that the tool can pick up which formats support header-only output
+ # (sort of like the datatypes and creation options are currently set as
+ # metadata items in the drivers).
+
+ sbox = GtkHBox(spacing=10)
+ label=GtkLabel('Output Header Format:')
+ label.set_alignment(0,0.5)
+ label.show()
+ sbox.pack_start(label)
+
+ self.format_list = ['VRT','PAux']
+ self.format_menu = gvutils.GvOptionMenu(self.format_list)
+ self.format_menu.show()
+ sbox.pack_start(self.format_menu)
+ box1.pack_start(sbox)
+ sbox.show()
+
+ # Ok/Cancel buttons
+ separator = GtkHSeparator()
+ box1.pack_start(separator, expand=FALSE)
+
+ box3 = GtkHBox(spacing=10)
+ box1.pack_start(box3, expand=FALSE)
+
+ current_btn = GtkButton("Current View")
+ current_btn.connect("clicked", self.import_cb,'Current')
+ box3.pack_start(current_btn)
+
+ new_btn = GtkButton("New View")
+ new_btn.connect("clicked", self.import_cb,'New')
+ box3.pack_start(new_btn)
+
+ save_btn = GtkButton("Save")
+ save_btn.connect("clicked", self.import_cb,'Save')
+ box3.pack_start(save_btn)
+
+ close_btn = GtkButton("Close")
+ close_btn.connect("clicked", self.close)
+ box3.pack_start(close_btn)
+
+ self.tips.set_tip(close_btn,
+ 'Exit the Open Raw tool')
+ self.tips.set_tip(save_btn,
+ 'Create dataset and save header in selected format')
+ self.tips.set_tip(new_btn,
+ 'Create dataset and display in a new view')
+ self.tips.set_tip(current_btn,
+ 'Create dataset and display in current view')
+ box3.show()
+
+ def open_cb(self, *args):
+ if gview.get_preference('save_recent_directory') == 'on':
+ recent_dir = gview.get_preference('recent_directory')
+ else:
+ recent_dir = None
+
+ filename=pgufilesel.GetFileName(title="Open raw image file",
+ default_filename=recent_dir)
+ if filename is None:
+ return
+ self.open_entry.set_text(filename)
+ self.bytes_label.set_text(str(os.stat(filename)[ST_SIZE]))
+
+ def import_cb(self, *args):
+ # Check if the parameters valid
+ filename = self.open_entry.get_text()
+ if filename is '':
+ gvutils.error('You should select a raw file to load!')
+ return
+
+ if not os.path.isfile(filename):
+ gvutils.error('Unable to load '+ filename)
+ return
+
+ if args[1] == 'Save':
+ self.create_header(filename)
+ else:
+ lines=self.create_vrt_lines(filename)
+ vrtds=gdal.OpenShared(lines)
+ if args[1] == 'New':
+ self.app.new_view()
+ self.app.open_gdal_dataset(vrtds)
+
+ def create_vrt_lines(self,filename):
+ image_offset = long(self.header_entry.get_text())
+ width = long(self.width_entry.get_text())
+ height = long(self.height_entry.get_text())
+ bands = long(self.bands_entry.get_text())
+ interleaving = self.interleave_list[self.interleave_menu.get_history()]
+ dtype = self.type_list[self.type_menu.get_history()]
+ gdaltype = gdal.GetDataTypeByName(dtype)
+ datasize = gdal.GetDataTypeSize(gdaltype) / 8
+ byteorder = ['LSB','MSB'][self.swap_menu.get_history()]
+
+ vrtdsc = vrtutils.VRTDatasetConstructor(width,height)
+
+ if interleaving == 'Pixel':
+ pixoff = datasize*bands
+ lineoff = pixoff*width
+ for idx in range(bands):
+ imoff = image_offset + idx*datasize
+ vrtdsc.AddRawBand(filename, dtype, byteorder,
+ imoff, pixoff, lineoff)
+
+ elif interleaving == 'Line':
+ pixoff=datasize
+ lineoff=datasize*width*bands
+ for idx in range(bands):
+ imoff = image_offset + idx*lineoff
+ vrtdsc.AddRawBand(filename, dtype, byteorder,
+ imoff, pixoff, lineoff)
+
+ else:
+ pixoff=datasize
+ lineoff=datasize*width
+ for idx in range(bands):
+ imoff = image_offset + datasize*width*height*idx
+ vrtdsc.AddRawBand(filename, dtype, byteorder,
+ imoff, pixoff, lineoff)
+
+ return vrtdsc.GetVRTLines()
+
+
+ def create_header(self,filename):
+ fmt=self.format_list[self.format_menu.get_history()]
+ dtype=self.type_list[self.type_menu.get_history()]
+ dr=gdal.GetDriverByName(fmt)
+ tlist=string.split(dr.GetMetadata()["DMD_CREATIONDATATYPES"])
+ if dtype not in tlist:
+ gvutils.error(fmt+' format does not support '+dtype+' data type!')
+ return
+
+ if fmt == 'PAux':
+ self.create_paux_header(filename,dtype)
+ else:
+ fname,ext = os.path.splitext(filename)
+ vrtname = fname+'.vrt'
+
+ fname=pgufilesel.GetFileName(title="Select VRT Save Name",
+ default_filename=vrtname)
+ if fname is None:
+ return
+ if os.path.exists(fname):
+ resp = GtkExtra.message_box('Confirmation', \
+ fname + ' exists. Overwrite?', ('Yes','No'))
+ if resp == 'No':
+ return
+ lines=self.create_vrt_lines(filename)
+ fh=open(fname,'w')
+ fh.writelines(lines)
+ fh.close()
+
+ def create_paux_header(self,filename,datatype):
+ (path, ext) = os.path.splitext(filename)
+ auxname = path + ".aux"
+ if os.path.isfile(auxname):
+ resp = GtkExtra.message_box('Confirmation', \
+ auxname + ' exists. Overwrite?', ('Yes','No'))
+ if resp == 'No':
+ return
+
+ # Take the image parameters
+ header = long(self.header_entry.get_text())
+ width = long(self.width_entry.get_text())
+ height = long(self.height_entry.get_text())
+ bands = long(self.bands_entry.get_text())
+ aux_type_dict={'Byte':'8U','Int16':'16S','UInt16':'16U',
+ 'Float32':'32R'}
+ aux_type_list = ['8U', '16S', '16U', '32R']
+ type = aux_type_dict[datatype]
+ gdaltype = gdal.GetDataTypeByName(datatype)
+ interleaving = self.interleave_list[self.interleave_menu.get_history()]
+ datasize = gdal.GetDataTypeSize(gdaltype) / 8
+
+ # Calculate offsets
+ pixel_offset = []
+ line_offset = []
+ image_offset = []
+ if interleaving is 'Pixel':
+ for i in range(bands):
+ pixel_offset.append(datasize * bands)
+ line_offset.append(datasize * width * bands)
+ image_offset.append(header + datasize * i)
+ elif interleaving is 'Band':
+ for i in range(bands):
+ pixel_offset.append(datasize)
+ line_offset.append(datasize * width)
+ image_offset.append(header + datasize * width * height * i)
+ elif interleaving is 'Line':
+ for i in range(bands):
+ pixel_offset.append(datasize)
+ line_offset.append(datasize * width * bands)
+ image_offset.append(header + datasize * width * i)
+ else:
+ raise 'Unsupported interleaving type!'
+
+ aux_swap_list = ['Swapped', 'Unswapped']
+ swap = aux_swap_list[self.swap_menu.get_history()]
+
+ # Write out the auxilary file
+ aux = open(auxname, "wt")
+ aux.write("AuxilaryTarget: " + os.path.basename(filename) + '\n')
+ aux.write("RawDefinition: " + str(width) + ' ' \
+ + str(height) + ' ' + str(bands) + '\n')
+ for i in range(bands):
+ aux.write("ChanDefinition-" + str(i + 1) + ': ' + type + ' ' \
+ + str(image_offset[i]) + ' ' + str(pixel_offset[i]) \
+ + ' ' + str(line_offset[i]) + ' ' + swap + '\n')
+ aux.close()
+ aux = None
+
+ def guess_cb(self, *args):
+ """Guess image geometry parameters."""
+
+ def correlation(array1, array2):
+ """Calculate correlation coefficient of two arrays."""
+ n_elems = float(array1.shape[0])
+ M1 = Numeric.add.reduce(array1)
+ M2 = Numeric.add.reduce(array2)
+ D1 = Numeric.add.reduce(array1 * array1) - M1 * M1 / n_elems
+ D2 = Numeric.add.reduce(array2 * array2) - M2 * M2 / n_elems
+ K = (Numeric.add.reduce(array1 * array2) - M1 * M2 / n_elems) / math.sqrt(D1 * D2)
+
+ return K
+
+ header = long(self.header_entry.get_text())
+ width = long(self.width_entry.get_text())
+ height = long(self.height_entry.get_text())
+ bands = long(self.bands_entry.get_text())
+ gdaltype = \
+ gdal.GetDataTypeByName(self.type_list[self.type_menu.get_history()])
+ numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(gdaltype)
+ depth = gdal.GetDataTypeSize(gdaltype) / 8
+
+ filename = self.open_entry.get_text()
+ if os.path.isfile(filename) == 0:
+ gvutils.error('Input file '+filename+' does not exist!')
+ return
+
+ filesize = os.stat(filename)[ST_SIZE]
+ if filesize < header:
+ gvutils.error('Specified header size larger then file size!')
+ return
+ imagesize = (filesize - header) / bands / depth
+
+ if width != 0 and height == 0:
+ height = imagesize / width
+ elif width == 0 and height != 0:
+ width = imagesize / height
+ else:
+ rawfile = open(filename, 'rb')
+ longt = 40.0 # maximum possible height/width ratio
+ cor_coef = 0.0
+ w = long(math.sqrt(imagesize / longt))
+ w_max = long(math.sqrt(imagesize * longt))
+ if (self.swap_menu.get_history() == 0 \
+ and sys.byteorder == 'little') or \
+ (self.swap_menu.get_history() == 1 and sys.byteorder == 'big'):
+ swap = 0
+ else:
+ swap = 1
+ while w < w_max:
+ if imagesize % w == 0:
+ scanlinesize = w * depth
+ h = imagesize / w
+ rawfile.seek(header + h / 2 * scanlinesize)
+ buf1 = rawfile.read(scanlinesize)
+ buf2 = rawfile.read(scanlinesize)
+ a1 = Numeric.fromstring(buf1, numtype)
+ a2 = Numeric.fromstring(buf2, numtype)
+ if swap:
+ a1.byteswapped()
+ a2.byteswapped()
+
+ try:
+ tmp = correlation(a1.astype(Numeric.Float32), a2.astype(Numeric.Float32))
+ except:
+ # catch 0 division errors
+ gvutils.error('Unable to guess image geometry!')
+ return
+
+ if tmp > cor_coef:
+ cor_coef = tmp
+ width = w
+ height = h
+ w += 1
+
+ self.width_entry.set_text(str(width))
+ self.height_entry.set_text(str(height))
+
+TOOL_LIST = ['OpenRaw']
+
Added: packages/openev/branches/upstream/current/tools/open_subarea.py
===================================================================
--- packages/openev/branches/upstream/current/tools/open_subarea.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/open_subarea.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,339 @@
+##############################################################################
+# $Id: open_subarea.py,v 1.3 2004/10/23 11:03:40 andrey_kiselev Exp $
+#
+# Project: OpenEV
+# Purpose: Interactive tool to perform calculations on pair of images.
+# Authors: Iscander Latypov
+# Andrey Kiselev, dron at remotesensing.org
+#
+###############################################################################
+# Copyright (c) 2004, American Museum of Natural History. All rights reserved.
+# This software is based upon work supported by NASA under award
+# number NAG5-12333
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: open_subarea.py,v $
+# Revision 1.3 2004/10/23 11:03:40 andrey_kiselev
+# Updated to reflect changes in pgugrid.
+#
+# Revision 1.2 2004/07/04 09:21:30 andrey_kiselev
+# Added ability to select individual bands.
+#
+# Revision 1.1 2004/05/18 19:17:54 andrey_kiselev
+# New.
+#
+
+from gtk import *
+import gview, gdal, gdalconst, gvutils
+import gviewapp
+import vrtutils
+import pgugrid
+import osr
+
+def CoordFrame(name,f_names,visible):
+ frame = GtkFrame(name)
+ table = GtkTable(2,4,FALSE)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+ frame.add(table)
+ table.show()
+ list_entries = []
+ k = 0
+ for i in range(2):
+ for j in range(2):
+ label = GtkLabel(f_names[k])
+ label.set_alignment(0, 0.5)
+ table.attach(label,2*j,2*j+1,i,i+1)
+ label.show()
+ entry = GtkEntry()
+ list_entries.append(entry)
+ entry.show()
+ table.attach(entry,2*j+1,2*j+2,i,i+1)
+ k = k + 1
+
+ return [frame, list_entries, visible]
+
+def SetInitialCoord(dict_item, coords_list):
+ """This routine sets initial values of out image
+ to coordinates of input image corners"""
+ for i in range(4):
+ dict_item[1][i].set_text(str(coords_list[i]))
+
+def PixelCoordToGeocoord(x,y,geotransform):
+ px = geotransform[0]
+ py = geotransform[3]
+ px += geotransform[1] * x + geotransform[2] * y
+ py += geotransform[4] * x + geotransform[5] * y
+ return (px, py)
+
+def GeocoordToPixelCoord(px,py,geotransform):
+ s = px - geotransform[0]
+ t = py - geotransform[3]
+ det = geotransform[1] * geotransform[5] - geotransform[2] * geotransform[4]
+ x = (s * geotransform[5] - geotransform[2] * t) / det
+ y = (t * geotransform[1] - geotransform[4] * s) / det
+ return (x, y)
+
+def GetProjRect(pixcoords,geotransform):
+ (ulx,uly) = PixelCoordToGeocoord(pixcoords[1],pixcoords[0],geotransform)
+ (lrx,lry) = PixelCoordToGeocoord(pixcoords[3],pixcoords[2],geotransform)
+ return (uly, ulx, lry, lrx)
+
+def GeocoordToLatLong(gx,gy,raster):
+ """Build Spatial Reference object based on coordinate system,
+ fecthed from the opened dataset"""
+ srs = osr.SpatialReference()
+ srs.ImportFromWkt(raster.GetProjection())
+ srsLatLong = srs.CloneGeogCS()
+ ct = osr.CoordinateTransformation(srs, srsLatLong)
+ (lat, long, height) = ct.TransformPoint(gx, gy)
+ return (lat, long)
+
+def LatLongToGeocoord(lat,long,raster):
+ """Build Spatial Reference object based on coordinate system,
+ fecthed from the opened dataset"""
+ srs = osr.SpatialReference()
+ srs.ImportFromWkt(raster.GetProjection())
+ srsLatLong = srs.CloneGeogCS()
+ ct = osr.CoordinateTransformation(srsLatLong,srs)
+ (gx, gy, height) = ct.TransformPoint(lat, long)
+ return (gx, gy)
+
+def GetGeogrRect(raster,geocoord):
+ (ul_lat, ul_long) = GeocoordToLatLong(geocoord[1],geocoord[0],raster)
+ (br_lat, br_long) = GeocoordToLatLong(geocoord[3],geocoord[2],raster)
+ return (ul_lat,br_lat,ul_long,br_long)
+
+def ProjRectToPixelRect(proj_rect,geotransform):
+ (lx,ty) = GeocoordToPixelCoord(proj_rect[0],proj_rect[1],geotransform)
+ (rx,by) = GeocoordToPixelCoord(proj_rect[2],proj_rect[3],geotransform)
+ return (ty, lx, by-ty, rx-lx)
+
+def EmptyGeotransform(gt):
+ if gt[0] != 0 or gt[1] != 1 or gt[2] != 0:
+ return FALSE
+ if gt[3] != 0 or gt[4] != 0 or gt[5] != 1:
+ return FALSE;
+ return TRUE
+
+class OpenSubArea(gviewapp.Tool_GViewApp):
+ def __init__(self, app = None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("File/Open Subarea...",4,self.launch_dialog)
+
+ def file_selection_ok(self,*args):
+ self.source_name = self.o_s_d.get_filename()
+ self.o_s_d.hide()
+
+ rast = gdal.OpenShared(self.source_name, gdalconst.GA_ReadOnly)
+ self.input_rast = rast
+
+ self.pixsubarea = [0,0,rast.RasterYSize,rast.RasterXSize]
+ SetInitialCoord(self.frame_dict['pixcoord'],self.pixsubarea)
+
+ self.geotransform = rast.GetGeoTransform()
+
+ if EmptyGeotransform(self.geotransform):
+ self.coord_system.set_history(0)
+ self.update_gui()
+ self.coord_system.hide()
+ else:
+ self.projsubarea = GetProjRect(self.pixsubarea,self.geotransform)
+ SetInitialCoord(self.frame_dict['geocoord'],self.projsubarea)
+
+ self.geogsubarea = GetGeogrRect(rast,self.projsubarea)
+ SetInitialCoord(self.frame_dict['geodetic'],self.geogsubarea)
+
+ self.band_list = []
+ for i in range(rast.RasterCount):
+ item = ["Band " + str(i), "Yes"]
+ self.band_list.append(item)
+ if len(self.band_list) > 1:
+ self.band_grid.set_source(self.band_list,expose=0)
+ grid_titles = ['Band number', 'Load']
+ self.band_grid.define_columns(titles=grid_titles,editables=[0,1])
+ self.band_grid.resize_to_default()
+ for i in range(len(self.band_list)):
+ self.band_num_list.append(i+1)
+ self.band_grid.show_all()
+ else:
+ self.band_grid.hide()
+ self.dialog.show()
+
+ def launch_dialog(self,*args):
+ self.band_num_list = []
+ self.init_dialog()
+ self.o_s_d = GtkFileSelection("Source File Open")
+ self.o_s_d.ok_button.connect("clicked",self.file_selection_ok)
+ self.o_s_d.cancel_button.connect("clicked",self.o_s_d.hide)
+ self.o_s_d.show()
+
+ def open_subarea_cb(self,*args):
+
+ self.vrt_options = vrtutils.VRTCreationOptions(len(self.band_list))
+
+ if self.geocoding == 1:
+ # get data from pixel-frame and transform lat/long
+ # to proj and to pixels
+ g_east = float(self.frame_dict['geodetic'][1][0].get_text())
+ g_west = float(self.frame_dict['geodetic'][1][1].get_text())
+ g_north = float(self.frame_dict['geodetic'][1][2].get_text())
+ g_south = float(self.frame_dict['geodetic'][1][3].get_text())
+ (east,north) = LatLongToGeocoord(g_east,g_north,self.input_rast)
+ (west,south) = LatLongToGeocoord(g_west,g_south,self.input_rast)
+ proj_rect = (east,north,west,south)
+ (sline,spix,nlines,npix) = \
+ ProjRectToPixelRect(proj_rect, self.geotransform)
+ elif self.geocoding == 2:
+ # get data from pixel-frame and translate proj to pixels
+ east = float(self.frame_dict['geocoord'][1][1].get_text())
+ west = float(self.frame_dict['geocoord'][1][3].get_text())
+ north = float(self.frame_dict['geocoord'][1][0].get_text())
+ south = float(self.frame_dict['geocoord'][1][2].get_text())
+ proj_rect = (east,north,west,south)
+ (sline,spix,nlines,npix) = \
+ ProjRectToPixelRect(proj_rect,self.geotransform)
+ else:
+ # get data from pixel-frame
+ spix = int(self.frame_dict['pixcoord'][1][1].get_text())
+ sline = int(self.frame_dict['pixcoord'][1][0].get_text())
+ npix = int(self.frame_dict['pixcoord'][1][3].get_text())
+ nlines = int(self.frame_dict['pixcoord'][1][2].get_text())
+
+ if spix < 0:
+ spix = 0
+ elif spix > self.pixsubarea[3]:
+ gvutils.error("Source Area does not cover required Rectangle")
+ return
+ if sline < 0:
+ sline = 0
+ elif sline > self.pixsubarea[2]:
+ gvutils.error("Source Area does not cover required Rectangle")
+ return
+ if spix + npix > self.pixsubarea[3]:
+ npix = self.pixsubarea[3] - spix
+ if sline + nlines > self.pixsubarea[2]:
+ nlines = self.pixsubarea[2] - sline
+
+ self.vrt_options.set_src_window((spix,sline,npix,nlines),self.band_num_list)
+ self.vrt_options.set_dst_window((0,0,npix,nlines))
+
+ vrt_tree=vrtutils.serializeDataset(self.input_rast,self.vrt_options,self.band_num_list)
+ vrt_lines=gdal.SerializeXMLTree(vrt_tree)
+ vrtdataset=gdal.Open(vrt_lines)
+ gview.app.open_gdal_dataset(vrtdataset)
+ self.close()
+
+ def update_gui(self,*args):
+ for item in self.frame_dict.keys():
+ self.frame_dict[item][2] = FALSE
+ self.frame_dict[item][0].hide()
+ self.geocoding = self.coord_system.get_history()
+ if self.geocoding == 0:
+ self.frame_dict['pixcoord'][2] = TRUE
+ elif self.geocoding == 1:
+ self.frame_dict['geodetic'][2] = TRUE
+ else:
+ self.frame_dict['geocoord'][2] = TRUE
+
+ for item in self.frame_dict.keys():
+ if self.frame_dict[item][2]:
+ self.frame_dict[item][0].show()
+
+ def init_dialog(self):
+ self.dialog = GtkWindow()
+ self.dialog.set_title('Open Subarea')
+ self.dialog.set_border_width(10)
+
+ mainshell = GtkVBox(spacing=5)
+ self.dialog.add(mainshell)
+ mainshell.show()
+
+ self.geocoding = 0
+ coord_system_list = ["Pixels", "Geodetic (Lat/Long)", "Georeferenced"]
+ self.coord_system = \
+ gvutils.GvOptionMenu(coord_system_list,self.update_gui)
+ mainshell.pack_start(self.coord_system)
+ self.coord_system.show()
+
+ self.frame_dict = {}
+ pix_fields_names = \
+ ('Start Line','Start Pixel','Num of Lines','Num of Pixels')
+ self.frame_dict['pixcoord'] = \
+ CoordFrame('Pixel Coordinates', pix_fields_names, TRUE)
+ mainshell.pack_start(self.frame_dict['pixcoord'][0], expand=FALSE)
+
+ geo_fields_names = ('Westmost Longitude', 'Eastmost Longitude', \
+ 'Northmost Latitude', 'Southmost Latitude')
+ self.frame_dict['geodetic'] = \
+ CoordFrame('Geodetic (Lat/Long) Coordinates', \
+ geo_fields_names, FALSE)
+ mainshell.pack_start(self.frame_dict['geodetic'][0], expand=FALSE)
+
+ proj_fields_names = ('Northing', 'Westing', 'Southing', 'Easting')
+ self.frame_dict['geocoord'] = \
+ CoordFrame('Georeferenced Coordinates', proj_fields_names, FALSE)
+ mainshell.pack_start(self.frame_dict['geocoord'][0], expand=FALSE)
+
+ self.band_grid = pgugrid.pguGrid(config=(2,0,1,1,4,0,0,0))
+ self.band_grid.subscribe("cell-selection-changed",self.band_selected_cb)
+ mainshell.pack_start(self.band_grid,expand=TRUE)
+
+ button_box = GtkHBox(spacing = 10)
+ mainshell.pack_start(button_box, expand=FALSE)
+ button_box.show()
+ btOK = GtkButton('OK')
+ button_box.pack_start(btOK)
+ btOK.connect("clicked",self.open_subarea_cb)
+ btOK.show()
+
+ btCancel = GtkButton('Cancel')
+ button_box.pack_start(btCancel)
+ btCancel.connect("clicked", self.close)
+ btCancel.show()
+
+ # Trap window close event
+ self.dialog.connect('delete-event', self.close)
+
+ for item in self.frame_dict.keys():
+ if self.frame_dict[item][2]:
+ self.frame_dict[item][0].show()
+
+ for item in self.frame_dict.keys():
+ if self.frame_dict[item][2]:
+ self.frame_dict[item][0].show()
+
+ def band_selected_cb(self,widget,cell):
+ row = cell[0][0]
+ if self.band_list[row][1] == "NO":
+ self.band_list[row][1] = "YES"
+ self.band_num_list.append(row+1)
+ else:
+ self.band_list[row][1] = "NO"
+ self.band_num_list.remove(row+1)
+ self.band_grid.refresh()
+
+ def close(self,*args):
+ self.dialog.destroy()
+
+
+TOOL_LIST = ['OpenSubArea']
Added: packages/openev/branches/upstream/current/tools/rendertest.py
===================================================================
--- packages/openev/branches/upstream/current/tools/rendertest.py (rev 0)
+++ packages/openev/branches/upstream/current/tools/rendertest.py 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,920 @@
+###############################################################################
+# $Id: rendertest.py,v 1.14 2003/09/02 18:35:54 warmerda Exp $
+#
+# Project: OpenEV
+# Purpose: Interactive Test Suite for Various Rendering Modes.
+# Author: Frank Warmerdam, warmerdam at pobox.com
+#
+###############################################################################
+# Copyright (c) 2003, Frank Warmerdam <warmerdam at pobox.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+###############################################################################
+#
+# $Log: rendertest.py,v $
+# Revision 1.14 2003/09/02 18:35:54 warmerda
+# test layer symbol manager
+#
+# Revision 1.13 2003/05/17 02:12:01 warmerda
+# updated to test color inheritance
+#
+# Revision 1.12 2003/05/16 20:30:21 warmerda
+# improve label placement test
+#
+# Revision 1.11 2003/05/16 18:48:23 pgs
+# added text positioning tests
+#
+# Revision 1.10 2003/05/16 17:44:32 warmerda
+# added some extra tests of multi-level symbols (symbols containing symbols).
+#
+# Revision 1.9 2003/04/09 17:00:00 pgs
+# added tests for halo and dropshadow effects
+#
+# Revision 1.8 2003/04/08 11:57:31 andrey_kiselev
+# More symbol tests in vector_symbol_from_file().
+#
+# Revision 1.7 2003/04/07 16:57:42 andrey_kiselev
+# Typo fixed.
+#
+# Revision 1.6 2003/04/07 16:55:32 andrey_kiselev
+# Correct filename handling when loading symbol from file.
+#
+# Revision 1.5 2003/04/07 16:36:41 pgs
+# fixed path problems with symbols on nt platforms
+#
+# Revision 1.4 2003/04/07 15:58:27 andrey_kiselev
+# New test vector_symbol_from_file().
+#
+# Revision 1.3 2003/04/07 15:50:42 pgs
+# added PEN pattern test
+#
+# Revision 1.2 2003/04/03 14:14:39 warmerda
+# *** empty log message ***
+#
+# Revision 1.1 2003/03/07 22:52:16 warmerda
+# New
+#
+
+from gtk import *
+
+import gview
+import string
+import gvutils
+import GtkExtra
+import os
+import gviewapp
+
+class RenderTestTool(gviewapp.Tool_GViewApp):
+
+ def __init__(self,app=None):
+ gviewapp.Tool_GViewApp.__init__(self,app)
+ self.init_menu()
+
+ def launch_dialog(self,*args):
+ self.win = RenderTest()
+ self.win.show()
+
+ def init_menu(self):
+ self.menu_entries.set_entry("Tools/Render Test",2,
+ self.launch_dialog)
+
+class RenderTest(GtkWindow):
+
+ def __init__(self,app=None):
+ GtkWindow.__init__(self)
+
+ self.set_title('GvShapesLayer Render Test')
+
+ self.view = gview.app.sel_manager.get_active_view()
+
+ self.text_contents = ''
+ self.selected_shape = None
+ self.layer = None
+ self.create_gui()
+
+ self.step_list = [ self.startup,
+ self.vector_symbol,
+ self.vector_symbol_from_file,
+ self.ogrfs_points,
+ self.ogrfs_points2,
+ self.ogrfs_lines,
+ self.raster_symbol,
+ self.simple_poly,
+ self.transparent_poly,
+ self.simple_points_and_lines,
+ self.ogrfs_labels ]
+ self.step = 0
+ self.cleanup_func = None
+
+ def show(self):
+ GtkWindow.show_all(self)
+ self.show_step()
+
+ def close(self, *args):
+ self.hide()
+ self.visibility_flag = 0
+ return TRUE
+
+ def create_gui(self):
+ box1 = GtkVBox()
+ self.add(box1)
+ box1.show()
+
+ text = GtkText()
+ text.set_usize(400,150)
+ text.set_line_wrap(FALSE)
+ text.set_word_wrap(FALSE)
+ text.set_editable(FALSE)
+ text.show()
+ self.text = text
+ box1.pack_start(text, expand=TRUE)
+
+ box2 = GtkHBox()
+ box1.pack_start(box2, expand=FALSE)
+ box2.show()
+
+ self.prev_btn = GtkButton("<--- Previous")
+ self.prev_btn.connect("clicked", self.prev_cb)
+ box2.pack_start(self.prev_btn)
+
+ self.next_btn = GtkButton("Next --->")
+ self.next_btn.connect("clicked", self.next_cb)
+ box2.pack_start(self.next_btn)
+
+ def next_cb( self, *args ):
+ if self.step < len(self.step_list)-1:
+ self.step = self.step + 1
+ self.show_step()
+
+ def prev_cb( self, *args ):
+ if self.step > 0:
+ self.step = self.step - 1
+ self.show_step()
+
+ def show_step( self ):
+ self.cleanup()
+
+ func = self.step_list[self.step]
+ func()
+
+ def cleanup( self ):
+ if self.cleanup_func is not None:
+ self.cleanup_func()
+
+ layer_list = self.view.list_layers()
+ for layer in layer_list:
+ self.view.remove_layer( layer )
+
+ def set_step_name( self, text ):
+ self.set_title( '%d: %s' % (self.step, text) )
+
+ def set_text( self, text ):
+
+ self.text.freeze()
+ self.text.delete_text(0,-1)
+ self.text.insert_defaults( text )
+ self.text.thaw()
+
+###############################################################################
+# Initial test screen.
+
+ def startup( self ):
+ self.set_step_name( 'Render Test Introduction' )
+ self.set_text( 'Welcome to the render test.' )
+
+###############################################################################
+# Display a simple polygon with fill using the layer defaults
+# mechanism.
+
+ def simple_poly( self ):
+ self.set_step_name( 'Simple Polygon Display' )
+ self.set_text( 'You should see a five sided polygon with a red edge\n'
+ +'and blue fill. The edge should be 3 pixels wide.\n'
+ +'The polygon should have a triangular hole.')
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ poly = gview.GvShape( type = gview.GVSHAPE_AREA )
+ poly.set_node( 10, 10, node=0 )
+ poly.set_node( 80, 10, node=1 )
+ poly.set_node( 80, 90, node=2 )
+ poly.set_node( 50, 80, node=3 )
+ poly.set_node( 10, 90, node=4 )
+ poly.set_node( 10, 10, node=5 )
+ poly.set_node( 20, 20, node=0, ring=1 )
+ poly.set_node( 40, 20, node=1, ring=1 )
+ poly.set_node( 30, 50, node=2, ring=1 )
+ shapes.append( poly )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test_poly' )
+ layer.set_property( '_area_edge_color', '255 0 0 255' )
+ layer.set_property( '_area_fill_color', '0 0 255 255' )
+ layer.set_property( '_area_edge_width', '3' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+
+###############################################################################
+# Transparent poly.
+
+ def transparent_poly( self ):
+ self.set_step_name( 'Polygon Transparency' )
+ self.set_text( 'You should see two overlaping polygons, with the\n'
+ +'rear one showing through the top one a little.' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ poly = gview.GvShape( type = gview.GVSHAPE_AREA )
+ poly.set_node( 20, 5, node=0 )
+ poly.set_node( 40, 5, node=1 )
+ poly.set_node( 30, 50, node=2 )
+ shapes.append( poly )
+
+ poly = gview.GvShape( type = gview.GVSHAPE_AREA )
+ poly.set_node( 10, 10, node=0 )
+ poly.set_node( 80, 10, node=1 )
+ poly.set_node( 80, 90, node=2 )
+ poly.set_node( 50, 80, node=3 )
+ poly.set_node( 10, 90, node=4 )
+ poly.set_node( 10, 10, node=5 )
+ shapes.append( poly )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test_poly' )
+ layer.set_property( '_area_edge_color', '255 0 0 255' )
+ layer.set_property( '_area_fill_color', '0 0 255 150' )
+ layer.set_property( '_area_edge_width', '3' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# Simple points and lines.
+
+ def simple_points_and_lines( self ):
+ self.set_step_name( 'Simple Points and Lines' )
+ self.set_text( 'You should see a four segment red line, and\n'
+ +'a blue cross hair 12 pixels tall.\n\n'
+ +'Try zooming in, the crosshair should *not* get bigger.' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 20, 50, node=0 )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+ shape.set_node( 10, 10, node=0 )
+ shape.set_node( 80, 10, node=1 )
+ shape.set_node( 80, 90, node=2 )
+ shape.set_node( 50, 80, node=3 )
+ shape.set_node( 10, 90, node=4 )
+ shapes.append( shape )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test_poly' )
+ layer.set_property( '_line_color', '255 0 0 255' )
+ layer.set_property( '_line_width', '3' )
+ layer.set_property( '_point_color', '0 0 255 255' )
+ layer.set_property( '_point_size', '12' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# Test of raster symbol.
+
+ def raster_symbol( self ):
+ self.set_step_name( 'Raster Symbol Test' )
+ self.set_text( 'A red symbol (the busy indicator from thet toolbar)\n'
+ +'should be shown. When zooming in or out it should\n'
+ +'remain the same size on screen.\n'
+ +''
+ +'NOTE: This symbols should really be green but it\n'
+ +'seems that currently the color attribute of\n'
+ +'SYMBOL directives for raster symbols is ignored\n'
+ +'\n'
+ +'\n'
+ +'' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+
+ if os.name == "nt":
+ sym_file = gview.home_dir + '\\pics\\busy.xpm'
+ sym_file2 = gview.home_dir + '\\pics\\idle.xpm'
+ sym_name = '\\three_idle'
+ else:
+ sym_file = gview.home_dir + '/pics/busy.xpm'
+ sym_file2 = gview.home_dir + '/pics/idle.xpm'
+ sym_name = '/three_idle'
+
+
+ # Unoffset icon
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 20, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#00FF00,id:"'+sym_file+'")' )
+ shapes.append( shape )
+
+ # Pixel Offset
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 20, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#00FF00,dx:30px,dy:-10px,id:"'+sym_file+'")' )
+ shapes.append( shape )
+
+ # Geo Offset
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 20, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#00FF00,dx:30g,dy:-30g,id:"'+sym_file+'")' )
+ shapes.append( shape )
+
+ # Inject a vector icon symbol that consists of three raster symbols,
+ # but do it on the vector layer.
+
+ sm = layer.get_symbol_manager( 1 )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 0.0, 0, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(dy:-10px,dx:-40px,id:"' + sym_file2 + '");' + \
+ 'SYMBOL(id:"' + sym_file2 + '");' + \
+ 'SYMBOL(dy:10px,dx:40px,id:"' + sym_file2 + '")' )
+
+ sm.inject_vector_symbol( sym_name, shape )
+
+ # Place the "3" idle symbol.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#00FF00,id:"'+sym_name+'")' )
+ shapes.append( shape )
+
+ # Add line for context.
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+ shape.set_node( 10, 10, node=0 )
+ shape.set_node( 80, 10, node=1 )
+ shape.set_node( 80, 90, node=2 )
+ shape.set_node( 50, 80, node=3 )
+ shape.set_node( 10, 90, node=4 )
+ shapes.append( shape )
+
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# _gv_ogrfs controlled lines.
+
+ def ogrfs_lines( self ):
+ self.set_step_name( 'OGRFS Lines' )
+ self.set_text('You should see a thick (8 pixels wide) green line\n'
+ +'with a thin (2 pixel wide) red line down the center.\n'
+ +'\n'
+ +'You should also see a second line in blue rendered \n'
+ +'in a dash-dot pattern\n'
+ +'')
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+ shape.set_node( 10, 10, node=0 )
+ shape.set_node( 80, 10, node=1 )
+ shape.set_node( 80, 90, node=2 )
+ shape.set_node( 50, 80, node=3 )
+ shape.set_node( 10, 90, node=4 )
+ shape.set_property( '_gv_ogrfs',
+ 'PEN(c:#00FF00,w:8);PEN(c:#FF0000,w:2)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+ shape.set_node( 20, 20, node=0 )
+ shape.set_node( 40, 20, node=1 )
+ shape.set_node( 40, 40, node=2 )
+ shape.set_node( 60, 60, node=3 )
+ shape.set_node( 40, 80, node=4 )
+ shape.set_property( '_gv_ogrfs', 'PEN(c:#0000FF,w:2,p:ogr-pen-6)' )
+ shapes.append( shape )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+
+
+###############################################################################
+# _gv_ogrfs controlled points.
+
+ def ogrfs_points( self ):
+ self.set_step_name( 'OGRFS Point Symbols' )
+ self.set_text('You should see two rows of yellow symbols.\n'
+ +'First Row: plus, circle, box, triangle, start\n'
+ +'Second Row: X, filled circle, box, triangle and star\n'
+ +'\n'
+ +'Symbols should stay the same size when you zoom.\n'
+ +'\n'
+ +'\n'
+ +'\n'
+ +'' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 15, 30, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-1)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 15, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-2)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 30, 30, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-3)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 45, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-4)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 45, 30, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-5)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-6)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 30, 35, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-7)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 75, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-8)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 75, 30, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,s:3,id:ogr-sym-9)' )
+ shapes.append( shape )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# _gv_ogrfs controlled points.
+
+ def ogrfs_points2( self ):
+ self.set_step_name( 'OGRFS Point Symbols' )
+ self.set_text( \
+ 'In the bottom right corner should be a yellow triangle\n'
+ + 'pointing "north west".\n'
+ + '\n'
+ + 'In the middle should be a white cross hair.\n'
+ + 'To the top/right is a red X.\n'
+ + 'To the lower/left is a green X.\n'
+ + '\n'
+ + 'As you zoom in the red X should remain a constant distance\n'
+ + 'in screen pixels from the white cross. It is "offset" from\n'
+ + 'the white cross a distance in screen pixels.\n'
+ + '\n'
+ + 'The green X is offset by a "georeferenced" distance, and\n'
+ + 'should move closer as you zoom out, and further as you zoom\n'
+ + 'in.\n'
+ + '\n'
+ + '\n'
+ + '\n' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 15, 15, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFF00,a:45,s:3,id:ogr-sym-7)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFFFF,s:2,id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,dx:20px,dy:10px,s:1,id:ogr-sym-1)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#00FF00,dx:-10g,dy:-5g,s:1,id:ogr-sym-1)' )
+ shapes.append( shape )
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# _gv_labels
+
+ def ogrfs_labels( self ):
+ self.set_step_name( 'OGRFS Labels' )
+ self.set_text( \
+ 'At the top of the screen should be two labels (red and blue)\n'
+ + 'The red label has a halo effect. The blue label has a drop\n'
+ + 'shadow effect\n'
+ + '\n'
+ + 'In the middle of the screen should be four labels (red and\n'
+ + 'yellow). They have different anchor positions, and should\n'
+ + 'be arrayed around a center reference point (not shown).\n'
+ + 'The labels indicate where they should be (ie. TOP_LEFT should\n'
+ + 'be to the top, and right of the center point).\n'
+ + '\n'
+ + 'In the lower left quadrant is a yellow "PIXEL_OFFSET" label\n'
+ + 'that should be right and down of the white reference point.\n'
+ + 'The offset is in screen pixels, so as you zoom it should\n'
+ + 'remain a constant distance away from the reference point.\n'
+ + '\n'
+ + 'In the bottom right quadrant is a similar situation but\n'
+ + 'the GEO_OFFSET label is offset in georeference coordinates\n'
+ + 'so it will move closer to the ref point as you zoom out, and\n'
+ + 'further from it as you zoom in.\n'
+ + '\n'
+ + 'All labels should be selectable and manipulatable. When\n'
+ + 'selected they should have a selection box around them.\n'
+ + '\n' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ # Test anchors.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FFFF00,t:"TOP_RIGHT")' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FF0000,p:7,t:"BOTTOM_RIGHT")' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FFFF00,p:9,t:"BOTTOM_LEFT")' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FF0000,p:3,t:"TOP_LEFT")' )
+ shapes.append( shape )
+
+ # more anchor tests
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 35, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#00FF00,p:2,t:"TOP_CENTER");' + \
+ 'SYMBOL(id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 43, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#00FF00,p:5,t:"CENTER_CENTER");' + \
+ 'SYMBOL(id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 35, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#00FF00,p:8,t:"BOTTOM_CENTER");' + \
+ 'SYMBOL(id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ # Test geographic and pixel offsets.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 25, 25, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFFFF,s:2,id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 25, 25, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FFFF00,dx:20px,dy:10px,t:"PIXEL_OFFSET")')
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 25, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FFFFFF,s:2,id:ogr-sym-0)' )
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 25, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FFFF00,dx:6g,dy:3g,t:"GEO_OFFSET")')
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 75, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#00FF00,b:#339933,t:"Text with shadow",sh:)')
+ shapes.append( shape )
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 80, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'LABEL(c:#FF0000,b:#993333,t:"Text with halo",h:)')
+ shapes.append( shape )
+
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# Vector symbols (GvShapes via symbolmanager requested via ogrfs).
+
+ def vector_symbol( self ):
+ self.set_step_name( 'OGRFS Vector Symbol' )
+ self.set_text( \
+ 'You should see two three symbols. In the middle of the screen\n'
+ + 'an arrow pointing straight up. Up and right of that should\n'
+ + 'be a crossed arrow (slightly larger) pointing northeast and\n'
+ + 'north west. The north-west arrow should be green, and the\n'
+ + 'north-east one red.\n'
+ + '\n'
+ + 'To the right of that should be a pair of blue arrows meeting\n'
+ + 'at their bases.\n'
+ + '\n'
+ + '\n' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ # Insert a vector symbol that looks like an arrow into the symbol
+ # manager.
+
+ sm = gview.GvSymbolManager()
+
+ shape = gview.GvShape( type = gview.GVSHAPE_LINE )
+ shape.set_node( 0.0, -6, node=0 )
+ shape.set_node( 0.0, 6, node=1 )
+ shape.set_node( -2, 4, node=2 )
+ shape.set_node( 0.0, 6, node=3 )
+ shape.set_node( 2, 4, node=4 )
+ shape.set_property('_gv_ogrfs','PEN(w:2)' )
+
+ if os.name == "nt":
+ sym_name = "\\rendertest_arrow"
+ else:
+ sym_name = "/rendertest_arrow"
+
+ sm.inject_vector_symbol( sym_name, shape )
+
+ # Place the symbol.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"'+sym_name+'")' )
+ shapes.append( shape )
+
+ # Insert a vector symbol consisting of crossed arrows.
+
+ sm = gview.GvSymbolManager()
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 0.0, 0, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(a:45,c:#00FF00,id:"' + sym_name + '");' + \
+ 'SYMBOL(a:-45,id:"' + sym_name + '")' )
+
+ if os.name == "nt":
+ sym_name2 = "\\rendertest_carrow"
+ else:
+ sym_name2 = "/rendertest_carrow"
+ sm.inject_vector_symbol( sym_name2, shape )
+
+ # Place the symbol.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 60, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:4,id:"'+sym_name2+'")' )
+ shapes.append( shape )
+
+ # Insert a vector symbol consisting scaled arrows with offsets.
+
+ sm = gview.GvSymbolManager()
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 0.0, 0, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(s:0.3333,a:45,dx:-6px,dy:-6px,id:"' + sym_name + '");' + \
+ 'SYMBOL(s:0.666,a:-45,dx:12px,dy:-12px,id:"' + sym_name + '")')
+
+ if os.name == "nt":
+ sym_name2 = "\\rendertest_carrow2"
+ else:
+ sym_name2 = "/rendertest_carrow2"
+ sm.inject_vector_symbol( sym_name2, shape )
+
+ # Place the symbol.
+
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 85, 60, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#0000FF,s:4,id:"'+sym_name2+'")' )
+ shapes.append( shape )
+
+ # Create the layer and display
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+###############################################################################
+# Loading vector symbols from XML file.
+
+ def vector_symbol_from_file( self ):
+ symbols_dir = os.path.join(gview.home_dir, 'symbols' )
+ symbol1 = os.path.join( symbols_dir, 'square.xml' )
+ symbol2 = os.path.join( symbols_dir, 'square_filled.xml' )
+ symbol3 = os.path.join( symbols_dir, 'cross.xml' )
+ symbol4 = os.path.join( symbols_dir, 'x.xml' )
+ symbol5 = os.path.join( symbols_dir, 'triangle.xml' )
+ symbol6 = os.path.join( symbols_dir, 'triangle_filled.xml' )
+ symbol7 = os.path.join( symbols_dir, 'circle.xml' )
+ symbol8 = os.path.join( symbols_dir, 'circle_filled.xml' )
+ symbol9 = os.path.join( symbols_dir, 'dash.xml' )
+ self.set_step_name( 'OGRFS Vector Symbol from File' )
+ self.set_text( \
+ 'In the middle of the screen should be 9 green symbols.\n'
+ 'Symbols loaded from the following files:\n'
+ + symbol1 + '\n'
+ + symbol2 + '\n'
+ + symbol3 + '\n'
+ + symbol4 + '\n'
+ + symbol5 + '\n'
+ + symbol6 + '\n'
+ + symbol7 + '\n'
+ + symbol8 + '\n'
+ + symbol9 + '\n'
+ + '\n'
+ + '\n' )
+
+ shapes = gview.GvShapes()
+ gview.undo_register( shapes)
+
+ sm = gview.GvSymbolManager()
+
+ sm.get_symbol(symbol1)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 40, 40, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol1 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol2)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 40, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol2 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol3)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 40, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol3 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol4)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 40, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol4 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol5)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol5 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol6)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 50, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol6 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol7)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 40, 60, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol7 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol8)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 50, 60, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol8 +'")' )
+ shapes.append( shape )
+
+ sm.get_symbol(symbol9)
+ shape = gview.GvShape( type = gview.GVSHAPE_POINT )
+ shape.set_node( 60, 60, node=0 )
+ shape.set_property('_gv_ogrfs',
+ 'SYMBOL(c:#FF0000,s:2,id:"' + symbol9 +'")' )
+ shapes.append( shape )
+
+ # Create the layer and display
+
+ layer = gview.GvShapesLayer( shapes )
+ layer.set_name( 'test' )
+ self.view.add_layer( layer )
+ self.view.set_active_layer( layer )
+
+ self.view.fit_extents( 0, 0, 100, 100 )
+
+
+TOOL_LIST = ['RenderTestTool']
+
Added: packages/openev/branches/upstream/current/xmlconfig/CVS/Entries
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/CVS/Entries (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/CVS/Entries 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,4 @@
+/DefaultIconFile.xml/1.2/Mon Aug 9 13:39:28 2004//
+/DefaultMenuFile.xml/1.2/Fri Jul 2 16:40:51 2004//
+/DefaultPyshellFile.xml/1.1/Mon Jul 28 19:45:07 2003//
+D
Added: packages/openev/branches/upstream/current/xmlconfig/CVS/Repository
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/CVS/Repository (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/CVS/Repository 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+openev/xmlconfig
Added: packages/openev/branches/upstream/current/xmlconfig/CVS/Root
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/CVS/Root (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/CVS/Root 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1 @@
+:pserver:anonymous at cvs.sourceforge.net:/cvsroot/openev
Added: packages/openev/branches/upstream/current/xmlconfig/DefaultIconFile.xml
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/DefaultIconFile.xml (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/DefaultIconFile.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,89 @@
+<GViewAppIconBar>
+ <Iconbar>
+ <icon>
+ <xpm>'openfile.xpm'</xpm>
+ <hint>'Open and Display Raster/Vector File'</hint>
+ <callback>self.file_open_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'print.xpm'</xpm>
+ <hint>'Print Current View'</hint>
+ <callback>self.print_cb</callback>
+ <help>'gvprint.html'</help>
+ </icon>
+ <icon>
+ <xpm>'nonelut.xpm'</xpm>
+ <hint>'Revert to no Enhancement'</hint>
+ <callback>self.nonelut_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'linear.xpm'</xpm>
+ <hint>'Linear Stretch/Enhancement'</hint>
+ <callback>self.linear_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'equalize.xpm'</xpm>
+ <hint>'Apply Equalization Enhancement to Raster'</hint>
+ <callback>self.equalize_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'log.xpm'</xpm>
+ <hint>'Logarithmic Enhancement to Raster'</hint>
+ <callback>self.log_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'windowed.xpm'</xpm>
+ <hint>'Windowed Raster Re-enhancement'</hint>
+ <callback>self.restretch_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'classify.xpm'</xpm>
+ <hint>'Classify Layer'</hint>
+ <callback>self.classify_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'legend.xpm'</xpm>
+ <hint>'Show Legend'</hint>
+ <callback>self.show_legend_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'seeall.xpm'</xpm>
+ <hint>'Fit All Layers'</hint>
+ <callback>self.seeall_cb</callback>
+ </icon>
+ <icon>
+ <widget>self.zoom_factor</widget>
+ <hint>'Zoom Ratio'</hint>
+ </icon>
+ <icon>
+ <xpm>'zoomin.xpm'</xpm>
+ <hint>'Zoom in x2'</hint>
+ <callback>self.zoomin_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'zoomout.xpm'</xpm>
+ <hint>'Zoom out x2'</hint>
+ <callback>self.zoomout_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'refresh.xpm'</xpm>
+ <hint>'Refresh Rasters From Disk'</hint>
+ <callback>self.refresh_cb</callback>
+ </icon>
+ <icon>
+ <pixmap>self.rawgeo_pixmap</pixmap>
+ <hint>'Georeferenced'</hint>
+ <callback>self.rawgeo_cb</callback>
+ </icon>
+ <icon>
+ <xpm>'help.xpm'</xpm>
+ <hint>'Launch Online Help'</hint>
+ <callback>self.helpcb</callback>
+ </icon>
+ <icon>
+ <pixmap>self.idlebusy_pixmap</pixmap>
+ <hint>'Busy Indicator'</hint>
+ <callback>self.do_nothing</callback>
+ </icon>
+ </Iconbar>
+</GViewAppIconBar>
Added: packages/openev/branches/upstream/current/xmlconfig/DefaultMenuFile.xml
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/DefaultMenuFile.xml (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/DefaultMenuFile.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,140 @@
+<GViewAppMenu>
+ <Menu>
+ <entry>
+ <path>'File/Import'</path>
+ <callback>self.file_import_cb</callback>
+ </entry>
+ <entry>
+ <path>'File/Open'</path>
+ <accelerator>control+O</accelerator>
+ <callback>self.file_open_cb</callback>
+ </entry>
+ <entry>
+ <path>'File/Open 3D'</path>
+ <callback>self.open_3D_request</callback>
+ </entry>
+ <entry>
+ <path>'File/Save Vector Layer'</path>
+ <callback>self.save_vector_layer_request</callback>
+ </entry>
+ <entry>
+ <path>'File/Save Project'</path>
+ <callback>self.menu_save_project</callback>
+ </entry>
+ <entry>
+ <path>'File/Save Project as...'</path>
+ <callback>self.menu_save_project_as</callback>
+ </entry>
+ <entry>
+ <path>'File/New View'</path>
+ <callback>self.menu_new_view</callback>
+ </entry>
+ <entry>
+ <path>'File/Print'</path>
+ <callback>self.print_cb</callback>
+ </entry>
+ <entry>
+ <path type="separator">'File/'</path>
+ </entry>
+ <entry>
+ <path>'File/rfl1'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>1</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path>'File/rfl2'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>2</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path>'File/rfl3'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>3</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path>'File/rfl4'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>4</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path>'File/rfl5'</path>
+ <callback>self.rfl_cb</callback>
+ <arguments>
+ <arg>5</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path type="separator">'File/'</path>
+ </entry>
+ <entry>
+ <path>'File/Close'</path>
+ <callback>self.close</callback>
+ </entry>
+ <entry>
+ <path>'File/Exit'</path>
+ <accelerator>control+Q</accelerator>
+ <callback>self.exit</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Undo'</path>
+ <callback>self.undo</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Layers...'</path>
+ <callback>self.app.show_layerdlg</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Vector Layer Attributes...'</path>
+ <callback>self.show_oeattedit</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Edit Toolbar...'</path>
+ <callback>self.app.show_toolbardlg</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Go To...'</path>
+ <callback>self.goto_dlg</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Python Shell...'</path>
+ <callback>self.pyshell</callback>
+ </entry>
+ <entry>
+ <path>'Edit/3D Position...'</path>
+ <callback>self.position_3d</callback>
+ </entry>
+ <entry>
+ <path>'Edit/Preferences...'</path>
+ <callback>self.app.launch_preferences</callback>
+ </entry>
+ <entry>
+ <path>'Help/Help...'</path>
+ <callback>self.helpcb</callback>
+ <arguments>
+ <arg>'openevmain.html'</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path type="separator">'Help/'</path>
+ </entry>
+ <entry>
+ <path>'Help/Web Page...'</path>
+ <callback>self.helpcb</callback>
+ <arguments>
+ <arg>'http://OpenEV.Sourceforge.net/'</arg>
+ </arguments>
+ </entry>
+ <entry>
+ <path>'Help/About...'</path>
+ <callback>self.aboutcb</callback>
+ </entry>
+ </Menu>
+</GViewAppMenu>
\ No newline at end of file
Added: packages/openev/branches/upstream/current/xmlconfig/DefaultPyshellFile.xml
===================================================================
--- packages/openev/branches/upstream/current/xmlconfig/DefaultPyshellFile.xml (rev 0)
+++ packages/openev/branches/upstream/current/xmlconfig/DefaultPyshellFile.xml 2007-06-23 22:26:29 UTC (rev 916)
@@ -0,0 +1,2 @@
+<GViewAppPyshell>
+</GViewAppPyshell>
\ No newline at end of file
More information about the Pkg-grass-devel
mailing list