SRTM рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд┐рдЬрд┐рдЯрд▓ рдЙрдиреНрдирдпрди рдореЙрдбрд▓

рдореИрдк рд╕рд░реНрд╡рд░ рдмрдирд╛рддреЗ рд╕рдордп, рдореБрдЭреЗ рдЙрдЪреНрдЪ рдКрдВрдЪрд╛рдИ рд╡рд╛рд▓реЗ рдЗрд▓рд╛рдХреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдбрд┐рдЬрд┐рдЯрд▓ рдКрдВрдЪрд╛рдИ рдореЙрдбрд▓ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ SRTM (NASA рд╢рдЯрд▓ рд░рдбрд╛рд░ рдЯреЛрдкреЛрдЧреНрд░рд╛рдлреА рдорд┐рд╢рди) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реИрдХрд▓реНрдкрд┐рдХ рдбреЗрдЯрд╛рд╕реЗрдЯ рд╣реИрдВ , SRTM рд╕рдЯреАрдХрддрд╛ рдореЗрдВ рд╕рдмрд╕реЗ рдЖрдо рдФрд░ рдХрд╛рдлреА рд╕рдВрддреЛрд╖рдЬрдирдХ рд╣реИред рдбреЗрдЯрд╛ рдХреЛ рдХрдИ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - 1 рдЖрд░реНрдХ рд╕реЗрдХрдВрдб рдФрд░ 3 рдЪрд╛рдк рд╕реЗрдХрдВрдб рдХреЗ рд╕реЗрд▓ рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ рдЧреНрд░рд┐рдбред рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рдПрдХ-рд╕реЗрдХрдВрдб рдбреЗрдЯрд╛ (SRTM1) рд╕рдВрдпреБрдХреНрдд рд░рд╛рдЬреНрдп рдЕрдореЗрд░рд┐рдХрд╛ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдХреЗрд╡рд▓ рддреАрди-рд╕реЗрдХрдВрдб рдбреЗрдЯрд╛ (SRTM3) рдкреГрдереНрд╡реА рдХреЗ рдмрд╛рдХреА рд╣рд┐рд╕реНрд╕реЛрдВ (60 рдбрд┐рдЧреНрд░реА рдЙрддреНрддрд░реА рдЕрдХреНрд╖рд╛рдВрд╢ рдФрд░ 54 рдбрд┐рдЧреНрд░реА рджрдХреНрд╖рд┐рдг рдЕрдХреНрд╖рд╛рдВрд╢ рдХреЗ рдмреАрдЪ) рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред рдлрд╝рд╛рдЗрд▓реЗрдВ 1201x1201 рдХрд╛ рдореИрдЯреНрд░рд┐рдХреНрд╕ рд╣реИрдВ (рдпрд╛ рдПрдХ-рджреВрд╕рд░реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП 3601x3601) рдорд╛рдиред
рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕реНрд░реЛрдд рд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдбрд╛рдЙрдирд▓реЛрдб рдХреЗ рд▓рд┐рдП , рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╕реНрдХреЗрдЪ рдХрд┐рдпрд╛
srtm_download
#! / рдмрд┐рди / рдмреИрд╢

рдЙрдкрдпреЛрдЧ () {
рдЗрдХреЛ "рдЙрдкрдпреЛрдЧ:" $ 0 "-region -lat_semisphere -lon_semisphere -min_lat -max_lat -min_lon -max_lon"
рдЧреВрдВрдЬ "рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реЗ рдПрдХ: рдЕрдлреНрд░реАрдХрд╛ рдСрд╕реНрдЯреНрд░реЗрд▓рд┐рдпрд╛ рдпреВрд░реЗрд╢рд┐рдпрд╛ рджреНрд╡реАрдкрд╕рдореВрд╣ рдЙрддреНрддрд░_рдЕрдореЗрд░рд┐рдХрд╛ рджрдХреНрд╖рд┐рдг_рдЕрдореЗрд░рд┐рдХрд╛"
рдЗрдХреЛ "рдЙрджрд╛рд╣рд░рдг: srtm_download рдпреВрд░реЗрд╢рд┐рдпрд╛ NE 43 53 21 142"
рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВ 1
}

