function getOldTownBounds() {
  var coords = new Array();
  coords[0] = new GLatLng(51.13105377532131, 17.002243995666504);
  coords[1] = new GLatLng(51.1093421706695, 16.99687957763672);
  coords[2] = new GLatLng(51.1042764577832, 17.002201080322266);
  coords[3] = new GLatLng(51.10147391000868, 17.00881004333496);
  coords[4] = new GLatLng(51.104384244689136, 17.022113800048828);
  coords[5] = new GLatLng(51.099749180773266, 17.036104202270508);
  coords[6] = new GLatLng(51.10713272587037, 17.039108276367188);
  coords[7] = new GLatLng(51.10702494537346, 17.044429779052734);
  coords[8] = new GLatLng(51.11085099910474, 17.049150466918945);
  coords[9] = new GLatLng(51.11486532058065, 17.0357608795166);
  coords[10] = new GLatLng(51.11281779078326, 17.02855110168457);
  coords[11] = new GLatLng(51.11435344663691, 17.021942138671875);
  coords[12] = new GLatLng(51.11836746386068, 17.01683521270752);
  coords[13] = new GLatLng(51.12248887705868, 17.02108383178711);
  coords[14] = new GLatLng(51.12593657426229, 17.01906681060791)
  coords[15] = new GLatLng(51.128306716819104, 17.014474868774414);
  return coords;
}
function getCityBounds() {
  var coords = new Array();
  coords[0] = new GLatLng(51.18729212289149, 17.031748294830322);
  coords[1] = new GLatLng(51.174957585841305, 17.02481746673584);
  coords[2] = new GLatLng(51.16435558686151, 17.075929641723633);
  coords[3] = new GLatLng(51.1747961523557, 17.082924842834473);
  coords[4] = new GLatLng(51.17460781257482, 17.101163864135742);
  coords[5] = new GLatLng(51.187735943292545, 17.137298583984375);
  coords[6] = new GLatLng(51.178051618415424, 17.161502838134766);
  coords[7] = new GLatLng(51.146294287889894, 17.155323028564453);
  coords[8] = new GLatLng(51.123997276249064, 17.139616012573242);
  coords[9] = new GLatLng(51.12275823766943, 17.153778076171875);
  coords[10] = new GLatLng(51.10912661972892, 17.170429229736328);
  coords[11] = new GLatLng(51.0834688793963, 17.165021896362305);
  coords[12] = new GLatLng(51.07565014181984, 17.132234573364258);
  coords[13] = new GLatLng(51.07974840353906, 17.11618423461914);
  coords[14] = new GLatLng(51.0651871435207, 17.099361419677734);
  coords[15] = new GLatLng(51.05585474252802, 17.093610763549805);
  coords[16] = new GLatLng(51.050513389298544, 17.1097469329834);
  coords[17] = new GLatLng(51.04409215945304, 17.10124969482422);
  coords[18] = new GLatLng(51.04738382544955, 17.08150863647461);
  coords[19] = new GLatLng(51.059199518706656, 17.070865631103516);
  coords[20] = new GLatLng(51.05949622105481, 17.062454223632812);
  coords[21] = new GLatLng(51.050945036682585, 17.06279754638672);
  coords[22] = new GLatLng(51.050540367377906, 17.0582914352417);
  coords[23] = new GLatLng(51.04571104081335, 17.054729461669922);
  coords[24] = new GLatLng(51.04916446529361, 17.031383514404297);
  coords[25] = new GLatLng(51.045387269067376, 17.027177810668945);
  coords[26] = new GLatLng(51.04676328335867, 17.013230323791504);
  coords[27] = new GLatLng(51.0517004099243, 17.01606273651123);
  coords[28] = new GLatLng(51.054991535259155, 17.005290985107422);
  coords[29] = new GLatLng(51.05161947766628, 17.00211524963379);
  coords[30] = new GLatLng(51.052644609150875, 16.99713706970215);
  coords[31] = new GLatLng(51.05744623874488, 16.991171836853027);
  coords[32] = new GLatLng(51.05520733858494, 16.97409152984619);
  coords[33] = new GLatLng(51.0490295707323, 16.967697143554688);
  coords[34] = new GLatLng(51.05860610830619, 16.955723762512207);
  coords[35] = new GLatLng(51.068962724957466, 16.95937156677246);
  coords[36] = new GLatLng(51.076189407522506, 16.94117546081543);
  coords[37] = new GLatLng(51.082013076650576, 16.938858032226562);
  coords[38] = new GLatLng(51.08115035710853, 16.928300857543945);
  coords[39] = new GLatLng(51.08487072022205, 16.920833587646484);
  coords[40] = new GLatLng(51.09689245643723, 16.924095153808594);
  coords[41] = new GLatLng(51.1004498597854, 16.893539428710938);
  coords[42] = new GLatLng(51.0912593413331, 16.88525676727295);
  coords[43] = new GLatLng(51.099048491141716, 16.85955047607422);
  coords[44] = new GLatLng(51.107752458850065, 16.855688095092773);
  coords[45] = new GLatLng(51.10794107158581, 16.826763153076172);
  coords[46] = new GLatLng(51.115053904288466, 16.8460750579834);
  coords[47] = new GLatLng(51.12133060853491, 16.83676242828369);
  coords[48] = new GLatLng(51.12372792286324, 16.822986602783203);
  coords[49] = new GLatLng(51.13003038046751, 16.821012496948242);
  coords[50] = new GLatLng(51.13590112701754, 16.831741333007812);
  coords[51] = new GLatLng(51.136089624860126, 16.82783603668213);
  coords[52] = new GLatLng(51.13366602251198, 16.816377639770508);
  coords[53] = new GLatLng(51.13703210252993, 16.80809497833252);
  coords[54] = new GLatLng(51.14559430391679, 16.810970306396484);
  coords[55] = new GLatLng(51.157169597952674, 16.8380069732666);
  coords[56] = new GLatLng(51.16879580692051, 16.820926666259766);
  coords[57] = new GLatLng(51.182087001044266, 16.825475692749023);
  coords[58] = new GLatLng(51.182678827459796, 16.842212677001953);
  coords[59] = new GLatLng(51.177190691070415, 16.859378814697266);
  coords[60] = new GLatLng(51.187413165242916, 16.88375473022461);
  coords[61] = new GLatLng(51.18015006146679, 16.899890899658203);
  coords[62] = new GLatLng(51.18614892944895, 16.904397010803223);
  coords[63] = new GLatLng(51.19515921451807, 16.88624382019043);
  coords[64] = new GLatLng(51.201505700935925, 16.882810592651367);
  coords[65] = new GLatLng(51.20225861588382, 16.896800994873047);
  coords[66] = new GLatLng(51.20967954757961, 16.904010772705078);
  coords[67] = new GLatLng(51.208496580611865, 16.904568672180176);
  coords[68] = new GLatLng(51.204409733638954, 16.912508010864258);
  coords[69] = new GLatLng(51.195777766475885, 16.920275688171387);
  coords[70] = new GLatLng(51.205162601119824, 16.951045989990234);
  coords[71] = new GLatLng(51.20451728688964, 16.977310180664062);
  coords[72] = new GLatLng(51.1965576679779, 17.00357437133789);
  coords[73] = new GLatLng(51.182571223222126, 17.002029418945312);
  coords[74] = new GLatLng(51.17950439685516, 17.012500762939453);
  coords[75] = new GLatLng(51.18692899392984, 17.01430320739746);
  return coords;
}

