рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рдлрд╝реЛрдЯреЛ рдХрд╛ рдЪрдпрди рдХрд░рдирд╛, рдХреИрд╢рд┐рдВрдЧ рдХрд░рдирд╛ рдФрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рдпрд╣ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдХрд┐ рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдерд╛рди рдкрд░ рдлрд╝реЛрдЯреЛ рдХреЛ рдЪреБрдирдиреЗ рдФрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣рдорд╛рд░реА рдлреЛрдЯреЛ рд╕реЗрд╡рд╛ gfranq.com рдореЗрдВ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХреА рдЧрдИ рдереАред рдлреЛрдЯреЛ рд╕реЗрд╡рд╛ рдЕрдм рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреА рд╣реИред



рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рдореЗрдВ рдмрд╣реБрдд рд╕реА рддрд╕реНрд╡реАрд░реЗрдВ рдереАрдВ рдФрд░ рд╣рд░ рдмрд╛рд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рд╕реЗ рд╡реНрдпреВрдкреЛрд░реНрдЯ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рдВрд╕рд╛рдзрди-рдЧрд╣рдирддрд╛ рдереА, рдЗрд╕рд▓рд┐рдП рдореИрдк рдХреЛ рдХрдИ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рддрд░реНрдХрд╕рдВрдЧрдд рдерд╛ рдЬрд┐рд╕рдореЗрдВ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрддреА рд╣реИред рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдПрдХ рдЖрдпрддрд╛рдХрд╛рд░ рдЖрдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╣реЗрдХреНрд╕рд╛рдЧреЛрдирд▓ рдЧреНрд░рд┐рдб рдХреЛ рднреА рдорд╛рдирд╛ рдЬрд╛рддрд╛ рдерд╛)ред рдЪреВрдВрдХрд┐ рдХреНрд╖реЗрддреНрд░ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдЕрдзрд┐рдХ рдЧреЛрд▓рд╛рдХрд╛рд░ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рдЧреЛрд▓рд╛рдХрд╛рд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреЗ рддрддреНрд╡реЛрдВ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рднреА рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореБрджреНрджреЗ рдЙрдард╛рдП рдЧрдП рдереЗ:


  • рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдлрд╝реЛрдЯреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рдФрд░ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕рд░реНрд╡рд░ (SQL, C #, ASP.NET) рдкрд░ рдХреИрд╢рд┐рдВрдЧ рдХрд░рдирд╛ред
  • рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рдЖрд╡рд╢реНрдпрдХ рдлрд╝реЛрдЯреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреИрд╢ (рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ) рдореЗрдВ рд╕рд╣реЗрдЬрдирд╛ред
  • рд╡реНрдпреВрдкреЛрд░реНрдЯ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрдиреЗ рдкрд░ рдЫрд┐рдкреА рдпрд╛ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рд╡рд╛рд▓реА рддрд╕реНрд╡реАрд░реЛрдВ рдХрд╛ рдкреБрди: рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
  • рдЧреЛрд▓рд╛рдХрд╛рд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреЗ рддрддреНрд╡ред

рдЕрдВрддрд░реНрд╡рд╕реНрддреБ



рд╕рд░реНрд╡рд░ рднрд╛рдЧ


рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рднреВ-рд╕реВрдЪрдирд╛ рдХреЗ рдЪрдпрди рдФрд░ рднрдВрдбрд╛рд░рдг рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддрд░реАрдХреЗ рдбрд┐рдЬрд╛рдЗрди рдХрд┐рдП рдЧрдП рдереЗ:


  • SQL рд╕рд░реНрд╡рд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рднреВрдЧреЛрд▓ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ред
  • рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╛рдорд╛рдиреНрдп рдЪрдпрдиред
  • рдЕрддрд┐рд░рд┐рдХреНрдд рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред

рдЖрдЧреЗ, рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╡рд┐рд╡рд░рдг рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдирд┐рд░реНрдорд┐рдд рднреВрдЧреЛрд▓


рдЬреИрд╕рд╛ рдХрд┐ рдЬреНрдЮрд╛рдд рд╣реИ, SQL Server 2008 рднреВрдЧреЛрд▓ рдФрд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рднреМрдЧреЛрд▓рд┐рдХ (рдХреНрд╖реЗрддреНрд░ рдкрд░) рдФрд░ рдЬреНрдпрд╛рдорд┐рддреАрдп (рд╡рд┐рдорд╛рди рдкрд░) рдЬрд╛рдирдХрд╛рд░реА, рдЬреИрд╕реЗ рдмрд┐рдВрджреБ, рд░реЗрдЦрд╛, рдмрд╣реБрднреБрдЬ рдЖрджрд┐ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ ред ред рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ ( lngMin latMin ) рдФрд░ ( latMax lngMax ) рдХреЗ рд╕рд╛рде рдПрдХ рдЖрдпрдд рджреНрд╡рд╛рд░рд╛ рд╕рдВрд▓рдЧреНрди рд╕рднреА рддрд╕реНрд╡реАрд░реЛрдВ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд╡реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 DECLARE @h geography; DECLARE @p geography; SET @rect = geography::STGeomFromText('POLYGON((lngMin latMin, lngMax latMin, lngMax latMax, lngMin latMax, lngMin latMin))', 4326); SELECT TOP @cound id, image75Path, geoTag.Lat as Lat, geoTag.Long as Lng, popularity, width, height FROM Photo WITH (INDEX(IX_Photo_geoTag)) WHERE @rect.STContains(geoTag) = 1 ORDER BY popularity DESC 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдмрд╣реБрднреБрдЬ рдЙрдиреНрдореБрдЦ рд╡рд╛рдорд╛рд╡рд░реНрдд рд╣реИ рдФрд░ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╕реНрдерд╛рдирд┐рдХ рд╕реВрдЪрдХрд╛рдВрдХ IX_Photo_geoTag рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдерд╛рдирд┐рдХ рд╕реВрдЪрдХрд╛рдВрдХ рдмреА-рдкреЗрдбрд╝реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред


рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ Microsoft SQL Server 2008 рдореЗрдВ, рд╕реНрдерд╛рдирд┐рдХ рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рднреВрдЧреЛрд▓ рдХреЗ рд╕рд╛рде рд╕реНрддрдВрдн NULL рдорд╛рдиреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдПрдХ рд╕рдордЧреНрд░ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рднреВрдЧреЛрд▓ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ рдХреЙрд▓рдо рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рд╕рд╡рд╛рд▓ рдкрд░ Stackoverflow рдкрд░ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рдереАред рдЗрд╕реАрд▓рд┐рдП рдРрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ (рдмрд┐рдирд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛) рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдмрд╣реБрдд рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


  • рдЪреВрдВрдХрд┐ NULL рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕ рдХреЙрд▓рдо рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ (0, 0) рд╣реИрдВ рдЬреЛ рдЕрдлреНрд░реАрдХрд╛ рдХреЗ рдкрд╛рд╕ рдЕрдЯрд▓рд╛рдВрдЯрд┐рдХ рдорд╣рд╛рд╕рд╛рдЧрд░ рдореЗрдВ рдПрдХ рд╕реНрдерд╛рди (рдЕрдХреНрд╖рд╛рдВрд╢ рдФрд░ рджреЗрд╢рд╛рдВрддрд░ рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБ) рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рдЬрдЧрд╣ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдкрд╛рд╕ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдмрд┐рдВрджреБрдУрдВ рдХреЛ рднреА рд╕реНрдерд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдирдХреНрд╢реЗ рд╕реЗ рдирд╣реАрдВ рдлрд╝реЛрдЯреЛ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдЖрдк рд╢реВрдиреНрдп рдмрд┐рдВрджреБ (0, 0) рдХреЛ рд╕реБрджреВрд░ рдЙрддреНрддрд░ рдмрд┐рдВрджреБ (0, 90) рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЕрдХреНрд╖рд╛рдВрд╢ 90 рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдХрд┐рдирд╛рд░реЗ рдкрд░ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рдЧреНрд░рд┐рдб рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рд╕рдордп рдЗрд╕ рдореВрд▓реНрдп рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЕрд░реНрдерд╛рдд рдЕрдХреНрд╖рд╛рдВрд╢ 89 рддрдХ рдирд┐рд░реНрдорд╛рдг)ред
  • SQL рд╕рд░реНрд╡рд░ 2012 рдпрд╛ рдЙрдЪреНрдЪрддрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рдВрдЧрддрддрд╛ рд╕реНрддрд░ рдХреЛ 110 рдпрд╛ рдЙрд╕рд╕реЗ рдЕрдзрд┐рдХ рдореЗрдВ рдмрджрд▓рдХрд░ ALTER DATABASE database_name SET COMPATIBILITY_LEVEL = 110 рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдХреЗред SQL рд╕рд░реНрд╡рд░ рдХреЗ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рднреВрдЧреЛрд▓ рдХреЗ NULL рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдмрдЧ рдХреЛ рдареАрдХ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдЭреБрдХрд╛рд╡ (рд╡рд╛рдорд╛рд╡рд░реНрдд рдФрд░ рджрдХреНрд╖рд┐рдгрд╛рд╡рд░реНрдд) рдХреЗ рдмрд╣реБрднреБрдЬ рдХрд╛ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛ред

