Sổ tay kỹ thuật · Quy trình vận hành

Nạp dữ liệu vào WebGIS Quy hoạch

Cách đưa dữ liệu từ file CAD, shapefile, GeoJSON, KML/KMZ, GeoPackage, File Geodatabase, CSV và Excel vào kho 153 lớp chuẩn — làm sạch dữ liệu rác, tự động hoá số hoá từ bản vẽ, và giữ toạ độ chính xác tuyệt đối.

Chuẩn CSDL TT 16/2025/TT-BXD · 153 feature class · 2 142 cột Hệ toạ độ VN-2000 / TM-3 → lưu trữ EPSG:4326 Lõi xử lý GDAL/OGR 3.9+ · PostGIS
← Về ứng dụng WebGIS
00

Năm nguyên tắc bất di bất dịch

Mọi quyết định kỹ thuật đều phục vụ năm nguyên tắc này. Khi có mâu thuẫn, nguyên tắc thắng.

Nguyên tắc 1 — Không mất dữ liệu âm thầm

Mỗi đối tượng bị bỏ qua phải có lý do ghi lại được: không hình học, hình học rỗng sau khi sửa, nằm ngoài phạm vi, sai kiểu. Báo cáo nạp luôn nêu đã nạp / đã bỏ qua theo từng lớp. Con số "đã bỏ qua" khác 0 là cảnh báo cần người xem.

Nguyên tắc 2 — Bản gốc bất khả xâm phạm

Toàn bộ thuộc tính gốc giữ nguyên 100% trong cột props (JSONB). Cột "typed" chỉ là bản sao đã ép kiểu để truy vấn và vẽ; ép kiểu thất bại (vd "R8", "D300" vào cột số) thì cột typed nhận NULL nhưng props vẫn giữ chuỗi gốc.

Nguyên tắc 3 — Xem trước rồi mới ghi

Luồng bắt buộc: inspect (đọc cấu trúc) → preview (trả GeoJSON hiện trên bản đồ, không chạm CSDL) → run (ghi). Người vận hành thấy hình học và số lượng trước khi commit.

Nguyên tắc 4 — Một hệ quy chiếu lưu trữ

Mọi thứ về EPSG:4326 khi lưu. Nguồn VN-2000 nắn về WGS-84 một lần duy nhất lúc nạp bằng 7 tham số Helmert của tỉnh; gói tải xuống chiếu ngược về VN-2000. Không có phép chiếu trung gian nào khác.

Nguyên tắc 5 — Chính xác tuyệt đối = không tự ý dịch chuyển

"Làm sạch" nghĩa là sửa hình học không hợp lệ, khử nhiễu CAD, bắt điểm theo dung sai đã khai báo. Không co giãn, xoay, tịnh tiến, làm tròn toạ độ ngoài mức COORDINATE_PRECISION=8 (≈ 1 mm). Mọi thao tác snapping phải có tham số dung sai rõ ràng và ghi nhật ký.

Tám chặng của quy trình nạp

Mọi định dạng đầu vào đều đi qua đúng tám chặng. Khác biệt giữa các định dạng nằm ở chặng 2–4; từ chặng 5 dòng dữ liệu là một FeatureCollection GeoJSON WGS-84 thống nhất.

01 Tiếp nhận upload · giới hạn dung lượng 02 Nhận diện nguồn giải nén · chọn driver OGR 03 Thanh tra lớp · trường · CRS · rác 04 Phân loại & ánh xạ → 1 trong 153 lớp chuẩn 05 Làm sạch & nắn toạ độ makevalid · Helmert · snap 06 Xem trước GeoJSON · không ghi CSDL 07 Nạp giao dịch INSERT hàng loạt · props gốc 08 Hậu kiểm đối chiếu · tile · bounds

Chặng 4 & 5 tạo ra khác biệt: cùng một tuyến đường, đến từ .gdb thì đã đúng lớp đúng cột; đến từ .dxf thì phải suy ra từ tên lớp CAD và tự polygonize.

01

Tiếp nhận & nhận diện nguồn

File tải lên lưu vào thư mục phiên _incoming/<token>/ kèm giới hạn dung lượng (MAX_GDB_MB). Đuôi file quyết định bước chuẩn bị nhưng vẫn để OGR tự xác nhận driver ở chặng thanh tra.

