function Map()
{
    global $link, $lev, $fco, $xm, $ym, $xo, $yo, $csi, $bsi, $fsi, $cro, $bro, $cwt, $loi, $bwt, $dev, $ndev, $bdev, $cdev;
    global $devlink, $ctylink, $bldlink, $rdevlink, $rctylink, $rbldlink, $nctylink, $nbldlink, $imgmap;
    global $geo, $xbl, $ybl, $xct, $yct, $mapbg, $mapinfo, $mapframes, $maplinks, $mapitems, $locsep;
    $mapinfo = "";
    $mapframes = "";
    $maplinks = "";
    $mapitems = "";
    $ctyscalx = 1.3;
    $ctyscaly = 1;
    $nreg = count($rdev);
    $ncty = count($cdev);
    if ($nreg == 1) {
        $rk = array_keys($rdev);
        if ($ncty == 1) {
            $ctyscalx = 0;
            $ctyscaly = 0;
            $ck = array_keys($rdev[$rk[0]]);
            $mapbg = TopoMap($rk[0], $ck[0]);
        } else {
            $mapbg = TopoMap($rk[0]);
        }
    } else {
        $mapbg = TopoMap();
    }
    if ($geo) {
        $bg = Imagecreatefrompng("log/{$mapbg}");
        $xm = Imagesx($bg);
        $ym = Imagesy($bg);
        Imagedestroy($bg);
        $query = GenQuery('locations');
        $res = @DbQuery($query, $link);
        if ($res) {
            while ($l = @DbFetchRow($res)) {
                if ($l[3]) {
                    if ($mapbg == TopoMap($l[1], $l[2])) {
                        $xbl["{$l['1']}{$locsep}{$l['2']}"][$l[3]] = $l[4];
                        $ybl["{$l['1']}{$locsep}{$l['2']}"][$l[3]] = $l[5];
                    }
                } elseif ($l[2]) {
                    if ($mapbg == TopoMap($l[1])) {
                        $xct["{$l['1']}{$locsep}{$l['2']}"] = $l[4];
                        $yct["{$l['1']}{$locsep}{$l['2']}"] = $l[5];
                    }
                } else {
                    $xrg[$l[1]] = $l[4];
                    $yrg[$l[1]] = $l[5];
                }
            }
            @DbFreeResult($res);
        } else {
            echo @DbError($link);
        }
    }
    $ctynum = 0;
    ksort($cdev);
    foreach (Arrange($cdev, "c") as $cty) {
        $ctynum++;
        $nbld = count($ndev[$cty]);
        $ncl = $nctylink[$cty] ? $nctylink[$cty] : 1;
        $l = explode($locsep, $cty);
        if (!(isset($xct[$cty]) and isset($yct[$cty]))) {
            $phi = $cro * M_PI / 180 + 2 * $ctynum * M_PI / $ncty;
            $ctywght = pow($ncl, $cwt / 10);
            $xct[$cty] = intval(intval($xm / 2) + $xo + $csi * cos($phi) * $ctyscalx / $ctywght);
            $yct[$cty] = intval(intval($ym / 2) + $yo + $csi * sin($phi) * $ctyscaly / $ctywght);
        }
        if ($lev == "c" or $lev == "C") {
            $mapitems .= Drawitem($xct[$cty], $yct[$cty], $cdev[$cty], $l[1], $lev);
            $area = $xct[$cty] - 20 . "," . ($yct[$cty] - 20) . "," . ($xct[$cty] + 20) . "," . ($yct[$cty] + 20);
            $imgmap .= "<area href=?flt=" . rawurlencode($cty) . "&lev=b&loi=1&draw=1 coords=\"{$area}\" shape=rect title=\"Show {$nbld} buildings\">\n";
        } else {
            if ($nbld == 1) {
                $bldscalx = 0;
                $bldscaly = 0;
            } else {
                $bldscalx = 1.3;
                $bldscaly = 1;
                if ($loi) {
                    $mapinfo .= Drawitem($xct[$cty], $yct[$cty], '0', "{$l['1']} {$l['0']}", 'ci');
                }
            }
            $bldnum = 0;
            foreach (Arrange($ndev[$cty], "b") as $bld) {
                $bldnum++;
                $nbl = $nbldlink[$bld] ? $nbldlink[$bld] : 1;
                if (!(isset($xbl[$bld]) and isset($ybl[$bld]))) {
                    $eps = $bro * M_PI / 180 + 2 * $bldnum * M_PI / $nbld;
                    $bldwght = pow($nbl, $bwt / 10);
                    $xbl[$bld] = intval($xct[$cty] + $bsi * cos($eps) * $bldscalx / $bldwght);
                    $ybl[$bld] = intval($yct[$cty] + $bsi * sin($eps) * $bldscaly / $bldwght);
                }
                if ($lev == "b" or $lev == "B") {
                    $mapitems .= Drawitem($xbl[$bld], $ybl[$bld], $bdev[$cty][$bld], $bld, $lev);
                    $area = $xbl[$bld] - 20 . "," . ($ybl[$bld] - 20) . "," . ($xbl[$bld] + 20) . "," . ($ybl[$bld] + 20);
                    $imgmap .= "<area href=?flt=" . rawurlencode($bld) . "&lev=f&loi=1&ipi=1&draw=1 coords=\"{$area}\" shape=rect title=\"Show " . $bdev[$cty][$bld] . " devices\">\n";
                } else {
                    $cury = $rows = 0;
                    $cols = 1;
                    foreach (array_keys($ndev[$cty][$bld]) as $flr) {
                        # Determine building size
                        $cols = max(count($ndev[$cty][$bld][$flr]), $cols);
                        # find max cols
                        if ($cols > $fco) {
                            # Break row, if > Floor columns
                            $rrow = ceil($cols / $fco);
                            # How many rows result?
                            $rows += $rrow;
                            $cols = $fco;
                        } else {
                            $rows++;
                        }
                    }
                    $woff = intval($fsi * ($cols - 1) / 2);
                    $hoff = intval($fsi * ($rows - 1) / 2);
                    $mapframes .= Drawbox($xbl[$bld] - $woff - intval($fsi / 2) - 10, $ybl[$bld] - $hoff - intval($fsi / 2), $xbl[$bld] + $woff + intval($fsi / 2), $ybl[$bld] + $hoff + intval($fsi / 2), $bld);
                    uksort($ndev[$cty][$bld], "Floorsort");
                    foreach (array_keys($ndev[$cty][$bld]) as $flr) {
                        $mapitems .= Drawitem($xbl[$bld] - $woff - intval($fsi / 2), $ybl[$bld] - $hoff + $cury * $fsi, 0, $flr, 'fl');
                        usort($ndev[$cty][$bld][$flr], "Roomsort");
                        $curx = 0;
                        foreach ($ndev[$cty][$bld][$flr] as $dv) {
                            $xd[$dv] = $xbl[$bld] - $woff + $curx * $fsi;
                            $yd[$dv] = $ybl[$bld] - $hoff + $cury * $fsi;
                            $mapitems .= Drawitem($xd[$dv], $yd[$dv], '0', $dv, 'd');
                            $area = $xd[$dv] - 20 . "," . ($yd[$dv] - 20) . "," . ($xd[$dv] + 20) . "," . ($yd[$dv] + 20);
                            $imgmap .= "<area href=Devices-Status.php?dev=" . rawurlencode($dv) . " coords=\"{$area}\" shape=rect title=\"Show {$dv} Status\">\n";
                            $curx++;
                            if ($curx == $fco) {
                                $curx = 0;
                                $cury++;
                            }
                        }
                        $cury++;
                    }
                }
            }
        }
    }
    if ($lev == "c" or $lev == "C") {
        # Draw links after we set all coordinates
        foreach (array_keys($ctylink) as $ctyl) {
            foreach (array_keys($ctylink[$ctyl]) as $ctyn) {
                $mylink = Drawlink($xct[$ctyl], $yct[$ctyl], $xct[$ctyn], $yct[$ctyn], $ctylink[$ctyl][$ctyn]);
                $maplinks .= $mylink[0];
                $mapitems .= $mylink[1];
            }
        }
    } elseif ($lev == "b" or $lev == "B") {
        foreach (array_keys($bldlink) as $bldl) {
            foreach (array_keys($bldlink[$bldl]) as $bldn) {
                $mylink = Drawlink($xbl[$bldl], $ybl[$bldl], $xbl[$bldn], $ybl[$bldn], $bldlink[$bldl][$bldn]);
                $maplinks .= $mylink[0];
                $mapitems .= $mylink[1];
            }
        }
    } elseif ($lev == "f") {
        foreach (array_keys($devlink) as $devl) {
            foreach (array_keys($devlink[$devl]) as $devn) {
                $mylink = Drawlink($xd[$devl] - 8, $yd[$devl] - 4, $xd[$devn] - 8, $yd[$devn] - 4, $devlink[$devl][$devn]);
                $maplinks .= $mylink[0];
                $mapitems .= $mylink[1];
            }
        }
    }
}
function Drawitem($x,$y,$opt,$label,$typ) {

	global $fmt,$dev,$loi,$ipi,$redbuild;

	$itxt  = "";
	$pfont = "1";
	$vfont = "font-size=\"9\"";
	$vicon = "32";
	if($opt > 2){$r = 8;}else{$r = 4;}

	if($typ == "f"){
		$cury = $rows = 0;
		$cols = 1;
		foreach(array_keys($ndev[$cty][$bld]) as $flr){			# Determine building size
			$cols = max(count($ndev[$cty][$bld][$flr]),$cols);	# find max cols
			if($cols > $fco){					# Break row, if > Floor columns
				$rrow  = ceil($cols / $fco);			# How many rows result?
				$rows += $rrow;
				$cols = $fco;
			}else{
				$rows++;
			}
		}
		$woff = intval($fsi*($cols-1)/2);
		$hoff = intval($fsi*($rows-1)/2);

		$mapframes .= Drawbox(	$xbl[$bld] - $woff - intval($fsi/2) - 10,
					$ybl[$bld] - $hoff - intval($fsi/2),
					$xbl[$bld] + $woff + intval($fsi/2),
					$ybl[$bld] + $hoff + intval($fsi/2),
					$bld);
		uksort($ndev[$cty][$bld], "Floorsort");
		foreach(array_keys($ndev[$cty][$bld]) as $flr){
			$mapitems .= Drawitem(	$xbl[$bld] - $woff - intval($fsi/2),
						$ybl[$bld] - $hoff + $cury*$fsi,
						0,$flr,'fl');
			usort( $ndev[$cty][$bld][$flr],"Roomsort" );
			$curx = 0;
			foreach($ndev[$cty][$bld][$flr] as $dv){
				$xd[$dv] = $xbl[$bld] - $woff + $curx*$fsi;
				$yd[$dv] = $ybl[$bld] - $hoff + $cury*$fsi;
				$mapitems .= Drawitem($xd[$dv],$yd[$dv],'0',$dv,'d');
				$area = ($xd[$dv]-20) .",". ($yd[$dv]-20) .",". ($xd[$dv]+20) .",". ($yd[$dv]+20);
				$imgmap .= "<area href=Devices-Status.php?dev=". rawurlencode($dv) ." coords=\"$area\" shape=rect title=\"Show $dv Status\">\n";
				$curx++;
				if($curx == $fco){
					$curx = 0;
					$cury++;
				}
			}
			$cury++;
		}	
	}elseif($typ == "B"){
		if( preg_match("/$redbuild/",$label) ){$bc = "red";}else{$bc = "cornflowerblue";}
		if($fmt == "svg"){
			$itxt .= "	<rect fill=\"$bc\" stroke=\"black\" x=\"".($x-$r)."\" y=\"".($y-$r)."\" width=\"".(2*$r)."\" height=\"".(2*$r)."\" />\n";
			$itxt .= "	<text x=\"".($x-20)."\" y=\"".($y+20)."\" fill=\"blue\">$label</text>\n";
		}else{
			$itxt .= "Imagefilledrectangle(\$image, ".($x-$r).", ".($y-$r).", ".($x+$r).", ".($y+$r).", \$$bc);\n";
			$itxt .= "Imagerectangle(\$image, ".($x-$r).", ".($y-$r).", ".($x+$r).", ".($y+$r).", \"\$black\");\n";
			$itxt .= "ImageString(\$image, 1, ".($x-10).", ".($y+10).", \"$label\", \"\$blue\");\n";
		}
		return $itxt;
	}elseif($typ == "C"){
		if($fmt == "svg"){
			$itxt .= "	<circle fill=\"cornflowerblue\" stroke=\"black\" cx=\"$x\" cy=\"$y\" r=\"$r\"/>\n";
			$itxt .= "	<text x=\"".($x-20)."\" y=\"".($y+20)."\" fill=\"navy\">$label</text>\n";

		}else{
			$itxt .= "Imagefilledellipse(\$image, $x, $y, ".(2*$r).", ".(2*$r).", \"\$cornflowerblue\");\n";
			$itxt .= "Imageellipse(\$image, $x, $y, ".(2*$r).", ".(2*$r).", \"\$black\");\n";
			$itxt .= "ImageString(\$image, 1, ".($x-10).", ".($y+10).", \"$label\", \"\$navy\");\n";
		}
		return $itxt;
	}elseif($typ == "ci"){
		$img = "cityg";
		$lcol = "gray";
	}elseif($typ == "c"){
		$img = CtyImg($opt);
		$lcol = "navy";
		$pfont = "5";
		$vfont = "font-size=\"15\" font-weight=\"bold\"";
		$vicon = "50";
	}elseif($typ == "b"){
		$img  = BldImg($opt,$label);
		$lcol = "blue";
	}elseif($typ == "fl"){
		$img = "stair";
		$lcol = "navy";
		$pfont = "3";
		$vfont = "font-size=\"12\" font-weight=\"bold\"";
		$vicon = "10";
	}elseif($typ == "d"){
		$img = "dev/" . $dev[$label]['ic'];
		$lcol = "black";
	}
	if($fmt == "svg"){
		$itxt .= "	<image x=\"".($x-$vicon/2)."\" y=\"".($y-$vicon/2)."\" width=\"$vicon\" height=\"$vicon\" xlink:href=\"../img/$img.png\"/>\n";
		if ($typ == "d"){
			if ($loi){$itxt .= "	<text x=\"".($x-$vicon/2)."\" y=\"".($y-$vicon/2-4)."\" $vfont fill=\"$lcol\">".$dev[$label]['rom']."</text>\n";}
			if ($ipi){$itxt .= "<text x=\"".($x-$vicon/2)."\" y=\"".($y+$vicon/2+20)."\" fill=\"gray\">".$dev[$label]['ip']."</text>\n";}
		}
		$itxt .= "	<text x=\"".($x-$vicon/2)."\" y=\"".($y+$vicon/2+10)."\" $vfont fill=\"$lcol\">".Safelabel($label)."</text>\n";

	}else{
		$itxt .= "\$icon = Imagecreatefrompng(\"../img/$img.png\");\n";
		$itxt .= "\$w = Imagesx(\$icon);\n";
		$itxt .= "\$h = Imagesy(\$icon);\n";
		$itxt .= "Imagecopy(\$image, \$icon,intval($x - \$w/2),intval($y - \$h/2),0,0,\$w,\$h);\n";
		if ($typ == "d"){
			if ($loi){$itxt .= "ImageString(\$image, $pfont, intval($x  - \$w/1.8), intval($y - \$h/1.6 - 10), \"".$dev[$label]['rom']."\", \$cornflowerblue);\n";}
			if ($ipi){$itxt .= "ImageString(\$image, $pfont, intval($x  - \$w/1.8), intval($y + \$h/1.6 + 10), \"".$dev[$label]['ip']."\", \$gray );\n";}
		}
		$itxt .= "ImageString(\$image, $pfont, intval($x  - \$w/1.8), intval($y + \$h/1.6), \"".Safelabel($label)."\", \$$lcol);\n";
		$itxt .= "Imagedestroy(\$icon);\n";
	}
	return $itxt;
}
function Map()
{
    global $lev, $fco, $xm, $ym, $xo, $yo, $csi, $bsi, $fsi, $cro, $bro, $cwt, $loi, $bwt, $dev, $ndev, $bdev, $fdev;
    global $devlink, $ctylink, $bldlink, $rdevlink, $rctylink, $rbldlink, $nctylink, $nbldlink, $imgmap;
    $ncty = count($ndev);
    if ($ncty == 1) {
        $ctyscalx = 0;
        $ctyscaly = 0;
    } else {
        $ctyscalx = 1.3;
        $ctyscaly = 1;
    }
    $ctynum = 0;
    $bldnum = 0;
    foreach (Arrange($ndev, "c") as $cty) {
        $phi = $cro * M_PI / 180 + 2 * $ctynum * M_PI / $ncty;
        $ctynum++;
        $ncl = $nctylink[$cty] ? $nctylink[$cty] : 1;
        $ctywght = pow($ncl, $cwt / 10);
        $xct[$cty] = intval(intval($xm / 2) + $xo + $csi * cos($phi) * $ctyscalx / $ctywght);
        $yct[$cty] = intval(intval($ym / 2) + $yo + $csi * sin($phi) * $ctyscaly / $ctywght);
        $nbld = count($ndev[$cty]);
        if ($lev == "c") {
            Drawitem($xct[$cty], $yct[$cty], $nbld, $cty, $lev);
            $area = $xct[$cty] - 20 . "," . ($yct[$cty] - 20) . "," . ($xct[$cty] + 20) . "," . ($yct[$cty] + 20);
            $imgmap .= "<area href=?flt=" . urlencode($cty) . "&lev=b&loi=1&draw=1 coords=\"{$area}\" shape=rect title=\"Show {$nbld} buildings\">\n";
        } else {
            if ($nbld != 1) {
                $bldscalx = 1.3;
                $bldscaly = 1;
                if ($loi and $cty != "-") {
                    Drawitem($xct[$cty], $yct[$cty], '0', $cty, 'ci');
                }
            }
            foreach (Arrange($ndev[$cty], "b") as $bld) {
                $eps = $bro * M_PI / 180 + 2 * $bldnum * M_PI / $nbld;
                $bldnum++;
                $nbl = $nbldlink[$bld] ? $nbldlink[$bld] : 1;
                $bldwght = pow($nbl, $bwt / 10);
                $xbl[$bld] = intval($xct[$cty] + $bsi * cos($eps) * $bldscalx / $bldwght);
                $ybl[$bld] = intval($yct[$cty] + $bsi * sin($eps) * $bldscaly / $bldwght);
                if ($lev == "b") {
                    Drawitem($xbl[$bld], $ybl[$bld], $bdev[$cty][$bld], $bld, $lev);
                    $area = $xbl[$bld] - 20 . "," . ($ybl[$bld] - 20) . "," . ($xbl[$bld] + 20) . "," . ($ybl[$bld] + 20);
                    $imgmap .= "<area href=?flt=" . urlencode($bld) . "&lev=f&loi=1&ipi=1&draw=1 coords=\"{$area}\" shape=rect title=\"Show " . $bdev[$cty][$bld] . " devices\">\n";
                } else {
                    $cury = $nflr = $mdfl = 0;
                    $nflr = count($ndev[$cty][$bld]);
                    $mdfl = max(array_values($fdev[$cty][$bld]));
                    foreach (array_keys($fdev[$cty][$bld]) as $flr) {
                        if ($fdev[$cty][$bld][$flr] > $fco) {
                            $afl = intval($fdev[$cty][$bld][$flr] / $fco);
                            $rem = bcmod($fdev[$cty][$bld][$flr], $fco);
                            if ($rem) {
                                $nflr = $nflr + $afl;
                            } else {
                                $nflr = $nflr + $afl - 1;
                            }
                            $mdfl = $fco;
                        }
                    }
                    $xb1 = intval($xbl[$bld] - $fsi / 2 * $mdfl - 50);
                    $yb1 = intval($ybl[$bld] - $fsi / 2 * $nflr + $fsi - 50);
                    $xb2 = intval($xbl[$bld] + $fsi / 2 * $mdfl - $fsi + 50);
                    $yb2 = intval($ybl[$bld] + $fsi / 2 * $nflr + 40);
                    Drawbox($xb1, $yb1, $xb2, $yb2, $bld);
                    uksort($ndev[$cty][$bld], "floorsort");
                    foreach (array_keys($ndev[$cty][$bld]) as $flr) {
                        $cury++;
                        $curx = 0;
                        usort($ndev[$cty][$bld][$flr], "Roomsort");
                        $xf = $xbl[$bld] - intval($fsi * $mdfl / 2 + 40);
                        $yf = $ybl[$bld] + intval($fsi * ($cury - $nflr / 2));
                        Drawitem($xf, $yf, 0, $flr, "fl");
                        foreach ($ndev[$cty][$bld][$flr] as $dv) {
                            if ($curx == $fco) {
                                $curx = 0;
                                $cury++;
                            }
                            $xd[$dv] = $xbl[$bld] + intval($fsi * ($curx - $mdfl / 2));
                            $yd[$dv] = $ybl[$bld] + intval($fsi * ($cury - $nflr / 2));
                            Drawitem($xd[$dv], $yd[$dv], '0', $dv, $lev);
                            $area = $xd[$dv] - 20 . "," . ($yd[$dv] - 20) . "," . ($xd[$dv] + 20) . "," . ($yd[$dv] + 20);
                            $imgmap .= "<area href=Devices-Status.php?dev=" . urlencode($dv) . " coords=\"{$area}\" shape=rect title=\"Show {$dv} Status\">\n";
                            $curx++;
                        }
                    }
                }
            }
        }
    }
    if ($lev == "c") {
        foreach (array_keys($ctylink) as $ctyl) {
            foreach (array_keys($ctylink[$ctyl]) as $ctyn) {
                Drawlink($xct[$ctyl], $yct[$ctyl], $xct[$ctyn], $yct[$ctyn], $ctylink[$ctyl][$ctyn]);
            }
        }
    } elseif ($lev == "b") {
        foreach (array_keys($bldlink) as $bldl) {
            foreach (array_keys($bldlink[$bldl]) as $bldn) {
                Drawlink($xbl[$bldl], $ybl[$bldl], $xbl[$bldn], $ybl[$bldn], $bldlink[$bldl][$bldn]);
            }
        }
    } elseif ($lev == "f") {
        foreach (array_keys($devlink) as $devl) {
            foreach (array_keys($devlink[$devl]) as $devn) {
                Drawlink($xd[$devl] - 8, $yd[$devl] - 4, $xd[$devn] - 8, $yd[$devn] - 4, $devlink[$devl][$devn]);
            }
        }
    }
}