Ich bin ziemlich neu in Postgis und RGEO. Ich vermute, dass ich Dinge auf die falsche Art angehen kann, aber ich war ein wenig überrascht, ein paar Operationen zu finden, insbesondere enthält & innerhalb, sind auf sphärischen Objekten nicht möglich.Polygon 'enthält' und andere Operationen auf Geometrien nicht unterstützt
Ich habe eine Reihe von geografisch verteilten Objekten, die ich gerne zusammen gruppieren würde basierend auf Dinge wie Postleitzahl. Für jede dieser Gruppierungen habe ich eine Grenze und ich möchte überprüfen, ob sich ein Objekt innerhalb dieser Grenze befindet und auch prüfen, ob eine Grenze innerhalb einer anderen liegt. Ich bin mit Schienen und dies ist die Migration meiner Sammlung Modell
class CreateGeoCollectionDefinition < ActiveRecord::Migration[5.0]
def change
create_table :geo_collection_definitions do |t|
t.string :name
t.string :geo_place_id
t.string :geo_place_types, array: true, default: []
t.st_polygon :boundary, geographic: true
t.jsonb :boundary_json
t.st_point :latlng, geographic: true
end
end
end
einzurichten Derzeit ist die Grenze von einem Google kommenden geocode-Reverse-Lookup. Die Nordost- und Südwest Begrenzungsbox Koordinaten werden in diesem Verfahren auf Objekterstellung übergeben
GEO_FACTORY = RGeo::Geographic.spherical_factory(srid: 4326)
def self.createBoundary(pointOne, pointTwo)
point1 = GEO_FACTORY.point(pointOne['lat'], pointOne['lng'])
point2 = GEO_FACTORY.point(pointTwo['lat'], pointTwo['lng'])
boundingBox = RGeo::Cartesian::BoundingBox.create_from_points(point1, point2).to_geometry
boundingBox
end
Ich habe ein paar von Spezifikationen geschrieben, dass alles, was zu überprüfen ist in der Art und Weise verhalten, die ich erwarte. Die einfachen entfernungsbasierten Tests werden alle wie erwartet durchgeführt, aber es gibt Probleme mit denen, die zum Testen der Grenzfunktion verwendet werden. Ich laufe in den folgenden
# ------------------
# --- Caused by: ---
# PG::UndefinedFunction:
# ERROR: function st_contains(geography, geography) does not exist
# LINE 1: ...COUNT(*) FROM "geo_collection_definitions" WHERE (ST_Contain...
# ^
# HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Wenn ich versuche, und eine Abfrage wie (ich weiß, es ist ein bisschen eine dumme ein) laufen
GeoCollectionDefinition.where("ST_Contains(boundary, boundary)")
oder wenn ich versuche, das RGEO-Objekt direkt
it "should be possible to test is points belong in GeoCollection.boundary" do
factory = RGeo::Geographic.spherical_factory(srid: 4326)
externalPoint = factory.point(EmptyGeocodeLatLag['lng'], EmptyGeocodeLatLag['lat'])
expect(someplace_def.boundary.contains?(someplace_def.latlng)).to be_truthy
expect(someplace_def.boundary.contains?(externalPoint)).to be_falsy
end
ich
RGeo::Error::UnsupportedOperation:
Method Geometry#contains? not defined.
Diggin g ringsherum fand ich diese rgeo issue und andere Beweise, dass diese Operationen nur für sphärische Fabrik basierte Objekte nicht unterstützt werden
Ich frage mich nur;
- Ist dies definitiv der Fall
- die Grenze und die Lage der Objekte in der Art und Weise in meiner Migration beschrieben Modellierung scheint Sinn für mich zu machen, aber ich nehme an, ich bin falsch daran?
- Wie soll ich herausfinden, ob eine Reihe von Punkten innerhalb eines Polygons mit Hilfe von Postgis, Rgeo und dem aktiven Record-Adapter sind?
- Ist es möglich zu prüfen, ob ein Polygon in einem anderen liegt?
EDIT:
folgte ich auf Tilt Vorschlag auf und lief auf meinem db einige Anfragen direkt. Zuerst, nur um meine Einrichtung zu überprüfen
SELECT PostGIS_full_version();
NOTICE: Function postgis_topology_scripts_installed() not found. Is topology support enabled and topology.sql installed? postgis_full_version
POSTGIS="2.1.7 r13414" GEOS="3.5.0-CAPI-1.9.0 r4084" PROJ="Rel. 4.9.2, 08 September 2015" GDAL="GDAL 1.11.5, released 2016/07/01" LIBXML="2.9.2" LIBJSON="UNKNOWN" RASTER
Ich habe auch einige Abfragen ausgeführt;
SELECT name FROM geo_collection_definitions WHERE st_contains(latlng, boundary);
ERROR: function st_contains(geography, geography) does not exist
LINE 1: ...ELECT name FROM geo_collection_definitions WHERE st_contain...
So raten enthält nur nicht auf geographies.Ich kramte und ich fand st_covers
SELECT name FROM geo_collection_definitions WHERE st_covers(boundary, latlng);
name
------
(0 rows)
SELECT name FROM geo_collection_definitions WHERE st_covers(boundary, ST_GeomFromText('POINT(12.9549709 55.5563043)', 4326));
name
------
(0 rows)
Das ist wirklich überraschend, da latlng der Mittelpunkt der Grenze ist. Ich bin ziemlich verwirrt und sicher, dass ich etwas ziemlich dummes mache. Jede Hilfe würde sehr geschätzt
Da das Problem scheint rein postgis basiert, könnte es besser sein, wenn Sie Ihre Frage mit Hilfe von neu formulieren eine SQL-Anweisung anstelle von Rails. Meiner Erfahrung nach ist es immer besser, Ihre Abfragen in reinem SQL zu testen, bevor Sie sie mit einem Framework verbinden. Dies gibt Ihnen eine bessere Kontrolle. – tilt
Hallo Tilt! Tausend Dank für deine Antwort. Ich bin mir sicher, dass es nur etwas Dummes ist, was ich mache. Ich werde prüfen, ob ich proj4 installiert habe. Ich werde dann versuchen, einige Abfragen direkt auf Postgis-DB zu starten, um Dinge zu testen – Conor
Können Sie eine WKT-Ausgabe dieser Grenze geben? (ST_AsText (Grenze)). Sind Sie sicher, dass Sie Geografie weiterhin verwenden möchten? Es macht Sinn, wenn Sie mit großen Datenmengen (über nationale Grenzen hinaus) arbeiten, aber normalerweise ist es besser, in der lokalen Projektion zu arbeiten. Ich bin überrascht, dass Ihre Postleitzahlen sowieso geografisch sind, normalerweise würden sie projiziert werden. – tilt