2008-11-24 11 views
12

¿Hay alguna forma de generar automáticamente una lista de coordenadas compatible con el mapa HTML de objetos similares a polígonos (por ejemplo, países en un mapa) con bordes muy distintivos?Generar HTML-Map a partir de la imagen

imagen Ejemplo:

Map of CEE countries http://www.bankaustria.at/landkarten/CEE_2007_w524.jpg

de salida final:

<map id ="ceemap" name="ceemap"> 
    <area shape="poly" coords="149,303,162,301,162,298,171,293,180,299,169,309,159,306,148,306,149,303" href="austria.html" target ="_blank" alt="Austria" />  
    <!-- ... --> 
</map> 

Cualquier herramientas/scripts de extracción de las coordenadas de un polígono de selección como sería de gran ayuda.

Respuesta

8

Abra el mapa en Inkscape. Si es un mapa de bits, use Path -> Trace Bitmap para rastrear los bordes. Limpie los datos vectoriales para incluir solo las rutas que desea que aparezcan en su mapa de imágenes. Guarde el documento, sugiero a un archivo POVRay. Ahora tiene una lista de vértices (y un montón de marcado o metadatos que no le importan) en un formato de texto sin formato. La conversión de la sintaxis HTML necesaria sigue siendo un problema, pero no tan complejo como el primer paso.

Por lo que vale la pena, hay una solicitud de función de larga duración para que Inkscape incluya una opción para exportar mapas de imágenes HTML.

1

Puedo darle un paso del proceso: necesitará usar el filtro Sobel (a menudo llamado detección de bordes en programas como Photoshop).

Después de eso, tendrá que encontrar una biblioteca de seguimiento en el idioma de su elección.

10

¡Gracias por su ayuda!

Aunque Jonathans sugerencia de usar el filtro Sobel definitivamente funcionaría, he elegido Sparrs enfoque de convertir primero el mapa de bits de una imagen vectorial en (a través de Inkscape) y luego procesar el archivo SVG. Después de estudiar algunos de los conceptos básicos de la especificación SVG, fue muy fácil extraer los mapas de imágenes HTML necesarios, las coordenadas X/Y de todos los demás elementos no deseados y generar un código adecuado.

Aunque no es una ciencia exacta, alguien podría encontrar esta pieza de código útil:

// input format: M 166,362.27539 C 163.525,360.86029 161.3875,359.43192 161.25,359.10124 C ... 
private static void Svg2map(string svg_input) 
{ 
    StringBuilder stringToFile = new StringBuilder(); 

    // get rid of some spaces and characters 
    var workingString = svg_input.Replace("z", "").Replace(" M ", "M").Replace(" C ", "C"); 
    // split into seperate polygons 
    var polygons = workingString.Split('M'); 
    foreach (var polygon in polygons) 
    { 
     if (!polygon.Equals(String.Empty)) 
     { 
      // each polygon is a clickable area 
      stringToFile.Append("<area shape=\"poly\" coords=\""); 
      // split into point information 
      var positionInformation = polygon.Split('C'); 
      foreach (var position in positionInformation) 
      { 
       var noise = position.Trim().Split(' '); 
       // only the first x/y-coordinates after C are relevant 
       var point = noise[0].Split(','); 
       foreach (var value in point) 
       { 
        var valueParts = value.Split('.'); 
        // remove part after comma - we don't need this accurancy in HTML 
        stringToFile.Append(valueParts[0]); 
        // comma for seperation - don't worry, we'll clean the last ones within an area out later 
        stringToFile.Append(","); 
       } 
      } 
      stringToFile.AppendLine("\" href=\"targetpage.html\" alt=\"Description\" />"); 
     } 
    } 
    // clean obsolete commas - not pretty nor efficient 
    stringToFile = stringToFile.Replace(",\"", "\""); 

    var fs = new StreamWriter(new FileStream("output.txt", FileMode.Create)); 
    fs.Write(stringToFile.ToString()); 
    fs.Close(); 
} 
+1

Embarazosamente soy incapaz de identificar qué lenguaje que es sólo con mirarlo. La 'var' reveladora dice javascript, pero los encabezados se parecen más a C++ o Java. T.T; ¿es C#? ¿Tal vez? – Ziggy

0

hice algunos cambios y la implementación del código de Gerhard Dinhof.

La función PHP genera un mapa de imagen de las coordinadas svg proporcionadas. Puede especificar un número de factor que cambie el tamaño del área y los números de traducción x-y para alinear el mapa a su imagen.

<?php 

/** 
* $str SVG coordinates string 
* $factor number that multiply every coordinate (0-1) 
* $x translation on the x-axis 
* $y translation on the y-axis 
*/ 
function svg2imap($str, $factor=1, $x=0, $y=0) { 

    $res = ""; 

    $str = str_replace(array(" M ","M ", " C "," z "," z"),array("M","M","C","",""), $str); 

    $polygons = explode("M", $str); 

    for($i=0; $i<count($polygons); $i++) { 

     if($polygons[$i]!="") { 

      $res .= "<area shape=\"poly\" coords=\""; 

      $coordinates = explode("C", $polygons[$i]); 

      foreach($coordinates as $position) { 

       $noise = explode(" ", trim($position)); 
       $point = explode(",", $noise[0]); 

       for($j=0; $j<2; $j++) { 

        $val = round($point[$j]*$factor, 0); 

        if($j==0) 
         $res .= ($val + $x).","; 
        else 
         $res .= ($val + $y).","; 
       } 
      } 
      $res .= "\" href=\"link.html\" alt=\"desc\" />"; 
     } 
    } 

    return $res = str_replace(",\"","\"", $res);; 
} 
?> 