Bảng 1 — Chuẩn bị theo đuôi file.
Đầu vàoBước chuẩn bịNguồn OGRDriver
.zipGiải nén, tìm theo ưu tiên: *.gdb/*.shp → geojson/gpkg/kml/tab/dxf/csvFile đầu tiên khớptự động
.gdb (.zip)Giải nén, lấy thư mục .gdb đầu tiênThư mục .gdbOpenFileGDB
.kmzGiải nén, lấy *.kml đầu tiênFile .kmlLIBKML/KML
.dxf / .dwgGiữ nguyênFile gốcCAD, hạ cấp DXF
.shpCần đủ .dbf .shx .prj .cpg đi kèmFile .shpESRI Shapefile
.geojson .json .gpkg .kml .tabGiữ nguyênFile gốctự động
.csv .xlsxGiữ nguyênFile gốcCSV / XLSX
Bẫy — Shapefile thiếu file đi kèm

Người dùng hay chỉ gửi mỗi .shp. Không có .dbf thì mất toàn bộ thuộc tính; không có .prj thì mất CRS. Xử lý: luôn yêu cầu gửi shapefile trong .zip; thấy .shp đơn lẻ thì báo rõ "thiếu .dbf/.prj" thay vì nạp im lặng.

02

Thanh tra: đọc trước khi động vào

ogrinfo -ro -so -json cho toàn bộ cấu trúc: danh sách lớp, kiểu hình học, số đối tượng, danh sách trường, WKT hệ toạ độ.

Rút CRS từ WKT

Regex bắt ID["EPSG",xxxx] ở cuối chuỗi WKT. Có mã EPSG → dùng thẳng. Chỉ có WKT không mã → đánh dấu "wkt". Không có gì → has_crs=false, hỏi người dùng chọn kinh tuyến trục.

Nhánh CAD: bóc tách theo lớp bản vẽ

DXF/DWG thường chỉ có một lớp OGR tên entities. Truy vấn SQLite gom theo trường "Layer""SubClasses" để dựng bảng phân rã cho bộ phân loại tự động.

SELECT "Layer" L, "SubClasses" SC, GeometryType(geometry) GT, count(*) N
FROM entities GROUP BY L, SC, GT;
Bảng 2 — Ánh xạ SubClasses DWG → vai trò.
SubClass AutoCADVai tròÝ nghĩa
AcDbHatch, AcDbFacepolygonVùng tô — ranh lô, khu chức năng
AcDbPolyline, AcDbLine, AcDbSpline, AcDbArc, AcDbCirclelineTuyến — chỉ giới, tim đường, hạ tầng
AcDbPoint, AcDbBlockReferencepoint / blockĐiểm — mốc, trạm, cột
AcDbText, AcDbMText, AcDbAttribute*textNhãn — không là đối tượng địa lý, chỉ gán thuộc tính
AcDbDimension, AcDbLeader, AcDbMLeaderjunkKích thước, đường dẫn chú thích — loại bỏ
03

Phân loại & ánh xạ vào 153 lớp chuẩn

Kho dữ liệu cố định: 153 feature class, 2 142 cột, dựng sẵn theo bốn file mẫu HienTrang / MocGioi / NenDiaHinh / QuyHoach.gdb. Nạp thêm chỉ được rót vào một trong các lớp này — không tạo lớp ngoài chuẩn. Bảng phi không gian đi vào kho chung x_table.

Nguồn đã đúng chuẩn (GDB / GPKG / SHP đặt tên chuẩn)

Ánh xạ theo tên feature class. Trùng khớp fc_name → chọn sẵn lớp đích, người vận hành xác nhận.

Nguồn tự do (CAD / KML / GeoJSON không theo chuẩn)

Dùng bộ luật cad_rules.yml. Mỗi luật khớp theo chuỗi con trong tên lớp và trả về:

  • rolekeep (nạp), annotation (làm nhãn), ignore (bỏ), unmatched (chờ chọn).
  • target — lớp đích <Nhóm>/<FcName>.
  • force_geom — ép kiểu hình học.
  • polygonize — nối LINESTRING khép kín thành POLYGON.
  • phanloai — gán phanLoai theo từ khoá trong tên lớp.
  • duongkinh_from_name — rút D300, Ø200 từ tên lớp vào duongKinh.
Bẫy — lớp CAD "unmatched" bị nạp nhầm chỗ

unmatched để trống lớp đích, buộc người vận hành chọn tay hoặc bỏ qua. Không đoán bừa — thà thiếu một lớp còn hơn có một lớp sai nằm lẫn trong CSDL.

Chuẩn hoá tên trường

Shapefile cắt tên còn 10 ký tự; ArcGIS xuất PascalCase. Bảng _FIELD_ALIASES + hàm _norm ánh xạ mọi biến thể về tên cột chuẩn. Giá trị gốc vẫn nằm nguyên trong props.

"8"            -> 8.0
"1 631 234,56" -> 1631234.56       # bỏ khoảng trắng, "," -> "."
"R8" "D300"    -> NULL (cột typed) # giữ "R8" trong props.banKinh
"25/12/2025"   -> "2025-12-25"     # dd/mm/yyyy -> ISO
"(null)" ""    -> NULL
04

Làm sạch hình học & nắn toạ độ

Chuyển đổi bằng ogr2ogr — bộ cờ chuẩn

ogr2ogr -f GeoJSON out.geojson SOURCE LAYER \
  -s_srs "<CRS nguồn>" -t_srs EPSG:4326 \
  -nlt PROMOTE_TO_MULTI \        # đồng nhất Multi*
  -makevalid \                   # SỬA hình học lỗi, không bỏ
  -lco COORDINATE_PRECISION=8 \  # ~1 mm
  -lco RFC7946=NO \
  -mapFieldType DateTime=String,Date=String,Time=String,\
IntegerList=String,RealList=String,StringList=String \
  -skipfailures                  # 1 feature hỏng không giết cả lớp

Nếu -makevalid lỗi ở OGR cũ → chạy lại không có cờ đó. Nếu kết quả rỗng và nguồn không có CRS → thử lại -a_srs EPSG:4326 (coi toạ độ như đã là kinh/vĩ độ).

VN-2000 → WGS-84: một phép nắn duy nhất

Ba kinh tuyến trục: 108°00′ (EPSG:5898, mặc định Quảng Ngãi), 107°45′, 107°30′.

+proj=tmerc +lat_0=0 +lon_0=108 +k=0.9999 +x_0=500000 +y_0=0
+ellps=WGS84
+towgs84=-191.90441429,-39.30318279,-111.45032835,
         -0.00928836,0.01975479,-0.00427372,0.252906278
+units=m +no_defs
Bẫy — sai kinh tuyến trục = lệch hàng trăm mét

File CAD gần như không bao giờ mang CRS. Chọn nhầm 107°45′ cho dữ liệu vẽ theo 108° thì cả đồ án lệch ~1–2 km về phía đông. Xử lý: ở bước xem trước chồng lên nền bản đồ — lệch KTT lộ ra ngay; thêm kiểm tra biên độ toạ độ X (500 000 ± vài chục km) để cảnh báo tự động.

Xử lý hình học trong PostGIS (khi gộp / polygonize)

Bảng 3 — Hàm PostGIS ở chặng làm sạch. Kết quả cuối luôn qua ST_Force2D.
Tình huốngHàmGhi chú
Vòng LINESTRING khép kín → vùngST_Polygonize(ST_Collect(ST_MakeValid(…)))Dựng vùng từ mạng tuyến CAD
Nối nhiều tuyến rời thành 1ST_LineMerge(ST_UnaryUnion(ST_Collect(g)))"1 tuyến = 1 đối tượng"
Hợp nhiều vùng thành 1ST_UnaryUnion(ST_Collect(g))Giữ thuộc tính chung
Gộp điểmST_CollectionHomogenize(ST_Collect(g))ST_MakeValid lỗi với POINT ở bản này
GEOMETRYCOLLECTION / CircularString từ makevalidST_CollectionExtract(ST_CurveToLine(geom), dim)Ép về kiểu đơn theo FC đích
05

Bảng tra nhanh theo định dạng

Bảng 4 — Rác điển hình & điểm cần canh theo từng định dạng.
Định dạngCRS đến từ đâuRác / rủi roXử lý bắt buộc
DXF / DWGKhông có. Chọn KTT. Dimension & leader lẫn vào tuyến; text hiểu thành điểm; polyline hở không thành vùng; block lồng hình học; Z rác; đơn vị mm/cm lẫn m. Bóc theo lớp CAD; loại junk; text → annotation; polygonize; force_geom; kiểm biên độ toạ độ.
SHP (.zip).prj. Không có → hỏi. Tên trường cắt 10 ký tự; encoding .dbf sai → tiếng Việt vỡ; ranh giới nhiều phần bị tách; đỉnh trùng. Gửi kèm .cpg/.prj; _FIELD_ALIASES; PROMOTE_TO_MULTI; -makevalid.
GeoJSONLuôn WGS-84. Đôi khi mang toạ độ mét chưa reproject; polygon quấn ngược chiều; null geometry; thuộc tính lồng object. Kiểm biên độ toạ độ (>180 ⇒ chưa reproject); phẳng hoá thuộc tính lồng vào props.
KML / KMZLuôn WGS-84. Thuộc tính nằm trong HTML mô tả; MultiGeometry trộn kiểu; style lẫn dữ liệu; placemark rỗng. Bóc bảng thuộc tính từ ExtendedData; tách kiểu bằng geom_kind; loại placemark không hình học.
GPKGBảng gpkg_spatial_ref_sys — đáng tin. Nhiều lớp trong 1 file; lớp aspatial lẫn spatial; trigger vướng khi đọc nhanh. Liệt kê toàn bộ lớp ở thanh tra; lớp aspatial → x_table.
GDB (.zip)WKT metadata lớp — chính xác nhất. Feature dataset lồng nhau; domain coded-value; quan hệ (relationship class); subtype; cột SHAPE_Length/Area tự sinh. Đọc dataset để giữ nhóm; áp domain để giải mã coded-value; quan hệ & bảng → x_table.
CSVKhông có. Cần cột toạ độ hoặc WKT. Dấu phân cách lẫn (,/;/tab); BOM đầu file; số kiểu Việt 1.234,5; tiêu đề kép; ô trống vs "0". Auto-detect delimiter + đọc utf-8-sig; khai báo cột X/Y hoặc WKT + CRS; bỏ dòng nhãn tiếng Việt.
XLSXKhông có (như CSV). Nhiều sheet; ô gộp; công thức chưa tính giá trị; ngày Excel serial; hàng/cột trống chèn giữa. Chọn sheet rõ ràng; đọc data_only; bỏ hàng rỗng; ngày serial → ISO.
06

Phân loại dữ liệu rác & cách xử lý

"Rác" chia làm ba mức. Đỏ phải chặn hoặc sửa trước khi nạp; vàng nạp được nhưng phải ghi cảnh báo; xanh xử lý tự động.

Hình học tự cắt / vòng hở

Polygon biên tự giao; polyline "gần khép" đầu–cuối cách vài cm.

Sửa: ST_MakeValid cho tự cắt; bắt điểm đầu–cuối theo dung sai (đề xuất 0,02 m) rồi ST_Polygonize.

Hình học rỗng sau khi sửa

Polygon suy biến, tuyến độ dài 0, điểm trùng nhau hoàn toàn.

Sửa: loại bỏ, ghi vào danh sách bị bỏ kèm lý do. Không đếm vào "đã nạp".

Toạ độ ngoài miền

X không quanh 500 000; điểm rơi ra biển; đơn vị mm lẫn m khiến vật to gấp 1000 lần.

Sửa: kiểm biên độ bounding-box trước khi nạp; lệch > ngưỡng → chặn, báo "kiểm tra lại KTT / đơn vị".

Nhiễu CAD

Dimension, leader, mtext, hatch trang trí, khung bản vẽ, ghi chú kỹ thuật.

Sửa: phân rã theo SubClassesjunk; lớp tên "GHICHU"/"KHUNG"/"TITLE" → role: ignore.

Đỉnh trùng & sliver

Cạnh lô hàng chục đỉnh cách nhau < 1 mm; mảnh vùng < 0,5 m² kẹp giữa hai lô.

Sửa: ST_SnapToGrid theo lưới dung sai; lọc vùng theo ngưỡng diện tích tối thiểu, báo cáo số bị lọc.

Trùng lặp đối tượng

Cùng tuyến vẽ hai lần chồng khít; feature lặp do nhập nhiều lần.

Sửa: hash hình học đã snap + khoá thuộc tính; trùng → giữ 1, ghi log số bản sao đã loại.

Thuộc tính "gần rỗng"

"(null)", "N/A", "-", khoảng trắng, "#".

Sửa: danh sách token rỗng → NULL ở cột typed; vẫn giữ nguyên trong props.

Toạ độ Z thừa

File CAD/GDB mang cao độ Z trong khi bảng geom là 2D.

Tự động: ST_Force2D ở mọi lối ghi. Cao độ thật nằm ở cột caoDo*.

Kiểu hình học hỗn hợp

Lớp lẫn Polygon + MultiPolygon; KML MultiGeometry trộn line và point.

Tự động: PROMOTE_TO_MULTI; lọc theo geom_kind đã chọn.

Sai kiểu giá trị

"R8" vào cột số, "12,5" phẩy thập phân, ngày dd/mm/yyyy.

Tự động (khi NẠP HÀNG LOẠT): ép mềm — fail thì NULL ở cột typed, props giữ gốc. Khi SỬA TAY trên bảng: nghiêm ngặt — báo lỗi, không cho lưu sai kiểu.

Encoding tiếng Việt

DBF Windows-1258, CSV có BOM, XLSX ô chuỗi lẫn số.

Tự động: đọc utf-8-sig; tôn trọng .cpg; OGR -oo ENCODING=.

Feature không hình học

Placemark rỗng, dòng CSV thiếu toạ độ, bảng quan hệ trong GDB.

Tự động: có bảng thuộc tính → x_table; thật sự rỗng → bỏ qua, đếm vào "đã bỏ qua".

07

Cổng kiểm soát chất lượng & nghiệm thu

Sau chặng nạp, báo cáo nghiệm thu đối chiếu nguồn với đích. Ngưỡng dưới là gợi ý khởi điểm — mọi lần vượt ngưỡng phải có người xác nhận.

  • Đối soát số lượng|nguồn − đích| = đã bỏ qua Số feature nguồn trừ số đã nạp phải bằng đúng số ghi trong "đã bỏ qua". Chênh không giải thích được ⇒ dừng.
  • Hình học hợp lệ≥ 99,5 % ST_IsValid trên toàn lớp sau khi nạp. Phần còn lại phải nằm trong log makevalid.
  • Độ đầy cột khoámaDoiTuong ≥ 95 % Cột định danh phải gần đầy; rỗng nhiều ⇒ nguồn thiếu hoặc ánh xạ sai tên trường.
  • Biên độ toạ độX = 500 000 ± 80 km Bounding-box lớp sau khi nắn phải nằm trong phạm vi hành chính tỉnh.
  • Trùng lặp= 0 cặp trùng khít Không còn feature trùng hình học + khoá thuộc tính sau khi khử.
  • Topology lớp vùng0 overlap · gap < ngưỡng Với lớp phủ kín: không chồng lấn; khe hở nhỏ hơn dung sai bắt điểm.
  • Bảo toàn thuộc tính gốcprops ⊇ mọi trường nguồn Mọi tên trường của nguồn xuất hiện trong props ít nhất một dòng.
08

Lộ trình nâng cấp — nạp thông minh hơn

Quy trình hiện tại đủ chắc để không mất dữ liệu. Mười hạng mục sau nâng nó lên "tự động hoá cao, chính xác kiểm chứng được".

Nâng cấp 1 — Bảng dàn & đối sánh (staging + diff)

Nạp vào bảng tạm trước, so khớp theo maDoiTuong, sinh báo cáo thêm / sửa / xoá. Người vận hành duyệt bản diff rồi mới commit.

Nâng cấp 2 — Snapping có cấu hình theo lớp

Khai báo dung sai bắt điểm cho từng nhóm lớp (ranh lô 0,02 m; tuyến hạ tầng 0,05 m; mốc 0). Dùng ST_Snap/ST_SnapToGrid khử đỉnh trùng, khép vòng, làm khít ranh giới chung — chỉ trong dung sai đã ký, ghi số đỉnh bị dịch.

Nâng cấp 3 — Phát hiện & gộp trùng lặp

Hash hình học chuẩn hoá + khoá thuộc tính. Trùng khít → giữ một; trùng một phần → đánh dấu để xử lý.

Nâng cấp 4 — Kiểm tra topology tự động

Với lớp phủ kín: quét overlap, gap, sliver, dangle ngay trong bước xem trước và tô đỏ trên bản đồ — thấy lỗi trước khi ghi.

Nâng cấp 5 — Trình biên tập luật ánh xạ trên web

Sửa cad_rules.yml qua giao diện; học từ lịch sử: lớp CAD tên tương tự → gợi ý lớp đích đã dùng.

Nâng cấp 6 — Hàng đợi & xử lý song song

Nạp nhiều lớp/file cùng lúc qua hàng đợi worker, tiến độ realtime. GDB lớn không khoá cả phiên.

Nâng cấp 7 — Nhật ký nguồn gốc (provenance)

Mỗi feature ghi: file nguồn, lớp nguồn, phiên nạp, người nạp, thời điểm, bộ cờ ogr2ogr đã dùng.

Nâng cấp 8 — Báo cáo nghiệm thu xuất PDF

Tự dựng từ §07: đối soát số lượng, % hình học hợp lệ, độ đầy cột, danh sách bị bỏ kèm lý do, ảnh bản đồ trước/sau. Đính kèm hồ sơ đồ án.

Nâng cấp 9 — Giải mã coded-value từ domain GDB

Đọc domain File Geodatabase, thay giá trị số bằng nhãn (1 → "Đất ở đô thị").

Nâng cấp 10 — Nhận diện đơn vị & KTT tự động

Từ biên độ toạ độ và mật độ đỉnh, đoán đơn vị (m/mm) và kinh tuyến trục, đề xuất sẵn — giảm hẳn lỗi lệch KTT.