function drawBounds(map, coords, color, size, point) {
  for (i = 0; i < coords.length; i++) {
    var firstPoint =  coords[i];
    var ind = i == coords.length - 1 ? 0 : i + 1;
    var secondPoint = coords[ind];
    var polyline = new GPolyline([ firstPoint, secondPoint ], color, size);
    map.addOverlay(polyline);
  }
  if (point != '') {
    var nearest = getNearestPointOnRegion(point, coords);
    map.addOverlay(new GPolyline([ point, nearest ], "#00ff00", 3));
  }
}

function drawOldTownBounds(map, point) {
  drawBounds(map, getOldTownBounds(), "#0000ff", 2, point);
}

function drawCityBounds(map, point) {
  drawBounds(map, getCityBounds(), "#ff0000", 3, point);
}

function calculateDistanceFromCityCenter(point) {
  var centrum = new GLatLng(51.11011006272512, 17.031919956207275);
  var distance = point.distanceFrom(centrum) / 1000 - 0.8;
  if (distance < 0) distance = 0;
  distance = Math.round(distance * 2) / 2;
  return distance;
}

function calculateDistanceFromRegion(point, coords, tolerance) {
  if (tolerance == '') {
    tolerance = 0.1;
  }
  if (!isOutsideOfRegion(point, coords)) {
    return 0;
  }
  var distance = point.distanceFrom(getNearestPointOnRegion(point, coords)) / 1000 - 0.1;
  distance = Math.round(distance * 2) / 2;
  return distance;
}

