Tổ chức triển khai

Một phần của tài liệu Một số thuật toán khái quát hóa bản đồ và ứng dụng (Trang 63)

Phần mềm đƣợc xây dựng phát triển trên môi trƣờng Microsoft Visual Studio 2010.

- Thƣ mục Core lƣu trữ các project lõi của DotSpatial, cung cấp các chức năng, API phục vụ xây dựng chƣơng trình khái quá hóa.

- Thƣ mục MapGeneralization chứa project chính của chƣơng trình khái quá hóa. - Thƣ mục Plugins chứa các project đƣợc xây dựng cung cấp, mở rộng các chức năng cho chƣơng trình chính.

Project MapGeneralizationPlugin

Cài đặt triển khai các chức năng khái quát hóa. Sử dụng các thuật toán đơn giản hóa đƣờng cong.

59

Cài đặt thuật toán Douglas- Peucker

+ Thuật toán đƣợc cài đặt trong file clsDouglasPeucker.cs

/// <summary>

/// Khái quát hóa đối tượng dạng đường

/// Sử dụng thuật toán Douglas-Peucker

/// </summary>

public class DouglasPeuckerSimplifyLine

{

//Khai báo các biến toàn cục

private readonly IList<Point> _pts; private bool[] _usePoint;

private double _tolerance;

private readonly LineSegment _seg = new LineSegment(); /// <summary>

/// Đơn giải hóa đường

/// </summary>

/// <param name="pts">Danh sách các điểm</param>

/// <param name="distanceTolerance">Dung sai</param>

/// <returns>Trả lại kết quả là tập điểm được giữ lại</returns>

public static IList<Point> Simplify(IList<Point> pts, double distanceTolerance)

{

DouglasPeuckerSimplifyLine simplify = new

DouglasPeuckerSimplifyLine(pts); simplify._tolerance = distanceTolerance; return simplify.Simplify(); } /// <summary> /// Hàm khởi tạo /// </summary>

/// <param name="pts">Danh sách điểm</param>

private DouglasPeuckerSimplifyLine(IList<Point> pts) {

_pts = pts; }

/// <summary>

/// Đơn giản hóa tập điểm _pts

/// </summary>

/// <returns></returns>

private Point[] Simplify() {

//Khởi tạo mảng bool với số phần tử bằng số lượng điểm của //đường cần giản lược

_usePoint = new bool[_pts.Count];

//Gán giá trị true cho mảng bool _usePoint

for (int i = 0; i < _pts.Count; i++) _usePoint[i] = true;

60

//Gọi hàm đơn giản hóa với đường ban đầu - vị trí điểm đầu, //điểu cuối

SimplifyLine(0, _pts.Count - 1);

//Khai báo list chứa các điểm giữ lại của đường

PointList pointList = new PointList(); //Duyệt qua danh sách điểm ban đầu

for (int i = 0; i < _pts.Count; i++)

//Nếu điểm thứ i được giữ lại (_usePoint[i] = true), thì đưa //điểm đó vào danh sách kết quả

if (_usePoint[i])

pointList.Add(new Point(_pts[i])); //Trả lại kết quả là tập điểm được giữ lại

return pointList.ToPointArray(); }

/// <summary>

/// Đơn giản hóa một đoạn trên đường gốc

/// </summary>

/// <param name="i">điểm đầu đoạn</param>

/// <param name="j">điểm cuối đoạn</param>

private void SimplifyLine(int i, int j) {

//Nếu từ i đến j là một đoạn thẳng

if ((i + 1) == j) return;

//Khởi tạo một đường thẳng

_seg.P0 = _pts[i]; _seg.P1 = _pts[j];

//Khởi tạo giá trị khoảng cách lớn nhất từ các điểm đến đường //thẳng _seg

double maxDistance = -1.0;

//Vị trí của điểm có khoảng cách lớn nhất tới đường thẳng _seg

int maxIndex = i;

//Duyệt danh sách điểm từ i đến j của đường ban đầu

for (int k = i + 1; k < j; k++) {

//Tính khoảng cách từ điểm thứ k tới đường i-j

double distance = _seg.Distance(_pts[k]);

//Xác định khoảng cách lớn nhất, và vị trị điểm có khoảng //cách lớn nhất if (distance > maxDistance) { maxDistance = distance; maxIndex = k; }

61 }

//Nếu khoảng cách lớn nhất <= dung sai

if (maxDistance <= _tolerance)

//Bỏ hết các điểm nằm trong khoảng từ i đến j

for (int k = i + 1; k < j; k++) _usePoint[k] = false;

//Xác định được một điểm có khoảng cách lớn nhất, lớn hơn dung //sai

else {

//Thực hiện đơn giản trên 2 đường mới được tạo ra,

//bẻ gẫy tại vị trí điểm có khoảng cách lớn nhất

//Đơn giản đường 1 từ i đến vị trí điểm có khoảng cách lớn //nhất

SimplifyLine(i, maxIndex);

//Đơn giản đường 2 ưừ vị trí điểm có khoảng cách lớn nhất //đến j

SimplifyLine(maxIndex, j); }

} }

62

Cài đặt thuật toán Reumann-Witkam

+ Thuật toán đƣợc cài đặt trong file clsReumannWitkam.cs /// <summary>

/// Khái quát hóa đối tượng dạng đường

/// Sử dụng thuật toán Reumann-Witkam

/// </summary>

public class ReumannWitkamSimplify

