尝试聚类多几何特征时出现断言错误
Assertion error while trying to cluster multigeometry features
我有一个非常大的 KML 文件(8MB | 8300 多个要素),我需要一种离线加载它的方法。经过一些研究,我喜欢使用 OpenLayers Cluster
的聚类方法,但它仅适用于点:
Layer source to cluster vector data. Works out of the box with point geometries. For other geometry types, or if not all geometries should be considered for clustering, a custom geometryFunction can be defined.
如果我尝试对多边形使用该方法,则不会显示任何内容。因此,我尝试在缩放缩小时 'transform' 点中的特征,并将这些特征显示为点簇,然后在缩放足够近时恢复到原始几何形状。我找到了一些我依赖的very similar problem。但是现在我得到一个错误,我以前在应用方法而不转换为点时没有收到:
AssertionError {
code: 10,
name: "AssertionError",
message: "Assertion failed. See https://openlayers.org/en/v5.3.3/doc/errors/#10 for details."
}
The default geometryFunction can only handle ol/geom/Point geometries.
我发现收到此错误很奇怪,因为在问题中 link 我提到 OP 执行相同的过程并且没有收到任何错误。
加载层函数
// Create layer and sources
let newVectorSource = new VectorSource({})
let newVectorLayer = new VectorLayer({
source: new Cluster({
distance: 50,
source: newVectorSource,
}),
name: layer['layer_id'],
visible: false
});
// Read file and add to map
this.file.readAsText(path, filename).then(layer_file => {
let format = new KML({});
newVectorSource.addFeatures(format.readFeatures(layer_file, {
featureProjection:"EPSG:3857",
dataProjection: "EPSG:4326"
}));
this.map.addLayer(newVectorLayer);
for (let i = newVectorSource.getFeatures().length - 1; i >= 0; i--) {
/* Create style function to polygons act like points,
so we can show them like clusters
*/
let stroke = new Stroke({
color: 'orange',
width: 3
});
let fill = new Fill({
color: 'rgba(255, 165, 0, 0.1)'
})
// Create geometry function
let zoomInStyle = new Style({
stroke: stroke,
fill: fill,
geometry: (feature) => {
let originalFeature = newVectorSource.getFeatures()[i];
return originalFeature.getGeometry();
}
});
let zoomOutStyle = new Style({
stroke: stroke,
fill: fill,
geometry: (feature) => {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
// also tried feature.getClosestPoint();
return getCenter(feature.getGeometry().getExtent());
}
}
});
let featureStyleFunction = (feature, res) => {
if (res > 10) {
return zoomOutStyle;
} else {
return zoomInStyle;
}
};
// Set new style to feature
newVectorSource.getFeatures()[i].setStyle(featureStyleFunction);
}
});
编辑缓存样式
let styleCache = {};
let newVectorLayerCluster = new VectorLayer({
source: new Cluster({
distance: 100,
source: newVectorSource,
geometryFunction: (feature) => {
let resolution = this.map.getView().getResolution();
if (resolution > 10) {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
return feature.getGeometry().getCoordinateAt(0.5);
}
}
}
}),
style: (feature) => {
let size = feature.get('features').length;
let style = styleCache[size];
if (!style) {
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: '#fff',
}),
fill: new Fill({
color: '#3399CC',
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
})
});
styleCache[size] = style;
}
return style;
},
name: layer['layer_id'],
visible: false
});
文档和链接问题所指的 geometryFunction 是集群源中的一个选项
source: new Cluster({
distance: 50,
source: newVectorSource,
geometryFunction: function(feature) {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
return feature.getGeometry().getCoordinateAt(0.5);
}
},
}),
线串的中点(标注点)可能比范围中心更方便
我有一个非常大的 KML 文件(8MB | 8300 多个要素),我需要一种离线加载它的方法。经过一些研究,我喜欢使用 OpenLayers Cluster
的聚类方法,但它仅适用于点:
Layer source to cluster vector data. Works out of the box with point geometries. For other geometry types, or if not all geometries should be considered for clustering, a custom geometryFunction can be defined.
如果我尝试对多边形使用该方法,则不会显示任何内容。因此,我尝试在缩放缩小时 'transform' 点中的特征,并将这些特征显示为点簇,然后在缩放足够近时恢复到原始几何形状。我找到了一些我依赖的very similar problem。但是现在我得到一个错误,我以前在应用方法而不转换为点时没有收到:
AssertionError {
code: 10,
name: "AssertionError",
message: "Assertion failed. See https://openlayers.org/en/v5.3.3/doc/errors/#10 for details."
}
The default geometryFunction can only handle ol/geom/Point geometries.
我发现收到此错误很奇怪,因为在问题中 link 我提到 OP 执行相同的过程并且没有收到任何错误。
加载层函数
// Create layer and sources
let newVectorSource = new VectorSource({})
let newVectorLayer = new VectorLayer({
source: new Cluster({
distance: 50,
source: newVectorSource,
}),
name: layer['layer_id'],
visible: false
});
// Read file and add to map
this.file.readAsText(path, filename).then(layer_file => {
let format = new KML({});
newVectorSource.addFeatures(format.readFeatures(layer_file, {
featureProjection:"EPSG:3857",
dataProjection: "EPSG:4326"
}));
this.map.addLayer(newVectorLayer);
for (let i = newVectorSource.getFeatures().length - 1; i >= 0; i--) {
/* Create style function to polygons act like points,
so we can show them like clusters
*/
let stroke = new Stroke({
color: 'orange',
width: 3
});
let fill = new Fill({
color: 'rgba(255, 165, 0, 0.1)'
})
// Create geometry function
let zoomInStyle = new Style({
stroke: stroke,
fill: fill,
geometry: (feature) => {
let originalFeature = newVectorSource.getFeatures()[i];
return originalFeature.getGeometry();
}
});
let zoomOutStyle = new Style({
stroke: stroke,
fill: fill,
geometry: (feature) => {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
// also tried feature.getClosestPoint();
return getCenter(feature.getGeometry().getExtent());
}
}
});
let featureStyleFunction = (feature, res) => {
if (res > 10) {
return zoomOutStyle;
} else {
return zoomInStyle;
}
};
// Set new style to feature
newVectorSource.getFeatures()[i].setStyle(featureStyleFunction);
}
});
编辑缓存样式
let styleCache = {};
let newVectorLayerCluster = new VectorLayer({
source: new Cluster({
distance: 100,
source: newVectorSource,
geometryFunction: (feature) => {
let resolution = this.map.getView().getResolution();
if (resolution > 10) {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
return feature.getGeometry().getCoordinateAt(0.5);
}
}
}
}),
style: (feature) => {
let size = feature.get('features').length;
let style = styleCache[size];
if (!style) {
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: '#fff',
}),
fill: new Fill({
color: '#3399CC',
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff',
}),
})
});
styleCache[size] = style;
}
return style;
},
name: layer['layer_id'],
visible: false
});
文档和链接问题所指的 geometryFunction 是集群源中的一个选项
source: new Cluster({
distance: 50,
source: newVectorSource,
geometryFunction: function(feature) {
let type = feature.getGeometry().getType();
if (type === 'Polygon') {
return feature.getGeometry().getInteriorPoint();
} else if (type === 'LineString') {
return feature.getGeometry().getCoordinateAt(0.5);
}
},
}),
线串的中点(标注点)可能比范围中心更方便