рднреВрдЧреЛрд▓ рдХреА рд╡реНрдпрд╛рдкрдХ рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж (рд╡реЗ рдЖрдкрдХреЛ рди рдХреЗрд╡рд▓ рдПрдХ рд╕рд░рд▓ рдЪрдпрди рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджреВрд░реА рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдмрд╣реБрднреБрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА), рд╣рдордиреЗ рдЙрдиреНрд╣реЗрдВ рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ред


рд╕рд╛рдорд╛рдиреНрдп рдЪрдпрди


рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ ( lngMin latMin ) рдФрд░ ( latMax lngMax ) рд╕реЗ latMax рдХреНрд╖реЗрддреНрд░ рд╕реЗ рдлрд╝реЛрдЯреЛ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╢реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:


 SELECT TOP @Count id, url, ... FROM Photo WHERE latitude > @latMin AND longitude > @lngMin AND latitude < @latMax AND longitude < @lngMax ORDER BY popularity DESC 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЖрдк latitude рдФрд░ longitude рдХреНрд╖реЗрддреНрд░реЛрдВ (рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рдХреЗ рд╡рд┐рдкрд░реАрдд) рдХреЗ рд▓рд┐рдП рдХреЛрдИ рднреА рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдлреНрд▓реЛрдЯ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рдЪрдпрди рдореЗрдВ 4 рддреБрд▓рдирд╛рддреНрдордХ рд╕рдВрдЪрд╛рд▓рди рд╣реИрдВред


