Đây có thể coi là hạt nhân, là phần quan trọng nhất của bài toán.
Trong bài toán “cung cấp quang cảnh đường phố Hà Nội”, đối với việc xử lý nhìn góc 360 độ tại 1 điểm, tạo cảm giác 3d, có nhiều phương pháp thực hiện khác nhau:
- Xử lý 1 ảnh 360 độ, cắt ảnh thành nhiều phần, mỗi phần 1 pixel, sau đó bắt sự di chuyển của chuột để đưa vào mảnh nào thích hợp, Action Script hỗ trợ bằng lệnh copyPixel. Yêu cầu: có ảnh 360 độ
Ví dụ:
Hình 12. Ví dụ vềảnh 360°
- Tạo một khối lập phương (cube) trong không gian 3d, đưa ảnh vào các mặt trong của khối lập phương đó. Yêu cầu: phải có ảnh thích hợp với từng mặt của khối. - Các phương pháp khác
Cách thứ nhất có thể thực hiện dễ dàng, tuy nhiên kết quả thu được không tạo cho người sử dụng cảm giác 3d, đơn giản chỉ là 1 bức ảnh 2d có thể kéo qua kéo lại.
MapJack cũng sử dụng ảnh 360°, nhưng ảnh được chia thành từng mảnh nhỏ (pieces), có thuật toán xử lý với các mắt cá (fisheyes) và các thuật toán xác định từng pixel nào của ảnh đang nằm ở vị trí nào trên màn hình, và với độ zoom cùng với việc co giãn ảnh (scale) ứng với từng pixel, các pixel càng gần 2 lề của màn hình thì càng đc zoom to, tạo cho ta cảm giác nhưđang “nhìn”, có nghĩa là càng ở gần thì vật càng lớn (ở 2 lề), càng xa thì vật càng nhỏ (ở giữa). Hạn chế của MapJack là chỉ cho nhìn 360° xung quanh chứ không cho phép nhìn phía trên và bên dưới.
Cách thứ 2 cho kết quả khá khả quan, Google Maps Street View cũng sử dụng cách làm này, tuy nhiên, để có thể chụp được ảnh cho cả 6 mặt của khối lập phương, cần phải có sựđầu tư về phương tiện. Phương tiện đó là 1 chiếc máy ảnh với 6 camera được bố trí để chụp 6 hướng tại một điểm bất kỳ, chụp 6 ảnh tại cùng một thời điểm, các ảnh này khi ghép vào khối lập phương sẽ khớp với nhau, người sử dụng khó có thể phát hiện ra mối nối.
Để phục vụ cho việc sử dụng cách này, hiện nay tôi đã chụp ảnh 4 hướng tại 1 điểm để gán vào 4 mặt xung quanh của khối lập phương, 4 ảnh này có thểđược tạo bằng cách chia bức ảnh 360 độ thành 4 phần bằng nhau. Nếu dùng máy ảnh thông thường chụp các bức ảnh tại 1 điểm theo các hướng khác nhau rồi ghép lại thành ảnh 360 độ thì sai số sẽ rất cao, đồng thời khó tìm được nơi nào mà cảnh vật và con người đều bất động cho ta chụp vì khi ta chụp với góc nhìn này, chuyển sang góc nhìn khác để chụp tiếp sẽ mất một khoảng thời gian, con người, phương tiện di chuyển sẽ gây sai số khi ghép nối các ảnh.
Về mặt lý thuyết, nhưđã nêu ở trên, cách tạo ra ảnh nhìn 360° là sử dụng một khối lập phương với 6 mặt được gán ảnh. Chúng ta cần tạo 1 khối lập phương như vậy, cần 1 container để chứa các đối tượng 3d, cần một điểm nhìn (view point) và 1 camera để quan sát các đối tượng được đưa vào không gian 3D này.
Có một phương pháp khác là là sử dụng ảnh mặt cầu, tưởng tượng bề mặt của quả địa cầu, trong các sách giáo khoa địa lý, để thể hiện bề mặt địa cầu, người ta thường giãn ra thành một bức ảnh trên giấy, tương tự, đây là một ví dụ vềảnh mặt cầu (sphere)
Hình 13. Ảnh mặt cầu
3.4.2. Xử lý việc cho phép người sử dụng dịch chuyển tới các vị trí khác nhau
Việc di chuyển từđiểm này tới điểm khác trong chương trình, đơn giản chỉ là thay đổi hình ảnh hiển thịđược gán trên 6 mặt của khối lập phương.
- Sử dụng bàn phím: Bắt sự kiện người sử dụng bấm vào một phím nào đó của bàn phím, nếu phím được bấm là lên (hoặc xuống), ta thay đổi đường dẫn tới 6 ảnh ứng với 6 mặt. Khi sử dụng bàn phím, chỉ cho phép dịch chuyển tới điểm liền kề phía trước (hoặc phía sau).
- Sử dụng các button có trên màn hình: ta sẽ tạo ra 2 button tiến lên và lùi lại trên màn hình, việc xử lý 2 button này tương tự với viêc xử lý di chuyển từ bàn phím, có nghĩa là chỉ cho phép tiến lên (hoặc lùi lại) tới điểm liền kề với điểm hiện tại. Đối với 2 cách này, xử lý trên 1 đoạn đường thẳng sẽ cho kết quả tốt, tuy nhiên, đến những đoạn ngã 3 hay ngã tư, hoặc đoạn rẽ vào những con đường nhỏ, vì chỉ có 2 button (và 2 phím )là tiến và lùi, việc thay đổi phương hướng để rẽ sang ngả khác là không thể thực hiện được. Vấn đề cũng xảy ra khi ta nhìn xung quanh, nếu ta quay ngược lại 180°, khi đó tiến lên hoặc lùi lại sẽ ngược??? Do đó ta cần phải kiểm soát về phương
hướng và góc nhìn của người sử dụng, để có thểđưa người sử dụng tới đúng vị trí mà họ chọn.
- Cách thứ 3, đó là định vị sẵn phương hướng ngay trên bản đồ cho người sử dụng. Google Maps Street View sử dụng 1 đường thằng nằm nối từ điểm hiện tại tới các điểm gần nó nhất, còn MapJack sử dụng các điểm nằm trên đường. Vấn đề đặt ra ở đây là “trục” làm thế nào để nằm được trên đường, khi ta nhìn xung quanh thì trục cũng phải di chuyển theo. Vì tại mỗi điểm thì “trục” sẽ khác nhau (có thể cong sang hướng khác, cũng có thể đến ngã rẽ), do đó việc thiết lập “trục” cho từng điểm là bất khả thi. Ý tưởng ở đây chính là: ta thiết kế một trục đường dựa trên hình dạng con đường thật, trên trục ta định vị tọa độ cho các điểm mà ta chọn làm điểm quan sát (view point), tại điểm nào ta sẽ load ảnh tương ứng với điểm ấy. “Trục” phải được đưa vào trong không gian 3D, với độ quay thích hợp với độ quay của khối lập phương để “trục” không bị lệch ra khỏi đường. Đối với MapJack, do có các điểm xanh nằm trên mặt đường nên việc xác định vị tri điểm tiếp theo dễ dàng hơn, đồng thời cho ta hình ảnh cụ thể về con đường. Còn đối với Google Maps Street View, việc nối từ điểm này tới các điểm liền kề không cho người sử dụng hình dung được hình dạng của con đường, nhất là tại các ngã rẽ.
Google Maps Street View và MapJack đều có bản đồ nhỏ, trên bản đồ nhỏ đó có các điểm ứng với các điểm trên bản đồ lớn. Các điểm đó có thuộc tính là kinh độ (Longitude) và vĩ độ (latitude ), khi người sử dụng click vào bản đồ nhỏ, chương trình sẽ tìm điểm gần với vị trí click chuột nhất, lấy ra 2 giá trị kinh độ và vĩđộ.
Trên bản đồ lớn, nhận 2 giá trị vừa lấy được và hiển thị ra màn hình hình ảnh của điểm có tọa độ tương ứng. Bản đồ lớn và bản đồ nhỏ là 2 flash độc lập với nhau, việc truyền biến thì flash này sang flash khác, ta có thể sử dụng đến hàm localConnection của flash.
Việc tạo sẵn một trục của bản đồ như vậy thường dẫn đến sai lệch giữa trục và hình dạng con đường thật, và việc tính toán độ xoay của góc nhìn người sử dụng sao cho khớp với gọc nhìn của trục cũng khá khó khăn. Liệu có cách nào mà ta xác định được vị trí của các điểm gần với vị trí hiện tại, hiển thị chúng lên và điều quan trọng là “đặt” chúng trên đường, không bị lệch ra ngoài? Câu trả lời là có, đó là sử dụng hotspot (các điểm nóng). Các điểm nóng được đưa lên và cố định vào một vị trí nào đó của flash, hostspot được đưa lên tại layer 2 của flash, trong khi layer 1 xử lý việc hiển thịảnh 360°, khi ta click vào một hotspot, chương trình sẽ gọi một hàm tương ứng (giống như javascript), và khi đó ta sẽ load lại file swf với các thông số được thay đổi, cụ thể là đường dẫn đến file ảnh tương ứng với vị trí của hotspot. Các thuộc tính và chỉ số của hotspot thường được lưu trong file xml.
Khi dịch chuyển từđiểm này sang điểm khác, vì thời gian load ảnh có thể sẽ lâu, do đó trước khi ảnh được load, màn hình sẽ hiện ra một màu xám (màu mặc định khi giá trị truyền vào là null), để khắc phục, ta sẽđưa lên một ảnh mờ (độ phân giải rất thấp) của ảnh định load, do dung lượng của ảnh này khá nhỏ nên load sẽ nhanh. Người sử dụng sẽ biết được “lờ mờ” về quang cảnh tại điểm đó, và hiểu rằng dữ liệu tại điểm đó đang được load lên. Sau đây là ảnh mờ của một điểm, dùng cho cả 2 phương pháp: sử dụng khối lập phương 6 mặt và sử dụng ảnh mặt cầu.
Hình 14. Ảnh mờ của ảnh mặt cầu
3.4.3. Cách lưu trữ Cơ sơ dữ liệu
Flash có thể cho phép import các file vào trong thư viện của mình, do đó việc sử dụng các file đó khá đơn giản và tốc độ truy cập là rất nhanh, tuy nhiên số lượng file được import vào bị hạn chế, càng nhiều file được import thì file flash có kích thước càng lớn, và việc load file flash lên một trang web càng lâu.
Do đó, ta sẽ lưu trữ các file ảnh cùng với các file xml ở bên ngoài flash và đặt trên máy chủ (server). Ta sẽ có 1 file xml để xác định điểm có kinh độ x và vĩ độ y trên bản đồ nhỏứng với thư mục lưu trữảnh nào được sử dụng trên bản đồ lớn.
Để phục vụ cho chức năng tìm kiếm theo tên sẽ được hoàn thiện sau này, ta nên lưu trữ theo cấu trúc:
Tên_thư_mục_gốc/Tên_thành_phố/Tên_đường/Vị_trí_điểm_trên_đg/các_file_ảnh Ví dụ: images/Hà Nội/Nguyễn Trãi/3/front.jpg
Trong đó, 3 chính là vị trí của điểm được thể hiện trên màn hình, giá trị này được lưu trong file xml xác định tọa độđiểm được nói ở trên.
Ảnh có kích thước càng lớn thì tốc độ load ảnh càng lâu, ngược lại, ảnh có kích thước nhỏ thì tốc độ load nhanh hơn. Lấy một ví dụ, bằng thực nghiệm với Adobe Flash CS3 và Action Script 3.0, khi load một bức ảnh có kích thước 600 x 800 (pixel) vào một biến, đặt độ trễ trước khi xử lý với biến đó là 0,2s (300 ms), kết quả trả về cho biến là null (kiểm tra bằng câu lệnh trace(tên_biến);), có nghĩa là trong 0,2s ảnh vẫn chưa được load lên. Cũng với ảnh đó, ta chia thành 4 ảnh nhỏ kích thước 300 x 400 (pixel), với cùng độ trễ như vậy, kết quả trả về cho biến là 1 Bitmap Object. Như vậy, ta nên chia ảnh panorama ra thành các ảnh với kích thước nhỏđể tăng tốc độ load ảnh.
Như đã nói ở phần trước, việc sử dụng hotspot rất tiện lợi, flash sẽ đọc file xml để biết được vị trí, số lượng của hotspot đối với từng điểm, đồng thời biết được hành động khi ta click vào một hotspot nào đó. Cách lưu file xml là, với mỗi thử mục chứa ảnh của mỗi điểm, ta đều có một file xml, trong đó có lưu theo dạng:
<?xml version = ‘1.0’?> <hotspots>
<spot id="1" pan="0" tilt="0" url="hotspot.jpg" zoom="1"
Street=”….” Point=”….”
onClick="………." />
</hotspots> Ở mục này
- id=”1” để phân biệt giữa các hotspt với nhau, tại một điểm (“điểm” là nơi ảnh 360° được hienr thị, và hotspot được gán lên trên đó) có thể có số lượng hotspot kahcs nhau, ví dụ tại ngã ba thì số lượng hotspot sẽ nhiều hơn trên đường thẳng.
- pan=”0” và tilt=”0” là 2 biến để định vị trí của hotspot, 2 biến này quan hệ chặt chẽ với 2 biến lastPanAngle và lastTiltAngel trong flash.
- url=”hotspot.jpg” là đường dẫn đến file hình ảnh hiển thị cho hotspot.
- Zoom=”1” là mức độ zoom của hotspot, giá trị này thay đổi theo giá trị zoom của flash.
- Street và point là 2 thuộc tính xác định đường dẫn đến fie ảnh cần thiết
- onClick=”……….”, trong phần …. là đoạn script mà flash sẽ thực hiện khi ta click vào hotspot, ở chương trình của chúng ta, đơn giản chỉ là thay đổi đường dẫn tới thư mục có ảnh tương ứng.