I have been having some trouble converting polygons from Geometry to Geography.
I have found the following articles and have taken the steps advised but I am still unable to convert all the instances to valid geography objects.
Union start point to ensure correct orientation
blogs.msdn.com/b/edkatibah/archive/2008/08/19/working-with-invalid-data-and-the-sql-server-2008-geography-data-type-part-1b.aspx
Reduce polygon
blogs.msdn.com/b/edkatibah/archive/2009/06/05/working-with-invalid-data-and-the-sql-server-2008-geography-data-type-part-2.aspx
Buffer and negative buffer
http://www.beginningspatial.com/fixing_invalid_geography_data
Remove points from collection after reduce
http://alastaira.wordpress.com/2012/03/02/cleaning-up-artefacts-created-by-reduce/
My process thus far is the following.
Import shape file to SQL Server Developer Edition (64-bit) using Morten Nielsen's excellent Shape2Sql tool from www.sharpgis.net/page/SQL-Server-2008-Spatial-Tools.aspx
I had to import the shape file as geometry as I was getting errors about invalid geography values.
Then I tried to create geography's as per my SQL script below.
drop table [MapData].[dbo].[World_SeasSplitGeog]
SELECT
[IDX]
,[OBJECTID]
,[NAME]
,[ID]
,[Gazetteer_]
,[Shape_Leng]
,[Shape_Le_1]
,[Shape_Area]
,[ORIG_FID]
,dbo.RemoveArtefacts(GEOGRAPHY::STGeomFromWKB(shape.STUnion(shape.STStartPoint()).STBuffer(0.00001).STBuffer(-0.00001).Reduce(0.000001).STAsBinary(),4326).MakeValid()).MakeValid() as [Shape]
INTO
[MapData].[dbo].[World_SeasSplitGeog]
FROM
[MapData].[dbo].[World_SeasSplit]
The problem however is that not all the geometries are converted to valid geographies
Related
I am looking to create a field that tells me the nearest neighbour distance in km between 2 geometric columns.
I have a point dataset and multiline dataset both with the geometric fields.
I tried the following:
SELECT
p.GEOM.STDistance(l.GEOM) AS distance
FROM
[points] p, [dbo].[lines] l
after running this query I get the following message
Msg 6522, Level 16, State 1, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "geometry":
System.ArgumentException: 24144: This operation cannot be completed because the instance is not valid. Use MakeValid to convert the instance to a valid instance. Note that MakeValid may cause the points of a geometry instance to shift slightly.
System.ArgumentException:
Could you help me with this one please?
Much appreciated!
Thanks!
The error seems to indicate you have bad spatial data in one of the tables but the query you're using has issues as well. Run this
select ID, geom.STisValid() from lines
and
SELECT ID, geom.STisValid() from points
To see if you have any bad geometry records. If you do run
update table 'with bad spatial datatype'
set geom = geom.MakeValid()
Once you're sure the spatial data is valid rework your query to use a cross join (compare every line to every point (and get the distance) and store the results in a temp table.
Query the temp table for the min(distance) for each point or line. Provided you only need to know the closest feature and not a distance you can do all this with geometry data. If you need to have a measure in feet or meters you will need to convert your data from geometry to geography.
If you have a large number of features in either table the cross join could take forever. Try to work it out on a subset.
I'm not being able to understand how is the data type geography in SQL server...
For example I have the following data:
0xE6100000010CCEAACFD556484340B2F336363BCA21C0
what I know:
0x is prefix for hexadecimal
last 16 numbers are longitude: B2F336363BCA21C0 (double of decimal format)
16 numbers before the last 16 are latitude: CEAACFD556484340 (double of decimal format)
4 first numbers are SRID: E610 (hexadecimal for WGS84)
what I don't understand:
numbers from 5 to 12 : 0000010C
what is this?
From what I read this seems linked to WKB(Well Known Binary) or EWKB(Extended Well Known Binary) anyway i was not abble to find a definition for EWKB...
And for WKB this is supposed to be geometry type (4-byte integer) but the value doesn't match with the Geometry types codes (this example is for one point coordinate)
Can you help to understand this format?
The spatial types (geometry and geography) in SQL Server are implemented as CLR data types. As with any such data types, you get a binary representation when you query the value directly. Unfortunately, it's not (as far as I know) WKB but rather whatever format Microsoft decided was best for their implementation. For us (the users), we should work with the published interface of methods that have been published by MS (for instance the geography method reference). Which is to say that you should only try to decipher the MS binary representation if you're curious (and not for actually working with it).
That said, if you need/want to work with WKB, you can! For example, you can use the STGeomFromWKB() static method to create a geography instance from WKB that you provide and STAsBinary() can be called on a geography instance to return WKB to you.
The Format spec can be found here:
https://msdn.microsoft.com/en-us/library/ee320529(v=sql.105).aspx
As that page shows, it used to change very frequently, but has slowed down significantly over the past 2 years
I am currently needing to dig into the spec to serialize from JVM code into a bcp file so that I can use SQLServerBulkCopy rather than plain JDBC to upload data into tables (it is about 7x faster to write a bcp file than using JDBC), but this is proving to be more complicated than what I originally anticipated.
After testing with bcp, you can upload geographies by specifying an off row format ( varchar(max) ) and store the well known text, SQL server will see this and assume you wanted a geography based on the WKT it sees.
In my case converting to nvarchar resolved the issue.
I'm trying to run an INSERT query but it asks me to convert varchar to null. Here's the code:
INSERT Runtime.dbo.History (DateTime, TagName, vValue)
VALUES ('2015-09-10 09:00:00', 'ErrorComment', 'Error1')
Error message:
Error converting data type nvarchar to (null).
The problem is at the vValue column.
column vValue(nvarchar, null)
How it looks in the database:
The values inside vValue are placed by the program I'm using. I'm just trying to manually insert into the database.
Last post was with the wrong column, I apologize.
After contacting Wonderware support i found out that INSERT is not supported on the vValue column by design. It’s a string value and updates are supposed to carry out via the StringHistory table.
What is the type of the column value in the database ?
If it's float, you should insert a number, not string.
Cast "error1" to FLOAT is non-sense.
Float is a number exemple : 1.15, 12.00, 150.15
When you try to CAST "Error1" to float, he tries to transform the text "error1" to number and he can't, it's logic.
You should insert a number in the column.
I think I can help you with your problem since I've got a decent test environment to experiment with.
Runtime.dbo.History is not a table you can interact directly with, it is a View. In our case here the view is defined as:
select * from [INSQL].[Runtime].dbo.History
...Which I believe implies the History data you are viewing is from the Historian flat file storage itself, a Wonderware Proprietary system. You might see some success if you expand the SQL Server Management Studio's
Server Objects -> Linked Servers -> INSQL
...and play with the data there but I really wouldn't recommend it.
With that said, for what reason do you need to insert tag history? There might be other workarounds for the purpose you need.
I'm trying to write a SQL query which determine if a given point is into a polygon. (I'm using SQL Server 2008 R2).
I was following this tutorial (just copy / paste it and change some table name) and it approximatively works BUT it is not precise at all. For example, let's considerate a given point which coordinates are :
P = 45.7664, 4.87383.
If you draw a little polygon (an approximate square) around this point with 4 vertices coordinates :
S = 45.97215 4.693909, 45.687 4.674683, 45.73302 5.460205, 46.05227 5.366821, 45.97215 4.693909
the procedure given in the link below answers the point is NOT in polygon, whereas it is...
This is the output (with my own formatting text) :
(Polygon 20 is the polygon above)
But if you enlarged the square (10 times bigger in my test), the procedure answers my point is in the square.
So, I'm seeking for another algorithm, more precise.
Here is my VERTICE table, containing all vertices coordinates of each polygon of my DB
I need to check, for ALL polygons (there are a few thousands) if a given point passed in parameter is in a polygon (and if yes, which one(s)). I can do the loop by myself, but I miss a correct Point in polygon algorithm.
Could someone help me ?
Thank you very much.
SUMMARY
The corresponding SQL fiddle : http://sqlfiddle.com/#!3/0caa4/1
Your problem is that you've defined the polygon backwards. Let's explore this with the native SQL geography types
declare #s geography, #t geography, #p geography;
select #s = geography::STPolyFromText('POLYGON((45.97215 4.693909, 45.687 4.674683, 45.73302 5.460205, 46.05227 5.366821, 45.97215 4.693909))', 4326);
select #t = geography::STPolyFromText('POLYGON((46.05227 5.366821, 45.73302 5.460205, 45.687 4.674683, 45.97215 4.693909, 46.05227 5.366821))', 4326);
select #p = geography::STPointFromText('POINT(45.7664 4.87383)', 4326);
select #p.STIntersects(#s), #p.STIntersects(#t);
select #p.STBuffer(10), #s, #t;
As you can see, #s holds pretty much the whole world. In the result set viewer, if you zoom into where your "square" should be, you'll find a hole. Contrast that with #t which is the area that you expect. Also note that I ran this in SQL 2012 which improved on a limitation that existed pre-2012 that says that a geospatial instance can't cross a hemisphere boundary. If you run the above on a 2008 instance, you'll likely get an error to that effect for #s. Comment out the line defining #s and it'll run.
There's a "right-hand" rule when defining geo(graphy/metry) polygons. Imagine that you were in a car visiting the points in the order you've specified. The area that you're defining is what you'd see if you were looking out the right side of the car.
I am using SQL Server 2012. I have a table where I am tracking single point instances in a geography column. Storing them as a single point is working fine but I am trying to group some of them together into a new table where they would be a multipoint. I can get it working by inserting lat and long into a multipoint column like this:
DECLARE #g geography;
SET #g = geography::STMPointFromText('MULTIPOINT(-104.952784 39.524092, -104.935269 39.542652)', 4326);
INSERT INTO test(loc) values(#g)
What I want to do is select the values from a table that are already a geography data type. I am not sure if I can do this with a basic query or if I have to build it with a loop? I cannot seem to get it working either way.
Also, after I have that is there a method that will return me the center point of a multipoint column? I have been playing with some of the methods like STStartPoint and STEndpoint but I cannot seem to find a methods that return the center point?
Any help on these questions would be great and highly appreciated.
Thanks!
What you're looking for is the STCentroid() method but, unfortunately, it doesn't work for MultiPoint objects. I raised a Connect issue for this a few years back which has been closed by Microsoft as "Won't Fix", but you're welcome to vote it up anyway: https://connect.microsoft.com/SQLServer/feedback/details/588316/make-geometry-stcentroid-method-work-on-geometries-other-than-polygons
Meanwhile, you'll have to manually sum and then average the X and Y coordinate values individually to get the average "centre" of a Multipoint.
If I'm understanding your first question correctly, you have two points, stored individually as geography instances. If that's the case, you can use the STUnion method to combine them into one geography multipoint instance.