рдЕрддрд┐рд░рд┐рдХреНрдд рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдХреБрдЫ рдХреНрд╖реЗрддреНрд░реЛрдВ рд╕реЗ рдлрд╝реЛрдЯреЛ рдЪреБрдирдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдмрд╕реЗ рдЗрд╖реНрдЯрддрдо рд╕рдорд╛рдзрд╛рди рдЕрддрд┐рд░рд┐рдХреНрдд рддрд╛рд▓рд┐рдХрд╛ Zooms рдмрдирд╛рдирд╛ рд╣реИ рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рдЬрд╝реВрдо рдХреЗ рд▓рд┐рдП рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рд░рд╛рдЦ рдпреБрдХреНрдд рддрд╛рд░реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред



рдирд┐рдореНрди SQL рдХреНрд╡реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ( zn - рд╡рд░реНрддрдорд╛рди рдЬрд╝реВрдо рд╕реНрддрд░):


 DECLARE @hash float; SET @hash = (@latMin + 90) + (@lngMin + 180) * 180 + (@latMax + 90) * 64800 + (@lngMax + 180) * 11664000; SELECT TOP @Count id, url, ... FROM Photo WHERE id = (SELECT id FROM Zooms WHERE zn = @hash) 

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдиреБрдХрд╕рд╛рди рдпрд╣ рд╣реИ рдХрд┐ рдЕрддрд┐рд░рд┐рдХреНрдд рддрд╛рд▓рд┐рдХрд╛ рдЕрддрд┐рд░рд┐рдХреНрдд рдореЗрдореЛрд░реА рд╕реНрдерд╛рди рдкрд░ рд░рд╣рддреА рд╣реИред


рдмрд╛рдж рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдлрд╛рдпрджреЗ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рд╣рдордиреЗ рд╕рд░реНрд╡рд░ рдкрд░ рджреВрд╕рд░реА рд╡рд┐рдзрд┐ ( рд╕рд╛рдорд╛рдиреНрдп рдЪрдпрди ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдЕрдЪреНрдЫрд╛ рдкреНрд░рджрд░реНрд╢рди рдерд╛ред


рдорд▓реНрдЯреА-рдереНрд░реЗрдбреЗрдб рдПрдХреНрд╕реЗрд╕ рдХреЗ рд▓рд┐рдП рдХреИрд╢рд┐рдВрдЧ рддрд╕реНрд╡реАрд░реЗрдВ


рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реБрдП рд╕рд░реНрд╡рд░ рдХреИрд╢ рдореЗрдВ рддрд╕реНрд╡реАрд░реЗрдВ рд░рдЦреА рдЬрд╛рддреА рд╣реИрдВ:


 private static object SyncObject = new object(); ... List<Photo> photos = (List<Photo>)CachedAreas[hash]; if (photos == null) { // Use lock to avoid extracting from and adding to the cache more than once. lock (SyncObject) { photos = (List<Photo>)CachedAreas[hash]; if (photos == null) { photos = PhotoList.GetAllFromRect(latMin, lngMin, latMax, lngMax, count); // Adding information about photos to the cache with a storage time of 2 minutes with a high storage priority. CachedAreas.Add(hash, photos, null, DateTime.Now.AddSeconds(120), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } } } // Further usage of CachedAreas[hash] 

рдЗрд╕ рдЦрдВрдб рдиреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдлрд╝реЛрдЯреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреИрд╢ рдореЗрдВ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ред рдЕрдЧрд▓рд╛ рднрд╛рдЧ рдпрд╣ рд╡рд░реНрдгрди рдХрд░реЗрдЧрд╛ рдХрд┐ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рддрд░рдл рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред


рдЧреНрд░рд╛рд╣рдХ рдкрдХреНрд╖


рдЙрд╕ рдкрд░ рдорд╛рдирдЪрд┐рддреНрд░ рдФрд░ рдлрд╝реЛрдЯреЛ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Google рдорд╛рдирдЪрд┐рддреНрд░ API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдирдХреНрд╢реЗ рдХреЛ рддрд╕реНрд╡реАрд░реЛрдВ рдХреЗ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдХреЗ рдЕрдиреБрд░реВрдк рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реНрдерд╛рди рдкрд░ рд▓реЗ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред


рдорд╛рдирдЪрд┐рддреНрд░ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдирд╛


рдорд╛рдирдЪрд┐рддреНрд░ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рддреЗ рд╕рдордп рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЗ рд╣реИрдВ: рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрд╡-рдЧрдгрдирд╛ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред


HTML5 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг


 function detectRegion() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(success); } else { map.setZoom(defaultZoom); map.setCenter(defaultPoint); } } function success(position) { ... map.setZoom(defaultZoom); map.setCenter(new google.maps.LatLng(position.coords.latitude, position.coords.longitude)); } 

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдиреБрдХрд╕рд╛рди рдпрд╣ рд╣реИ рдХрд┐ рд╕рднреА рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдПрдЪрдЯреАрдПрдордПрд▓ 5 рдХреА рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдкрдиреЗ рдбрд┐рд╡рд╛рдЗрд╕ рдкрд░ рдЬрд┐рдпреЛрдЗрдирдлреЙрд░реНрдореЗрд╢рди рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛ рд╣реИред


