Neue KUBA-Karten

Karten


Das Arbeiten mit Geodaten und Karten ist ein wesentlicher Bestandteil vieler Geschäftsanwendungen. Dies können städtische und regionale Informationssysteme, Anwendungen für die Öl- und Gasindustrie, Verkehrsinfrastruktur-Managementsysteme sowie Lieferservices und viele andere sein. In unserer CUBA-Plattform gibt es zum Erstellen solcher Anwendungen zusätzlich zu den sofort einsatzbereiten Grundfunktionen eine Reihe umfangreicher Add-Ons und Komponenten . Eines davon sind Diagramme und Karten , mit denen Sie neben der Anzeige von Diagrammen auch Google Maps in den visuellen Teil der Anwendung integrieren können. Im vergangenen Jahr hat Google die Nutzungsbedingungen seiner Kartendienste aktualisiert, was zu einem Anstieg der Kosten geführt hat, und die Bedingung für das obligatorische Vorhandensein eines Zahlungsprofils für die Verwendung der API eingeführt. Diese Umstände veranlassten die meisten unserer Kunden, über alternative Kartenanbieter nachzudenken, und wir wurden aufgefordert, eine neue Kartenkomponente zu entwickeln.


Jetzt freuen wir uns, Ihnen eine völlig neue Komponente vorstellen zu können - CUBA Maps . CUBA Maps ergänzt die Anwendungsfunktionalität durch eine visuelle Darstellung und intuitive Tools zum Bearbeiten von Geodaten. Die Komponente arbeitet sowohl mit Raster- als auch mit Vektordaten. Sie können jeden Kartenanbieter verwenden, der mit dem Web Map Service-Protokoll kompatibel ist, oder Kacheln im XYZ-Format als Rasterdaten bereitstellen. Für die Arbeit mit Vektordaten verwendet die Komponente geometrische Datentypen (Punkt, Polylinie, Polygon) aus der JTS Topology Suite (JTS) -Bibliothek - der beliebtesten Java-Bibliothek für die Arbeit mit Geodaten. Die Komponente bietet alle erforderlichen Tools zum Erstellen eines umfassenden geografischen Informationssystems auf der Basis von CUBA.


In diesem Artikel werden wir über neue Funktionen der Kartenkomponente sprechen und diese auch mit unserer vorherigen Kartenkomponente vergleichen.


Schichtbasierte Struktur


Die Komponente unterstützt die traditionelle Mehrschichtstruktur, die in professionellen geografischen Informationssystemen weit verbreitet ist. Ebenen werden hauptsächlich in Raster und Vektor unterteilt. Rasterebenen bestehen aus Rasterbildern, während Vektorebenen Vektorgeometrien enthalten.


Die Komponente unterstützt die folgenden Arten von Ebenen:


  • Kachelebene zeigt die von den Kacheldiensten bereitgestellten Kacheln im XYZ-Format an.
  • Auf der Ebene des Web Map Service (WMS) werden die von den WMS-Diensten bereitgestellten Bilder angezeigt.
  • Die Vektorebene enthält Geoobjekte (Objekte mit geometrischen Attributen).

Diese Ebenen sind Strukturelemente von Karten. Beispielsweise kann die untere Schicht eine Basiskarte sein, die aus Kacheln besteht, die zweite Schicht kann Polygone enthalten, die Gebietseinheiten beschreiben, beispielsweise Regionen, und die obere Schicht kann geografische Punkte enthalten (Standort von Kunden, Geschäften usw.). Wenn wir diese Ebenen übereinander legen, erhalten wir die endgültige Karte:


Schichten


Dank dieses Ansatzes können Sie klar strukturierte Karten mit beliebigen Inhalten erstellen.


