brick / geo

GIS geometry library for PHP
MIT License
220 stars 31 forks source link

Changing visibility method from private to protected #24

Open OleksandrWebLab opened 3 years ago

OleksandrWebLab commented 3 years ago

Hi. I found one problem when switching between different databases.

My code:

GeometryEngineRegistry::set(new PDOEngine($pdo));

$cs = CoordinateSystem::xy(4326);

$polygon = new Polygon($cs, ...[
    new LineString($cs, ...[
        new Point($cs, 0, 0),
        new Point($cs, 0, 1),
        new Point($cs, 1, 1),
        new Point($cs, 1, 0),
        new Point($cs, 0, 0),
    ]),
]);

$area = $polygon->area();

A request similar to this is being executed:

SELECT ST_Area(ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))', 4326));

MySQL returns 12308778368.75034 sq meters; PostgreSQL returns 1

But if I want to get square meters from PostgreSQL, I need to add the true parameter to the ST_Area function. But this parameter results in an error for MySQL

SELECT ST_Area(ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))', 4326), true);

In this case, PgSQL returns a result very close to MySQL MySQL: 12308778368.75034 PgSQL: 12308778361.469454

To solve this problem I decided to inherit the class and override the area method for PostgreSQL

use Brick\Geo\Engine\PDOEngine;
use Brick\Geo\Geometry;

class PostgreSQLEngine extends PDOEngine
{
    /**
     * @inheritDoc
     */
    public function area(Geometry $g): float
    {
        return $this->queryFloat('ST_Area', $g, true);
    }
}
BenMorel commented 3 years ago

Hi, this class wasn't designed to be extended, although I definitely agree that your use case is valid, given the non-support for PostGIS geographies at the moment.

That being said, I'd be more interested in finding a way for the library to natively support PostGIS geographies, by automatically applying ST_GeographyFromText() instead of ST_GeomFromText(), depending, for example, on the SRID in use.

If the input is a Geography, I can see in the docs for ST_Area() that the calculation is done on the spheroid by default, so you wouldn't even need to pass an extra parameter to ST_Area() as far as I understand.

Basically, if we transparently used Geographies on PostGIS for a specific SRID (4326, I don't know if there are others), we could align PostGIS' behaviour with that of MySQL. I suggested the same thing in #23 just a few days ago.

What do you think? Are there any cases when you'd want to use SRID 4326 but want the calculation results in square degrees?

OleksandrWebLab commented 3 years ago

Hi, thanks for the reply.

I recently started working with geography, and I wish I didn't have to think about what SRIDs are, what they are, and so on. I just want to call the function $polygon->areaSpheroid() and get the area in square meters, let the library default to SRID 4326, but I should be able to change this SRID if necessary.

I searched a bit and found this site: https://epsg.io/?q=, here is a complete list of all SRIDs that exist, and for each SRID there are many options to install. For example, here is the description for SRID 4326:

image

The SRID 4326 setup looks like this:

GEOGCS["WGS 84",
    DATUM["WGS_1984",
        SPHEROID["WGS 84",6378137,298.257223563,
            AUTHORITY["EPSG","7030"]],
        AUTHORITY["EPSG","6326"]],
    PRIMEM["Greenwich",0,
        AUTHORITY["EPSG","8901"]],
    UNIT["degree",0.0174532925199433,
        AUTHORITY["EPSG","9122"]],
    AUTHORITY["EPSG","4326"]]

where 6378137 - is the radius of the Earth

For example, I found the standard 'ERSI 104905', it describes the coordinate system of Mars:

GEOGCS["GCS_Mars_2000",
    DATUM["D_Mars_2000",
        SPHEROID["Mars_2000_IAU_IAG",3396190.0,169.8944472236118]],
    PRIMEM["Reference_Meridian",0.0],
    UNIT["Degree",0.0174532925199433]
]

Sources: https://www.esri.com/arcgis-blog/products/3d-gis/3d-gis/to-infinity-and-beyond-arcgis-online-now-supports-extraterrestrial-mapping/ https://developers.arcgis.com/javascript/3/jshelp/gcs.html https://docs.geotools.org/stable/javadocs/org/opengis/referencing/doc-files/WKT.html Therefore, I want the library to remain flexible.

By the way, thanks for the library, it's very cool), I tried about 3 packages before finding yours, and I like everything about it)