function calculateDistanceFromOldTown(point) {
  return calculateDistanceFromRegion(point, getOldTownBounds(), 0.2);
}

function calculateDistanceFromCityBounds(point) {
  return calculateDistanceFromRegion(point, getCityBounds());
}

function getNearestPointOnRegion(point, coords) {

  var minD = -1;
  var minP;

  for (i = 0; i < coords.length; i++) {
    var firstPoint =  coords[i];
    var ind = i == coords.length - 1 ? 0 : i + 1;
    var secondPoint = coords[ind];

    var np = getNearestPoint(firstPoint, secondPoint, point);
    var distance = point.distanceFrom(np);

    if (minD == -1 || distance < minD) {
      minD = distance;
      minP = np;
    }

  }
  return minP;
}

function isOutsideOfRegion(point, coords) {

  var xCounter = 0;
  var yCounter = 0;

  for (i = 0; i < coords.length; i++) {
    var firstPoint =  coords[i];
    var ind = i == coords.length - 1 ? 0 : i + 1;
    var secondPoint = coords[ind];

    if (getValidCrossingPointX(firstPoint, secondPoint, point) != null ) xCounter++;
    if (getValidCrossingPointY(firstPoint, secondPoint, point) != null ) yCounter++;
  }
  return xCounter % 2 == 0 && yCounter % 2 == 0;
}

function getValidCrossingPointX(p1, p2, p3) {
  var cp = getCrossingPointX(p1, p2, p3);
  var x1 = p1.lat(); var x2 = p2.lat(); var x3 = p3.lat(); var x4 = cp.lat();
  if (x4 <= x3 && (x2 > x1 && x4 >= x1 && x4 <= x2 || x2 <= x1 && x4 >= x2 && x4 <= x1)) {
    return cp;
  }
  return null;
}

function getValidCrossingPointY(p1, p2, p3) {
  var cp = getCrossingPointY(p1, p2, p3);
  var y1 = p1.lng(); var y2 = p2.lng(); var y3 = p3.lng(); var y4 = cp.lng();
  if (y4 <= y3 && (y2 > y1 && y4 >= y1 && y4 <= y2 || y2 <= y1 && y4 >= y2 && y4 <= y1)) {
    return cp;
  }
  return null;
}

function getCrossingPointX(p1, p2, p3) {
  var x1 = p1.lat(); var x2 = p2.lat(); var x3 = p3.lat();
  var y1 = p1.lng(); var y2 = p2.lng(); var y3 = p3.lng();

  var a = (y1 - y2) / (x1 - x2);
  var b = y2 - a * x2;

  var x4 = (y3 - b) / a;
  var y4 = y3;

  return new GLatLng(x4, y4);
}

function getCrossingPointY(p1, p2, p3) {
  var x1 = p1.lat(); var x2 = p2.lat(); var x3 = p3.lat();
  var y1 = p1.lng(); var y2 = p2.lng(); var y3 = p3.lng();

  var a = (y1 - y2) / (x1 - x2);
  var b = y2 - a * x2;

  var x4 = x3;
  var y4 = a * x3 + b;

  return new GLatLng(x4, y4);
}

function getNearestPoint(p1, p2, p3) {

  var d1 = p3.distanceFrom(p1);
  var d2 = p3.distanceFrom(p2);

  var x1 = p1.lat(); var x2 = p2.lat(); var x3 = p3.lat();
  var y1 = p1.lng(); var y2 = p2.lng(); var y3 = p3.lng();

  var x4, y4;

  if (y1 == y2) {
    x4 = x3;
    y4 = y1;
  } else if (x1 == x2) {
    x4 = x1;
    y4 = y3;
  } else {
    var a = (y1 - y2) / (x1 - x2);
    var b = y2 - a * x2;
    var c = y3 + x3 / a;

    x4 = (c - b) / (a + 1/a);
    y4 = a * x4 + b;
  }

  var dm = Math.min(d1, d2);

  if (x2 > x1 && x4 >= x1 && x4 <= x2 || x2 <= x1 && x4 >= x2 && x4 <= x1) {
    var p4 = new GLatLng(x4, y4);
    var d4 = p3.distanceFrom(p4);
    if (d4 < dm) {
      return p4;
    }
  }

  return d1 < d2 ? p1 : p2;
}