Để tạo dữ liệu thƣờng qua các bƣớc số hoá bản đồ, chuẩn hoá, thu thập thông tin thuộc tính,...Việc này có thể đƣợc thực hiện Khi xây dựng dữ liệu phục vụ cho WebGis giới thiệu danh lam thắng cảnh Hà Nội chúng ta cần các thông tin về các quận, các điểm du lịch, các khu di tích, đƣờng giao thông, khách sạn, công viên, hồ,
Bệnh viện, các trƣờng Đại học. Vì vậy khi số hoá bản đồ du lịch Hà Nội chúng ta cần chia các đối tƣợng trên bản đồ ra thành các lớp trên. Mỗi lớp trên bản đồ tƣơng đƣơng với một bảng trong cơ sở dữ liệu, chúng ta hoàn toàn có thể thêm vào mỗi đối tƣợng trong lớp một số thuộc tính nào đó về đối tƣợng nhằm cung cấp thông tin thoả mãn yêu cầu của du khách.
Trong quá trình phát triển một ứng dụng GIS thì việc tạo dữ liệu thƣờng tốn thời gian và tiền bạc nhiều nhất. Chúng tôi sử dụng dữ liệu có sẵn với định dạng ERSI Shapefile. Trong đó mỗi lớp bản đồ đƣợc ghi vào các file.shx,.shp chứa dữ liệu không gian và các file.dbf chứa dữ liệu thuộc tính.
3.3.1. Cấu trúc các lớp bản đồ
- Lớp các đƣờng giao thông chính:
Tên lớp Kiểu lớp Các trƣờng thuộc tính Duong Line Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(20) Tên đƣờng Chieudai Decimal(6,0) Chiều dài đƣờng - Lớp các công viên:
Tên lớp Kiểu lớp Các trƣờng thuộc tính Congvien Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(20) Tên đƣờng Diachi Character(100) Địa chỉ Lat Character(20) Kinh độ Lon Character(20) Vĩ độ
Tên lớp Kiểu lớp Các trƣờng thuộc tính danhlam Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên của danh lam Diachi Character(50) Địa chỉ danh lam Lat Character(20) Vĩ độ
Lon Character(20) Kinh độ Mota Charater(256) Mô tả - Lớp các quận:
Tên lớp Kiểu lớp Các trƣờng thuộc tính
Quan Polygon Tên trƣờng Kiểu dữ liệu Mô tả Ten Character(100) Tên quận Dientich Decimal(6,0) Diện tích quận Chuvi Decimal(6,0) Chu vi quận - Lớp các bệnh viện
Tên lớp Kiểu lớp Các trƣờng thuộc tính
Benhvien Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên bệnh viện Diachi Character(100) Địa chỉ bệnh viện - Lớp hồ:
Tên lớp Kiểu lớp Các trƣờng thuộc tính
Ho Point Tên trƣờng Kiểu dữ liệu Mô tả Ten Character(100) Tên hồ Diachi Character(100) Địa chỉ Dientich Decimal(6,0) Diện tích Chuvi Decimal(6,0) Chu vi
- Lớp bảo tàng:
Tên lớp Kiểu lớp Các trƣờng thuộc tính Baotang Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên bảo tàng Diachi Decimal(6,0) Địa chỉ Lat Decimal(11,0) Kinh độ Lon Character(254) Vĩ độ
Nam Decimal(4) Năm thành lập - Lớp các khu di tích lịch sử:
Tên lớp Kiểu lớp Các trƣờng thuộc tính Ditich Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên di tích
Diachi Character(50) Địa chỉ của di tích
Tendiaphuong Character(100) Tên địa phƣơng của di tích
Lat_x Character(20) Vĩ độ Lon_y Character(20) Kinh độ
Dacdiem Character(254) Thông tin bổ sung - Lớp sông
Tên lớp Kiểu lớp Các trƣờng thuộc tính Song Line Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên di tích Chieudai Decimal(6,0) chiều dài
- Lớp các trƣờng đại học
Tên lớp Kiểu lớp Các trƣờng thuộc tính daihoc Point Tên trƣờng Kiểu dữ liệu Mô tả
Ten Character(100) Tên trƣờng Diachi character(100) Địa chỉ
Nam Decimal(4) Năm thành lập Lat Character(20) Kinh độ Lon Character(20) Vĩ độ
3.3.2. Chuyển đổi dữ liệu
Từ các lớp dữ liệu nhƣ trên ta chuyển đổi sang cơ sở dữ liệu postGIS/postgreSQL qua các bƣớc sau:
- Tạo cơ sở dữ liệu hanoidb với template là template_postgis để có thể lƣu dữ liệu không gian.
- Ghi dữ liệu mỗi lớp vào một file sql bằng lệnh: shp2pgsql <shapefile> <newtablename> > afile.sql Trong đó:
Shapefile: tên file shape
newtablename: tên bảng sẽ tạo ra trong postgreSQL afile: tên file sql
- Mở cơ sở dữ liệu hanoidb và thực thi file sql.
Việc chuyển đổi thành công mỗi lớp bản đồ sẽ tƣơng ứng với một bảng trong cơ sở dữ liệu postgreSQL. Định danh đối tƣợng lƣu trong trƣờng gid, dữ liệu không gian lƣu trong trƣờng với tên cố định là the_geom.
3.3.3. Thiết kế trường lưu dữ liệu đa phương tiện
Chúng tôi cũng chỉ thực hiện việc lƣu ảnh vào trong cơ sở dữ liệu còn các file video sẽ đƣợc lƣu trong thƣ mục và trong cơ sở dữ liệu chỉ lƣu tên file do kích thƣớc của file video lớn dẫn đến việc truy cập dữ liệu trở lên chậm trễ. Để thuận tiện, chúng tôi trình bầy riêng đối với lớp các khu di tích (các lớp khác là tƣơng đƣơng).
Để việc load bản đồ đƣợc nhanh hơn, chúng tôi lƣu trƣờng ảnh sang một bảng khác: templemul có hai trƣờng (gid:integer, image:bytea). Trong đó gid là khoá ngoại liên kết đến gid trong bảng templetbl, image là trƣờng lƣu dữ liệu ảnh.
Để lƣu dữ liệu video cho đối tƣợng thuộc lớp này chúng tôi tạo thêm trong bảng templetbl trƣờng video_name(integer) lƣu tên video và trƣờng video_ext(character(5)) để lƣu phần mở rộng của file video.
3.4. Quản trị dữ liệu đa phương tiện
3.4.1. Dữ liệu hình ảnh
3.4.1.1. Lưu ảnh
Có hai cách để lƣu ảnh trong cơ sở dữ liệu (lƣu theo kiểu đối tƣợng lớn hoặc lƣu trong trƣờng bytea). Ở đây chúng tôi chọn lƣu dữ liệu trong trƣờng bytea vì trƣờng bytea có kích thƣớc nhỏ hơn do đó việc truy cập dữ liệu sẽ nhanh hơn.
Thẻ cho phép mở file:
<input type=“ file” name=“ image1” style=“ font-size: 14pt; font-family: Times New Roman; color: #000080” size=40>
Đọc nội dung tạm của file ảnh:
$data = file_get_contents($_FILES['image1']['tmp_name']);
Trƣớc khi lƣu nội dung file ảnh vào cơ sở dữ liệu, thực hiện việc chuyền đổi dữ liệu sang kiểu bytea bằng lệnh:
$escaped = pg_escape_bytea($data);
Cuối cùng cập nhật giá trị $escape vào trƣờng bytea nhƣ với các kiểu dữ liệu bình thƣờng khác.
3.4.1.2. Hiển thị ảnh từ cơ sở dữ liệu
Tại vị trí cần hiển thị ảnh ta đặt một đƣờng thẻ nhƣ sau: print” <img src = getflag.php?str=“ . $str.” ><br>“ ; Trang getflag.php có nội dung:
<?
header(“ Content-type: image/gif” ); $str = $_REQUEST['str'];
{ đoạn lấy biến $strTable - tên bảng và $gid- gid của bản ghi lƣu ảnh}
$conn = pg_connect('port = 5432 dbname = hanoidb1 password=tra123 user = postgres');
$query=“ SELECT gid,anh1 FROM” .$strTable.” WHERE gid='“ .$id.” '“ ; $query_result=pg_exec($conn,$query);
echo $val; ?>
Lƣu ý trƣớc khi hiển thị ảnh cần chuyển dữ liệu khỏi kiểu bytea bằng lệnh pg_unescapebytea.
3.4.2. Dữ liệu video
3.4.2.1. Lưu tệp video
Tạo thƣ mục video trong thƣ mục ứng dụng, trong thƣ mục video tạo ra các thƣ mục con ứng với tên các lớp để lƣu file video cho các đối tƣợng riêng theo từng lớp. Dùng dịch vụ upload file đƣa file video lên máy chủ.
Để tránh việc trùng lặp tên file trƣớc khi lƣu ta xác định tên file bằng cách: Kiểm tra trong cơ sở dữ liệu trƣờng video_name của đối tƣợng tƣơng ứng xem đã tồn tại tên file chƣa nếu tồn tại rồi chỉ cần di chuyển file video trong thƣ mục tạm của máy chủ vào trong thƣ mục video của ứng dụng với cái là tên lấy trong cơ sở dữ liệu và sửa lại trƣờng video_ext với đuôi mở rộng mới
Nếu chƣa tồn tại tên file của đối tƣợng trong bảng tìm max tên file. Nếu max bằng 0 tên ảnh=1, còn không tên ảnh bằng max + 1. Di chuyển file video đang trong thƣ mục tạm vào trong thƣ mục video của ứng dụng với tên mới xác định và cập nhật tên file này cùng phần mở rộng vào bảng.
3.4.2.2. Hiển thị file video.
Từ đối tƣợng lựa chọn ta xác định đƣợc tên file video và phần mở rộng của nó ghép tên và phần mở rộng này vào cùng với đƣờng dẫn là thƣ mục lƣu file video của ứng dụng ta đƣợc biến lƣu đƣờng dẫn đến file video đặt tên là $video_path.
Đoạn mã hiển thị file video nhƣ sau:
<OBJECT onmousemove=uMouseMove() id=mediaplayer onmouseout=uMouseOut() height=350 width=400 align=middle classid=clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6>
<PARAM NAME=“ URL” VALUE=“ <?php echo $video_path; ?>“ > <PARAM NAME=“ fullScreen” VALU=E=“ 0” >
<PARAM NAME=“ autoStart” VALUE=“ 0” > <PARAM NAME=“ volume” VALUE=“ 50” > <PARAM NAME=“ stretchToFit” VALUE=“ 0” > <PARAM NAME=“ windowlessVideo” VALUE=“ 0” > <PARAM NAME=“ enabled” VALUE=“ -1” >
<PARAM NAME=“ enableContextMenu” VALUE=“ -1” > <PARAM NAME=“ rate” VALUE=“ 1” >
<PARAM NAME=“ balance” VALUE=“ 0” >
<PARAM NAME=“ currentPosition” VALUE=“ 0” > <PARAM NAME=“ defaultFrame” VALUE=““ > <PARAM NAME=“ playCount” VALUE=“ 2” > <PARAM NAME=“ currentMarker” VALUE=“ 0” > <PARAM NAME=“ invokeURLs” VALUE=“ 0” > <PARAM NAME=“ baseURL” VALUE=““ > <PARAM NAME=“ mute” VALUE=“ 0” > <PARAM NAME=“ uiMode” VALUE=“ full” > <PARAM NAME=“ SAMIStyle” VALUE=““ > <PARAM NAME=“ SAMILang” VALUE=““ > <PARAM NAME=“ SAMIFilename” VALUE=““ > <PARAM NAME=“ captioningID” VALUE=““ >
<PARAM NAME=“ enableErrorDialogs” VALUE=“ -1” >
<embed src=“<?php echo $video_path; ?>“ autostart=“0” url=“ <?php echo $video_path; ?>“ volume=“50” stretchtofit=“100%” windowlessvideo=“fit” enabled=“ -1” enablecontextmenu=“-1” align=“middle” height=“ 350” width=“400” >
</OBJECT>
3.5. Xây dựng ứng dụng
3.5.1. Hệ thống nền
Ứng dụng đƣợc xây dựng trên môi trƣờng mã nguồn mở, sử dụng gói sản phẩm miễn phí MapServer For Windows - MS4W_2.2.3 cài đặt trên nền Windows Vista bao gồm:
Apache version 2.2.4
PHP version 5.2.1 (MS4W 2.x) or 4.4.4 (MS4W 1.x)
MapServer 4.10.1 CGI and MapScript (CSharp, Java, PHP, Python)
support GD 2.0.33, FreeType 2.1.10, GDAL/OGR 1.4.0, PROJ, WMS/WFS, Flash, PDF, ECW3.1, PostGIS, GEOS, libcurl 7.15.1, FastCGI
gdal/ogr utilities proj.4 utilities shp2tile utility shapelib utilities shpdiff utility PHP_OGR Extension 1.1.1 OWTChart 1.2.0
Sử dụng cơ sở dữ liệu PostgreSQL8.2 và postGis1.2.1 để hỗ trợ dữ liệu không gian.
3.5.2. Thiết kế chức năng
3.5.3. Các chức năng phía người dùng
Cấu hình file map để hiển thị bản đồ.
File map bao gồm một số nội dung cơ bản nhƣ sau: SIZE: Kích thƣớc khi hiển thị bản đồ
SYMBOLSET: Đƣờng dẫn đến file khai báo biểu tƣợng dùng hiển thị các đối tƣợng trên mỗi lớp của bản đồ.
EXTENT: Vùng bao của bản đồ (có thể xác định bằng công cụ orginfor.exe, ArcMap, MapInfor…)
QUERYMAP: Cách thể hiện đối tƣợng khi đƣợc truy vấn trên bản đồ (màu sắc, kiểu hiển thị …)
LAYER: Khai báo lớp bản đồ.
Kết nối đến cơ sở dữ liệu trong mỗi lớp bằng lệnh CONNECTIONTYPE postgis
CONNECTION” user=postgres password=tra123 dbname=hanoidb1 host=localhost port=5432”
Kết nối đến trƣờng dữ liệu không gian qua nhãn DATA DATA” the_geom from templetbl”
Khai báo tên của bảng thông qua nhãn METADATA
TABLE_NAME templetbl END
Trƣờng dữ liệu lấy làm nhãn gắn trên mỗi đối tƣợng khi hiển thị bản đồ đƣợc khai báo
LABELITEM ”name”
Khai báo biểu tƣợng, cấu hình font cho các nhãn khi hiển thị các đối tƣợng trên lớp TEMPLATE” ttt_query.html” SYMBOL 'triangle' COLOR 27 131 39 SIZE 6 LABEL COLOR 255 0 0 FONT fritqat-italic TYPE truetype SIZE 8 POSITION AUTO PARTIALS FALSE OUTLINECOLOR 255 255 255 END
3.5.4. Các chức năng kế thừa.
3.5.4.1. Chức năng phóng to
- Đầu vào:
+ Bản đồ hiện tại.
+ Tỷ lệ phóng to cho trƣớc.
+ Một điểm do ngƣời dùng kích chuột trên bản đồ hoặc một vùng chữ nhật do ngƣời dùng vẽ trên bản đồ.
- Đầu ra: Bản đồ đã đƣợc phóng to. - Giải thuật:
+ Kiểm tra đầu vào là điểm hay hình chữ nhật?
+ Nếu là điểm: sử dụng hàm ZoomPoint của MapObject với hệ số phóng dƣơng.
+ Ngƣợc lại: sử dụng hàm ZoomRectangle của MapObject.
3.5.4.2. Chức năng thu nhỏ
- Đầu vào:
+ Bản đồ hiện tại.
+ Tỷ lệ phóng to cho trƣớc.
+ Một điểm do ngƣời dùng kích chuột trên bản đồ hoặc một vùng chữ nhật do ngƣời dùng vẽ trên bản đồ.
- Đầu ra: Bản đồ đã đƣợc thu nhỏ. - Giải thuật:
+ Kiểm tra đầu vào là điểm hay hình chữ nhật?
+ Nếu là hình chữ nhật: Lấy tọa độ trung điểm của bản đồ tính theo pixel. + Sử dụng hàm ZoomPoint của MapObject với hệ số phóng âm.
3.5.4.3. Công cụ xem toàn phần
- Đầu vào:
+ Ngƣời dùng kích chọn công cụ xem toàn phần.
+ Các tham số thể hiện phạm vi của bản đồ (minX, maxX, minY, maxY). - Đầu ra: Bản đồ đã đƣợc phóng về tỉ lệ xem toàn phần.
- Giải thuật:
3.5.4.4. Công cụ dịch chuyển theo các hướng
Hƣớng Bắc: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Bắc. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Bắc.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX, minY + deltaY, maxX, maxY + deltaY.
Hƣớng Nam: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Nam. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Nam.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX, minY - deltaY, maxX, maxY - deltaY.
Hƣớng Đông: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Đông. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Đông.
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX + deltaX, minY, maxX + deltaX, maxY.
Hƣớng Tây: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Tây. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Tây.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX - deltaX, minY, maxX - deltaX, maxY.
Hƣớng Đông Bắc: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Đông Bắc. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Đông Bắc.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX+deltaX, minY+deltaY, maxX +deltaX, maxY+deltaY.
Hƣớng Đông Nam: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Đông Nam. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Đông Nam.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX+deltaX, minY-deltaY, maxX +deltaX, maxY-deltaY.
Hƣớng Tây Nam: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Tây Nam. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Tây Nam.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX - deltaX, minY - deltaY, maxX - deltaX, maxY - deltaY.
Hƣớng Tây Bắc: - Đầu vào:
+ Bản đồ hiện tại. + Tham số dịch chuyển.
+ Ngƣời dùng kích chọn công cụ dịch chuyển theo hƣớng Tây Bắc. - Đầu ra: Bản đồ đã đƣợc dịch chuyển theo hƣớng Tây Bắc.
- Giải thuật:
+ Xác định khoảng cách dịch chuyển theo trục X bằng cách lấy hệ số dịch chuyển nhân với độ rộng của bản đồ: deltaX.
+ Xác định khoảng cách dịch chuyển theo trục Y bằng cách lấy hệ số dịch chuyển nhân với độ cao của bản đồ: deltaY.
+ Sử dụng hàm SetMapExtents của MapObject với các tham số: minX - deltaX,