{

//Khai báo các biến toàn cục

private readonly IList<Point> _pts; private double _tolerance;

private readonly LineSegment _seg = new LineSegment(); /// <summary>

/// Đơn giải hóa đường

/// </summary>

/// <param name="pts">Danh sách các điểm</param>

/// <param name="distanceTolerance">Dung sai</param>

/// <returns>Trả lại kết quả là tập điểm được giữ lại</returns>

public static IList<Point> Simplify(IList<Point> pts, double distanceTolerance)

{

ReumannWitkamSimplify simplify = new

ReumannWitkamSimplify(pts); simplify._tolerance = distanceTolerance; return simplify.Simplify(); } /// <summary> /// Hàm khởi tạo /// </summary>

/// <param name="pts">Danh sách điểm</param>

private ReumannWitkamSimplify(IList<Point> pts) {

_pts = pts; }

/// <summary>

/// Đơn giản hóa tập điểm _pts

/// </summary>

/// <returns></returns>

private Point[] Simplify() {

//Số lượng điểm của đường cần giản lược

int pointCount = _pts.Count();

//Khai báo list chứa các điểm giữ lại của đường

PointList pointList = new PointList();

63

if (pointCount < 3 || _tolerance == 0) {

pointList.Add(new Point(_pts[0])); pointList.Add(new Point(_pts[1]));

//Trả lại kết quả là tập điểm được giữ lại

return pointList.ToPointArray(); }

//Khai báo các điểm cần kiểm tra

Point p0 = _pts[0]; Point p1 = _pts[1]; Point pi = p1; Point pj = p1;

//Điểm đầu tiên của đường được đưa vào kết quả

pointList.Add(new Point(_pts[0]));

//Kiểm tra các điểm _pts[j] sau đường thẳng _seg(_pts[0], //_pts[1])

for (int j = 2; j < pointCount; j++) {

pi = pj; pj = _pts[j];

//Tính khoảng cách từ điểm thứ j tới đường p0-p1

_seg.P0 = p0; _seg.P1 = p1;

double distance = _seg.Distance(_pts[j]);

//Nếu khoảng cách từ _pts[j] tới đường _seg[p0, p1] < dung //sai

if (distance < _tolerance) {

continue; }

//Khoảng cách từ pj tới đường _seg[p0, p1] > dung sai

//Đưa điểm pi trước pj vào kết quả

pointList.Add(new Point(pi)); //Cập nhật điểm mới p0 = pi; p1 = pj; _seg.P0 = p0; _seg.P1 = p1; }

//Điểm cuối của đường được đưa vào kết quả

pointList.Add(new Point(pj));

//Trả lại kết quả là tập điểm được giữ lại

return pointList.ToPointArray(); }

64 }

+ Giao diện của chức năng

Cài đặt thuật toán sử dụng điểm độc lập

+ Thuật toán đƣợc cài đặt trong file clsNPoint.cs

/// <summary>

/// Khái quát hóa đối tượng dạng đường

/// Sử dụng thuật toán sử dụng điểm độc lập

/// </summary>

public class clsNPointSimplify

{

//Khai báo các biến toàn cục

private readonly IList<Point> _pts; private int _nPoint;

private readonly LineSegment _seg = new LineSegment(); /// <summary>

/// Đơn giải hóa đường

/// </summary>

/// <param name="pts">Danh sách các điểm</param>

/// <param name="nPoint">Chu kỳ lấy điểm</param>

/// <returns>Trả lại kết quả là tập điểm được giữ lại</returns>

public static IList<Point> Simplify(IList<Point> pts, int nPoint) {

clsNPointSimplify simplify = new clsNPointSimplify(pts); simplify._nPoint = nPoint;

return simplify.Simplify(); }

65 /// <summary>

/// Hàm khởi tạo

/// </summary>

/// <param name="pts">Danh sách điểm</param>

private clsNPointSimplify(IList<Point> pts) {

_pts = pts; }

/// <summary>

/// Đơn giản hóa tập điểm _pts

/// </summary>

/// <returns></returns>

private Point[] Simplify() {

//Số lượng điểm của đường cần giản lược

int pointCount = _pts.Count();

//Khai báo list chứa các điểm giữ lại của đường

PointList pointList = new PointList();

//Kiểm tra thỏa mãn điều kiện để thực hiện giản lược hóa

if (pointCount < 3 || _nPoint < 2) {

pointList.Add(new Point(_pts[0])); pointList.Add(new Point(_pts[1]));

//Trả lại kết quả là tập điểm được giữ lại

return pointList.ToPointArray(); }

//Điểm đầu tiên của đường được đưa vào kết quả

pointList.Add(new Point(_pts[0])); bool bMove = true;

int intIndex = 0;

//Lấy điểm theo chu kỳ nPoint

while (bMove) {

//Xác định vị trí cần lấy tiếp theo

intIndex += _nPoint;

//Nếu vị trí lấy vượt quá hoặc số lượng điểm của _pts

if (intIndex >= _pts.Count() - 1) {

//Đưa điểm cuối vào danh sách kết quả

pointList.Add(new Point(_pts[_pts.Count() - 1])); bMove = false;

} else {

//Đưa điểm thứ intIndex vào kết quả

pointList.Add(new Point(_pts[intIndex])); }

66 }

//Trả lại kết quả là tập điểm được giữ lại

return pointList.ToPointArray(); }

}

67

Một phần của tài liệu Một số thuật toán khái quát hóa bản đồ và ứng dụng (Trang 63)

Tải bản đầy đủ (PDF)

(78 trang)