I'm working with postgresql with postgis.
I have few questions:
trying to insert into a table with polygon column using the following syntax:
ST_GeomFromText('POLYGON((long1 lat1, long2 lat2, long3 lat3))')
fails with the following error: function geomfromtext(unknown) does not exist
what is the difference between
CREATE TABLE my_table (my_polys polygon);
and
CREATE TABLE my_table2 (my_polys GEOGRAPHY(POLYGON));
and why does the following:
INSERT INTO my_table (my_polys) VALUES ('
(51.504824, -0.125918),
(51.504930, -0.122743),
(51.504930, -0.110297),
(51.504824, -0.102229),
(51.503435, -0.099311)'
);
work fine with my_table and not with my_table2 (I've changed the table name to my_table2)
what is the maximum number of points a polygon can have?
The geography data type is mostly useful when your geometry might wrap around the date line. If it does not, you are better off using normal geometry data types, as most functions in Postgis are designed to work on planar geometries. If your data are lat/lon, you can explicitly set this when you create your column with:
create table foo geom geometry(POLYGON, 4326);
Explicitly setting the coordinate reference system is useful if you want to convert between one coordinate system and another and helps prevent suprises if you attempt to run an intersection, say, between geometries in different coordinate systems.
It is hard to imagine your insert fragment above working with any table, not only is there a trailing comma, but there is no st_geomfromtext, st_makepolygon or anything else to convert what you have written into any geometry.
I have no idea what the maximum size for a polygon is, although, as Chris has already said, you are likely to have performance issues with polygons of 1gb in size, when you try and do spatial queries on them.
Your polygon size is limited by the max storage size. I believe this is limited to 1gb for a toasted column, though my guess is that you are likely to run into performance issues long before you exceed the maximum number of points.
Polygon is a built in type in PostgreSQL, and PostGIS offers additional types for geometry and geography. As I understand it the built-in-types only work for 2d Euclidean space, while PostGIS offers additional options there.
As for why your query fails, I wonder which version of PostGIS you are running and why st_geomfromtext is calling geomfromtext.
Related
I have been assuming based on old posts I found here and elsewhere that a NUMBER data type with no scale specified defaults to zero. However, when I look at our data on our server, I see rational numbers (read non-integers) even with no scale specified. Is this expected behavior?
To give some context, I am a technical writer and I am documenting various things associated with the data we house. I have been assuming that all NUMBERS with no scale specified have been integers. If this is incorrect, I'll need to update my documentation.
I have basically used the following link as a citation for my reasoning concerning scale, but now I believe that it is outdated. Link
I have also read the oracle documentation here and here. The last link also states that if no scale is specified, then the default is set to zero.
I think the Oracle documentation is misleading. If no precision and no scale is specified, then the number is stored as-is; the default to 0 scale only occurs when there is a specified precision.
So, the following code stores the first few digits of pi:
create table t (n number);
insert into t(n) values (3.14159265358979);
But this does not:
create table t2 (n number(5));
insert into t2(n) values (3.14159265358979);
Here is a db<>fiddle illustrating this.
This is rather indelibly marked in my memory, from a fun time porting an Oracle database to BigQuery (which did not even have numeric at the time). The Oracle number data type was one of the most difficult parts of the transition. In the end, we needed to move that into strings.
How would I create a table that contains a geography point (lat/long) using PostGIS? Then also, what would the format be for inserting into this table (Using SQL/PostgreSQL)?
Would it just the following for table creation:
CREATE TABLE x (geog geography(point, 4326))
If so, what is the point and when would you instead use ST_Point(X,Y)
Should this column have an index?
Note: Many questions previously answered detail how to convert. But I want to create an empty table from scratch that supports storing latitude and longitude.
Yes, the Syntax for Creating a table with Geography is as simple as CREATE TABLE x (geog geography(POINT,4326) );
In this Command, POINT is the type of shape that this table will be storing. Other possibilities are :
LINESTRING
POLYGON
MULTIPOINT
MULTILINESTRING
MULTIPOLYGON
GEOMETRYCOLLECTION
The reason why storing a Geography in a table makes sense in some cases, is that it gives you the ability to run several functions which would give you results as if you are calculating on a Spherical Earth. So for example I could have two points stored as Geography (knowing only lat-long of each), and I could easily find the distance between them in Meters
ST_Point(X,Y) is just a function that takes in two numbers, and then creates a point which has X as the first number and Y as the second number. It need not be a Lat-long pair. Infact this Point has not concept of which Coordinate reference system it is in.
Once you create the table, inserting records in it, is as simple as:
INSERT INTO X (geog) VALUES (ST_GeographyFromText('POINT(2.5559 49.0083)'));
Here You are are creating a Geography point for Paris, with latitude of 49.0083N and longitude of 2.5559 E
Background:
My application needs to display the MBR of the spatial data (geometry) stored in Oracle. For this, I'm currently using Oracle's SDO_AGGR_MBR() function, but it is very slow. On researching a little, I found a function SDO_TUNE.EXTENT_OF() which also computes MBR and is much faster than SDO_AGGR_MBR. It has 2 problems though. It works only with 2D data in projection coordinates. To tap into the performance benefits of EXTENT_OF, I decided to use it for projected data and fallback to SDO_AGGR_MBR for geographic data.
The Problem:
I started out with an assumption that all data with SRID between 4000 to 5000 is geographic but that is not entirely true. I found a table/view named MDSYS.CS_SRS which stores the coordinate system information.
I'm planning to find the SRID using query:
select a.COLUMN_NAME.SDO_SRID from TABLE_NAME a where rownum = 1;
and then using this SRID to query MDSYS.CS_SRS to find out whether the data is geographic or projected. It has column named WKTEXT whose rows start with either PROJCS or GEOGCS.
I could prototype this and it seems to work but entirely confident this is the right approach. The query above fetches the SRID of the first row of the data. I don't know if SRID can be different in a single column. Another assumption I'm making is the text in WKTEXT column. I'll be in a lot of trouble if it's not PROJCS/GEOGCS in all cases and if the values change between different releases of Oracle. In fact, right now, I'm just assuming that PROJCS means projection CS and GEOGCS means geographic CS and I'm not sure if it's right..
I wonder if there's an easier way to find out whether the spatial data in an Oracle DB is projection or geographic.
You did not say which version of the database you are looking at. I am assuming 10gR2 or later.
The easiest is to check table SDO_COORD_REF_SYS:
SQL> select srid, coord_ref_sys_kind from sdo_coord_ref_sys where srid in (4326, 4327, 27700, 7405);
SRID COORD_REF_SYS_KIND
---------- --------------------
4326 GEOGRAPHIC2D
4327 GEOGRAPHIC3D
7405 COMPOUND
27700 PROJECTED
4 rows selected.
So I added geometry columns to a spatial table and using some of the msdn references I ended up specifying the SRID as 0 like so:
update dbo.[geopoint] set GeomPoint = geometry::Point([Longitude], [Latitude], 0)
However, I believe this was a mistake, but before having to update the column, is 0 actually the default = 4326? The query works as long as I specify the SRID as 0 on the query, but I'm getting weird results in comparison to the geography field I have... SRID 0 does not exist in sys.spatial_reference_systems and I haven't been able to dig up any information on it. Any help would be appreciated.
A SRID of 0 doesn't technically exist, it just means no SRID -- ie, the default if you forget to set it. So, technically, you can still perform distance, intersection and all other queries, so long as both sets of geometries have a SRID of 0. If you have one field of geometries with a SRID of 0 and another set with a SRID that actually exists, you will most likely get very strange results. I remember scratching my head once when not getting any results from a spatial query in exactly this situation and SQL Server did not complain, just 0 results (for what is is worth Postgis will actually fail, with a warning about non-matching SRIDs).
In my opinion, you should always explicitly set the SRID of your geometries (or geographies, which naturally will always be 4326), as not only does it prevent strange query results, but it means you can convert from one coordinate system to another. Being able to convert on the fly from lat/lon (4326), to Spherical Mercator (3857), as used in Google Maps/Bing, which is in meters, or some local coordinate system, such as 27700, British National Grid, also in meters, can be very useful. SQL Server does not to my knowledge support conversion from one SRID to another, but as spatial types are essentially CLR types, there are .NET libraries available should you ever need to do so, see Transform/ Project a geometry from one SRID to another for an example.
If you do decide to change you geometries, you can do something like:
UPDATE your_table SET newGeom = geometry::STGeomFromWKB(oldGeom.STAsBinary(), SRID);
which will create a new column or to do it in place:
UPDATE geom SET geom.STSrid=4326;
where 4326 is just an example SRID.
There is a good reference for SRIDs at http://spatialreference.org/, though this is essentially the same information as you find in sys.spatial_reference_systems.
SRIDs are a way to take into account that the distances that you're measuring on aren't on a flat, infinite plane but rather an oblong spheroid. They make sense for the geography data type, but not for geometry. So, if you're doing geographic calculations (as your statement of "in comparison to the geography field I have"), create geography points instead of geometry points. In order to do calculations on any geospatial data (like "find the distance from this point to this other point"), the SRID of all the objects involved need to be the same.
TL;DR: Is the point on the Cartesian plane? Use geometry. Is the point on the globe? Use geography.
We have an application that has a database full of polygons (currently stored as points) that a .net app pulls out and checks if they overlap.
I occurred to me that it would be much nicer to convert these point arrays to polygon / polyline objects within the database and use sql to get a bool of weather they overlap or not.
I have seen different methods suggested to do this but non of the examples given were quite in-line with my needs.
I would be very happy to receive input from those kind enough to offer their experience.
Additional:
In response to questions: It is indeed 2D. and yes any crossover of the two is considered true. The polygons have n points and can be concave. The polygons will be saved as 1 per row (after data conversion task) as polygons (i.e. the polygon type .. it might be called something else spatial / geom my memory is not on my side right now)
You can use .STIntersection with .STAsText() to test for overlapping polygons. (I really hate the terminology Microsoft has used (or whoever set the standard terms). "Touching," in my mind, should be a test for whether or not two geometry/geography shapes overlap at all, not just share a border.)
Anyway....
If #RadiusGeom is a geometry representing a radius from a point, the following will return a list of any two polygons where an intersection (a geometry that represents the area where two geometries overlap) is not empty.
SELECT CT.ID AS CTID, CT.[Geom] AS CensusTractGeom
FROM CensusTracts CT
WHERE CT.[Geom].STIntersection(#RadiusGeom).STAsText() <> 'GEOMETRYCOLLECTION EMPTY'
If your geometry field is spatially indexed, this runs pretty quickly. I ran this on 66,000 US CT records in about 3 seconds. There may be a better way, but since no one else had an answer, this was my attempt at an answer for you. Hope it helps!
Calculate and store the bounding rectangle of each polygon in a set of new fields within the row which is associated with that polygon. (I assume you have one; if not, create one.) When your dotnet app has a polygon and is looking for overlapping polygons, it can fetch from the database only those polygons whose bounding rectangles overlap, using a relatively simple SQL SELECT statement. Those polygons should be relatively few, so this will be efficient. Then, your dotnet app can perform the finer polygon overlap calculations in order to determine which ones of those really overlap.
Okay, I got another idea, so I am posting it as a different answer. I think my previous answer with the bounding polygons probably has some merit on its own, even if it was to reduce the number of polygons fetched from the database by a small percentage, but this one is probably better.
MSSQL supports integration with the CLR since version 2005. This means that you can define your own data type in an assembly, register the assembly with MSSQL, and from that moment on MSSQL will be accepting your user-defined data type as a valid type for a column, and it will be invoking your assembly to perform operations with your user-defined data type.
An example article for this technique on the CodeProject: Creating User-Defined Data Types in SQL Server 2005
I have never used this mechanism, so I do not know details about it, but I presume that you should be able to either define a new operation on your data type, or perhaps overload some existing operation like "less-than", so that you can check if one polygon intersects another. This is likely to speed things up a lot.