рд╕рд░реНрд╡рд░ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░рдирд╛


рдорд╛рдирдЪрд┐рддреНрд░ рдХреЛ рдиреАрдЪреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЗ рдЦрдВрдб рдореЗрдВ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд╣рд╛рдВ bounds рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдХреНрд╖реЗрддреНрд░ (рдЖрдмрд╛рджреА рд╡рд╛рд▓реЗ рдХреНрд╖реЗрддреНрд░, рдХреНрд╖реЗрддреНрд░ рдпрд╛ рджреЗрд╢) рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╣реИрдВред рдЕрдиреБрдорд╛рдирд┐рдд рдЬрд╝реВрдо рд╕реНрддрд░ рдХреА рдЧрдгрдирд╛ рдлрд╝рдВрдХреНрд╢рди getZoomFromBounds ( getZoomFromBounds рд╕реЗ рд▓реА рдЧрдИ) рдореЗрдВ рдХреА рдЬрд╛рддреА рд╣реИред


 var northEast = bounds.getNorthEast(); var southWest = bounds.getSouthWest(); var myOptions = { zoom: getZoomFromBounds(northEast, southWest), center: new google.maps.LatLng((northEast.lat() + southWest.lat()) / 2, (northEast.lng() + southWest.lng()) / 2), mapTypeId: google.maps.MapTypeId.ROADMAP, minZoom: 3, maxZoom: 19 } map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 

 function getZoomFromBounds(ne, sw) { var GLOBE_WIDTH = 256; // a constant in Google's map projection var west = sw.lng(); var east = ne.lng(); var angle = east - west; if (angle < 0) { angle += 360; } return Math.round(Math.log($('#map_canvas').width() * 360 / angle / GLOBE_WIDTH) / Math.LN2); } 

рд╕рд░реНрд╡рд░ рдкрд░, рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЧрдгрдирд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЖрдИрдкреА рдкрддреЗ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреА рдЬрд╛рддреА рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рд╕реАрдорд╛рдУрдВ рдХреЗ рд╕рднреА рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Google рдЬрд┐рдпреЛрдХреЛрдбрд┐рдВрдЧ рдПрдкреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЬрд╛рдирдХрд╛рд░реА рдСрдлрд╝рд▓рд╛рдЗрди рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реИрдз рдирд╣реАрдВ рд╣реИ; рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░рддрд┐ рджрд┐рди 2500 рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕реАрдорд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╢рд╣рд░, рдХреНрд╖реЗрддреНрд░ рдФрд░ рджреЗрд╢ рдХреЗ рд▓рд┐рдП, рдПрдХ рдХреНрд╡реЗрд░реА рдЙрддреНрдкрдиреНрди рдХреА рдЧрдИ рдереА рдЬреЛ viewport рдФрд░ bounds рдХреА рдЖрд╡рд╢реНрдпрдХ рд╕реАрдорд╛рдУрдВ рдХреЛ viewport bounds ред рд╡реЗ рдХреЗрд╡рд▓ рдмрдбрд╝реЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд╡реНрдпреВрдкреЛрд░реНрдЯ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗред рдпрджрд┐ рд╕рд░реНрд╡рд░ рдиреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рд╡рд╛рдкрд╕ рдХреА, рддреЛ рдЕрдиреНрдп рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬрд┐рд╕рдореЗрдВ рдЙрд╕ рдХреНрд╖реЗрддреНрд░ рдпрд╛ рдЕрдВрдЧреНрд░реЗрдЬреА рдХреА рдореВрд▓ рднрд╛рд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рднрд╛рдЧ {рдЖрдмрд╛рдж рдХреНрд╖реЗрддреНрд░} рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЖрджрд┐ред http://maps.googleapis.com/maps/api/geocode/xml?address={Country},{Region},{Populated area}&sensor=false


рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╢реНрди рдХреЗ рд▓рд┐рдП: http://maps.googleapis.com/maps/api/geocode/xml?address=Russia, рдЗрд╡рд╛рдирд╡рд╛% 20 рдХреНрд╖реЗрддреНрд░, рдЗрд╡рд╛рдиреЛрд╡реЛ рдФрд░ рд╕реЗрдВрд╕рд░ = рдЧрд▓рдд


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдП рдЬрд╛рдПрдВрдЧреЗ (рдЯреБрдХрдбрд╝реЗ)
 ... <location> <lat>56.9951313</lat> <lng>40.9796047</lng> </location> <location_type>APPROXIMATE</location_type> <viewport> <southwest> <lat>56.9420231</lat> <lng>40.8765941</lng> </southwest> <northeast> <lat>57.0703221</lat> <lng>41.0876169</lng> </northeast> </viewport> <bounds> <southwest> <lat>56.9420231</lat> <lng>40.8765941</lng> </southwest> <northeast> <lat>57.0703221</lat> <lng>41.0876169</lng> </northeast> </bounds> ... 

рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рджреГрд╢реНрдпрдорд╛рди рдЖрдпрддрд╛рдХрд╛рд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЧрдгрдирд╛


рдХреИрд╢рд┐рдВрдЧ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛


рддреЛ, рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рджреЛрдиреЛрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рд╕рднреА рддрд╕реНрд╡реАрд░реЗрдВ рдЖрдпрддрд╛рдХрд╛рд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рджреНрд╡рд╛рд░рд╛ рдХреИрд╢ рдХреА рдЬрд╛рддреА рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБ рдПрдХ рдордирдорд╛рдирд╛ рдмрд┐рдВрджреБ рд╣реИ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ (0, 0) рдХреЗ рд╕рд╛рде рдмрд┐рдВрджреБ), рдФрд░ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХреА рдЬрд╛рддреА рд╣реИ рд╡рд░реНрддрдорд╛рди рдЬрд╝реВрдо рд╕реНрддрд░ рдкрд░ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:


 // The initial window at which initMapSizeLat and initMapSizeLng were calculated var initDefaultDimX = 1000, var initDefaultDimY = 800; // The current default viewport which depends on the size of the areas. var currentDefaultDimX = 1080, var currentDefaultDimY = 500; var initMapSizeLat = 0.0003019; var initMapSizeLng = 0.00067055; // The coefficient of size reduction (increase). var initRatio = 0.75; // To calculate the size of the smallest caching area, the map was zoomed in to the maximum zoom level // Ie initMapSizeLat and initMapSizeLng were calculated empirically. var initZoomSize = new google.maps.Size( initMapSizeLat / initDefaultDimX * currentDefaultDimX * initRatio, initMapSizeLng / initDefaultDimY * currentDefaultDimY * initRatio); // All subsequent sizes of areas can be calculated based only on the smallest area (by multiplying each size by 2, because with increasing the zoom level by 1, the linear dimensions increase by 2 times, and the quadratic dimensions increase by 4 times). function initZoomSizes() { zoomSizes = []; var coef = 1; for (var i = 21; i >= 0; i--) { zoomSizes[i] = new google.maps.Size(initZoomSize.width * coef, initZoomSize.height * coef); coef *= 2; } } 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкреНрд░рддреНрдпреЗрдХ рдЬрд╝реВрдо рд╕реНрддрд░ рдкрд░, рдЖрдпрддрд╛рдХрд╛рд░ рдХреНрд╖реЗрддреНрд░ рдХрд╛ рдЖрдХрд╛рд░ рд╡рд░реНрддрдорд╛рди рд╡реНрдпреВрдкреЛрд░реНрдЯ рдХреЗ рдЖрдХрд╛рд░ рд╕реЗ 0.75^2=0.5625 рд╣реИ, рдпрджрд┐ рдЗрд╕рдХреА рдЪреМрдбрд╝рд╛рдИ 1080px рдФрд░ рдЪреМрдбрд╝рд╛рдИ 500px рд╣реИред