CUBA Maps bietet eine neue visuelle Komponente - GeoMap . Im XML-Deskriptor der Komponente können Sie die grundlegenden Parameter der Karte sowie eine Reihe angezeigter Layer festlegen. Ein Beispiel für eine solche Konfiguration:


 <maps:geoMap id="map" height="600px" width="100%" center="37.615, 55.752" zoom="10"> <maps:layers selectedLayer="addressLayer"> <maps:tile id="tiles" tileProvider="maps_OpenStreetMap"/> <maps:vector id="territoryLayer" dataContainer="territoryDc"/> <maps:vector id="addressLayer" dataContainer="addressDc" editable="true"/> </maps:layers> </maps:geoMap> 

Mit diesem Ansatz können Sie mehr Flexibilität erreichen, die in Diagrammen und Karten fehlte:


  • Schichtung. Mit dieser Struktur können Sie Karten mit beliebigen Inhalten erstellen, z. B. Kacheln kombinieren, die von verschiedenen Diensten bereitgestellt werden.
  • Ebenen bieten eine Abstraktion, die homogene Objekte zusammenbringt. In der Komponente " Diagramme und Karten" wurden alle Karteninhalte (z. B. Punkte, Polygone usw.) in einem gemeinsamen Heap in der UI-Komponente gespeichert. Um diese Objekte irgendwie zu strukturieren, mussten die Projektteams zusätzliche Logik schreiben.
  • Eine deklarative Methode zur Beschreibung von Ebenen. Wie im obigen Beispiel gezeigt, können Sie die Kartenstruktur (Satz von Layern) im XML-Deskriptor vollständig angeben. In vielen Fällen reicht dies aus, um keine zusätzliche Logik in der Bildschirmsteuerung zu implementieren. Mit Diagrammen und Karten war es fast unmöglich, auf das Schreiben zusätzlicher Logik zu verzichten.

Durch die Verwendung von Kachelebenen oder WMS können Sie mit jedem bevorzugten Kartenanbieter arbeiten. Sie sind nicht an einen bestimmten Anbieter gebunden, wie dies in Diagrammen und Karten der Fall war .


Vektorebenen vereinfachen die Anzeige, interaktive Bearbeitung und Zeichnung von Geoobjekten auf der Karte erheblich.


Es ist auch erwähnenswert, dass die visuelle Komponente von GeoMap standardmäßig eine spezielle Hilfsebene hat - Canvas . Canvas bietet eine praktische API zum Anzeigen und Zeichnen von Geometrien (Punkte, Polylinien, Polygone) auf einer Karte. Wir werden später in diesem Artikel Beispiele für die Verwendung von Canvas behandeln.


Geo-Objekte


Angenommen, wir haben eine Entität, die ein der Geometrie zugeordnetes Attribut enthält (Punkt, Polylinie, Polygon). Wir werden diese Entität ein Geoobjekt nennen. Die Komponente vereinfacht die Arbeit mit Geoobjekten erheblich.


Betrachten Sie beispielsweise das Geoobjekt Adresse :


 @Entity public class Address extends StandardEntity { ... @Column(name = "LOCATION") @Geometry @MetaProperty(datatype = "GeoPoint") @Convert(converter = CubaPointWKTConverter.class) protected Point location; ... } 

Es verfügt über ein location vom Typ org.locationtech.jts.geom.Point aus der JTS Topology Suite (JTS) -Bibliothek. Die Komponente unterstützt die folgenden geometrischen Typen von JTS:


  • org.locationtech.jts.geom.Point - Zeitraum.
  • org.locationtech.jts.geom.LineString - Polylinie.
  • org.locationtech.jts.geom.Polygon - Polygon.

