| 160 | | === 5.2 Додавање на колоната location (geography Point) === |
| 161 | | |
| 162 | | Главната просторна колона е {{{location}}}, која ги обединува latitude и longitude во една PostGIS геометрија: |
| 163 | | |
| 164 | | {{{ |
| 165 | | #!sql |
| 166 | | ALTER TABLE airport |
| 167 | | ADD COLUMN location geography(Point, 4326); |
| 168 | | |
| 169 | | UPDATE airport |
| 170 | | SET location = ST_MakePoint(longitude, latitude)::geography; |
| 171 | | }}} |
| 172 | | |
| 173 | | Неколку важни детали: |
| 174 | | |
| 175 | | * '''Тип {{{geography(Point, 4326)}}}.''' PostGIS нуди два главни типа на просторни податоци: {{{geometry}}} (рамна, евклидска геометрија) и {{{geography}}} (вистинска сферна геометрија на Земјата). За авиокомпаниски проект, {{{geography}}} е правилниот избор бидејќи летовите се на голема скала и кривината на Земјата е значајна — растојанијата мора да се мерат како great-circle distances, а не како евклидски растојанија. |
| 176 | | * '''SRID 4326.''' Ова е стандардот WGS 84 (World Geodetic System 1984), истиот референтен систем кој го користат GPS уредите. Со ова, координатите од нашиот CSV (кои се во WGS 84) се компатибилни со колоната без потреба од репроекција. |
| 177 | | * '''Редослед на параметри: {{{ST_MakePoint(longitude, latitude)}}}.''' PostGIS следи XY-конвенција, што значи дека longitude е X (надолжна, „хоризонтална" оска) и latitude е Y. Замена на овие два параметра е честа грешка која води до точки во погрешен дел на светот. |
| 178 | | |
| 179 | | === 5.3 Просторен GIST индекс === |
| 180 | | |
| 181 | | За да може PostGIS брзо да изврши просторни прашалници врз милиони редици, на колоната {{{location}}} се додаде GIST индекс: |
| 182 | | |
| 183 | | {{{ |
| 184 | | #!sql |
| 185 | | CREATE INDEX idx_airport_location ON airport USING GIST (location); |
| 186 | | }}} |
| 187 | | |
| 188 | | За разлика од B-tree индексите (кои се користат за подредени скаларни вредности — броеви, текстови, датуми), GIST индексите се специјализирани за повеќедимензионални податоци. Тие овозможуваат: |
| 189 | | |
| 190 | | * '''Range queries во просторот''' — „пронајди ги сите аеродроми во радиус од 500 km околу точката X" |
| 191 | | * '''Nearest-neighbor queries''' — „пронајди ги најблиските 10 аеродроми од дадена точка", преку K-nearest-neighbor операторот {{{<->}}} |
| 192 | | * '''Intersection queries''' — „пронајди ги сите рути кои поминуваат низ дадена област" |
| 193 | | |
| 194 | | Без GIST индекс, секоја таква претрага би била sequential scan низ целата табела. |
| 195 | | |
| 196 | | ---- |
| 197 | | |
| 198 | | == 6. Поглед FlightRoutes == |
| 199 | | |
| 200 | | Создаден е нов поглед кој ги претставува летовите како геометриски линии на мапата: |
| 201 | | |
| 202 | | {{{ |
| 203 | | #!sql |
| 204 | | CREATE VIEW FlightRoutes (FlightID, FlightNumber, Departure, Arrival, |
| 205 | | Origin, Destination, Route, Distance) AS |
| 206 | | SELECT flight.id, flight.flightnumber, |
| 207 | | flight.departure, flight.arrival, |
| 208 | | ad.code, aa.code, |
| 209 | | ST_MakeLine(ad.location::geometry, aa.location::geometry), |
| 210 | | scheduledflight.distance |
| 211 | | FROM flight |
| 212 | | JOIN gate AS ga ON flight.actualgatearrivalid = ga.id |
| 213 | | JOIN gate AS gd ON flight.actualgatedepartureid = gd.id |
| 214 | | JOIN terminal AS ta ON ta.id = ga.terminalid |
| 215 | | JOIN terminal AS td ON td.id = gd.terminalid |
| 216 | | JOIN airport AS aa ON aa.id = ta.airportid |
| 217 | | JOIN airport AS ad ON ad.id = td.airportid |
| 218 | | JOIN scheduledflight ON flight.scheduleid = scheduledflight.id |
| 219 | | WHERE aa.location IS NOT NULL AND ad.location IS NOT NULL; |
| 220 | | }}} |
| 221 | | |
| 222 | | '''Како функционира:''' |
| 223 | | |
| 224 | | * Функцијата {{{ST_MakeLine(departure_point, arrival_point)}}} гради {{{LineString}}} геометрија — права линија помеѓу две точки во геометрискиот простор. |
| 225 | | * Низ ланецот од JOIN-ови, погледот ги доведува аеродромите за полетување и слетување на секој лет (преку gate → terminal → airport). |
| 226 | | * Резултатот е една редица по лет, со полно име, временски печат, кодови на полетниот и слетниот аеродром, реална географска линија помеѓу нив и пресметана дистанца. |
| 227 | | |
| 228 | | '''Случаи на употреба:''' |
| 229 | | |
| 230 | | * '''Визуелизација во QGIS''' — погледот може да се вчита како просторен слој и да прикаже сите рути на мапа. |
| 231 | | * '''Мрежна анализа''' — кои аеродроми се најпрометни, кои рути се најфреквентни, која е географската покриеност на авиокомпанијата. |
| 232 | | * '''Просторни прашалници''' — на пример, „кои летови поминуваат во радиус од 200 km околу одредена точка" може да се изврши со {{{ST_DWithin}}} врз колоната {{{Route}}}. |
| 233 | | |
| 234 | | === 6.1 Скриншоти === |
| 235 | | |
| 236 | | '''Сите аеродроми на светот:'''[[BR]] |
| 237 | | [[Image(Screenshots/World-Airports.png)]] |
| 238 | | |
| 239 | | '''Аеродроми на Балканот:'''[[BR]] |
| 240 | | [[Image(Screenshots/Balkan.png)]] |
| 241 | | |
| 242 | | '''Рути од Скопје:'''[[BR]] |
| 243 | | [[Image(Screenshots/RoutesFromSkopje.png)]] |
| 244 | | |
| 245 | | '''Рути до Newark (EWR):'''[[BR]] |
| 246 | | [[Image(Screenshots/RoutesToNewark.png)]] |
| 247 | | |
| 248 | | ---- |
| 249 | | |
| 250 | | == 7. Ажурирање на дистанците во ScheduledFlight == |
| 251 | | |
| 252 | | Една од најважните придобивки на PostGIS во овој проект е замена на лажните, синтетички дистанци со вистински географски вредности. |
| 253 | | |
| 254 | | {{{ |
| 255 | | #!sql |
| 256 | | UPDATE scheduledflight AS sf |
| 257 | | SET distance = GREATEST(1, ROUND(ST_Distance(dep.location, arr.location) / 1000)::int) |
| 258 | | FROM slot AS ds |
| 259 | | JOIN gate AS dg ON ds.gateid = dg.id |
| 260 | | JOIN terminal AS dt ON dg.terminalid = dt.id |
| 261 | | JOIN airport AS dep ON dep.id = dt.airportid, |
| 262 | | slot AS asl |
| 263 | | JOIN gate AS ag ON asl.gateid = ag.id |
| 264 | | JOIN terminal AS at ON at.id = ag.terminalid |
| 265 | | JOIN airport AS arr ON arr.id = at.airportid |
| 266 | | WHERE sf.departure = ds.id |
| 267 | | AND sf.arrival = asl.id |
| 268 | | AND dep.location IS NOT NULL |
| 269 | | AND arr.location IS NOT NULL; |
| 270 | | }}} |
| 271 | | |
| 272 | | '''Детали за пресметката:''' |
| 273 | | |
| 274 | | * {{{ST_Distance(dep.location, arr.location)}}} враќа great-circle дистанца помеѓу две {{{geography}}} точки во метри. |
| 275 | | * Делењето со 1000 ја претвора во километри. |
| 276 | | * {{{ROUND(...)::int}}} ја кружи до цел број за да одговара на типот на колоната. |
| 277 | | * {{{GREATEST(1, ...)}}} гарантира минимална вредност од 1 km (поради CHECK ограничувањето {{{distance > 0}}}). Ова е важно за ретки случаи каде два аеродроми се толку близу што дистанцата заокружена на километри би била 0. |
| 278 | | |
| 279 | | '''Последица низ остатокот на системот:''' |
| 280 | | |
| 281 | | Постоечкиот тригер {{{AwardMilePoints}}} (од Фаза 4) ги пресметува миљните поени на патниците врз основа на {{{ScheduledFlight.Distance}}}, помножена со множител по класа (Economy: 1×, Business: 2×, First: 3×). По ова ажурирање, поените повеќе не се „измислени" — патник со First класа на лет JFK → LAX добива ~4000 km × 3 = 12,000 поени, што одговара на реално долг лет. |
| 282 | | |
| 283 | | ---- |
| 284 | | |
| 285 | | == 8. Тригер SetDistance (CalculateDistance) == |
| 286 | | |
| 287 | | За да не мора рачно да се пресметува дистанцата секогаш кога ќе се додаде нов закажан лет, имплементиран е тригер кој автоматски ја пресметува: |
| 288 | | |
| 289 | | {{{ |
| 290 | | #!sql |
| 291 | | CREATE OR REPLACE FUNCTION CalculateDistance() |
| 292 | | RETURNS trigger AS $$ |
| 293 | | BEGIN |
| 294 | | SELECT GREATEST(1, ROUND(ST_Distance(dep.location, arr.location) / 1000)::int) |
| 295 | | INTO NEW.distance |
| 296 | | FROM slot AS ds |
| 297 | | JOIN gate AS dg ON ds.gateid = dg.id |
| 298 | | JOIN terminal AS dt ON dg.terminalid = dt.id |
| 299 | | JOIN airport AS dep ON dep.id = dt.airportid, |
| 300 | | slot AS asl |
| 301 | | JOIN gate AS ag ON asl.gateid = ag.id |
| 302 | | JOIN terminal AS at ON at.id = ag.terminalid |
| 303 | | JOIN airport AS arr ON arr.id = at.airportid |
| 304 | | WHERE NEW.departure = ds.id |
| 305 | | AND NEW.arrival = asl.id |
| 306 | | AND dep.location IS NOT NULL |
| 307 | | AND arr.location IS NOT NULL; |
| 308 | | |
| 309 | | RETURN NEW; |
| 310 | | END; |
| 311 | | $$ LANGUAGE plpgsql; |
| 312 | | |
| 313 | | CREATE TRIGGER SetDistance |
| 314 | | BEFORE INSERT OR UPDATE OF departure, arrival ON scheduledflight |
| 315 | | FOR EACH ROW EXECUTE FUNCTION CalculateDistance(); |
| 316 | | }}} |
| 317 | | |
| 318 | | '''Карактеристики:''' |
| 319 | | |
| 320 | | * '''{{{BEFORE INSERT OR UPDATE}}}''' — тригерот се извршува ''пред'' редицата да биде впишана/ажурирана. Тоа му овозможува да ја смени вредноста на {{{NEW.distance}}} пред таа да биде валидирана од CHECK ограничувањата. |
| 321 | | * '''{{{UPDATE OF departure, arrival}}}''' — тригерот се извршува само кога овие конкретни колони се менуваат. Доколку се ажурира некоја друга колона (на пример, {{{active}}}), тригерот не се активира — оптимизација која штеди непотребна работа. |
| 322 | | * '''{{{SELECT ... INTO NEW.distance}}}''' — наместо да враќа вредност на повикувачот, тригерот ја менува вредноста на {{{NEW}}} пред commit-ирање. |
| 323 | | |
| 324 | | '''Зошто тригер наместо generated column?''' PostgreSQL поддржува {{{GENERATED ALWAYS AS (...) STORED}}} колони, но тие не можат да користат subqueries или JOIN-ови (бидејќи мораат да бидат детерминистички и без странични ефекти). Бидејќи пресметката на дистанцата бара JOIN преку {{{slot → gate → terminal → airport}}}, мораше да се користи тригер. |
| 325 | | |
| 326 | | '''Случај на употреба:''' доколку во иднина се додадат нови закажани летови (нови дестинации, проширување на мрежата), нивната дистанца автоматски се пресметува правилно — администраторот не мора да внимава да ја внесе како посебен чекор. |
| 327 | | |
| 328 | | ---- |
| 329 | | |
| 330 | | == 9. Функција FindNearestAirport == |
| 331 | | |
| 332 | | {{{ |
| 333 | | #!sql |
| 334 | | CREATE OR REPLACE FUNCTION FindNearestAirport( |
| 335 | | longitude_P numeric, |
| 336 | | latitude_P numeric, |
| 337 | | distanceKm int |
| 338 | | ) RETURNS TABLE ( |
| 339 | | AirportCode char(3), |
| 340 | | AirportName text, |
| 341 | | AirportLocation geography(Point, 4326), |
| 342 | | Distance_KM numeric |
| 343 | | ) AS $$ |
| 344 | | BEGIN |
| 345 | | RETURN QUERY |
| 346 | | SELECT a.code, a.name, a.location, |
| 347 | | (ST_Distance(a.location, ST_MakePoint(longitude_P, latitude_P)::geography) / 1000)::numeric |
| 348 | | FROM airport AS a |
| 349 | | WHERE ST_DWithin( |
| 350 | | a.location, |
| 351 | | ST_MakePoint(longitude_P, latitude_P)::geography, |
| 352 | | distanceKm * 1000 |
| 353 | | ) |
| 354 | | ORDER BY a.location <-> ST_MakePoint(longitude_P, latitude_P)::geography; |
| 355 | | END; |
| 356 | | $$ LANGUAGE plpgsql; |
| 357 | | }}} |
| 358 | | |
| 359 | | '''Како функционира:''' |
| 360 | | |
| 361 | | * Прима три параметри: longitude и latitude на референтна точка, плус максимален радиус во километри. |
| 362 | | * Враќа табела на сите аеродроми во тој радиус, заедно со нивната локација и точното растојание. |
| 363 | | * Резултатите се сортирани по растојание — најблискиот аеродром е прв. |
| 364 | | |
| 365 | | '''Клучни PostGIS компоненти:''' |
| 366 | | |
| 367 | | * '''{{{ST_DWithin(geog_a, geog_b, distance_meters)}}}''' — враќа TRUE доколку две географски точки се на растојание помало или еднакво на дадениот број метри. Ова е првиот филтер кој го „сече" пребарувањето. |
| 368 | | * '''Множењето {{{distanceKm * 1000}}}''' ги претвора километрите во метри (PostGIS интерно работи во метри за geography). |
| 369 | | * '''KNN оператор {{{<->}}}''' — посебен оператор за nearest-neighbor сортирање. За разлика од обичен {{{ORDER BY ST_Distance(...)}}}, овој оператор го користи GIST индексот директно и е значајно побрз при големи табели. |
| 370 | | |
| 371 | | '''Случаи на употреба:''' |
| 372 | | |
| 373 | | * '''Препораки за алтернативни аеродроми''' — кога одреден лет се откажува, можеме да им предложиме на патниците блиски аеродроми (на пример, ако се откажува лет до LHR, можеме да предложиме LGW, STN, LTN). |
| 374 | | * '''Логистика на товар''' — наоѓање најблизок аеродром до магацин или дистрибутивен центар. |
| 375 | | * '''Кориснички интерфејс''' — „наоѓаш ли се близу аеродром?" функционалност за мобилна апликација. |
| 376 | | |
| 377 | | '''Демонстрација:''' наоѓање на најблиските аеродроми во радиус од 100 km околу Скопје (координати 21.62°E, 41.96°N): |
| 378 | | |
| 379 | | {{{ |
| 380 | | #!sql |
| 381 | | SELECT * FROM FindNearestAirport(21.62, 41.96, 100); |
| 382 | | }}} |
| 383 | | |
| 384 | | [[Image(Screenshots/NearestAirportsSkopje.png)]] |
| 385 | | |
| 386 | | ---- |
| 387 | | |
| 388 | | == 10. Функција FlightAtTime == |
| 389 | | |
| 390 | | Оваа функција пресметува каде се наоѓа определен лет (естимативно) во даден временски момент — без потреба од посебна табела со логирани локации. |
| 391 | | |
| 392 | | {{{ |
| 393 | | #!sql |
| 394 | | CREATE OR REPLACE FUNCTION FlightAtTime( |
| 395 | | FlightID_P int, |
| 396 | | Time_P timestamp |
| 397 | | ) RETURNS TABLE ( |
| 398 | | CurrentLocation geography, |
| 399 | | Route geography |
| 400 | | ) AS $$ |
| 401 | | DECLARE |
| 402 | | DepartureTime timestamp; |
| 403 | | ArrivalTime timestamp; |
| 404 | | DepartureLocation geography; |
| 405 | | ArrivalLocation geography; |
| 406 | | Fraction numeric; |
| 407 | | CurrentPosition_V geography; |
| 408 | | Route_V geography; |
| 409 | | BEGIN |
| 410 | | SELECT flight.departure, flight.arrival, ad.location, aa.location |
| 411 | | INTO DepartureTime, ArrivalTime, DepartureLocation, ArrivalLocation |
| 412 | | FROM flight |
| 413 | | JOIN gate AS ga ON flight.actualgatearrivalid = ga.id |
| 414 | | JOIN gate AS gd ON flight.actualgatedepartureid = gd.id |
| 415 | | JOIN terminal AS ta ON ta.id = ga.terminalid |
| 416 | | JOIN terminal AS td ON td.id = gd.terminalid |
| 417 | | JOIN airport AS aa ON aa.id = ta.airportid |
| 418 | | JOIN airport AS ad ON ad.id = td.airportid |
| 419 | | WHERE flight.id = FlightID_P; |
| 420 | | |
| 421 | | IF Time_P <= DepartureTime THEN |
| 422 | | CurrentPosition_V := DepartureLocation; |
| 423 | | ELSIF Time_P >= ArrivalTime THEN |
| 424 | | CurrentPosition_V := ArrivalLocation; |
| 425 | | ELSE |
| 426 | | Fraction := EXTRACT(epoch FROM (Time_P - DepartureTime)) |
| 427 | | / EXTRACT(epoch FROM (ArrivalTime - DepartureTime)); |
| 428 | | |
| 429 | | CurrentPosition_V := ST_LineInterpolatePoint( |
| 430 | | ST_MakeLine(DepartureLocation::geometry, ArrivalLocation::geometry), |
| 431 | | Fraction |
| 432 | | )::geography; |
| 433 | | END IF; |
| 434 | | |
| 435 | | Route_V := ST_MakeLine( |
| 436 | | DepartureLocation::geometry, |
| 437 | | ArrivalLocation::geometry |
| 438 | | )::geography; |
| 439 | | |
| 440 | | RETURN QUERY SELECT CurrentPosition_V, Route_V; |
| 441 | | END; |
| 442 | | $$ LANGUAGE plpgsql; |
| 443 | | }}} |
| 444 | | |
| 445 | | '''Како функционира:''' |
| 446 | | |
| 447 | | 1. '''Се извлекуваат деталите за летот''' — времето на полетување и слетување, и локациите на двата аеродрома преку познатиот ланец на JOIN-ови. |
| 448 | | 2. '''Се определува моменталната локација според временскиот параметар:''' |
| 449 | | * Доколку времето е ''пред'' полетувањето, авионот сè уште е на полетниот аеродром. |
| 450 | | * Доколку времето е ''по'' слетувањето, авионот веќе пристигнал на слетниот аеродром. |
| 451 | | * Во спротивно, се пресметува {{{Fraction}}} — фракција помеѓу 0 и 1 која означува „колку процент од летот е изминат". |
| 452 | | 3. '''Се користи {{{ST_LineInterpolatePoint}}}''' — функција која враќа точка на одредена фракција должина по една линија. Со fraction = 0.5, се добива средината на патот; со fraction = 0.25, една четвртина од него. |
| 453 | | 4. '''Се враќа и моменталната локација и целата рута''' — корисно за визуализација (точка на мапа за авионот, плус линија која ја прикажува неговата траектoрија). |
| 454 | | |
| 455 | | '''Битна забелешка за реалност:''' |
| 456 | | |
| 457 | | Оваа функција користи '''линеарна интерполација по great-circle линија''' — претпоставува дека авионот лета со константна брзина по најкраткиот пат на сфера. Во вистинскиот свет: |
| 458 | | |
| 459 | | * Авионите не летаат со константна брзина (имаат фази на качување, крстарење и спуштање). |
| 460 | | * Реалните рути често отстапуваат од идеалната great-circle линија поради воздушни кориди, временски услови, забранети воздушни простори. |
| 461 | | * Реалните системи за следење на летови (Flight Tracking) користат '''посебна табела за логирање на локации''' — на пример, ADS-B транспондерите на авионите емитуваат локација секои неколку секунди, а сите тие точки се чуваат во база. |
| 462 | | |
| 463 | | Бидејќи во овој проект немаме вистински авиони, импровизираме со пресметана локација. Во документацијата експлицитно споменуваме дека ова е демонстративен пристап, не продукциски модел. |
| 464 | | |
| 465 | | '''Случаи на употреба:''' |
| 466 | | |
| 467 | | * '''Air Traffic Control визуелизација''' — приказ каде се сите авиони во моментот. |
| 468 | | * '''Информации за патници''' — „вашиот лет моментално е над Атлантскиот океан, на 70% од патот". |
| 469 | | * '''Анализа на оперативни инциденти''' — со повикување на {{{FlightAtTime(flight_id, incident_time)}}} се добива каде се наоѓал авионот кога настанал инцидентот. |
| 470 | | |
| 471 | | '''Демонстрација:''' |
| 472 | | |
| 473 | | [[Image(Screenshots/FlightAtDemo.png)]] |
| 474 | | |
| 475 | | ---- |
| 476 | | |
| 477 | | == 11. Визуелизација со QGIS == |
| 478 | | |
| 479 | | Една од најголемите предности на PostGIS е природната интеграција со '''QGIS''' — индустриски стандарден отворен GIS алат. QGIS може директно да се поврзе со нашата PostGIS база и да ги визуелизира просторните слоеви во реално време. |
| 480 | | |
| 481 | | '''Процес на конекција:''' |
| 482 | | |
| 483 | | 1. Во QGIS се додава PostGIS конекција (Browser → !PostgreSQL → New Connection) со параметрите на базата. |
| 484 | | 2. Сите табели и погледи со просторни колони (Airport, !FlightRoutes итн.) автоматски се препознаваат како слоеви. |
| 485 | | 3. Со drag-and-drop се додаваат на мапата. |
| 486 | | 4. Како подлога се користи !OpenStreetMap (преку XYZ Tiles), кој дава реален географски контекст. |
| 487 | | |
| 488 | | '''Што е визуелизирано:''' |
| 489 | | |
| 490 | | * '''Слој на аеродроми''' — секој аеродром се прикажува како точка, со label-от поставен на IATA код. |
| 491 | | * '''Слој на рути''' — секоја линија претставува лет помеѓу два аеродроми. При зголемување на zoom, се гледа конкретниот географски пат. |
| 492 | | * '''Демонстрација на функциите''' — {{{FindNearestAirport}}} и {{{FlightAtTime}}} се повикуваат преку DB Manager → SQL Window, и нивните резултати се вчитуваат како нови слоеви. |
| 493 | | |
| 494 | | QGIS проектот е зачуван како {{{SBAirlines.qgz}}} и претставува дел од испораката на оваа фаза. |
| 495 | | |
| 496 | | ---- |
| 497 | | |
| 498 | | == 12. Краток преглед на новите компоненти == |
| 499 | | |
| 500 | | || '''Компонента''' || '''Тип''' || '''Намена''' || |
| 501 | | || {{{airport.latitude}}}, {{{airport.longitude}}} || Нови колони || Сурови географски координати || |
| 502 | | || {{{airport.location}}} || Нова колона || PostGIS геометриска точка (geography Point, 4326) || |
| 503 | | || {{{idx_airport_location}}} || Просторен индекс || GIST индекс за брзи просторни прашалници || |
| 504 | | || {{{FlightRoutes}}} || Нов поглед || Сите летови како !LineString геометрии || |
| 505 | | || {{{ScheduledFlight.distance}}} || Ажурирана колона || Реални great-circle растојанија наместо синтетички || |
| 506 | | || {{{CalculateDistance()}}} + {{{SetDistance}}} || Нов тригер || Автоматска пресметка на дистанца при INSERT/UPDATE || |
| 507 | | || {{{FindNearestAirport(lon, lat, km)}}} || Нова функција || Враќа аеродроми во даден радиус, сортирани по близина || |
| 508 | | || {{{FlightAtTime(id, time)}}} || Нова функција || Пресметува локација на лет во даден момент || |
| 509 | | |
| 510 | | ---- |
| 511 | | |
| 512 | | == 13. Заклучок == |
| 513 | | |
| 514 | | Интеграцијата на PostGIS во проектот SBAirlines не претставува површно додавање на функционалност, туку природна еволуција на моделот кон вистинскиот свет на авиокомпанијата. Со неа: |
| 515 | | |
| 516 | | * '''Аеродромите имаат реални координати''', а не само имиња и кодови. |
| 517 | | * '''Растојанијата на летовите се вистински''', што влијае врз постоечките компоненти (миљни поени, оптимизација на флота, оперативни извештаи). |
| 518 | | * '''Се отвораат нови случаи на употреба''' кои се невозможни во чист релациски модел (наоѓање најблиски аеродроми, визуализација на мрежа, следење на локација). |
| 519 | | * '''Се демонстрира просторно индексирање''' — нов вид индекс кој не беше покриен во основните фази на проектот. |
| 520 | | * '''Базата на податоци станува извор на вистина''' за визуелни алатки како QGIS, кои директно ги читаат просторните слоеви. |
| 521 | | |
| 522 | | PostGIS ја претвора нашата база од „евиденција за авиокомпанија" во „геопросторна оперативна платформа" — токму она што го користат вистинските авиокомпании во светот. |