英文:
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中,所以我的问题是:
- 是否有可能告诉Mapbox不要显示LineString的任何标签?
 - 是否有可能告诉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:
<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>
            \* many coordinates *\
         </coordinates>
      </LineString>
</Placemark>
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:
<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>/* coordinate of the point */ </coordinates>
   </Point>
</Placemark>
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 ["get", "Name"] 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("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",
          },
        });
      });
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:
- Is it possible to tell mapbox not to display any labels of a LineString?
 - 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: ["==", ["geometry-type"], "Point"],
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^_^
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论