<?php 

$svg = "M 6247.5037,5935.0511 C 6246.0707,5940.7838 6247.5037,5947.9495 C 6243.2043,5959.4149 z"; 

highlight_string(svg2imap($svg, $factor=0.33, $x=0, $y=0)); 

?> 
+1

Eso no funciona con svg de inkscape. como en absoluto. y está lleno de código feo. no publique eso, este sitio web está destinado a AYUDAR a las personas. –

0

Parece función "Gerhard Dinhof" no es correcta y que estaba perdiendo el tiempo en eso. Aquí puede encontrar una versión modificada escrita en C# para convertir un archivo SVG simple en códigos de mapa html relevantes. Uso: MessageBox.Show (Svg2map ("c: \ test.svg"))

// Sample file contents: 
    // <?xml version="1.0" encoding="UTF-8" ?> 
    // <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
    // <svg width="739pt" height="692pt" viewBox="0 0 739 692" version="1.1" xmlns="http://www.w3.org/2000/svg"> 
    // <path fill="#fefefe" d=" M 0.00 0.00 L 190.18 0.00 C 188.15 2.70 186.03 5.53 185.30 8.90 L 0.00 0.00 Z" /> 
    // </svg> 
    private string Svg2map(string svg_file_path) 
    { 
     string[] svgLines = File.ReadAllLines(svg_file_path); 
     string svg = string.Join("", svgLines).ToLower(); 

     int temp; 
     int w = int.Parse(ExtractData(svg,0,out temp, "<svg", "width").Replace("pt", "").Replace("px", "")); 
     int h = int.Parse(ExtractData(svg, 0, out temp, "<svg", "height").Replace("pt", "").Replace("px", "")); 

     StringBuilder stringToFile = new StringBuilder(); 
     stringToFile.AppendLine(string.Format("<img id=\"image1\" src=\"image1.jpg\" border=\"0\" width=\"{0}\" height=\"{1}\" orgwidth=\"{0}\" orgheight=\"{1}\" usemap=\"#map1\" alt=\"\" />", w, h)); 
     stringToFile.AppendLine("<map name=\"map1\" id=\"map1\">"); 

     byte dataKey1 = (byte)'a'; 
     byte dataKey2 = (byte)'a'; 

     int startIndex = 0; 
     int endIndex = 0; 
     while (true) 
     { 
      string color = ExtractData(svg, startIndex, out endIndex, "<path", "fill"); 
      string svg_input = ExtractData(svg, startIndex, out endIndex, "<path", "d="); 
      if (svg_input == null) 
       break; 

      startIndex = endIndex; 

      /// Start.. 
      stringToFile.Append(string.Format("<area data-key=\"{0}{1}\" shape=\"poly\" href=\"targetpage.html\" alt=\"Description\" coords=\"", (char)dataKey1, (char)dataKey2)); 
      dataKey1 += 1; 
      if (dataKey1 > (byte)'z') 
      { 
       dataKey2 += 1; 
       dataKey1 = (byte)'a'; 
      } 

      bool bFinished = false; 
      while (!bFinished) 
      { 
       string[] points = new string[0]; 
       string pattern = ""; 
       svg_input = svg_input.ToUpper().Trim(); 
       char code = svg_input[0]; 
       switch (code) 
       { 
        case 'M': 
        case 'L': 
         pattern = svg_input.Substring(0, svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ") + 1) + 1)); 
         svg_input = svg_input.Remove(0, pattern.Length); 
         points = pattern.Trim().Substring(1).Trim().Split(' '); 
         break; 
        case 'C': 
         pattern = svg_input.Substring(0, svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ", svg_input.IndexOf(" ") + 1) + 1) + 1) + 1) + 1) + 1)); 
         svg_input = svg_input.Remove(0, pattern.Length); 
         points = pattern.Trim().Substring(1).Trim().Split(' '); 
         break; 
        case 'Z': 
         bFinished = true; 
         continue; 
        default: 
         throw new Exception("Invalid pattern"); 
       } 

       int count = points.Length; 
       if (count > 4) 
        count = 4; 
       for (int i = 0; i < count; i++) 
       { 
        var valueParts = points[i].Split('.'); 
        // remove part after comma - we don't need this accurancy in HTML 
        stringToFile.Append(valueParts[0]); 
        // comma for seperation - don't worry, we'll clean the last ones within an area out later 
        stringToFile.Append(","); 
       } 
      } 
      stringToFile.AppendLine("\" />"); 
     } 

     // clean obsolete commas - not pretty nor efficient 
     stringToFile.AppendLine("</map>"); 
     stringToFile = stringToFile.Replace(",\"", "\""); 


     return stringToFile.ToString(); 
    } 

    private string ExtractData(string data, int startIndex, out int endIndex, string key, string param) 
    { 
     try 
     { 
      endIndex = 0; 
      int a = data.IndexOf(key, startIndex); 
      int a2 = data.IndexOf(key, a + key.Length); 
      if (a2 == -1) 
       a2 = data.IndexOf(">", a + key.Length); 
      int b = data.IndexOf(param, a + key.Length); 
      int start = data.IndexOf("\"", b + param.Length) + 1; 
      int end = data.IndexOf("\"", start + 1); 
      if (b > a2 || start > a2 || end > a2) 
       return null; 
      int len = end - start; 
      endIndex = end; 
      string t = data.Substring(start, len); 
      return t; 
     } 
     catch 
     { 
      endIndex = 0; 
      return null; 
     } 
    } 
Cuestiones relacionadas