Assertionsfehler beim Clustering von Multigeometrie-Features
Ich habe eine sehr große KML-Datei (8 MB | 8300+ Funktionen) und brauche eine Möglichkeit, sie offline zu laden. Nach einigen Recherchen mochte ich die Clusterisierungsmethode mit OpenLayers Cluster, aber sie funktioniert nur für Punkte:
Schichtquelle für Cluster-Vektordaten. Funktioniert sofort mit Punktgeometrien. Für andere Geometrietypen oder wenn nicht alle Geometrien für das Clustering berücksichtigt werden sollen, kann eine benutzerdefinierte Geometriefunktion definiert werden.
Wenn ich versuche, die Methode mit den Polygonen zu verwenden, wird nichts angezeigt. Daher habe ich versucht, die Features in Punkte zu transformieren, während der Zoom ausgeschaltet ist, und diese Features als Punktcluster anzuzeigen. Dann werde ich zur ursprünglichen Geometrie zurückkehren, wenn der Zoom nah genug ist. Ich habe ein sehr ähnliches Problem gefunden , auf das ich mich verlassen habe. Aber jetzt erhalte ich eine Fehlermeldung, die ich beim Anwenden der Methode ohne Konvertierung in Punkte nicht erhalten habe:
AssertionError {
code: 10,
name: "AssertionError",
message: "Assertion failed. See https://openlayers.org/en/v5.3.3/doc/errors/#10 for details."
}
Fehlercode Nr. 10 :
Die Standard-Geometriefunktion kann nur ol / geom / Punkt-Geometrien verarbeiten.
Ich fand es seltsam, diesen Fehler zu erhalten, da das OP in dem von mir erwähnten Problemlink das gleiche Verfahren ausführt und keinen Fehler erhält.
Layer-Funktion laden
// 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);
}
});
EDIT Cache-Stil
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
});
Antworten
Die Geometriefunktion, auf die sich die Dokumentation und die verknüpfte Frage beziehen, ist eine Option in der Clusterquelle
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);
}
},
}),
Der Mittelpunkt (Beschriftungspunkt) eines Linienstreifens kann bequemer sein als das Ausdehnungszentrum