Das location ist mit der Annotation @Geometry . Diese Anmerkung gibt an, dass der Wert dieses Attributs verwendet werden soll, wenn ein Geoobjekt auf der Karte angezeigt wird. Das Attribut ist außerdem mit den folgenden Anmerkungen gekennzeichnet:


  • @MetaProperty - wird in diesem Fall verwendet, um das Datentypattribut anzugeben. Die Datatype vom CUBA-Framework verwendet, um Werte in und aus einer Zeichenfolge zu konvertieren.
  • @Convert - Definiert einen JPA-Konverter für ein dauerhaftes Attribut. Der JPA-Konverter konvertiert Attributwerte zwischen seinen Darstellungen in der Datenbank und Java-Code. Die Komponente bietet eine Reihe von räumlichen Datentypen und JPA-Konvertern. Weitere Informationen finden Sie in der Komponentendokumentation. Sie können auch eine eigene Implementierung des JPA-Konverters verwenden, mit der Sie mit verschiedenen Geodatenquellen (z. B. PostGIS ) arbeiten können.

Um eine Entität in ein Geoobjekt zu verwandeln, müssen Sie ein Attribut des JTS-Geometrietyps definieren und mit @Geometry . Es gibt noch eine andere Option: Erstellen Sie ein nicht persistentes Attribut, indem Sie Getter / Setter-Methoden bereitstellen. Dies kann nützlich sein, wenn Sie keine Änderungen am Datenmodell vornehmen und DDL-Skripte neu generieren möchten.


Betrachten Sie beispielsweise die Entitätsadresse mit separaten Attributen für Längen- und Breitengrad:


 import com.haulmont.addon.maps.gis.utils.GeometryUtils; ... @Entity public class Address extends StandardEntity { ... @Column(name = "LATITUDE") protected Double latitude; @Column(name = "LONGITUDE") protected Double longitude; ... @Geometry @MetaProperty(datatype = "GeoPoint", related = {"latitude", "longitude"}) public Point getLocation() { if (getLatitude() == null || getLongitude() == null) { return null; } return GeometryUtils.createPoint(getLongitude(), getLatitude()); } @Geometry @MetaProperty(datatype = "GeoPoint") public void setLocation(Point point) { Point prevValue = getLocation(); if (point == null) { setLatitude(null); setLongitude(null); } else { setLatitude(point.getY()); setLongitude(point.getX()); } propertyChanged("location", prevValue, point); } ... } 

Wenn Sie sich für diesen Ansatz entscheiden, stellen Sie sicher, dass die propertyChanged Methode im Setter aufgerufen wird, da die Komponente auf dieses Ereignis reagiert, indem sie die Geometrie auf der Karte aktualisiert.


Nachdem wir die Klasse unseres Geoobjekts vorbereitet haben, können wir der Vektorebene Instanzen dieser Klasse hinzufügen. Eine Vektorebene ist im Wesentlichen ein Verbindungselement zwischen Daten (Geoobjekten) und einer Karte. Um Geoobjekte mit einer Ebene zu verbinden, müssen Sie den Datencontainer oder bei veralteten Bildschirmen (bis Version 7 von CUBA) die Datenquelle auf die Vektorebene übertragen. Dies kann in einem XML-Deskriptor erfolgen:


 <maps:geoMap id="map"> <maps:layers> ... <maps:vector id="addressesLayer" dataContainer="addressesDc"/> </maps:layers> </maps:geoMap> 

Infolgedessen werden die im Address Container enthaltenen Adressklasseninstanzen auf der Karte angezeigt.


Betrachten wir eine elementare Aufgabe: Erstellen eines Bildschirms zum Bearbeiten eines Geoobjekts mit einer Karte, auf dem Sie die Geometrie des Objekts bearbeiten können. Um das Problem zu lösen, müssen Sie die visuelle Komponente von GeoMap im XML-Deskriptor des Bearbeitungsbildschirms deklarieren und eine Vektorebene hinzufügen, die dem Container zugeordnet ist, der das bearbeitete Geoobjekt enthält:


 <maps:geoMap id="map" height="600px" width="100%" center="37.615, 55.752" zoom="10"> <maps:layers selectedLayer="addressLayer"> <maps:tile ..."/> <maps:vector id="addressLayer" dataContainer="addressDc" editable="true"/> </maps:layers> </maps:geoMap> 

