Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.5] Geo Spatial blueprint methods #21056

Merged
merged 1 commit into from
Sep 7, 2017
Merged

[5.5] Geo Spatial blueprint methods #21056

merged 1 commit into from
Sep 7, 2017

Conversation

antonkomarev
Copy link
Contributor

@antonkomarev antonkomarev commented Sep 7, 2017

I've targeted it to 5.5 but if 5.6 (master) is more appropriate for it - I'm ready to make another one PR.

This PR introduces Geo spatial blueprint methods to MySQL, PostgreSQL, SQLite. It allows to create database engine agnostic spatial data types columns without using raw expressions and conditionals.

Schema::create('conferences', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->point('location')->nullable();
    $table->timestamps();
});

Complete list of methods:

  • geometry (not supported by PostgreSQL)
  • point
  • lineString
  • polygon
  • geometryCollection
  • multiPoint
  • multiLineString
  • multiPolygon

If blueprints PR will be accepted I will continue integration of query\eloquent Geo spatial related methods. They are much more complicated and requires to implement all geometry classes. As for now I'm making it as external package. Current functionality already implemented in package too, but it's pretty common stuff and doesn't require any new dependencies.

Note: Latest stable MySQL and PostgreSQL has spatial data types support out of the box. SQLite has extended version called SpatiaLite.

*/
protected function typeGeometry(Fluent $column)
{
throw new \Exception('Geometry data type not supported for current database engine.');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't know what type of exception would be better to throw here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've thought about RuntimeException too.

@taylorotwell taylorotwell merged commit 8f92b9f into laravel:5.5 Sep 7, 2017
@antonkomarev antonkomarev deleted the feature/geospatial-blueprint-methods branch September 7, 2017 12:28
@antonkomarev
Copy link
Contributor Author

Thank you! ❤️ This change removes about to 12 classes from the package.

@edmandiesamonte
Copy link
Contributor

Any Eloquent guide for this?

@antonkomarev
Copy link
Contributor Author

antonkomarev commented Sep 12, 2017

@edsamonte this PR includes only blueprint methods to create spatial data columns. To add Spatial queries to Eloquent there are much more things should be solved. First of all implement all geometry classes, WKT & WKB format parsers and generators.
There will be requirement to add more dependencies to Illuminate\Database package and I'm not sure Taylor will accept all of them. I've got all of this things done in extra 3 packages, but they are not documented and private at this moment. I need more time to refactor them, cover with documentation, only then they will be ready to be published.

@elynnaie
Copy link

elynnaie commented Jul 26, 2018

Why do you say that the geometry type is "not supported by PostgreSQL"? If you have PostGIS (which I assume is required for all of these types), geometry is a perfectly valid column type. Instead of returning "geography({$type}, 4326)" you could return "geometry" or "geometry('geometry', 4326)" or even "geography('geometry', 4326)". Is there a reason this was not implemented?

@antonkomarev
Copy link
Contributor Author

antonkomarev commented Jul 26, 2018

@denaje thank you for raising this important question!

I excluded geometry type because it wasn't worked in my PostgreSQL and I didn't found any solution. If you could make it work - post a PR covered with tests and I'm sure Taylor will merge it.

@paulofreitas
Copy link
Contributor

paulofreitas commented Jul 27, 2018

Indeed, this is an interesting question. Thanks @denaje! 👍

There are two different spatial types used in PostGIS: geometry (planar) and geography (spheroid). Quoting the PostGIS documentation:

The basis for the PostGIS geometry type is a plane. The shortest path between two points on the plane is a straight line. That means calculations on geometries (areas, distances, lengths, intersections, etc) can be calculated using cartesian mathematics and straight line vectors.

The basis for the PostGIS geographic type is a sphere. The shortest path between two points on the sphere is a great circle arc. That means that calculations on geographies (areas, distances, lengths, intersections, etc) must be calculated on the sphere, using more complicated mathematics. For more accurate measurements, the calculations must take the actual spheroidal shape of the world into account, and the mathematics becomes very complicated indeed.

This applies to SQL Server as well: https://docs.microsoft.com/en-us/sql/relational-databases/spatial/spatial-data-sql-server

MySQL implementation is more simplified. By default every geometry feature type is planar (SRID 0), requiring you to use appropriate functions (e.g. ST_Distance_Sphere) and SRIDs (e.g. 4326 "WGS84") to calculate over a sphere.

We are deliberately using the geography spatial type for PostgreSQL/SQL Server because it's the most accurate when calculating distances from the globe: https://gis.stackexchange.com/a/33577

So in short we can't return the geometry type and mix those two different spatial types.

The geometry method currently not supported in Laravel is about the feature type from the spatial type as defined in the OpenGIS specification. The geometry feature type is a special feature used to store any other feature type.
Indeed both spatial types have the geometry feature type, and we would want to use the geographic spatial type here: geography('geometry', 4326)

To help in the matter I just tested creating a column with geography('geometry', 4326) on PostgreSQL 10.4 and PostGIS 2.4 and it worked as expected.

With all that said, I think it would be really welcome to fix this mistake. 👍 😉

@elynnaie
Copy link

Thanks for the thorough analysis @paulofreitas! I was not aware about the difference between geometry and geography before. I will be happy to make a PR with the proposed change.

@dtheb
Copy link

dtheb commented Oct 1, 2018

Any progress on eloquent support?
If the concern is too many dependencies what about adding just the type casts to do the WKB to GeoJson, latlng array, or something similar?

this would keep eloquent base clean(ish) but provides an easy way to query GIS types?
Note: PHP 7.2.0 added the BE/LE to float & double for the pack/unpack methods this should make it a litlle easier to parse WKB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants