如何在使用Mapbox时仅显示MVT中点的Placemark名称?

huangapple go评论57阅读模式
英文:

How to only display Placemark names of points in MVT using mapbox?

问题

我正在尝试使用Mapbox来显示矢量瓦片集。矢量瓦片集是从kml文件转换而来的。我使用gdal将其转换为MVT,并在Mapbox上正常显示,除了一个问题:它还显示了所有线段点的名称作为标签。

我的kml文件中的LineString具有以下结构:

<Placemark>
   <name>mainlayer_0</name>
   <Style>
      <LineStyle><color>ffffffff</color><width>1</width></LineStyle>
   </Style>
   <OvStyle>
      <TrackStyle><type>5</type><width>79</width></TrackStyle>
   </OvStyle>
   <LineString>
      <coordinates>
         * 许多坐标 *
      </coordinates>
   </LineString>
</Placemark>

Mapbox显示“mainlayer_0”作为标签,并且相同的标签被放置在LineString中的每个坐标上(每个LineString中最多有数百个坐标),这是不希望的。我只想显示独立点的标签,具有以下结构:

<Placemark>
   <name>First Label Name</name>
   <description>I want to show this label</description>
   <Style>
      <IconStyle>
         <Icon>
         </Icon>
         <color>ffffffff</color>
         <scale>1.0</scale>
      </IconStyle>
      <LabelStyle>
         <color>ffffffff</color>
      </LabelStyle>
   </Style>
   <Point>
      <coordinates>/* 点的坐标 */ </coordinates>
   </Point>
</Placemark>

我首先做的是使用以下命令将kml文件转换为MVT:

ogr2ogr -f MVT output input.kml -dsco COMPRESS=NO -dsco MAXZOOM=15

然后使用下面的代码在mapbox中显示MVT。lineLayer显示了我需要显示的所有线条。在symbolLayer中,我使用["get", "Name"]来获取文本,但是LineString的名称也在“Name”字段中。我认为这是问题所在,但我不知道如何解决它。

map.on("load", () => {
    map.addSource("map_name", {
      type: "vector",
      tiles: ["http://127.0.0.1:8080/output/{z}/{x}/{y}.pbf"],
      minzoom: 0,
      maxzoom: 15,
    });

    map.addLayer({
      id: "lineLayer",
      type: "line",
      source: "map_name",
      "source-layer": "mainlayer",
    });

    map.addLayer({
      id: "symbolLayer",
      type: "symbol",
      source: "map_name",
      "source-layer": "mainlayer",
      layout: {
        "text-field": ["get", "Name"],
        "text-anchor": "top",
      },
    });
  });

使用上述代码,除了线条的名称反复显示在其中的每个点上以外,一切都看起来很好。

我尝试修改kml文件,将所有LineString的名称替换为空字符串,视觉效果符合预期。但是,我需要自动化这个过程,不想每次手动修改kml文件。当MapBox渲染标签时,我相信它知道这个点是一个点还是在LineString中,所以我的问题是:

  1. 是否有可能告诉Mapbox不要显示LineString的任何标签?
  2. 是否有可能告诉Mapbox只显示点的名称?

我还想知道在将kml转换为MVT的过程中是否有什么我可以做的,以帮助解决这个问题。感谢任何建议!

英文:

I am trying to use Mapbox to display a vector tileset. The vector tileset is converted from a kml file. I used gdal to convert it to MVT, and it displays on Mapbox fine, except for one thing: it also shows the name of all lineString points as labels.

A lineString in my kml file has following structure:

&lt;Placemark&gt;
   &lt;name&gt;mainlayer_0&lt;/name&gt;
      &lt;Style&gt;
         &lt;LineStyle&gt;&lt;color&gt;ffffffff&lt;/color&gt;&lt;width&gt;1&lt;/width&gt;&lt;/LineStyle&gt;
      &lt;/Style&gt;
      &lt;OvStyle&gt;
         &lt;TrackStyle&gt;&lt;type&gt;5&lt;/type&gt;&lt;width&gt;79&lt;/width&gt;&lt;/TrackStyle&gt;
      &lt;/OvStyle&gt;
      &lt;LineString&gt;
         &lt;coordinates&gt;
            \* many coordinates *\
         &lt;/coordinates&gt;
      &lt;/LineString&gt;
&lt;/Placemark&gt;

Mapbox shows the "mainlayer_0" as labels, and the same label was put on every single coordinate in the LineString (up to hundreds in each), which is undesired. The only labels I want to show are independent points, with following structure:

&lt;Placemark&gt;
   &lt;name&gt;First Label Name&lt;/name&gt;
   &lt;description&gt;I want to show this label&lt;/description&gt;
   &lt;Style&gt;
      &lt;IconStyle&gt;
         &lt;Icon&gt;
         &lt;/Icon&gt;
         &lt;color&gt;ffffffff&lt;/color&gt;
         &lt;scale&gt;1.0&lt;/scale&gt;
         &lt;/IconStyle&gt;
            &lt;LabelStyle&gt;
               &lt;color&gt;ffffffff&lt;/color&gt;
            &lt;/LabelStyle&gt;
   &lt;/Style&gt;
   &lt;Point&gt;
      &lt;coordinates&gt;/* coordinate of the point */ &lt;/coordinates&gt;
   &lt;/Point&gt;
&lt;/Placemark&gt;

What I did first was converting the kml file into MVT using following command:

ogr2ogr -f MVT output input.kml -dsco COMPRESS=NO -dsco MAXZOOM=15

And display the MVT in mapbox using code below. The lineLayer shows all the lines I need to display. In the symbolLayer, I used [&quot;get&quot;, &quot;Name&quot;] to get the text, but the lineString name are also in "Name" field. I think this is the problem, but I do not know how to solve it.

map.on(&quot;load&quot;, () =&gt; {
        map.addSource(&quot;map_name&quot;, {
          type: &quot;vector&quot;,
          tiles: [&quot;http://127.0.0.1:8080/output/{z}/{x}/{y}.pbf&quot;],
          minzoom: 0,
          maxzoom: 15,
        });

        map.addLayer({
          id: &quot;lineLayer&quot;,
          type: &quot;line&quot;,
          source: &quot;map_name&quot;,
          &quot;source-layer&quot;: &quot;mainlayer&quot;,
        });

        map.addLayer({
          id: &quot;symbolLayer&quot;,
          type: &quot;symbol&quot;,
          source: &quot;map_name&quot;,
          &quot;source-layer&quot;: &quot;mainlayer&quot;,
          layout: {
            &quot;text-field&quot;: [&quot;get&quot;, &quot;Name&quot;],
            &quot;text-anchor&quot;: &quot;top&quot;,
          },
        });
      });

With above code, everything looks fine except the names of lineStrings are repetitively displayed on every points in them.

I tried to modify the kml file by replacing all the lineString names to empty string, and the visual outcome met the expectation. However, I need to automate this process and I do not want to manually modify the kml file every time. When MapBox is rendering the labels, I believe it knows if this point is just a point or it is in a LineString, so my questions are:

  1. Is it possible to tell mapbox not to display any labels of a LineString?
  2. Is it possible to tell mapbox to only show name of points?

I also wonder if there is anything I can do in the process of converting kml to MVT that can help with this issue. Any suggestion is appreciated!

答案1

得分: 0

这有点尴尬,因为我在发布问题后五分钟就找到了答案。答案是一行代码,将以下内容添加到 map.addLayer({...}) 中:

filter: ["==", ["get", "geometry-type"], "Point"],

详细信息可以在这里找到:setFilter

并且有一个解释用法的示例在这里:
使用新表达式按几何类型筛选

希望这对将来的某人有所帮助^_^

英文:

This is a bit akward as I found the answer five minutes after I post the question. The answer is one line, adding

filter: [&quot;==&quot;, [&quot;geometry-type&quot;], &quot;Point&quot;],

in map.addLayer({...}). Details can be found here: setFilter

And an explained usage is here:
Filter by geometry-type with new expressions

Hope this help someone in the future^_^

huangapple
  • 本文由 发表于 2023年6月26日 10:39:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553223.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定