рдЕрдЧрд░ ("$ #" <7)); рддреЛ
рдкреНрд░рдпреЛрдЧ
рдЕрдиреНрдпрдерд╛
рдХреНрд╖реЗрддреНрд░ = $ рез
LATITUDE_SEMISPHERE = $ 2
LONGITUDE_SEMISPHERE = $ 3
MIN_LATITUDE = $ 4
MAX_LATITUDE = $ 5
MIN_LONGITUDE = $ 6
MAX_LONGITUDE = $ 7
SERVER_ADDRESS = " dds.cr.usgs.gov/srtm/version2_1/SRTM3 $ {REGION}"
mkdir srtm
рдореИрдВ $ рдореЗрдВ (seq $ MIN_LATITUDE $ MAX_LATITUDE)
рдХрд░рдирд╛
j рдореЗрдВ $ рдХреЗ рд▓рд┐рдП (seq $ MIN_LONGITUDE $ MAX_LONGITUDE)
рдХрд░рдирд╛
wget -P srtm -nv "$ SERVER_ADDRESS / $ LATITUDE_SEMISPHERE $ i $ LONGITUDE_SEMISPHERE`printf% 03d $ j`" "ред hgt.zip"
рдХрд┐рдпрд╛
рдХрд┐рдпрд╛
рдлрд╛рдИ

рд╕рднреА рдЙрдкрд▓рдмреНрдз DEM рдлрд╛рдЗрд▓реЗрдВ srtm рдлреЛрд▓реНрдбрд░ рдореЗрдВ рд╕реЗрд╡ рд╣реЛ рдЬрд╛рдПрдВрдЧреАред
рдЙрдЪреНрдЪ-рдКрдВрдЪрд╛рдИ рд╡рд╛рд▓реЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рд╕рдордп, рдбрдЪ рдСрд╕рдо-рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЙрдЬрд░реНрд╕ рдкреНрд░реЛрд╡реЛрд╕реНрдЯ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдореИрдВрдиреЗ рдСрд╕рдо-рд╕рд░реНрд╡рд░ рдЯрд╛рдЗрд▓реЗрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдХреЗ рд╢реБрд░реВ рдХрд┐рдпрд╛ред рдЙрдмрдВрдЯреВ 12.04 рдХреЗ рддрд╣рдд рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдШрдЯрдХреЛрдВ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЗрдХрдЯреНрдард╛ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдФрд░ рддреНрд╡рд░рд┐рдд рддрд░реАрдХрд╛ рд╣реИ ред рдбреЗрдмрд┐рдпрди рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдорд╛рдг, рднреА рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рдерд╛ред рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрд╣рд╛рдВ рдФрд░ рдпрд╣рд╛рдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред
PostgreSQL рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрди рд╕реЗрдЯреЛрдВ рдХреЗ рд╕рд╛рде рд╕реНрдЯреЛрд░ рдФрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ PostgreSQL рдореЗрдВ srtm рдирд╛рдордХ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

sudo -u postgres -i
createuser username # answer yes for superuser (although this isn't strictly necessary)
createdb -E UTF8 -O username srtm
exit

рддрд╛рд▓рд┐рдХрд╛ рдмрдирд╛рдиреЗ рдФрд░ рдЖрдмрд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП psycopg2 (PostgreSQL рдПрдбреЗрдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛) рдФрд░ SRTM рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП GDAL рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЖрдкрдХреЛ SRTM рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рдЕрдЬрдЧрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рдмрдирд╛рдИ рдЧрдИ рдереА рдФрд░ рдбреЗрдЯрд╛ рд╕реЗ рднрд░реА рд╣реБрдИ рдереАред
srtm2pgsql
#! / usr / рдмрд┐рди / рдЕрдЬрдЧрд░

рдЖрдпрд╛рдд pg, psycopg2

рдУрд╕реЗрдЧреЛ рдЖрдпрд╛рдд рд╕реЗ рдЧрджрд▓, рдЧрджрд▓_рдЕрд░реЗ
рдЖрдпрд╛рдд os