рд░рд┐рдбрд░рд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рджреЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдЪреВрдВрдХрд┐ рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рд╕рднреА рдлрд╝реЛрдЯреЛ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рдПрдХ рддреЗрдЬрд╝ рдСрдкрд░реЗрд╢рди рдирд╣реАрдВ рд╣реИ (рдЬреИрд╕рд╛ рдХрд┐ рдмрд╛рдж рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛), рд╣рдордиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдирдкреБрдЯ рдХреЗ рдмрд╛рдж рдХреБрдЫ рджреЗрд░реА рд╕реЗ рдЗрд╕реЗ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛:


 google.maps.event.addListener(map, 'bounds_changed', function () { if (boundsChangedInverval != undefined) clearInterval(boundsChangedInverval); var zoom = map.getZoom(); boundsChangedInverval = setTimeout(function () { boundsChanged(); }, prevZoom === zoom ? moveUpdateDelay : zoomUpdateDelay); prevZoom = zoom; }); 

рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рджреГрд╢реНрдпрдорд╛рди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдФрд░ рд╣реИрд╢ рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛


рд╕рднреА рдЖрдпрддреЛрдВ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдФрд░ рд╣реИрд╢ рдХреА рдЧрдгрдирд╛ рдЬреЛ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ ( latMin , lngMin ) рдХреЗ рд╕рд╛рде рджреГрд╢реНрдпрдорд╛рди рд╡рд┐рдВрдбреЛ рдХреЛ рдУрд╡рд░рд▓реИрдк рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкрд╣рд▓реЗ рд╡рд░реНрдгрд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрдгрдирд╛ рдХреА рдЧрдИ рдЖрдпрд╛рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИрдВ:



 var s = zoomSizes[zoom]; var beginLat = Math.floor((latMin - initPoint.x) / s.width) * s.width + initPoint.x; var beginLng = Math.floor((lngMin - initPoint.y) / s.height) * s.height + initPoint.y; var lat = beginLat; var lng = beginLng; if (lngMax <= beginLng) beginLng = beginLng - 360; while (lat <= maxlat) { lng = beginLng; while (lng <= maxLng) { // lat and normalizeLng(lng) coordinates are the coordinates of the overlapping rectangles. // Longitude normalization is used because the right boundary can be greater than 180 or the left boundary can be less than -180. loadIfNeeded(lat, normalizeLng(lng)); lng += s.height; } lat += s.width; } function normalizeLng(lng) { var rtn = lng % 360; if (rtn <= 0) rtn += 360; if (rtn > 180) rtn -= 360; return rtn; } 

рдЙрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдиреЗ рдкрд░ рд╕рд░реНрд╡рд░ рдХреЛ рдЕрдиреБрд░реЛрдз рднреЗрдЬрддрд╛ рд╣реИред рд╣реИрд╢ рдЧрдгрдирд╛ рдХрд╛ рд╕реВрддреНрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдореВрд▓реНрдп рджреЗрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБ рдФрд░ рдЖрдпрд╛рдо рддрдп рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред


 function loadIfNeeded(lat, lng) { var hash = calculateHash(lat, lng, zoom); if (!(hash in items)) { // Send a query to the database and put this cell in the client cache. } else { // Do nothing. } } function calculateHash(lat, lng, zoom) { // lat: [-90..90] // lng: [-180..180] return (lat + 90) + ((lng + 180) * 180) + (zoom * 64800); } 

рдкреНрд░рджрд░реНрд╢рд┐рдд рддрд╕реНрд╡реАрд░реЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдирд╛


рд╕рднреА рддрд╕реНрд╡реАрд░реЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рд╣реЛрдиреЗ рдпрд╛ рдХреИрд╢ рд╕реЗ рдирд┐рдХрд╛рд▓реЗ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЛ рдлрд┐рд░ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдлрд╝реЛрдЯреЛ, рдпрд╛ рдорд╛рд░реНрдХрд░ рдХреЗ рд╕рд╛рде, рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЛ рдЫрд┐рдкрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдлрд┐рд░ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрдерд╛рди рдкрд░ рдХрд┐рддрдиреЗ рдлрд╝реЛрдЯреЛ рд╕реНрдерд┐рдд рд╣реИрдВред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рд░реНрдХрд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛: рдлреЛрдЯреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдорд╛рд░реНрдХрд░ рдФрд░ рдпрд╣ рджрд┐рдЦрд╛рддреЗ рд╣реБрдП рдорд╛рд░реНрдХрд░ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рд╕реАрдорд╛рдУрдВ рдХреЛ рдмрджрд▓рдиреЗ рдкрд░ рд╕рднреА рдорд╛рд░реНрдХрд░ рдЫрд┐рдкреЗ рд╣реБрдП рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдлрд╝реНрд▓рд┐рдХрд░рд┐рдВрдЧ рдХреЛ рдиреЛрдЯрд┐рд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:


  1. рдХреНрд▓рд╛рдЗрдВрдЯ рдХреИрд╢ рд╕реЗ visMarks рддрдХ рд╕рднреА рджреГрд╢реНрдпрдорд╛рди рдлрд╝реЛрдЯреЛ рдХреЛ visMarks ред рддрд╕реНрд╡реАрд░реЛрдВ рдХреЗ рд╕рд╛рде рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЧрдгрдирд╛ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдереАред
  2. рдкреНрд░рд╛рдкреНрдд рдорд╛рд░реНрдХрд░реЛрдВ рдХреЛ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рд╕реЗ рдХреНрд░рдордмрджреНрдз рдХрд░рдирд╛ред
  3. рдорд╛рд░реНрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрддрд┐рд╡реНрдпрд╛рдкреА рдорд╛рд░реНрдХрд░реЛрдВ рдХрд╛ рдкрддрд╛ markerSize , SmallMarkerSize , minPhotoDistRatio рдФрд░ pixelDistance ред
  4. maxBigVisPhotosCount рд╕рд╛рде рдмрдбрд╝реЗ рдорд╛рд░реНрдХрд░реЛрдВ рдХреА рд╕рд░рдгрд┐рдпрд╛рдБ рдмрдирд╛рдирд╛ рдФрд░ maxBigVisPhotosCount рд╕рд╛рде рдЫреЛрдЯреЗ рдорд╛рд░реНрдХрд░ maxSmlVisPhotosCount ред
  5. рдкреБрд░рд╛рдиреЗ рдорд╛рд░реНрдХрд░реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛, рдЬрд┐рдиреНрд╣реЗрдВ рдЫрд┐рдкрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЙрдиреНрд╣реЗрдВ smlMarksToHide рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП smlMarksToHide рдФрд░ bigMarksToHide refreshMarkerArrays ред
  6. рдирдП рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдпрддрд╛ рдФрд░ рдЬрд╝реВрдо рдЗрдВрдбреЗрдХреНрд╕ zIndex рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рдЬреЛ рдХрд┐ zIndex рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
  7. addPhotoToRibbon рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝реАрдб рдореЗрдВ addPhotoToRibbon рдЧрдП рдлрд╝реЛрдЯреЛ, рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╕рдордп рдореЗрдВ рджрд┐рдЦрд╛рдИ addPhotoToRibbon ред

рджреГрд╢реНрдпрдорд╛рди рдорд╛рд░реНрдХрд░реЛрдВ рдХреЗ рдкреБрдирд░реНрдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рджрдо
 function redraw() { isRedrawing = true; var visMarker; var visMarks = []; var visBigMarks2; var visSmlMarks2; var bigMarksToHide = []; var smlMarksToHide = []; var photo; var i, j; var bounds = map.getBounds(); var northEast = bounds.getNorthEast(); var southWest = bounds.getSouthWest(); var latMin = southWest.lat(); var lngMin = southWest.lng(); var latMax = northEast.lat(); var lngMax = northEast.lng(); var ratio = (latMax - latMin) / $("#map_canvas").height(); var zoom = map.getZoom(); visMarks = []; var k = 0; var s = zoomSizes[zoom]; var beginLat = Math.floor((latMin - initPoint.x) / s.width) * s.width + initPoint.x; var beginLng = Math.floor((lngMin - initPoint.y) / s.height) * s.height + initPoint.y; var lat = beginLat; var lng = beginLng; i = 0; if (lngMax <= beginLng) beginLng = beginLng - 360; // Extracting all visible markers. while (lat <= latMax) { lng = beginLng; while (lng <= lngMax) { var hash = calcHash(lat, normLng(lng), zoom); if (!(hash in curItems)) { } else { var item = curItems[hash]; for (photo in item.photos) { if (bounds.contains(item.photos[photo].latLng)) { visMarks[i] = item.photos[photo]; visMarks[i].overlapCount = 0; i++; } } } k++; lng += s.height; } lat += s.width; } // Sorting markers by popularity. visMarks.sort(function (a, b) { if (b.priority !== a.priority) { return b.priority - a.priority; } else if (b.popularity !== a.popularity) { return b.popularity - a.popularity; } else { return b.id - a.id; } }); // Finding overlapping markers and markers that exceed a certain specified number. var curInd; var contains; var contains2; var dist; visBigMarks2 = []; visSmlMarks2 = []; for (i = 0; i < visMarks.length; i++) { contains = false; contains2 = false; visMarker = visMarks[i]; for (j = 0; j < visBigMarks2.length; j++) { dist = pixelDistance(visMarker.latLng, visBigMarks2[j].latLng, zoom); if (dist <= markerSize * minPhotoDistRatio) { contains = true; if (contains && contains2) break; } if (dist <= (markerSize + smallMarkerSize) / 2) { contains2 = true; if (contains && contains2) break; } } if (!contains) { if (visBigMarks2.length < maxBigVisPhotosCount) { smlMarksToHide[smlMarksToHide.length] = visMarker; visBigMarks2[visBigMarks2.length] = visMarker; } } else { bigMarksToHide[bigMarksToHide.length] = visMarker; if (!contains2 && visSmlMarks2.length < maxSmlVisPhotosCount) { visSmlMarks2[visSmlMarks2.length] = visMarker; } else { visBigMarks2[j].overlapCount++; } } } // Adding markers that should be hidden to smlMarksToHide and bigMarksToHide. refreshMarkerArrays(visibleSmallMarkers, visSmlMarks2, smlMarksToHide); refreshMarkerArrays(visibleBigMarkers, visBigMarks2, bigMarksToHide); // Hiding invisible markers and displaying visible markers when zIndex changes. var curZInd = maxBigVisPhotosCount + 1; curZInd = updateMarkersVis(visBigMarks2, bigMarksToHide, true, curZInd); curZInd = 0; curZInd = updateMarkersVis(visSmlMarks2, smlMarksToHide, false, curZInd); visibleBigMarkers = visBigMarks2; visibleSmallMarkers = visSmlMarks2; // Adding visible photos to the feed. trPhotosOnMap.innerHTML = ''; for (var marker in visBigMarks2) { addPhotoToRibbon(visBigMarks2[marker]); } isRedrawing = false; } function refreshMarkerArrays(oldArr, newArr, toHide) { for (var j = 0; j < oldArr.length; j++) { contains = false; var visMarker = oldArr[j]; for (i = 0; i < newArr.length; i++) { if (newArr[i].id === visMarker.id) { contains = true; break; } } if (!contains) { toHide[toHide.length] = visMarker; } } } function updateMarkersVis(showArr, hideArr, big, curZInd) { var marker; var bounds = map.getBounds(); for (var i = 0; i < showArr.length; i++) { var photo = showArr[i]; if (big) { marker = photo.bigMarker; $('#divOvlpCount' + photo.id).html(photo.overlapCount); } else { marker = photo.smlMarker; } marker.setZIndex(++curZInd); if (marker.getMap() === null) { marker.setMap(map); } } for (i = 0; i < hideArr.length; i++) { marker = big ? hideArr[i].bigMarker : hideArr[i].smlMarker; if (marker.getMap() !== null) { marker.setMap(null); marker.setZIndex(0); if (!bounds.contains(hideArr[i].latLng)) hideArr[i].priority = 0; } } return curZInd; } function addPhotoToRibbon(marker) { var td = createColumn(marker); if (isLatLngValid(marker.latLng)) { trPhotosOnMap.appendChild(td); } else { trPhotosNotOnMap.appendChild(td); if (photoViewMode == 'user') { var img = $("#photo" + marker.id).children()[0]; $('#photo' + marker.id).draggable({ helper: 'clone', appendTo: $('#map_canvas'), stop: function (e) { var mapBoundingRect = document.getElementById("map_canvas").getBoundingClientRect(); var point = new google.maps.Point(e.pageX - mapBoundingRect.left, e.pageY - mapBoundingRect.top); var latLng = overlay.getProjection().fromContainerPixelToLatLng(point); marker.latLng = latLng; marker.priority = ++curPriority; placeMarker(marker); }, containment: 'parent', distance: 5 }); } } } 

рдирдХреНрд╢реЗ рдкрд░ рджреВрд░реА


рдкрд┐рдХреНрд╕реЗрд▓ рдореЗрдВ рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рджреЛ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдмреАрдЪ рдХреА рджреВрд░реА рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:


 var Offset = 268435456; var Radius = 85445659.4471; function pixelDistance(latLng1, latLng2, zoom) { var x1 = lonToX(latLng1.lng()); var y1 = latToY(latLng1.lat()); var x2 = lonToX(latLng2.lng()); var y2 = latToY(latLng2.lat()); return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) >> (21 - zoom); } function lonToX(lng) { return Math.round(Offset + Radius * lng * Math.PI / 180); } function latToY(lat) { return Math.round(Offset - Radius * Math.log((1 + Math.sin(lat * Math.PI / 180)) / (1 - Math.sin(lat * Math.PI / 180))) / 2); } 

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╕реНрдЯреИрдХрдУрд╡рд░рдлрд╝реНрд▓реЛ рдкрд░ рднреА рдкрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред


рдорд╛рд░реНрдХрд░реЛрдВ рдХреЛ рдлрд╝реЛрдЯреЛ (рдЬреИрд╕реЗ vkontakte) рдХреЗ рд╕рд╛рде рдордВрдбрд▓рд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд▓рдЧрдЗрди рд░рд┐рдЪрдорд╛рд░реНрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП div рддрддреНрд╡ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред


рдирд┐рд╖реНрдХрд░реНрд╖


рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдорд╛рдирдЪрд┐рддреНрд░ рдкрд░ рдлрд╝реЛрдЯреЛ рдХреЛ рдЬрд▓реНрджреА рдФрд░ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдХреИрд╢рд┐рдВрдЧ рдФрд░ рдЧреЛрд▓рд╛рдХрд╛рд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдХрд╛рдлреА рд░реЛрдЪрдХ рдФрд░ рдЧреИрд░-рддреБрдЪреНрдЫ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рд╕рднреА рд╡рд░реНрдгрд┐рдд рд╡рд┐рдзрд┐рдпрд╛рдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХреА рдЧрдИ рдереАрдВ, рд╕рдордп рдмрд░реНрдмрд╛рдж рдирд╣реАрдВ рд╣реБрдЖ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдЬреЛ рдЕрдиреБрднрд╡ рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ рд╡рд╣ рдЕрдиреНрдп рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рднреА рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдкрдврд╝рд╛ рдФрд░ рд╕рдордЭрд╛ рд╣реИред

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


All Articles