Wenn Sie die Vektorebene als bearbeitbar markieren, wird die interaktive Bearbeitung des Geoobjekts auf der Karte aktiviert. Wenn die Geometrie des Objekts leer ist, wechselt die Karte automatisch in den Zeichenmodus. Wie Sie sehen, reicht es zur Lösung des Problems aus, eine Vektorebene auf der Karte zu deklarieren und sie an den Datencontainer / die Datenquelle zu übergeben.


Das ist alles. Wenn wir Diagramme und Karten verwenden würden , um dasselbe Problem zu lösen, müssten wir ziemlich viel Code in den Bildschirmcontroller schreiben, um ähnliche Funktionen bereitzustellen. Mit der neuen Komponente von Maps ist das Lösen solcher Probleme viel einfacher.


Leinwand


Es gibt Zeiten, in denen Sie nicht mit Entitäten arbeiten müssen. Stattdessen möchten Sie, dass eine einfache API Geometrien zu einer Karte hinzufügt und zeichnet, wie dies in Diagrammen und Karten der Fall war. Zu diesem GeoMap visuelle Komponente GeoMap über eine spezielle Ebene - Canvas . Dies ist eine Hilfsebene, die sich standardmäßig auf der Karte befindet und eine einfache API zum Hinzufügen und Zeichnen von Geometrien auf der Karte bietet. Sie können map.getCanvas() Map erhalten, indem Sie die map.getCanvas() -Methode aufrufen.


Als nächstes werden wir uns einige einfache Aufgaben ansehen, wie sie in Diagrammen und Karten gelöst wurden und wie Sie dasselbe mit Canvas tun können.


Geometrien auf einer Karte anzeigen


In Diagrammen und Karten wurden Geometrieobjekte mithilfe der visuellen Komponente der Karte erstellt, als Factory verwendet und dann zur Karte hinzugefügt:


 Marker marker = map.createMarker(); GeoPoint position = map.createGeoPoint(lat, lon); marker.setPosition(position); map.addMarker(marker); 

Die neue Maps- Komponente arbeitet direkt mit Klassen aus der JTS-Bibliothek:


 CanvasLayer canvasLayer = map.getCanvas(); Point point = address.getLocation(); canvasLayer.addPoint(point); 

Geometrie bearbeiten