рдЖрдпрд╛рдд zipfile

рдЖрдпрд╛рдд рдлрд┐рд░ рд╕реЗ
рдЖрдпрд╛рдд sys

рдЧрдгрд┐рдд рдЖрдпрд╛рдд sqrt рд╕реЗ

def getLatLonFromFileName (рдирд╛рдо):
# рд▓реИрдЯ рдФрд░ рд▓реЛрди рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВ:
p = re.compile ('[NSEW] \ d *')
[lat_str, lon_str] = p.findall (рдирд╛рдо)

# рдЙрддреНрддрд░ рдпрд╛ рджрдХреНрд╖рд┐рдг?
рдЕрдЧрд░ lat_str [0] == "N":
lat = int (lat_str [1:])
рдмрд╛рдХреА:
lat = -int (lat_str [1:])

# рдкреВрд░реНрд╡ рдпрд╛ рдкрд╢реНрдЪрд┐рдо?
рдЕрдЧрд░ lon_str [0] == "E":
lon = int (lon_str [1:])
рдмрд╛рдХреА:
lon = -int (lon_str [1:])

рд╡рд╛рдкрд╕реА [рдЕрд╡реНрдп, рд▓реЛрди]

def рд▓реЛрдбрдЯрд╛рдЗрд▓ (рдлрд╝рд╛рдЗрд▓ рдирд╛рдо):
# рдЗрд╕реЗ рдЦреЛрд▓ рджреЛ
zf = zipfile.ZipFile (рдлрд╝рд╛рдЗрд▓ рдирд╛рдо + ".hgt.zip")
zf.namelist рдореЗрдВ рдирд╛рдо рдХреЗ рд▓рд┐рдП ():
рдЖрдЙрдЯрдлрд┐рдЯ = рдЦреБрд▓рд╛ (рдирд╛рдо, 'wb')
outfile.write (zf.read (рдирд╛рдо))
outfile.flush ()
outfile.close ()

# рдкрдврд╝реЗрдВ
srtm = gdal.Open (рдлрд╝рд╛рдЗрд▓ рдирд╛рдо + '.hgt')

# рд╕рдлрд╛рдИ рдХрд░реЗрдВ
os.remove (рдлрд╝рд╛рдЗрд▓ рдирд╛рдо + '.hgt')

рд╡рд╛рдкрд╕реА gdal_array.DatasetReadAsArray (srtm)

рдкреАрдУрдПрд╕рдлреНрд░реЗрдорд▓реЛрди рдХреЛ рд╣рд░рд╛рдпрд╛ (рд▓реЗрдЯ, рд▓реЛрди):
рд╡рд╛рдкрд╕реА (lat * 360 + lon) * 1200 * 1200

рдбреЗрдЯрд╛рдмреЗрд╕ рдбреЗрдЯрд╛рдмреЗрд╕:
def __init __ (рд╕реНрд╡, db_name, db_user, db_pass):
self.db = pg.DB (dbname = db_name, рд╣реЛрд╕реНрдЯ = 'рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ', рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ = db_user, passwd = db_pass)

def CreateableAltitude (рд╕реНрд╡):
рдЯреЗрдмрд▓ = self.db.get_tables ()

рдпрджрд┐ рдирд╣реАрдВ (рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ 'public.altitude'):
self.db.query ("\"
рдмрдирд╛рдПрдБ рддрд╛рд▓рд┐рдХрд╛ рдКрдВрдЪрд╛рдИ (\)
рдкреЙрд╕ рдмрд┐рдЧрд┐рдВрдЯ рдиреЙрдЯ,
alt int NULL, \
рдкреНрд░рд╛рдердорд┐рдХ рдХреБрдВрдЬреА (рд╕реНрдерд┐рддрд┐) \
); \
")
рд╕рдЪ рд▓реМрдЯрд╛рдУ