In Diagrammen und Karten können Sie Geometrie als bearbeitbar festlegen. Wenn solche Geometrien über die Benutzeroberfläche geändert wurden, wurden die entsprechenden Ereignisse aufgerufen:


 Marker marker = map.createMarker(); GeoPoint position = map.createGeoPoint(lat, lon); marker.setPosition(position); marker.setDraggable(true); map.addMarker(marker); map.addMarkerDragListener(event -> { // do something }); 

In der Maps- Komponente gibt die entsprechende Methode beim Hinzufügen von JTS-Geometrie zu Canvas ein spezielles Objekt zurück, das diese Geometrie auf der Karte darstellt: CanvasLayer.Point , CanvasLayer.Polyline oder CanvasLayer.Polygon . Dieses Objekt verfügt über eine fließende Oberfläche zum Festlegen verschiedener Geometrieparameter. Es kann auch zum Abonnieren von Ereignissen im Zusammenhang mit Geometrie oder zum Löschen von Geometrie aus einem Canvas verwendet werden.


 CanvasLayer canvasLayer = map.getCanvas(); CanvasLayer.Point location = canvasLayer.addPoint(address.getLocation()); location.setEditable(true) .setPopupContent(address.getName()) .addModifiedListener(modifiedEvent -> address.setLocation(modifiedEvent.getGeometry())); 

Geometriezeichnung


In den alten Add-On- DrawingOptions und Karten gab es eine Hilfskomponente - DrawingOptions . Es wurde verwendet, um die Fähigkeit zum Zeichnen auf der Karte zu aktivieren. Nachdem die Geometrie gezeichnet wurde, wurde das entsprechende Ereignis ausgelöst:


 DrawingOptions options = new DrawingOptions(); PolygonOptions polygonOptions = new PolygonOptions(true, true, "#993366", 0.6); ControlOptions controlOptions = new ControlOptions( Position.TOP_CENTER, Arrays.asList(OverlayType.POLYGON)); options.setEnableDrawingControl(true); options.setPolygonOptions(polygonOptions); options.setDrawingControlOptions(controlOptions); options.setInitialDrawingMode(OverlayType.POLYGON); map.setDrawingOptions(options); map.addPolygonCompleteListener(event -> { //do something }); 

Die Maps-Komponente erleichtert dies erheblich. Der neue Kartenbereich enthält eine Reihe von Methoden zum Zeichnen von Geometrien. Verwenden canvas.drawPolygon() zum Zeichnen eines Polygons beispielsweise die Methode canvas.drawPolygon() . Nach dem Aufrufen dieser Methode wechselt die Karte in den Polygonzeichnungsmodus. Die Methode akzeptiert die Consumer<CanvasLayer.Polygon> -Funktion, mit der Sie zusätzliche Aktionen mit dem gezeichneten Polygon ausführen können.


 canvasLayer.drawPolygon(polygon -> { territory.setPolygon(polygon.getGeometry()); }); 

Geoanalyse-Tools


Clustering


Ein weiteres nützliches Tool in der neuen Maps-Komponente ist das Punktclustering. Wenn die Ebene aus einer großen Anzahl von Punkten besteht, können Sie das Clustering aktivieren, um nahegelegene Punkte in Cluster zu gruppieren, damit die Karte übersichtlicher und besser wahrgenommen wird:


Cluster


Das Clustering wird aktiviert, indem das cluster Tag innerhalb des vector Tags im XML-Deskriptor hinzugefügt wird:


 <maps:vector id="locations" dataContainer="locationsDc" > <maps:cluster/> </maps:vector> 

Sie können das Clustering auch basierend auf Punktgewichten aktivieren. Das Gewicht des Punkts ist der Wert des Attributs, das im Parameter weightProperty angegeben ist.


 <maps:vector id="orders" dataContainer="ordersDc" > <maps:cluster weightProperty="amount"/> </maps:vector> 

Heatmaps


Heatmaps sind eine visuelle Darstellung der Datendichte an mehreren geografischen Standorten. Die visuelle Komponente von GeoMap enthält eine Methode zum Hinzufügen einer Heatmap: addHeatMap(Map<Point, Double> intensityMap) .


Heatmap


Fazit


Die Verarbeitung, Analyse und Visualisierung von Geodaten ist ein wesentliches Element vieler Geschäftsanwendungen. Die CUBA Maps- Komponente stellt Ihrer CUBA-Anwendung alle erforderlichen Tools zur Implementierung dieser Funktionalität zur Verfügung.


Eine schichtenbasierte Struktur hilft beim Erstellen von Karten mit beliebigen Inhalten. Mit Kachel- / WMS-Ebenen können Sie jeden Anbieter verwenden, den Sie als Basiskarte benötigen. Mit Vektorebenen können Sie effektiv mit Gruppen homogener Geoobjekte arbeiten. Canvas bietet eine einfache API zum Anzeigen und Zeichnen von Geometrien auf einer Karte.


Die Komponente arbeitet mit räumlichen Typen aus der JTS-Bibliothek, wodurch sie mit vielen anderen Frameworks (z. B. GeoTools ) kompatibel ist, um eine Vielzahl von Aufgaben im Zusammenhang mit der Verarbeitung und Analyse geografischer Daten zu lösen.


Wir hoffen, Ihnen gefällt die Komponente. Warten auf Ihr Feedback!

Source: https://habr.com/ru/post/de464517/


All Articles