рдХрдХреНрд╖рд╛ рдбреЗрдЯрд╛рдмреЗрд╕рдкреАрд╕реЛрдкрдЧ 2:
def __init __ (рд╕реНрд╡, db_name, db_user, db_pass):
self.db_name = db_name

con = psycopg2.connect ("dbname = '" + db_name + "' host = 'localhost' рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ = '" + db_user + "' рдкрд╛рд╕рд╡рд░реНрдб = '" + db_pass + "")
self.cursor = conn.cursor ()

рдбреАрдИрдПрдлрд╝ рдЗрдВрдЯреЗрдХреНрдЯрд╛рдЗрд▓ (рд╕реНрд╡, рдЯрд╛рдЗрд▓, рд▓реИрдЯ0, рд▓реЛрди 0):
# рдореИрдВ Psycopg2 рдХрдиреЗрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рдХреЗ copy_to рдХреЗ рд╕рд╛рде рдФрд░
# copy_from рдХрдорд╛рдВрдб, рдЬреЛ рдЕрдзрд┐рдХ рдХреБрд╢рд▓ COPY рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
# рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдлрд╝рд╛рдЗрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред

# рдЧрдгрдирд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреА рд╕реНрдерд┐рддрд┐
рд╢реБрд░реВ = рдкреЙрдЬрд╝рдлреНрд░реЙрдорд▓реИрдЯрди (lat0, lon0)

# рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╣рдо рдбреЗрдЯрд╛ рдХреЛ рдПрдХ рдЕрд╕реНрдерд╛рдпреА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
f = рдЦреБрд▓рд╛ ('/ tmp / tempcopy', 'w')
# рд╣рдо рд╢реАрд░реНрд╖ рдкрдВрдХреНрддрд┐ рдФрд░ рджрд╛рдПрдБ рд╕реНрддрдВрдн рдХреЛ рдЫреЛрдбрд╝рддреЗ рд╣реИрдВред
рдкрдВрдХреНрддрд┐ рдореЗрдВ рдкрдВрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП (1, рд▓реЗрди (рдЯрд╛рдЗрд▓)):
рд╕реАрдорд╛ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ (0, рд▓реЗрди (рдЯрд╛рдЗрд▓) - 1):
f.write (str (\)
рд╢реБрд░реВ + (рдкрдВрдХреНрддрд┐ -1) * 1200 + рдХреЙрд▓реЛрдиреА
) + "\ t" + str (рдЯрд╛рдЗрд▓ [рдкрдВрдХреНрддрд┐] [col]] + "\ n")

f.close ()

# рдЕрдм рд╣рдо рдЕрд╕реНрдерд╛рдпреА рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЕрдВрджрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ
# рдКрдВрдЪрд╛рдИ рддрд╛рд▓рд┐рдХрд╛ред

f = рдЦреБрд▓рд╛ ('/ tmp / tempcopy', 'r')

рдЖрдпрд╛рдд рдЙрдкрдкреНрд░рдХрд╛рд░
psqlcmd = "/ usr / bin / psql"

p = subprocess.Popen ('psql' + self.db_name + '-c "STDIN рд╕реЗ рдХреЙрдкреА рдКрдВрдЪрд╛рдИ;"', stdin = f, shell = True);
p.wait ()

f.close

def рдореБрдЦреНрдп ():
рдЕрдЧрд░ рд▓реЗрди (sys.argv)! = 2:
рдкреНрд░рд┐рдВрдЯ "рддреНрд░реБрдЯрд┐! \ n рдЙрдкрдпреЛрдЧ: strm2pgsql рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо ┬╗
sys.exit ()
рдмрд╛рдХреА:
db_pg = DatabasePg ('srtm', sys.argv [1], '')
db_psycopg2 = DatabasePsycopg2 ('srtm', sys.argv [1], '')

db_pg.createTableAltitude ()

os.listdir ('ред') рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП:
рдЕрдЧрд░ (рдкреБрдирдГ рдЦреЛрдЬ ('hgt', рдлрд╝рд╛рдЗрд▓)):
tilename = file.split ('ред') [0]
рдкреНрд░рд┐рдВрдЯ "рд▓реЛрдб рдЯрд╛рдЗрд▓" + рддрд┐рд▓рдиреЗрдо + "srtm рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП"
[lat, lon] = getLatLonFromFileName (рддрд┐рд▓рдиреЗрдо)
рдЯрд╛рдЗрд▓ = рд▓реЛрдбрдЯрд╛рдЗрд▓ (рддрд┐рд▓реЗрди)
db_psycopg2.insertTile (рдЯрд╛рдЗрд▓, рд▓рд╛рдЯ, рд▓реЛрди)

рдЕрдЧрд░ __name__ == '__main__':
рдореБрдЦреНрдп ()

Qt рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рдкреНрд░рддреНрдпрдХреНрд╖ рдКрдВрдЪрд╛рдИ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдПред рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рдВрдмрдВрдз рдмрдирд╛рддреЗ рд╣реИрдВ (рдЖрдкрдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдбреНрд░рд╛рдЗрд╡рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ)
 db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("localhost"); db.setDatabaseName("srtm"); db.setUserName("user"); db.setPassword("pass"); bool ok = db.open(); 

рдЬрд┐рд╕ рдорд╛рд░реНрдЧ рдХреА рдКрдВрдЪрд╛рдИ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рд╣рдо рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрд╕рдореЗрдВ рдЬрд┐рдпреЛрдкреНрд╡рд╛рдЗрдВрдЯ рдкреЙрдЗрдВрдЯ рд╣реИрдВ рдЬреЛ рдЕрдХреНрд╖рд╛рдВрд╢, рджреЗрд╢рд╛рдВрддрд░ рдФрд░ рдКрдВрдЪрд╛рдИ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ
geopoint.h
рдХреНрд▓рд╛рд╕ рдЬрд┐рдпреЛрдкреНрд╡рд╛рдЗрдВрдЯ
{
рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ:
рдЬрд┐рдпреЛрдкреНрд╡рд╛рдЗрдВрдЯ ();
рдЬрд┐рдпреЛрдкреНрд╡рд╛рдЗрдВрдЯ (рдбрдмрд▓ рдЕрдХреНрд╖рд╛рдВрд╢, рдбрдмрд▓ рджреЗрд╢рд╛рдВрддрд░, рдбрдмрд▓ рдКрдВрдЪрд╛рдИ);

рдбрдмрд▓ рдЕрдХреНрд╖рд╛рдВрд╢ ();
рджреЛрд╣рд░рд╛ рджреЗрд╢рд╛рдВрддрд░ ();
рджреЛрд╣рд░реА рдКрдВрдЪрд╛рдИ ();

рд╢реВрдиреНрдп рд╕реЗрдЯрд▓реИрдЯрд┐рдЯреНрдпреВрдб (рдбрдмрд▓ рдЕрдХреНрд╖рд╛рдВрд╢);
рд╢реВрдиреНрдп рд╕рдореБрдЪреНрдЪрдп (рджреЛрд╣рд░рд╛ рджреЗрд╢рд╛рдВрддрд░);
рд╢реВрдиреНрдп рд╕рдореВрд╣ (рдбрдмрд▓ рдКрдВрдЪрд╛рдИ);

рдирд┐рдЬреА:
рдбрдмрд▓ m_latitude;
рдбрдмрд▓ m_longitude;
рдбрдмрд▓ m_altitude;
};

рдЖрд╡рд╢реНрдпрдХ рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдорд╛рд░реНрдЧ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рдКрдВрдЪрд╛рдИ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдФрд░ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
 interpolateRoute(route, numberRoutePoint); foreach (GeoPoint point, route) { point.setAltitude(altitude(db, point.latitude(), point.longitude())); } 

рдкреНрд░рдХреНрд╖реЗрдк рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдорд╛рд░реНрдЧ рдХреА рдХреБрд▓ рд▓рдВрдмрд╛рдИ ( рд╡рд┐рдВрд╕реЗрдВрдЯреА рд╕реВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) рдорд┐рд▓рддреА рд╣реИ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдирдП рдмрд┐рдВрджреБрдУрдВ рдХреЛ рдорд╛рд░реНрдЧ рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ
рдкреНрд░рдХреНрд╖реЗрдк
 void interpolateRoute(QVector<GeoPoint> &route, int number) { //     double length = routeLength(route); double minRes = length / number; //        : int i = 0; while (i < route.size() - 1) { QPair<GeoPoint, GeoPoint> pair = qMakePair(route[i], route[i+1]); int number = numberExtraPoints(pair, minRes); addPointsToRoute(route, i, number); i = i + number + 1; } } double routeLength(const QVector<GeoPoint> &route) { double length = 0; Geo geo; for (int i=0; i<route.size() - 1; i++) { GeoPoint origin = route[i]; GeoPoint destination = route[i+1]; length += geo.distance(origin, destination); } return length; } int numberExtraPoints(QPair<GeoPoint, GeoPoint> pair, double minRes) { Geo geo; double length = geo.distance(pair.first, pair.second); return qMax(int(floor(length / minRes) - 1), 0); } void addPointsToRoute(QVector<GeoPoint> &route, int index, int number) { double lat1 = route[index].latitude(); double lat2 = route[index+1].latitude(); double lon1 = route[index].longitude(); double lon2 = route[index+1].longitude(); double latRes = (lat2 - lat1) / number; double lonRes = (lon2 - lon1) / number; for (int i=0; i<number; i++) { lat1 += latRes; lon1 += lonRes; GeoPoint point(lat1, lon1, 0); route.insert(index + i, point); } } float WGS84MajorAxis = 6378.137; // km float WGS84MinorAxis = 6356.7523142; // km float WGS84Flattering = 1 / 298.257223563; double distance(GeoPoint origin, GeoPoint destination) { double lat1 = origin.latitude(); double lat2 = destination.latitude(); double lng1 = origin.longitude(); double lng2 = destination.longitude(); double major = WGS84MajorAxis; double minor = WGS84MinorAxis; double f = WGS84Flattering; double deltaLng = lng2 - lng1; double reducedLat1 = atan((1 - f) * tan(lat1)); double reducedLat2 = atan((1 - f) * tan(lat2)); double sinReduced1 = sin(reducedLat1); double sinReduced2 = sin(reducedLat2); double cosReduced1 = cos(reducedLat1); double cosReduced2 = cos(reducedLat2); double lambdaLng = deltaLng; double lambdaPrime = 2 * M_PI; double iterLimit = 20; double sinSigma = 0; double cosSigma = 0; double cos2SigmaM = 0; double sigma = 0; double cosSqAlpha = 0; while ((abs(lambdaLng - lambdaPrime) > 10e-12) && (iterLimit > 0)) { double sinLambdaLng = sin(lambdaLng); double cosLambdaLng = cos(lambdaLng); sinSigma = sqrt((cosReduced2*sinLambdaLng) * (cosReduced2*sinLambdaLng) + (cosReduced1*sinReduced2 - sinReduced1*cosReduced2*cosLambdaLng) * (cosReduced1*sinReduced2 - sinReduced1*cosReduced2*cosLambdaLng)); if (sinSigma == 0) return 0; //   cosSigma = sinReduced1*sinReduced2 + cosReduced1*cosReduced2*cosLambdaLng; sigma = atan2(sinSigma, cosSigma); double sinAlpha = cosReduced1*cosReduced2*sinLambdaLng/sinSigma; cosSqAlpha = 1 - sinAlpha*sinAlpha; cos2SigmaM = 0.; //   if (cosSqAlpha != 0) { cos2SigmaM = cosSigma - 2*(sinReduced1*sinReduced2/cosSqAlpha); } double C = f / 16. * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)); lambdaPrime = lambdaLng; lambdaLng = (deltaLng + (1 - C)*f*sinAlpha*(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma *(-1 + 2*cos2SigmaM*cos2SigmaM)))); --iterLimit; } if (iterLimit == 0) { return 0; log->info() << "Geo, calculate distance: Vincenty formula failed to converge!"; } double uSq = cosSqAlpha * (major*major - minor*minor) / (minor*minor); double A = 1 + uSq / 16384. * (4096 + uSq * (-768 + uSq *(320 - 175 * uSq))); double B = uSq / 1024. * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))); double deltaSigma = (B * sinSigma *(cos2SigmaM + B / 4. *(cosSigma * (-1 + 2 * cos2SigmaM*cos2SigmaM) - B / 6. * cos2SigmaM * (-3 + 4 * sinSigma*sinSigma)*(-3 + 4 * cos2SigmaM*cos2SigmaM)))); return minor * A * (sigma - deltaSigma); } 


рдкреНрд░рддреНрдпреЗрдХ рдорд╛рд░реНрдЧ рдмрд┐рдВрджреБ рдХреА рдКрдВрдЪрд╛рдИ рдХрд╛ рдЕрдиреБрдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЪрд╛рд░ рдирд┐рдХрдЯрддрдо рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ рдФрд░ рдмрд┐рд▓рд┐рдирд┐рдпрд░ рдкреНрд░рдХреНрд╖реЗрдк рдХрд░рддреЗ рд╣реИрдВ
рдКрдБрдЪрд╛рдИ рдХрд╛ рдЕрдиреБрдорд╛рди
 double altitude(PostgreSqlDatabase db, double latitude, double longitude) { qulonglong tl, tr, bl, br; double a, b; posFromLatLon(latitude, longitude, tl, tr, bl, br, a, b); int atl = db.fetchAltitude(tl); int atr = db.fetchAltitude(tr); int abl = db.fetchAltitude(bl); int abr = db.fetchAltitude(br); return bilinearInterpolation(atl, atr, abl, abr, a, b); } int PostgreSqlDatabase::fetchAltitude(qulonglong pos) { QSqlQuery query; if (query.exec("SELECT * FROM altitude WHERE pos = " + QString::number(pos))) { while (query.next()) { return query.value(1).toInt(); } } return Geo::undefinedAltitude; } void posFromLatLon(const double &latitude, const double &longitude, qulonglong &tl, qulonglong &tr, qulonglong &bl, qulonglong &br, double &a, double &b) { double lat0 = floor(latitude); double lon0 = floor(longitude); qulonglong pos0 = (lat0*360 + lon0) * 1200*1200; double latPos = (1199./1200 - (latitude - lat0)) * 1200*1200; double lonPos = (longitude - lon0) * 1200; double latPosTop = floor(latPos / 1200) * 1200; double latPosBottom = ceil(latPos / 1200) * 1200; double lonPosLeft = floor(lonPos); double lonPosRight = ceil(lonPos); a = (latPos - latPosTop) / 1200; b = (lonPos - lonPosLeft); tl = qulonglong(pos0 + latPosTop + lonPosLeft); tr = qulonglong(pos0 + latPosTop + lonPosRight); bl = qulonglong(pos0 + latPosBottom + lonPosLeft); br = qulonglong(pos0 + latPosBottom + lonPosRight); } double bilinearInterpolation(const double &tl, const double &tr, const double &bl, const double &br, const double &a, const double &b) { double b1 = tl; double b2 = bl - tl; double b3 = tr - tl; double b4 = tl - bl - tr + br; return b1 + b2*a + b3*b + b4*a*b; } 


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдкрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдирдХреА рдКрдВрдЪрд╛рдИ рдХреЗ рдЕрдиреБрдорд╛рди рдХреЗ рд╕рд╛рде рдорд╛рд░реНрдЧ рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рд╣реЛрдЧрд╛ред
рдпрджрд┐ STRM рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╡рд┐рд╖рдп рд╕рдореБрджрд╛рдп рдХреЗ рд▓рд┐рдП рд░реБрдЪрд┐ рд░рдЦрддрд╛ рд╣реИ, рддреЛ рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рд╕рд╛рдЭрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдореИрдВрдиреЗ рдЖрд╕рдо рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд░рдВрдЧреАрди рд░рд╛рд╣рдд рд╕рдмреНрд╕рдЯреНрд░реЗрдЯ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ред

Source: https://habr.com/ru/post/In161201/


All Articles